# HG changeset patch # User William Astle # Date 1719294279 21600 # Node ID 917b4893bb3d35289a75d7015e5173225d3af7e5 # Parent 95f174bf459b5e5ec5a1e6bec2ea01a4e88f8a5a Checkpoint before redoing a bunch of code for clarity diff -r 95f174bf459b -r 917b4893bb3d src/defs.s --- a/src/defs.s Sat May 18 00:41:46 2024 -0600 +++ b/src/defs.s Mon Jun 24 23:44:39 2024 -0600 @@ -14,6 +14,21 @@ stringstacknum equ 20 ; number of entries on the anonymous string descriptor stack stackheadroom equ 50 ; required headroom for the stack on OM checks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Program storage structure +; +; The program itself consists of two sets of data. The first is a table of line numbers. Each consists of a 16 bit +; pointer to the line data and a 16 bit unsigned line number. These entries are stored in line number order. The line +; data is also stored in line number order. The length of each line is the difference between the current line pointer +; and the next line pointer. There is a final dummy line number entry after the last program line which holds the +; pointer to the first free byte after the program. This is stored there to allow for simpler code for calculating line +; lengths. +; +; Note: linetab_stride + linetabent_size must be a power of two *less than* 256 +linetabent_ptr equ 0 ; offset of the pointer to the line data (must be first) +linetabent_num equ 2 ; offset to line number +linetabent_size equ 4 ; size of a line number table entry, must be power of two +linetab_stride equ 16 ; expand the line table in blocks of 16 entries, must be power of two +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Data structure used for calculations. Calculations are handled via structures called value accumulators. A value ; accumulator consists of a data type flag (at the end of the structure) and a data area whose layout varies based ; on the actual data type. The layouts for each value type are described below. diff -r 95f174bf459b -r 917b4893bb3d src/interp.s --- a/src/interp.s Sat May 18 00:41:46 2024 -0600 +++ b/src/interp.s Mon Jun 24 23:44:39 2024 -0600 @@ -79,7 +79,7 @@ beq immediate0 ; brif not - just read another line cmpa #0x20 ; space? bne immediate0c ; brif not -immediate0b leax 1,x ; move past the +immediate0b leax 1,x ; move past the space bra immediate0a ; keep looking for the start of input immediate0c bsr setcifdigit ; do we have a line number? bcs immediate1 ; brif so - go handle program editing @@ -90,85 +90,181 @@ jsr interpretline ; go interpret the tokenized line bra immediate ; go handle another line immediate1 bsr parse_lineno ; parse the line number - bsr prog_findline ; go see if the line is in the program - bne immediate3 ; brif not - no need to delete it - ldu ,x ; get next line pointer which is where we start the copy from - leay ,x ; use temp pointer for copying -immediate2 lda ,u+ ; get source byte - sta ,y+ ; stash it - cmpu vartab ; did we reach the end of the program text? - blo immediate2 ; brif not - sty vartab ; save new end of program + jsr prog_remove ; remove the line from the program if it exists immediate3 jsr curchar ; skip any spaces after line number tsta ; is it the end of input (don't test for colon) beq immediate6 ; brif so - we don't need to insert a line - pshs x ; save program insert location and line number ldx inputptr ; point to line text jsr parse ; tokenize line, get length to D - leay ,x ; save tokenized line pointer - addd #4 ; account for next line pointer and line number - ldx vartab ; get start of copy location - leau d,x ; set destination copy location D bytes further up - stu vartab ; save new end of program -immediate4 lda ,-x ; get byte from program - sta ,-u ; stash it above the empty space - cmpx ,s ; did we reach the insertion point? - bne immediate4 ; brif not - keep going - leas 2,s ; clear insertion location - stu ,x++ ; set next line pointer to not null - ldd binval ; set the line number for the program - std ,x++ -immediate5 lda ,y+ ; get byte from tokenized line - sta ,x+ ; stash it in the program - bne immediate5 ; brif not at end of tokenized line (see note for fixlineptrs) -immediate6 bsr prog_fixlineptrs ; fix up line pointers (all of them) - ldx vartab ; clear out variables + ldy binval ; get the line number + jsr prog_insert ; insert the encoded line at X into program as line Y +immediate6 ldx vartab ; clear out variables stx objecttab stx freestart bra immediate0 ; go handle more input ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Fix up next line pointers. Enter at prog_fixlineptrs to do the entire program. Enter at prog_fixlineptrsx to start -; at the line pointered to by X, which MUST NOT point to the end of the program. +; Find line number table entry +; +; Entry: +; D: the desired line number ; -; Works by simply scanning for a NUL in the program text after a line header (pointer to next line and line number) -; and uses that as the new next line pointer. A NULL next line pointer flags the end of the program. +; Exit: +; U: pointer to line number table entry +; CC.C: clear +; +; Error: +; CC.C: set ; -; Observation: if the program text format is changed such that it can include NULs embedded within a line, this routine -; will need to be updated to grok that. -prog_fixlineptrs - ldx progtext ; point to start of program -prog_fixlineptrsx - ldu ,x ; are we at the end of the program? - beq prog_findline2 ; brif not (borrow RTS from findline) - leau 4,x ; point to line text (past pointer and line number) -prog_fixlineptrs1 - lda ,u+ ; are we at the end of this line? - bne prog_fixlineptrs1 ; brif not - stu ,x ; set the next pointer for the previous line - leax ,u ; move to the next line - bra prog_fixlineptrsx ; go handle the next line +; This works by doing a binary search through the line number table. +prog_findline ldu prog_linetab ; point to program line table + ldx prog_linetabp ; get end of table + leax -prog_lineentl,u ; move back to the start of the last entry + pshs x,u ; save "high" at 0,s and "low" at 2,s + tfr d,x ; save line number for later comparisons +prog_findline1 ldd ,s ; get high pointer + subd 2,s ; get different with low pointer + bcs prog_findline2 ; brif high is below low - we didn't find it + lsra ; find half way + rorb + andb #0b11111100 ; round down for 4 bytes per entry + addd prog_linetab ; offset into line table + tfr d,u ; move to a pointer + cmpx linetabent_num,u ; is the desired number less, equal, or greater? + beq prog_findline2 ; brif match + blo prog_findline3 ; brif desired line is lower + leau prog_lineentl,u ; skip past this non-matching item + stu 2,s ; save new low pointer + bra prog_findline1 ; go do another iteration +prog_findline2 leas 4,s ; clean up the temporaries (C clear from compare above) + rts +prog_findline3 leau -prog_lineentl,u ; move before this non-matching entry + stu ,s ; save new top entry pointer + bra prog_findline1 ; go do another iteration +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Delete a line from the program: +; +; Entry: +; D: the line number to delete +; +; This routine removes a line from the program. This works by deallocating the line data and moving all subsequent +; line data forward to close the gap. The line table pointer will also be removed and the subsequent line table +; entries will also be brought forward to fill the gap. While closing the gap in the line table, the line data +; pointers will be adjusted to account for the relocation of the line data following the deleted line. The line number +; table size allocation will not be adjusted. +prog_delline bsr prog_findline ; get a pointer to the desired line table entry + bcs prog_delline3 ; brif the line wasn't in the program - we have nothing to do + ldd linetabent_size+linetabent_ptr,u ; get pointer to next line data + subd linetabent_ptr,u ; now D is the length of the line data to collapse out + pshs d ; save the calculated length - we need it for later + ldy linetabent_ptr,u ; get pointer to the line data to delete + leax d,y ; point to data to move + bra prog_delline1 ; go handle the loop, including the case where we copy nothing +prog_delline0 lda ,x+ ; copy a byte down + sta ,y+ +prog_delline1 cmpx vartab ; at the end of the program? + blo prog_delline0 ; brif not + sty vartab ; save new variable table location +prog_delline2 ldx linetabent_size+linetabent_num,u ; get number of next line + ldd linetabent_size+linetabent_ptr,u ; get pointer for next line + subd ,s ; adjust for length removed in the line data + std ,u++ ; save in the vacated entry + stx ,u++ + cmpu prog_linetabp ; at the end of allocated table entries? + blo prog_delline2 ; brif not + leau -linetabent_size,u ; move back to the last actual entry + stu prog_linetabp ; update the line table pointer + leas 2,s ; clear out the temp we no longer need + jsr cmd_newvars ; clear the variables out +prog_delline3 rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Find a line in the program. Returns with C set and Z clear if no match and C clear and Z set if a match is found. X -; will point to either the exact matched line *or* the line that would be immediately after the desired line number if -; the line had been present, which could be the end of the program. D and U are clobbered. Enter at prog_findlinex to -; start searching at the line pointed to by X. Enter at prog_findline to start at the beginning of the program. Enter -; with the desired line number in binval. -prog_findlinecl ldx curline ; get current line pointer - beq prog_findline ; brif immediate mode - ldd binval ; get desired line number - cmpd 2,x ; is the desired line number >= current line? - beq prog_findline2 ; brif this is the right line (optimizes goto self) - bhi prog_findlinex ; brif desired line higher: start here instead of program start -prog_findline ldx progtext ; point to start of program -prog_findlinex ldu binval ; get line number to search for -prog_findline0 ldd ,x ; end of program? - beq prog_findline1 ; brif not - cmpu 2,x ; does line number match? Z set if so, clear if not; C set not found - bls prog_findline2 - ldx ,x ; move to next line - bra prog_findline0 ; see if we found the line yet -prog_findline1 coma ; set carry for not found; also clears Z because D is zero from above -prog_findline2 rts +; prog_shrinklt: shrink the line table to its minimum possible size, but keep it a multiple of linetab_stride entries +prog_shrinklt ldd prog_linetabp ; get the end of the table entries + subd prog_linetab ; now we have the length of the table + andb #(linetabent_size*linetab_stride)-1 ; is there a remainder? + beq prog_shrinklt0 ; brif not + addd #linetabent_size*linetab_strider +prog_shrinklt0 tfr d,u ; put in a pointer register + leau linetabent_size,x ; move to the end of the phantom entry + cmpu prog_text ; anything to do? + beq prog_shrinklt2 ; brif not + ldx prog_text ; point to source copy point +prog_shrinklt1 lda ,x+ ; copy a byte down + sta ,u+ + cmpx vartab ; end of program? + blo prog_shrinklt1 ; brif not + stu vartab ; save new end of program + jmp cmd_newvars ; clear variables +prog_shrinklt2 rts + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Insert a line into the program +; +; Entry: +; D: length of line to insert +; X: pointer to line data to insert +; U: the line number we're adding +prog_addline pshs d,x,u ; save length and pointer + ldx prog_linetabp ; get line table pointer + leax linetabent_size,x ; add in space for new entry + cmpx prog_text ; did we run into the program? + blo prog_addline0 ; brif not + addd #linetabent_size*linetab_stride ; add in space for expanded line table +prog_addline0 addd vartab ; calculate the new end of program data + jsr checkmem_addr ; verify there is enough memory + cmpx prog_text ; do we need to expand the line number table? + blo prog_addline3 ; brif not + ldx vartab ; point to byte past end of program + leau linetab_stride*linetabent_size,x ; set up destination pointer + stu vartab ; set up new end of program text +prog_addline1 lda ,-x ; copy a byte up + sta ,-u + cmpx prog_text ; did we hit the start of the program? + bne prog_addline1 ; brif not + ldx prog_linetab ; point to start of line table +prog_addline2 ldd linetabent_ptr,x ; get pointer to this line + addd #linetab_stride*linetabent_size ; adjust offset for the expanded table + std linetabent_ptr,x + leax linetabent_size,x ; move to next entry + cmpx prog_linetabp ; at end of table? + bls prog_addline2 ; brif we're at the end of the table +prog_addline3 ldx prog_linetabp ; repoint to first "free" table entry + ldd linetabent_ptr,x ; get pointer for the end of the program + std linetabent_ptr+linetabent_size,x ; move it a slot forward + ldd 4,s ; get desired line number + std linetabent_num,x ; put line number in + bra prog_addline5 ; brif so - this is where we add it +prog_linetab4 cmpd -linetabent_size+linetabent_num,x ; is our line number less than previous entry? + bhs prog_addline6 ; brif not - we're at the right place + leax -linetabent_size,x ; move back an entry + ldu linetabent_num,x ; move line number to next entry + stu linetabent_num+linetabent_size,x + ldu linetabent_ptr,x ; and move the pointer + stu linetabent_ptr+linetabent_size,x +prog_linetab5 cmpx prog_linetab ; at the start of the table? + bhi prog_addline4 ; brif not +prog_linetab6 ldu vartab ; point to end of program data + ldd ,s ; get length of line + leay d,u ; Y points to the destination of the move + sty vartab ; save new end of program text + bra prog_linetab8 ; jump into loop in case nothing to copy +prog_linetab7 lda ,-u ; copy a byte up + sta ,-y +prog_linetab8 cmpu linetabent_ptr,x ; finished the copy? + bne prog_linetab7 ; brif not +prog_linetab9 leax linetabent_size,x ; move to next entry + ldd linetabent_ptr,x ; adjust the pointer for the newly inserted line + addd ,s + std linetabent_ptr,x + cmpx prog_linetabp ; run through the whole table? + blo prog_linetab9 ; brif not + puls y ; get copy length to counter + puls x ; get pointer to line data +prog_linetab10 lda ,x+ ; copy a byte into the program data + sta ,u+ + leay -1,y ; done all of it? + bne prog_linetab10 ; brif not + leas 2,s ; lose line number + jmp cmd_newvar ; erase variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Parse a line number and return it in binval; raise syntax error if the line number overflows 16 bits unsigned. ; Preserves; registers except D. This will accept the entire 16 bit unsigned number range which is why there is diff -r 95f174bf459b -r 917b4893bb3d src/parse.s --- a/src/parse.s Sat May 18 00:41:46 2024 -0600 +++ b/src/parse.s Mon Jun 24 23:44:39 2024 -0600 @@ -3,7 +3,13 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This is the overall parsing package. This is responsible for converting program text into the internal byte code and ; reporting any syntax errors and anything else reasonably detectable at parse time without having overly complicated -; code analysis. In almost all cases, the returned error will be a syntax error. +; code analysis. In almost all cases, the returned error will be a syntax error. The internal byte code shares the same +; token number allocations as the parser. Some allocated tokens cannot be identified by the lexer (parse_nexttok) but +; are used at runtime and when "decompiling" to text. +; +; In the event of a parse error, everything up to the next end of statement is retained as is using a special token +; that preserves the unparsable text and parsing resumes. Only the first error is referenced by the return error +; pointer. ; ; This is a recursive descent parser. ; @@ -12,14 +18,20 @@ ; B Nonzero to prevent generating any output (error check/length calculation only) ; ; Exit: -; U Points to the encoded line +; X Points to the encoded line ; D Length of the encoded line ; CC.C clear ; Error Exit: -; B Error code -; U Offset to error input +; X Points to the encoded line +; D Length of the encoded line +; Y Pointer to the first error location in the input +; U Error code ; CC.C set +; +; This is the error handler. It is responsible for resetting the stack to bail out to the top level +; parsing loop. It must also store the input pointer if this is the first error. Finally, it has to +; output all the text up to either the end of the line *or* the next valid statement separator. parse_errorsn ldb #err_sn parse_error lds parse_stackptr ; restore the original stack pointer so we can call from down stack puls u ; get back original free pointer @@ -82,6 +94,11 @@ leay 1,y ; move to next input character parse_curchar lda ,y ; fetch input character rts +parse_nexttokc bsr parse_nexttok ; fetch next token +parse_iseos cmpb #token_eot ; end of text? + beq parse_iseos0 ; brif so + cmpb #token_stmtsep ; is it a statement separator +parse_iseos0 rts parse_nexttok bsr parse_curchar ; fetch current input beq parse_nexttok1 ; brif end of input parse_nexttok0 cmpa #0x20 ; space? @@ -137,10 +154,6 @@ bhi parse_toupper0 ; brif not suba #0x20 ; adjust to upper case alpha parse_toupper0 rts ; Z only set here if input was zero entering from parse_nextcharu -parse_iseos cmpa #token_stmtsep ; end of statement? - beq parse_iseos0 ; brif so - cmpa #token_eot ; end of text? -parse_iseos0 rts parse_number jmp parse_tokerr ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Parse a statement that consists of just the command token @@ -154,49 +167,6 @@ stb parse_curtok rts ; return, pass back the C result from parse_write ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Parse an optional line number range which may be [lineno][-[lineno]] -parse_range jsr parse_write ; output the token - jsr parse_nexttok ; fetch input token - ldx zero ; set default start and end line numbers - whole program - leau -1,x - pshs x,u - bsr parse_iseos ; are there arguments? - beq parse_range3 ; brif so - cmpa #token_int32 ; is it an integer (line number)? - bne parse_range0 ; brif not - ldd val0+val.int ; is the upper 16 bits set? - beq parse_rangee ; brif yes - we have an error - ldd val0+val.int+2 ; set the start line number - std ,s - jsr parse_nexttok ; see what's after the line number -parse_range0 cmpa #token_minus ; do we have a range? - beq parse_range1 ; brif so - bsr parse_iseos ; end of statement? - bne parse_rangee ; brif not - error - ldd ,s ; set end line to start line - std 2,s - bra parse_range3 ; go output things -parse_range1 jsr parse_nexttok ; skip the - - bsr parse_iseos ; end of statement? - beq parse_range3 ; brif so - cmpa #token_int32 ; is it an integer? - bne parse_rangee ; brif not - ldx val0+val.int ; upper 16 bits set? - bne parse_rangee ; brif so - invalid number - ldx val0+val.int+2 ; get end line number - stx 2,s ; save end line number - cmpx ,s ; is end line lower than start line? - blo parse_rangee ; brif so - error -parse_range3 puls a ; write out the range - jsr parse_write - puls a - jsr parse_write - puls a - jsr parse_write - puls a - jmp parse_write -parse_rangee jmp parse_errorsn ; go raise the parse error -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This routine parses tokens using the table at parse_wordtab. The table is structured as follows: ; ; * two bytes which contain the length of the table less the two bytes for this length value @@ -277,6 +247,63 @@ coma ; make sure C is set for no match puls a,x,pc ; clean up stack and return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Validate a line number. Must enter with the token type in B. Will return the line number in X. It will return a +; syntax error if the line number is invalid or out of range. It will also consume a valid line number token. +parse_linenum cmpb #token_int32 ; is it an integer? + beq parse_linenum1 ; brif so +parse_linenum0 ldb #err_sn ; flag syntax error + coma ; flag error + rts +parse_linenum1 ldx val0+val.int ; get high word of integer + bne parse_linenum0 ; brif not a valid line number + ldx val0+val.int+2 ; get actual line number + pshs x ; save it + jsr parse_nexttok ; consume line number + puls x,pc ; get back line number and return it +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Parse a line number range which is one of the following forms: +; +; - +; - +; - +; The result will store two line numbers. If no - token appears, then both line numbers will be the same. Otherwise, +; if is omitted, it will be assumed to be 0. If is omitted, it will be assumed to be 65535. Those +; are the minimum and maximum line numbers. +; +; Parsing works by first looking for an integer token that is in range. If it finds one, it looks for an optional - +; followed by an optional integer token that is in range. If the first token is not an integer, it must be a - which may +; be optionally followed by another integer in range. +; +; It is technically valid to have a single - with no line numbers. +; +; Enter with the current token in B. +; +; The resulting line numbers will be returned in parse_buff +parse_linerange ldx zero ; default start line number + leau -1,x ; default end line number + pshs x,u ; save the return range + cmpb #token_minus ; range with no start? + beq parse_linerang1 ; brif so + bsr parse_linenum ; verify line number, return in X + bcs parse_linerang4 ; bail out on error + stx ,s ; save new start line number + jsr parse_nexttokc ; fetch next token, set Z if end of statement + bne parse_linerang0 ; brif not end of line + ldx ,s ; get end line to use as start line + bra parse_linerang2 ; go set range end and return +parse_linerang0 cmpb #token_minus ; do we have a range character? + bne parse_linerang3 ; brif not - we have an error +parse_linerang1 jsr parse_nexttokc ; parse what comes after the range mark + beq parse_linerang2 ; brif end of statement - use the default range end + bsr parse_linenum ; make sure it's a valid line number + bcs parse_linerang4 ; bail out on error +parse_linerang2 stx 2,s ; set range end + clra ; make sure C is clear + puls x,u,pc ; fetch return values and return +parse_linerang3 ldb #err_sn ; flag a syntax error + coma ; make sure C is set +parse_linerang4 puls x,u,pc ; clean up stack and return error condition +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This table defines the various handler routines for the various bytecode tokens. Each token is defined as follows: ; parse_tokdefT ,,, ; where: @@ -369,11 +396,15 @@ *pragmapop nolist endm *pragmapop list + ; the tokens defined in this section all have special parsing or meaning parse_tokendefp error ; Used to mark errors; should always be first so it's token #0 parse_tokendefp eot ; End of input marker or special handling in word tables parse_tokendefp int32 ; 32 bit integer (has special parsing) parse_tokendefp float ; floating point value (has special parsing) parse_tokendefp ident ; identifier (has special parsing) + parse_tokendefp linenum ; a 16 bit unsigned integer treated as a line number + parse_tokendefp linerange ; a pair of 16 bit unsigned integers treated as line numbers + ; everything below here references keywords or particle characters parse_tokendefp stmtsep ; statement separator parse_tokendefp times ; times (multiplication) operator (*) parse_tokendefp plus ; addition operator diff -r 95f174bf459b -r 917b4893bb3d src/progctrl.s --- a/src/progctrl.s Sat May 18 00:41:46 2024 -0600 +++ b/src/progctrl.s Mon Jun 24 23:44:39 2024 -0600 @@ -30,14 +30,16 @@ ; cmd_newvars: clears variables and resets the stack and other misc state ; cmd_newstack: just reset the stack and other misc state cmd_new bne cmd_new0 ; brif there was an argument - don't wipe things out on syntax error -cmd_newraw ldx progtext ; point to start of program - clr -1,x ; make sure there's a NUL before the start of the program - clr ,x+ ; put a NULL pointer at the start of the program - clr ,x+ +cmd_newraw ldx prog_linetab ; get start of program line table + stx prog_linetabp ; clear out all line entries + leax linetabent_size*(linetab_stride+1),x ; make room for default program line entries and one extra + stx [prog_linetabp] ; set the pointer for the dummy ending entry + stx prog_text ; set end of program line table stx vartab ; set start of variables after that -cmd_newinptr ldx progtext ;* set input pointer to the NUL before the program; this will cause the - leax -1,x ;* the interpreter to drop to immediate mode no matter what it was - stx inputptr ;* executing before this call if called from the main loop +cmd_newinptr ldx zero ; blank out current line pointer - we'll fall back to immediate mode + stx curline + ldx #zero ; point to a zero input byte - will read as end of line + stx inputptr cmd_newvars ldx memsize ; get top of memory stx stringtab ; clear out string space ldx vartab ; get start of variables diff -r 95f174bf459b -r 917b4893bb3d src/vars.s --- a/src/vars.s Sat May 18 00:41:46 2024 -0600 +++ b/src/vars.s Mon Jun 24 23:44:39 2024 -0600 @@ -11,8 +11,10 @@ freetop rmb 2 ; top of free memory (bottom of string space) stringtab rmb 2 ; bottom of used string space cstackptr rmb 2 ; bottom of the "stack frame" stack (the actual stack is below here) -progtext rmb 2 ; pointer to start of program text -vartab rmb 2 ; pointer to start of integer scalars +prog_linetab rmb 2 ; pointer to start of the program line table +prog_linetabp rmb 2 ; pointer to the first free program line table entry +prog_text rmb 2 ; start of the program text data (immediately after the line table) +vartab rmb 2 ; pointer to start of integer scalars (the runtime heap) objecttab rmb 2 ; pointer to start of arrays and other variable sized objects freestart rmb 2 ; pointer to start of unallocated memory readlinenoecho rmb 1 ; if nonzero, the readline routine won't echo its input