Mercurial > hg > index.cgi
changeset 29:455cdf81b33a
Command interpreation loop, END, STOP, DATA, ', REM, ELSE
Add the command interpretation loop, both immediate mode and program mode.
This also includes the END and STOP commands since their function is
intricately tied to the interpretation loop.
Also implement REM and ', which either skip to the next line OR return to
the original caller to the interpretation loop if immediate mode. There is
no need to bother skipping through the bytes to find the end of the line
which is wastefully slow. ELSE is implemented with the same routine for now
though some more complex things may be possible later if ENDIF is
implemented.
Finally, implement the DATA command which skips only to the end of the DATA
statement, but has to make sure it doesn't detect colons inside of quoted
strings.
author | William Astle <lost@l-w.ca> |
---|---|
date | Tue, 15 Nov 2022 23:37:38 -0700 |
parents | e451188b6e46 |
children | 4488ed12bb67 |
files | src/lwbasic.s |
diffstat | 1 files changed, 147 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lwbasic.s Tue Nov 15 23:34:03 2022 -0700 +++ b/src/lwbasic.s Tue Nov 15 23:37:38 2022 -0700 @@ -216,6 +216,11 @@ keyb_curscan rmb 1 ; current repeating scan code keyb_buffw rmb 2 ; keyboard ring buffer write pointer keyb_buffr rmb 2 ; keyboard ring buffer read pointer +curline rmb 2 ; pointer to current line +contline rmb 2 ; pointer to line for CONT +contstmt rmb 2 ; interpretation pointer for CONT +curstmt rmb 2 ; start of statement currently being interpreted +endflag rmb 1 ; 00 = END, FF = STOP 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) @@ -1038,11 +1043,127 @@ bra immediate ; go handle another line immediate1 ; handle line insert/delete/modify bra immediate0 -prompt fcn 'OK' +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Main interpretation loop +; +; Enter at interpret with inputptr pointing to the code stream to interpret. +; Enter at interpretline with X pointing to the command stream to interpret which will return to the caller one the +; command stream has completed. STOP or BREAK will return with carry set while END or falling off the end of the +; code will return with carry clear. In the event of an error, the usual error processing will be done and control +; will return to immediate mode with the stack reset. +interpret ldx inputptr ; get interpration address + stx curstmt ; save address of the current statement (needed for some stuff) + lda ,x+ ; are we at the end of the line? + beq interpret0 ; brif so + cmpa #': ; end of statement? + beq interpret3 ; brif so - do a statement +SNERROR ldb #err_sn ; raise a syntax error + jmp ERROR +interpret0 sta endflag ; flag the program exit state as "END" (will be zero) + ldd curline ; were we in immediate mode? + bne interpret1 ; brif not + clra ; clear carry to indicate normal exit + rts ; return to caller +interpret1 ldd ,x++ ; are we at the end of the program? + beq interpret4 ; brif so - bail out + stx curline ; save pointer to current line + leax 1,x ; set input pointer one before the start of the line text +interpret2 stx inputptr +interpret3 jsr nextchar ; fetch first character of next statement + beq interpret ; brif end of statement - do the next statement dance + ;lbpl cmd_let ; brif no command - do assignment (LET command is optional) + ldx primaryjump ; point to jump table + anda #0x7f ; lose bit 7 + leax a,x ; get half way to the correct offset + ldx a,x ; get the address the other half of the way from here + jsr nextchar ; skip past token and set flags + jsr ,x ; call the routine + bra interpret ; go handle the next statement dance +interpret4 bsr cmd_stop1 ; make sure stack is aligned correctly (will not return) +interpretline clr curline ; blank out current line pointer (for immediate mode) + clr curline+1 + leax -1,x ; move back before start of code stream + bra interpret2 ; go interpret this statement and then continue with stuff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; The END command. +cmd_end bne SNERROR ; error out if there is an argument + ;jsr closeall ; close all files for END + clra ; flag END + bra cmd_stop0 ; go do the stop/end +cmd_stop bne SNERROR ; raise error if there was an argument + lda #0xff ; flag STOP +cmd_stop0 sta endflag ; set stop/end flag +cmd_stop1 clr filenum ; reset I/O to console + ldx curline ; in immediate mode? + beq cmd_stop2 ; brif so - don't save the continue pointers + stx contline ; save pointer to current line for CONT + ldx curstmt ; get current statement address + stx contstmt ; save it for CONT +cmd_stop2 rol endflag ; get STOP/END to C (1=STOP) + ldx curline ; immediate mode? + beq cmd_stop3 ; brif so - just return END/STOP status + ldx #breakmsg ; do "BREAK IN" + jmp ERROR2 ; the bottom half of the error handler can deal with the details +cmd_stop3 puls x,pc ; lose return address and return to caller of interpretation loop +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; REM and ' commands; also ELSE comes here since it needs to skip the rest of the line in that case. +cmd_else +cmd_apos +cmd_rem clra ; clear carry + ldx curline ; get start of current line + beq cmd_stop3 ; brif immediate mode - fall back to caller + ldx ,x ; get address of next line + leax -1,x ; move back one + stx inputptr ; put input pointer there + rts +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; DATA command +; +; need to skip to the end of the current statement, which is either the end of the line OR a colon not included inside +; a quoted string +cmd_data ldx inputptr ; get input pointer +cmd_data0 lda ,x+ ; get character at pointer + beq cmd_data2 ; brif end of line + cmpa #': ; end of statement? + bne cmd_data1 ; brif not +cmd_data1 leax -1,x ; move back to the NUL or colon + stx inputptr ; reset input pointer for interpreter + rts +cmd_data2 cmpa #'" ; start of constant string? + bne cmd_data0 ; brif not - process more characters +cmd_data3 lda ,x+ ; get next string character + beq cmd_data1 ; brif end of line + cmpa #'" ; string delimiter? + bne cmd_data3 ; brif not - keep going + bra cmd_data0 ; process stuff outside string +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Miscelaneous strings +prompt fcn 'OK' ; general prompt +breakmsg fcn 'BREAK' ; "BREAK" message ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Error messages -errormsg fcn 'NEXT without FOR' ; 0 - fcn 'Syntax error' ; 1 +; +; Each error begins with a deferr macro invocation which will define a symbol err_slug with the next error number +; +; deferr slug +; +; This is then followed by the error message defined with fcn. +; +; Real error numbers start at 1; 0 is used to indicate no error. + *pragmapush list + *pragma nolist +__errnum set 0 +deferr macro noexpand +err_{1} equ __errnum +__errnum set __errnum+1 + endm + *pragmapop list +errormsg deferr none + fcn 'No error' + deferr nf + fcn 'NEXT without FOR' + deferr sn + fcn 'Syntax error' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Set carry if upper/lower case alpha setcifalpha cmpa #'z+1 ; is it above lower case Z? @@ -1202,20 +1323,42 @@ __funcnum set __funcnum+1 endm cmdtab macro + *pragmapush list + *pragma nolist includestr "%(__cmdtab)" + *pragmapop list fcb 0 ; flag end of table endm functab macro + *pragmapush list + *pragma nolist includestr "%(__functab)" + *pragmapop list fcb 0 ; flag end of table - endm + endm +cmdjump macro + *pragmapush nolist + *pragma nolist + includestr "%(__cmdjump)" + *pragmapop list + endm +funcjump macro + *pragmapush nolist + *pragma nolist + includestr "%(__funcjump)" + *pragmapop list + endm *pragmapop list defcmd 'REM',rem defcmd /'/,apos defcmd 'DATA',data defcmd 'ELSE',else + defcmd 'END',end + defcmd 'STOP',stop primarydict cmdtab secondarydict functab +primaryjump cmdjump +secondaryjump funcjump ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Need to ensure the vectors are at 0xbff2 zmb 0xbff2-* ; pad ROM up to the vector point