mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-04-05 03:37:43 +00:00
Ternary operators for PLASMA! And Floating point string conversion WIP
This commit is contained in:
parent
09a54be674
commit
a9bd3ebbeb
@ -36,7 +36,7 @@ import cmdsys
|
||||
//
|
||||
// CMD exported functions
|
||||
//
|
||||
predef putc(c)#0, putln()#0, puts(s)#0, puti(i)#0, getc()#1, gets(p)#1
|
||||
predef putc(c)#0, putln()#0, puts(s)#0, puti(i)#0, getc()#1, gets(p)#1, toupper(c)#1
|
||||
predef call(addr,areg,xreg,yreg,status)#1, syscall(cmd,params)#1
|
||||
predef heapmark()#1, heapallocalign(size, pow2, freeaddr), heapalloc(size)#1, heaprelease(newheap)#1, heapavail()#1
|
||||
predef memset(addr,value,size)#0, memcpy(dst,src,size)#0
|
||||
|
@ -753,19 +753,19 @@ end
|
||||
//
|
||||
def elemsLoad1(op, dst)#1
|
||||
if loadElems
|
||||
return sane[3](op, dst)
|
||||
return sane[6](op, dst)
|
||||
fin
|
||||
return -1
|
||||
end
|
||||
def elemsLoad2(op, dst, src)#1
|
||||
if loadElems
|
||||
return sane[4](op, dst, src)
|
||||
return sane[7](op, dst, src)
|
||||
fin
|
||||
return -1
|
||||
end
|
||||
def elemsLoad3(op, dst, src, src2)#1
|
||||
if loadElems
|
||||
return sane[4](op, dst, src, src2)
|
||||
return sane[8](op, dst, src, src2)
|
||||
fin
|
||||
return -1
|
||||
end
|
||||
|
@ -3,14 +3,173 @@
|
||||
//
|
||||
include "inc/cmdsys.plh"
|
||||
include "inc/sane.plh"
|
||||
struc t_decrecord
|
||||
word sgn
|
||||
word exp
|
||||
byte sig[29]
|
||||
end
|
||||
struc t_decformat
|
||||
word style
|
||||
word digits
|
||||
end
|
||||
//
|
||||
// Test values
|
||||
//
|
||||
word iA, iB, iC, zero, fpEnv
|
||||
byte xT[t_extended]
|
||||
word decrec = 0, 0
|
||||
byte strA[28] = "10"
|
||||
word decform = 0, 6
|
||||
byte strNum = "-100.25"
|
||||
byte strA[16]
|
||||
//
|
||||
// Parse string into decrecord
|
||||
//
|
||||
def str2ext(str, ext)
|
||||
byte i, s, d
|
||||
byte decrec[t_decrecord]
|
||||
word sgnadj, expadj
|
||||
|
||||
decrec:sgn = 0
|
||||
decrec:exp = 0
|
||||
decrec.sig = 0
|
||||
s = 1
|
||||
i = 1
|
||||
//
|
||||
// Skip whitespace
|
||||
//
|
||||
while ^(str+i) <= ' ' and i <= ^str; i++; loop
|
||||
//
|
||||
// Check for sign
|
||||
//
|
||||
if ^(str+i) == '-'
|
||||
decrec:sgn = 1
|
||||
i++
|
||||
elsif ^(str+i) == '+'
|
||||
i++
|
||||
fin
|
||||
//
|
||||
// Skip leading zeros
|
||||
//
|
||||
while i <= ^str and ^(str+i) == '0'
|
||||
i++
|
||||
loop
|
||||
//
|
||||
// Parse number
|
||||
//
|
||||
while i <= ^str
|
||||
d = toupper(^(str+i))
|
||||
if d >= '0' and d <= '9'
|
||||
//
|
||||
// Parse digit
|
||||
//
|
||||
decrec.sig[s] = ^(str+i)
|
||||
decrec:sig++
|
||||
s++
|
||||
elsif d == '.'
|
||||
//
|
||||
// Parse decimal point
|
||||
//
|
||||
i++
|
||||
while i <= ^str
|
||||
d = toupper(^(str+i))
|
||||
if d >= '0' and d <= '9'
|
||||
decrec.sig[s] = ^(str+i)
|
||||
decrec.sig++
|
||||
decrec:exp--
|
||||
s++
|
||||
elsif d == 'E'
|
||||
i--
|
||||
break
|
||||
else
|
||||
i = ^str
|
||||
fin
|
||||
i++
|
||||
loop
|
||||
elsif d == 'E'
|
||||
//
|
||||
// Parse exponent
|
||||
//
|
||||
i++
|
||||
expadj = 0
|
||||
sgnadj = 1
|
||||
if ^(str+i) == '-'
|
||||
sgnadj = -1
|
||||
i++
|
||||
elsif ^(str+i) == '+'
|
||||
i++
|
||||
fin
|
||||
while i <= ^str
|
||||
d = ^(str+i)
|
||||
if d >= '0' and d <= '9'
|
||||
expadj = expadj * 10 + (d - '0')
|
||||
else
|
||||
i = ^str
|
||||
fin
|
||||
loop
|
||||
decrec:exp = decrec:exp + (sgnadj * expadj)
|
||||
else
|
||||
i = ^str
|
||||
fin
|
||||
i++
|
||||
loop
|
||||
//
|
||||
// Strip leading zeros from sig
|
||||
//
|
||||
while decrec.sig > 1 and decrec.sig.1 == '0'
|
||||
decrec.sig--
|
||||
if decrec:exp < 0
|
||||
decrec:exp--
|
||||
fin
|
||||
memcpy(@decrec.sig.1, @decrec.sig.2, decrec.sig)
|
||||
loop
|
||||
//
|
||||
// Check for zero
|
||||
//
|
||||
if !decrec.sig
|
||||
decrec.sig = 1
|
||||
decrec.sig.1 = '0'
|
||||
fin
|
||||
//putc(decrec.sgn ?? '-' :: '+'); puts(@decrec.sig); putc('e'); puti(decrec:exp); putln
|
||||
return sane:fpOp2(FFEXT|FOD2B, ext, @decrec)
|
||||
end
|
||||
def ext2str(ext, str)
|
||||
byte d, i, dp
|
||||
byte decform[t_decformat]
|
||||
byte decrec[t_decrecord]
|
||||
|
||||
decform:style = 1
|
||||
decform:digits = 4
|
||||
sane:fpOp3(FFEXT|FOB2D, @decrec, ext, @decform)
|
||||
//putc(decrec.sgn ?? '-' :: '+'); puts(@decrec.sig); putc('e'); puti(decrec:exp); putln
|
||||
i = 0
|
||||
if decrec.sgn
|
||||
^(str+1) = '-'
|
||||
i = 1
|
||||
fin
|
||||
dp = decrec.sig + decrec:exp
|
||||
for d = 1 to decrec.sig
|
||||
i++
|
||||
^(str+i) = decrec.sig[d]
|
||||
if d == dp
|
||||
i++
|
||||
^(str+i) = '.'
|
||||
fin
|
||||
next
|
||||
^str = i
|
||||
return ^str
|
||||
end
|
||||
def divstri(strNum, denom)#0
|
||||
byte strResult[16]
|
||||
byte xResult[t_extended]
|
||||
|
||||
//
|
||||
// Convert string to and from SANE
|
||||
//
|
||||
sane:zpSave()
|
||||
str2ext(strNum, @xResult)
|
||||
sane:fpOp2(FFINT|FODIV, @xResult, @denom) // Div int denom into ext Result
|
||||
ext2str(@xResult, @strResult)
|
||||
sane:zpRestore()
|
||||
puts(strNum); putc('/'); puti(denom); putc('='); puts(@strResult); putln
|
||||
end
|
||||
//
|
||||
// My custom SANE exception handler
|
||||
//
|
||||
@ -27,6 +186,7 @@ def myException(pstatus)
|
||||
return pstatus=>4
|
||||
end
|
||||
|
||||
|
||||
iA = 3
|
||||
iB = 4
|
||||
iC = -1
|
||||
@ -73,14 +233,8 @@ sane:fpOp2(FFINT|FOX2Z, @iC, @xT) // Convert ext T to int C
|
||||
sane:zpRestore()
|
||||
puti(iA); putc('/'); puti(zero); putc('='); puti(iC); putc('\n')
|
||||
//
|
||||
// Convert string to and from SANE
|
||||
// String conversion tests
|
||||
//
|
||||
sane:zpSave()
|
||||
sane:fpOp2(FFEXT|FOD2B, @xT, @decrec)
|
||||
//sane:fpOp2(FFINT|FOZ2X, @xT, @iA) // Convert int A to ext T
|
||||
sane:fpOp2(FFINT|FODIV, @xT, @iB) // Div int B into ext T
|
||||
sane:fpOp2(FFINT|FOX2Z, @iC, @xT) // Convert ext T to int C
|
||||
sane:fpOp3(FFEXT|FOB2D, @decrec, @xT, @decform)
|
||||
sane:zpRestore()
|
||||
puts("10 / 4 = "); puts(@strA); putc('e'); puti(decrec:2); putc('('); puti(iC); putc(')'); putln
|
||||
divstri("-100.5", 4)
|
||||
divstri("00.5", 2)
|
||||
done
|
||||
|
@ -127,6 +127,10 @@ def dummy(zz)#0
|
||||
return 0
|
||||
end
|
||||
|
||||
def value1
|
||||
return 1
|
||||
end
|
||||
|
||||
puti(array[0]);putc(' ')
|
||||
puti(array[1]);putc(' ')
|
||||
puti(array[2]);putc(' ')
|
||||
@ -161,4 +165,7 @@ putln
|
||||
puts(@constr); puti(constval); putln
|
||||
puts("Signed byte constant:"); puti(-3); putln
|
||||
puts("Hello from in-line string!\$7F\n")
|
||||
puts(1 ?? "This is TRUE\n" :: "This is FALSE\n")
|
||||
puts(0 ?? "This is TRUE\n" :: "This is FALSE\n")
|
||||
ptr = 0
|
||||
done
|
||||
|
@ -1665,6 +1665,11 @@ int emit_pending_seq()
|
||||
case BRTRUE_CODE:
|
||||
emit_brtru(op->tag);
|
||||
break;
|
||||
case CODETAG_CODE:
|
||||
printf("_B%03d%c\n", op->tag, LBL);
|
||||
break;
|
||||
case NOP_CODE:
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
@ -64,6 +64,8 @@ typedef struct _opseq {
|
||||
#define BRNCH_CODE 0x031C
|
||||
#define BRFALSE_CODE 0x031D
|
||||
#define BRTRUE_CODE 0x031E
|
||||
#define CODETAG_CODE 0x031F
|
||||
#define NOP_CODE 0x0320
|
||||
|
||||
#define gen_uop(seq,op) gen_seq(seq,UNARY_CODE(op),0,0,0,0)
|
||||
#define gen_op(seq,op) gen_seq(seq,BINARY_CODE(op),0,0,0,0)
|
||||
@ -83,6 +85,9 @@ typedef struct _opseq {
|
||||
#define gen_drop(seq) gen_seq(seq,DROP_CODE,0,0,0,0)
|
||||
#define gen_brfls(seq,tag) gen_seq(seq,BRFALSE_CODE,0,tag,0,0)
|
||||
#define gen_brtru(seq,tag) gen_seq(seq,BRTRUE_CODE,0,tag,0,0)
|
||||
#define gen_brnch(seq,tag) gen_seq(seq,BRNCH_CODE,0,tag,0,0)
|
||||
#define gen_codetag(seq,tag) gen_seq(seq, CODETAG_CODE,0,tag,0,0)
|
||||
#define gen_nop(seq) gen_seq(seq,NOP_CODE,0,0,0,0)
|
||||
|
||||
void emit_flags(int flags);
|
||||
void emit_header(void);
|
||||
|
@ -388,6 +388,30 @@ t_token scan(void)
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
if (scanpos[1] == ':')
|
||||
{
|
||||
scantoken = TRIELSE_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = COLON_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
if (scanpos[1] == '?')
|
||||
{
|
||||
scantoken = TERNARY_TOKEN;
|
||||
scanpos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
scantoken = TERNARY_TOKEN;
|
||||
scanpos++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Simple single character tokens.
|
||||
|
@ -746,6 +746,32 @@ t_opseq *parse_expr(t_opseq *codeseq, int *stackdepth)
|
||||
if (stackdepth)
|
||||
(*stackdepth)--;
|
||||
}
|
||||
/*
|
||||
* Look for ternary operator
|
||||
*/
|
||||
if (scantoken == TERNARY_TOKEN)
|
||||
{
|
||||
int tag_else, tag_endtri;
|
||||
int stackdepth1;
|
||||
|
||||
if (*stackdepth != 1)
|
||||
parse_error("Ternary op must evaluate to single value");
|
||||
tag_else = tag_new(BRANCH_TYPE);
|
||||
tag_endtri = tag_new(BRANCH_TYPE);
|
||||
codeseq = gen_brfls(codeseq, tag_else);
|
||||
codeseq = parse_expr(codeseq, &stackdepth1);
|
||||
if (scantoken != TRIELSE_TOKEN)
|
||||
{
|
||||
parse_error("Missing '::' in ternary op");
|
||||
return (NULL);
|
||||
}
|
||||
codeseq = gen_brnch(codeseq, tag_endtri);
|
||||
codeseq = gen_codetag(codeseq, tag_else);
|
||||
codeseq = parse_expr(codeseq, stackdepth);
|
||||
if (stackdepth1 != *stackdepth)
|
||||
parse_error("Inconsistent value counts in ternary op");
|
||||
codeseq = gen_codetag(codeseq, tag_endtri);
|
||||
}
|
||||
return (codeseq);
|
||||
}
|
||||
t_opseq *parse_set(t_opseq *codeseq)
|
||||
|
@ -44,6 +44,11 @@
|
||||
#define STRUC_TOKEN TOKEN(31)
|
||||
#define CONTINUE_TOKEN TOKEN(32)
|
||||
//#define EVAL_TOKEN TOKEN(32)
|
||||
/*
|
||||
* Ternary operand operators.
|
||||
*/
|
||||
#define TERNARY_TOKEN TOKEN('?')
|
||||
#define TRIELSE_TOKEN TOKEN('_')
|
||||
/*
|
||||
* Double operand operators.
|
||||
*/
|
||||
|
@ -31,7 +31,7 @@ const CFFAEntryPtr = $0B
|
||||
// Pedefined functions.
|
||||
//
|
||||
predef syscall(cmd)#1, call(addr,areg,xreg,yreg,status)#1
|
||||
predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1
|
||||
predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1, toupper(c)#1
|
||||
predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr), releaseheap(newheap)#1, availheap()#1
|
||||
predef memset(addr,value,size)#0, memcpy(dst,src,size)#0
|
||||
predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1
|
||||
@ -74,6 +74,7 @@ byte putsstr[] = "PUTS"
|
||||
byte putistr[] = "PUTI"
|
||||
byte getcstr[] = "GETC"
|
||||
byte getsstr[] = "GETS"
|
||||
byte toupstr[] = "TOUPPER"
|
||||
byte sysstr[] = "SYSCALL"
|
||||
byte callstr[] = "CALL"
|
||||
byte hpmarkstr[] = "HEAPMARK"
|
||||
@ -99,6 +100,7 @@ word = @putsstr, @prstr
|
||||
word = @putistr, @print
|
||||
word = @getcstr, @cin
|
||||
word = @getsstr, @rdstr
|
||||
word = @toupstr, @toupper
|
||||
word = @hpmarkstr, @markheap
|
||||
word = @hpallocstr,@allocheap
|
||||
word = @hpalignstr,@allocalignheap
|
||||
|
@ -25,7 +25,7 @@ const modinitkeep = $4000
|
||||
// Pedefined functions.
|
||||
//
|
||||
predef syscall(cmd,params)#1, call(addr,areg,xreg,yreg,status)#1
|
||||
predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1
|
||||
predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1, toupper(c)#1
|
||||
predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr)#1, releaseheap(newheap)#1, availheap()#1
|
||||
predef memset(addr,value,size)#0, memcpy(dst,src,size)#0
|
||||
predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1
|
||||
@ -53,6 +53,7 @@ byte putsstr = "PUTS"
|
||||
byte putistr = "PUTI"
|
||||
byte getcstr = "GETC"
|
||||
byte getsstr = "GETS"
|
||||
byte toupstr = "TOUPPER"
|
||||
byte hpmarkstr = "HEAPMARK"
|
||||
byte hpalignstr = "HEAPALLOCALIGN"
|
||||
byte hpallocstr = "HEAPALLOC"
|
||||
@ -78,6 +79,7 @@ word = @putsstr, @prstr
|
||||
word = @putistr, @print
|
||||
word = @getcstr, @cin
|
||||
word = @getsstr, @rdstr
|
||||
word = @toupstr, @toupper
|
||||
word = @hpmarkstr, @markheap
|
||||
word = @hpallocstr,@allocheap
|
||||
word = @hpalignstr,@allocalignheap
|
||||
|
@ -26,7 +26,7 @@ const O_READ_WRITE = 3
|
||||
// Pedefined functions.
|
||||
//
|
||||
predef syscall(cmd,params)#1, call(addr,areg,xreg,yreg,status)#1
|
||||
predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1
|
||||
predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1, toupper(c)#1
|
||||
predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr), releaseheap(newheap)#1, availheap()#1
|
||||
predef memset(addr,value,size)#0, memcpy(dst,src,size)#0
|
||||
predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1
|
||||
@ -71,6 +71,7 @@ byte putsstr[] = "PUTS"
|
||||
byte putistr[] = "PUTI"
|
||||
byte getcstr[] = "GETC"
|
||||
byte getsstr[] = "GETS"
|
||||
byte toupstr[] = "TOUPPER"
|
||||
byte hpmarkstr[] = "HEAPMARK"
|
||||
byte hpalignstr[] = "HEAPALLOCALIGN"
|
||||
byte hpallocstr[] = "HEAPALLOC"
|
||||
@ -95,6 +96,7 @@ word = @putsstr, @prstr
|
||||
word = @putistr, @print
|
||||
word = @getcstr, @cin
|
||||
word = @getsstr, @rdstr
|
||||
word = @toupstr, @toupper
|
||||
word = @hpmarkstr, @markheap
|
||||
word = @hpallocstr,@allocheap
|
||||
word = @hpalignstr,@allocalignheap
|
||||
|
Loading…
x
Reference in New Issue
Block a user