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