changeset 40:68253ccbb9dc

Immediate mode line insertion, removal, and replacement This implements a first pass untested version of handling program line insertion and deletion in immediate mode. This comes with auxilliary routines for parsing line numbers and fixing up the next line pointers.
author William Astle <lost@l-w.ca>
date Wed, 23 Nov 2022 21:34:21 -0700
parents e956d8b6e806
children 090db8c5d509
files src/lwbasic.s
diffstat 1 files changed, 106 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/lwbasic.s	Mon Nov 21 23:18:40 2022 -0700
+++ b/src/lwbasic.s	Wed Nov 23 21:34:21 2022 -0700
@@ -194,14 +194,14 @@
 ; Start of memory which has the direct page and other data.
                 org 0
 dpstart         equ *                           ; start of direct page
+zero            rmb 2                           ; constant zero word used for faster zeroing of 16 bit registers
+binval          rmb 2                           ; arbitary binary value, usually a line number or integer
 memtop          rmb 2                           ; absolute top of memory in 64K memory map
 memsize         rmb 2                           ; top of memory not reserved
 freetop         rmb 2                           ; top of free memory (bottom of string space)
 stringtab       rmb 2                           ; bottom of used string space
 progtext        rmb 2                           ; pointer to start of program text
-vartabint       rmb 2                           ; pointer to start of integer scalars
-vartabfloat     rmb 2                           ; pointer to start of floating point scalars
-vartabstring    rmb 2                           ; pointer to start of string scalars
+vartab          rmb 2                           ; pointer to start of integer scalars
 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
@@ -461,9 +461,7 @@
                 stx progtext                    ; put the start of the program there
                 clr ,x+                         ; put a NULL pointer to mark end of program
                 clr ,x+
-                stx vartabint                   ; put start of integer variables at end of program
-                stx vartabfloat                 ; put start of floating point variables after that
-                stx vartabstring                ; put start of string variables after that
+                stx vartab                      ; put start of integer variables at end of program
                 stx objecttab                   ; also put the start of large objects there
                 stx freestart                   ; mark the start of free memory
                 lda #keyb_caps                  ; enable caps lock but disable all other shift states
@@ -1056,8 +1054,108 @@
                 jsr tokenize                    ; tokenize the line at inputptr, return with result at tokebuff
                 jsr interpretline               ; go interpret the tokenized line
                 bra immediate                   ; go handle another line
-immediate1      ; handle line insert/delete/modify
-                bra immediate0
+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
+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 tokenize                    ; 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
+                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.
+;
+; 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.
+;
+; 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
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; 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_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
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; 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
+; a BCS after every shift or add. Enter with the first character in A with C set for digits and clear otherwise.
+parse_lineno    ldd zero                        ; clear out accumlator but preserve carry flag
+                std binval
+                bcc parse_lineno1               ; brif first character wasn't a digit - default to zero
+parse_lineno0   suba #0x30                      ; adjust to binary digit
+                pshs a                          ; save digit so we can add it later
+                ldd binval                      ; get accumulated number
+                lslb                            ; multiply accumulator by 10
+                rola                            ; times 2
+                bcs SNERROR                     ; brif overflow
+                lslb
+                rola                            ; times 4
+                bcs SNERROR                     ; brif overflow
+                addd binval                     ; times 5 (add orignal value to times 4)
+                bcs SNERROR                     ; brif overflow
+                lslb
+                rola                            ; times 10
+                bcs SNERROR                     ; brif overflow
+                addb ,s+                        ; add in accumulated digit
+                adca #0
+                bcs SNERROR                     ; brif overflow
+                std binval                      ; save accumulated number
+                jsr nextcharraw                 ; get next input character; DO NOT skip spaces
+                bcs parse_lineno0               ; brif it's also a digit
+parse_lineno1   rts
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Main interpretation loop
 ;