diff --git a/apps/basic/glue.asm b/apps/basic/glue.asm index 9b9a634..dee6b50 100644 --- a/apps/basic/glue.asm +++ b/apps/basic/glue.asm @@ -9,6 +9,10 @@ jp basStart +; RAM space used in different routines for short term processing. +.equ SCRATCHPAD_SIZE 0x20 +.equ SCRATCHPAD USER_RAMSTART + .inc "core.asm" .inc "lib/util.asm" .inc "lib/ari.asm" @@ -17,7 +21,7 @@ .equ EXPR_PARSE parseLiteralOrVar .inc "lib/expr.asm" .inc "basic/tok.asm" -.equ VAR_RAMSTART USER_RAMSTART +.equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE .inc "basic/var.asm" .equ BUF_RAMSTART VAR_RAMEND .inc "basic/buf.asm" diff --git a/apps/basic/main.asm b/apps/basic/main.asm index 4a81e71..3812101 100644 --- a/apps/basic/main.asm +++ b/apps/basic/main.asm @@ -1,5 +1,3 @@ -; *** Constants *** -.equ BAS_SCRATCHPAD_SIZE 0x20 ; *** Variables *** ; Value of `SP` when basic was first invoked. This is where SP is going back to ; on restarts. @@ -9,8 +7,7 @@ ; Important note: this is **not** a line number, it's a pointer to a line index ; in buffer. If it's not zero, its a valid pointer. .equ BAS_PNEXTLN @+2 -.equ BAS_SCRATCHPAD @+2 -.equ BAS_RAMEND @+BAS_SCRATCHPAD_SIZE +.equ BAS_RAMEND @+2 ; *** Code *** basStart: @@ -18,11 +15,11 @@ basStart: call varInit call bufInit xor a + ld (BAS_PNEXTLN), a + ld (BAS_PNEXTLN+1), a ld hl, .welcome call printstr call printcrlf - ld hl, 0 ; points to a zero word - ld (BAS_PNEXTLN), hl jr basLoop .welcome: @@ -43,8 +40,8 @@ basLoop: jr basLoop .number: push ix \ pop de - call toWS - call rdWS + call toSep + call rdSep call bufAdd jp nz, basERR jr basLoop @@ -55,16 +52,7 @@ basLoop: ; If found, jump to it. If not found, unset Z. We expect commands to set Z ; on success. Therefore, when calling basCallCmd results in NZ, we're not sure ; where the error come from, but well... -; Before being evaluated, (HL) is copied in BAS_SCRATCHPAD because some -; evaluation routines (such as parseExpr) mutate the string it evaluates. -; TODO: straighten this situation up. Mutating a string like this breaks -; expectations. basCallCmd: - push de ; --> lvl 1 - ld de, BAS_SCRATCHPAD - call strcpy - ex de, hl ; HL now points to scratchpad - pop de ; <-- lvl 1 ; let's see if it's a variable assignment. call varTryAssign ret z ; Done! @@ -95,17 +83,13 @@ basCallCmd: ex de, hl ld a, b ; cmd's length call addHL - call rdWS + call rdSep jp (ix) - -basPrintLn: - call printstr - jp printcrlf - basERR: ld hl, .sErr - jr basPrintLn + call printstr + jp printcrlf .sErr: .db "ERR", 0 @@ -118,7 +102,8 @@ basERR: ; Commands are expected to set Z on success. basBYE: ld hl, .sBye - call basPrintLn + call printstr + call printcrlf ; To quit the loop, let's return the stack to its initial value and ; then return. xor a @@ -133,7 +118,7 @@ basLIST: .loop: ld e, (ix) ld d, (ix+1) - ld hl, BAS_SCRATCHPAD + ld hl, SCRATCHPAD call fmtDecimal call printstr ld a, ' ' @@ -169,7 +154,7 @@ basRUN: ; Print line number, then return NZ (which will print ERR) ld e, (ix) ld d, (ix+1) - ld hl, BAS_SCRATCHPAD + ld hl, SCRATCHPAD call fmtDecimal call printstr ld a, ' ' @@ -191,15 +176,33 @@ basRUN: ret basPRINT: + ld de, SCRATCHPAD + call rdWord + push hl ; --> lvl 1 + ex de, hl call parseExpr ret nz push ix \ pop de - ld hl, BAS_SCRATCHPAD + ld hl, SCRATCHPAD call fmtDecimal + call printstr + pop hl ; <-- lvl 1 + ; Do we have another arg? + call rdSep + jr z, .another + ; no, we can stop here cp a ; ensure Z - jp basPrintLn + jp printcrlf +.another: + ; Before we jump to basPRINT, let's print a space + ld a, ' ' + call stdioPutC + jr basPRINT basGOTO: + ld de, SCRATCHPAD + call rdWord + ex de, hl call parseExpr ret nz push ix \ pop de diff --git a/apps/basic/tok.asm b/apps/basic/tok.asm index d073898..0e07ffb 100644 --- a/apps/basic/tok.asm +++ b/apps/basic/tok.asm @@ -1,3 +1,12 @@ +; Sets Z is A is ' ' or '\t' (whitespace), or ',' (arg sep) +isSep: + cp ' ' + ret z + cp 0x09 + ret z + cp ',' + ret + ; Expect at least one whitespace (0x20, 0x09) at (HL), and then advance HL ; until a non-whitespace character is met. ; HL is advanced to the first non-whitespace char. @@ -5,7 +14,7 @@ ; Failure is either not having a first whitespace or reaching the end of the ; string. ; Sets Z if we found a non-whitespace char, unset if we found the end of string. -rdWS: +rdSep: ld a, (hl) call isSep ret nz ; failure @@ -47,10 +56,32 @@ fnWSIdx: pop hl ret -; Advance HL to the next whitespace or to the end of string. -toWS: +; Advance HL to the next separator or to the end of string. +toSep: ld a, (hl) call isSep ret z inc hl - jr toWS + jr toSep + +; Read (HL) until the next separator and copy it in (DE) +; DE is preserved, but HL is advanced to the end of the read word. +rdWord: + push af + push de +.loop: + ld a, (hl) + call isSep + jr z, .stop + or a + jr z, .stop + ld (de), a + inc hl + inc de + jr .loop +.stop: + xor a + ld (de), a + pop de + pop af + ret diff --git a/apps/basic/var.asm b/apps/basic/var.asm index 038cde3..b76f58b 100644 --- a/apps/basic/var.asm +++ b/apps/basic/var.asm @@ -44,29 +44,33 @@ varTryAssign: ; We have a variable! Its table index is currently in A. push ix ; --> lvl 1 push hl ; --> lvl 2 - push af ; --> lvl 3. save for later - ; Let's start by evaluating that expression + push de ; --> lvl 3 + push af ; --> lvl 4. save for later + ; Let's put that expression to read in scratchpad inc hl \ inc hl + ld de, SCRATCHPAD + call rdWord + ex de, hl + ; Now, evaluate that expression now in (HL) call parseExpr ; --> number in IX jr nz, .exprErr - pop af ; <-- lvl 3 + pop af ; <-- lvl 4 add a, a ; * 2 because each element is a word ld hl, VAR_TBL call addHL ; HL placed, write number - push de ; --> lvl 3 push ix \ pop de ld (hl), e inc hl ld (hl), d - pop de ; <-- lvl 3 xor a ; ensure Z .end: + pop de ; <-- lvl 3 pop hl ; <-- lvl 2 pop ix ; <-- lvl 1 ret .exprErr: - pop af ; <-- lvl 3 + pop af ; <-- lvl 4 jr .end ; Check if value at (HL) is a variable. If yes, returns its associated value. diff --git a/apps/lib/parse.asm b/apps/lib/parse.asm index 52e5cef..86ee32b 100644 --- a/apps/lib/parse.asm +++ b/apps/lib/parse.asm @@ -132,7 +132,7 @@ parseDecimal: pop hl ret z ; A is not 0? Ok, but if it's a space, we're happy too. - jp isSep + jp isWS .error: pop hl jp unsetZ diff --git a/apps/lib/util.asm b/apps/lib/util.asm index 736208f..b5be841 100644 --- a/apps/lib/util.asm +++ b/apps/lib/util.asm @@ -1,5 +1,5 @@ -; Sets Z is A is ' ' or '\t' -isSep: +; Sets Z is A is ' ' or '\t' (whitespace) +isWS: cp ' ' ret z cp 0x09 diff --git a/apps/zasm/tok.asm b/apps/zasm/tok.asm index 86e4638..e8657be 100644 --- a/apps/zasm/tok.asm +++ b/apps/zasm/tok.asm @@ -31,7 +31,7 @@ isLineEnd: ; Sets Z is A is ' ', ',', ';', CR, LF, or null. isSepOrLineEnd: - call isSep + call isWS ret z jr isLineEndOrComment @@ -68,7 +68,7 @@ isLabel: ; read char in A _eatWhitespace: call ioGetB - call isSep + call isWS ret nz jr _eatWhitespace