Mercurial > hg > index.cgi
changeset 64:2205c3c59a33
Checkpoint
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 22 Apr 2023 08:47:54 -0600 |
parents | a3122251b5fe |
children | bb9fe2bd4894 |
files | src/lwbasic.s |
diffstat | 1 files changed, 199 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lwbasic.s Thu Feb 23 21:56:49 2023 -0700 +++ b/src/lwbasic.s Sat Apr 22 08:47:54 2023 -0600 @@ -41,6 +41,9 @@ keyb_shift equ 0x01 ; shift pressed linebuffsize equ 0x100 ; the line input buffer (256 bytes) stringstacknum equ 20 ; number of entries on the anonymous string descriptor stack +valtype_none equ 0 ; unknown value type +valtype_int equ 1 ; integer (32 bit) value (signed) +valtype_float equ 2 ; float type (40 bit) value ifdef COCO3 ; GIME INIT0 GIME_COCO equ 0x80 ; Set for coco2 compatible mode (video display) @@ -230,10 +233,18 @@ tok_kwnum rmb 1 ; the actual token number tok_kwmatchl rmb 1 ; the length of the best match during lookup tok_kwmatch rmb 2 ; the current best matched token number -valtype0 rmb 1 ; type of value in valaccum0 -valaccum0 rmb 6 ; bucket of bytes for valaccum0 -valtype1 rmb 1 ; type of value in valaccum1 -valaccum1 rmb 6 ; bucket of bytes for valaccum1 +val0.type rmb 1 ; type of value in val0 +val0 rmb 0 ; bucket of bytes for val0 +val0.int rmb 0 ; 32 bit signed integer value (val0) +val0.exp rmb 1 ; floating point exponent (val0) +val0.mant rmb 4 ; floating point mantissa (val0) +val0.sign rmb 1 ; floating point sign (val0) +val1.type rmb 1 ; type of value in val1 +val1 rmb 0 ; bucket of bytes for val1 +val1.int rmb 0 ; 32 bit signed integer value (val1) +val1.exp rmb 1 ; floating point exponent (val1) +val1.mant rmb 4 ; floating point mantissa (val1) +val1.sign rmb 1 ; floating point sign (val1) rmb 0x71-* ; align RSTFLG/RSTVEC for stock ROM compatibility RSTFLG rmb 1 ; 0x55 if RSTVEC is valid RSTVEC rmb 2 ; points to warm start routine (must start with NOP) @@ -1529,7 +1540,91 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PRINT command -cmd_print rts +cmd_print beq cmd_printeol ; brif no argument - do a newline +cmd_print0 cmpa #'; ; semicolon? + bne cmd_print1 ; brif not + jsr nextchar ; skip the semicolon + bne cmd_print0 ; brif not end of the statement + rts +cmd_print1 jsr eval_expr ; evaluate the expression + ldb val0.type ; get value type + cmpb #valtype_int ; integer? + beq cmd_printint ; brif so - print integer + lda #'! ; flag unknown expression type + jsr console_outchr + jsr console_outchr + jsr console_outchr +cmd_printnext jsr curchar ; see what we have here + bra cmd_print ; and go process +cmd_printeol jmp console_outnl ; do a newline and return +cmd_printint leas -12,s ; make a buffer + leay ,s ; point to buffer + lda #0x20 ; default sign (positive) + ldb val0.int ; is it negative? + bpl cmd_printint0 ; brif not + lda #'- ; negative sign +cmd_printint0 sta ,y+ ; save sign + ldu #cmd_printintpc ; point to positive constant table + ldx #10 ; there are 10 constants to process + tsta ; negative value? + bmi cmd_printint3 ; brif so - start with addition loop +; subtraction loop - positive residue +cmd_printint1 lda #'0-1 ; initialize digit + sta ,y +cmd_printint2 inc ,y ; bump digit + ldd val0.int+2 ; subtract constant + subd 2,u + std val0.int+2 + ldd val0.int + sbcb 1,u + sbca ,u + std val0.int + bcc cmd_printint2 ; brif we didn't go negative + leay 1,y ; move to next digit in buffer + leau 4,u ; move to next constant + leax -1,x ; done all constants? + beq cmd_printint5 ; brif so - handle cleanup +; addition loop - negative residue +cmd_printint3 lda #'0-1 ; initialize digit + sta ,y +cmd_printint4 inc ,y ; bump digit + ldd val0.int+2 ; add the constant to the residue + addd 2,u + std val0.int+2 + ldd val0.int + adcb 1,u + adca ,u + std val0.int + bcc cmd_printint3 ; brif we didn't go positive (subtraction loop) + leay 1,y ; move to next digit + leau 4,u ; move to next constant + leax -1,x ; done all digits? + bne cmd_printint1 ; brif not - go do a subtraction loop +cmd_printint5 clr ,y ; NUL terminate the string + leax 1,s ; point past the sign +cmd_printint6 lda ,x+ ; get digit + beq cmd_printint8 ; brif end of number + cmpa #'0 ; is it a zero? + beq cmd_printint6 ; brif so - skip it +cmd_printint7 lda ,s ; get the sign + sta ,-x ; put it at the start of the number + jsr console_outstr ; display the number + leas 12,s ; clean up stack + bra cmd_printnext ; go print the next thing +cmd_printint8 leax -1,x ; restore one of the zeros + bra cmd_printint7 ; go finish up +cmd_printintpc fqb 1000000000 ; 10^9 + fqb 100000000 ; 10^8 + fqb 10000000 ; 10^7 + fqb 1000000 ; 10^6 + fqb 100000 ; 10^5 + fqb 10000 ; 10^4 + fqb 1000 ; 10^3 + fqb 100 ; 10^2 + fqb 10 ; 10^1 + fqb 1 ; 10^0 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error messages ; @@ -1558,6 +1653,8 @@ fcn 'Undefined line number' deferr rg fcn 'RETURN without GOSUB' + deferr ov + fcn 'Overflow' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The LET command which is the default if no token begins a statement cmd_let jmp SNERROR ; not yet implemented @@ -1591,26 +1688,113 @@ eval_expr3 jsr nextchar ; eat the operator token ldx 1,x ; get handler address of this operator pshs x ; save handler address for later - lda valtype0 ; get current value type - ldx valaccum0 ; get value accumlator contents (6 bytes) - ldy valaccum0+2 - ldu valaccum0+4 + lda val0.type ; get current value type + ldx val0 ; get value accumlator contents (6 bytes) + ldy val0+2 + ldu val0+4 pshs a,x,y,u ; save it on the stack jsr eval_expraux ; evaluate the following term and higher precedence expressions puls a,x,y,u ; get back saved value - stx valaccum1 ; save it to the second value accumulator - sty valaccum1+2 - stu valaccum1+4 - sta valtype1 ; save previous value type + stx val1 ; save it to the second value accumulator + sty val1+2 + stu val1+4 + sta val1.type ; save previous value type jsr [,s++] ; go handle the operator puls b ; get back the previous operator precedence bra eval_expr0 ; go process another operator or end of expression -eval_term jmp SNERROR +eval_term jsr curchar ; get current input character + beq eval_term0 ; brif end of input - this is an error + bcs eval_number ; brif digit - we have a number +; bmi eval_func ; brif we have a token - handle function call + cmpa #'. ; decimal point? + beq eval_number ; brif so - evaluate number + cmpa #'- ; negative sign? + beq eval_number ; brif so - evaluate number + cmpa #'+ ; positive sign? + beq eval_number ; brif so - evaluate number +eval_term0 jmp SNERROR ; we have something unrecognized - raise error +; Evaluate a number constant. Currently this only handles 32 bit integers. +eval_number ldb #valtype_int ; start with integer value + stb val0.type ; set return value + ldx zero ; blank out the value + stx val0 + stx val0+2 + stx val0+4 + bra eval_number1 ; go do the parsing +eval_number0 jsr nextchar ; fetch next input + beq eval_numberr ; brif end of expression - bail +eval_number1 cmpa #'- ; negative? + bne eval_number2 ; brif not + com val0.sign ; invert sign + bra eval_number0 ; deal with next input +eval_number2 cmpa #'+ ; unary +? + beq eval_number0 ; brif so - skip it +eval_number5 beq eval_float ; brif decimal - force float + cmpa #'0 ; is it a number? + blo eval_numberr ; brif below digit + cmpa #'9 ; is it still a number? + bhi eval_numberr ; brif above digit + suba #'0 ; offset to binary digit value + pshs a ; save digit value + ldx val0.int ; get current value for later (for quick multiply by 10) + ldd val0.int+2 + pshs d,x ; stored with words swapped on stack for efficiency for later + lsl val0.int+3 ; times 2 + rol val0.int+2 + rol val0.int+1 + rol val0.int + bcs OVERROR ; brif overflowed + lsl val0.int+3 ; times 4 + rol val0.int+2 + rol val0.int+1 + rol val0.int + bcs OVERROR ; brif overflowed + ldd val0.int+2 ; times 5 (add original value) + addd ,s++ + std val0.int+2 + ldd val0.int + adcb 1,s + adca ,s++ + std val0.int + bcs OVERROR + lsl val0.int+3 ; times 10 + rol val0.int+2 + rol val0.int+1 + rol val0.int + bcs OVERROR ; brif overflowed + ldd val0.int+2 ; get low word + addb ,s+ ; add in current digit + adca #0 + std val0.int+2 + ldd val0.int + adcb #0 + adca #0 + std val0.int + bcs OVERROR ; brif overflowed + bpl eval_number4 ; brif we haven't wrapped negative + cmpd #0x8000 ; is it valid negative two's complement? + bhi OVERROR ; brif not + ldd val0.int+2 ; is it still valid two's complement (max negative)? + bne OVERROR ; brif so +eval_number4 jsr nextchar ; fetch next input character + bra eval_number5 ; go handle it +OVERROR ldb #err_ov ; flag overflow + jmp ERROR +eval_numberr ldb val0.sign ; is the number we want negative? + beq eval_numberr0 ; brif not + ldd zero ; negate the value + subd val0.int+2 + std val0.int+2 + ldd zero + subd val0.int + std val0.int +eval_numberr0 rts +eval_float jmp SNERROR ; we don't handle floating point yet ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Operator table ; ; Each entry starts with the precedence value followed by the handler routine. Each handler will receive its left -; operand in valaccum1 and its right operand in valaccum0 and should return its result in valaccum0. +; operand in val1 and its right operand in val0 and should return its result in val0. oper_tab fcb 0x79 ; addition fdb SNERROR fcb 0x79 ; subtraction