comparison src/progctrl.s @ 74:e74d00ac6b79

Split some code into separate files for easier management (2) Because the source for lwbasic is so large, split it into several different files to make it easier to navigate and modify. This is part two of the split. Also includes fix for dependency tracking related to the split in the make file.
author William Astle <lost@l-w.ca>
date Sun, 06 Aug 2023 00:36:48 -0600
parents
children a6a53e5c04bd
comparison
equal deleted inserted replaced
73:2d52cd154ed1 74:e74d00ac6b79
1 *pragmapush list
2 *pragma list
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ; The END command.
5 cmd_end bne SNERROR ; error out if there is an argument
6 ;jsr closeall ; close all files for END
7 clra ; flag END (clear carry)
8 bra cmd_stop0 ; go do the stop/end
9 cmd_stop bne SNERROR ; raise error if there was an argument
10 coma ; flag STOP - set carry
11 cmd_stop0 ror endflag ; set stop/end flag
12 cmd_stop1 clr filenum ; reset I/O to console
13 ldx curline ; in immediate mode?
14 beq cmd_stop2 ; brif so - don't save the continue pointers
15 stx contline ; save pointer to current line for CONT
16 ldx curstmt ; get current statement address
17 stx contstmt ; save it for CONT
18 cmd_stop2 rol endflag ; get STOP/END to C (1=STOP)
19 bcc cmd_stop3 ; brif END - don't do message
20 ldx #breakmsg ; do "BREAK IN"
21 jmp ERROR2 ; the bottom half of the error handler can deal with the details
22 cmd_stop3 puls x,pc ; lose return address and return to caller of interpretation loop
23 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
24 ; The NEW command.
25 ;
26 ; This also includes several useful entry points:
27 ;
28 ; cmd_newraw: does the whole NEW but without any syntax checks
29 ; cmd_newinptr: skips clearing the program text
30 ; cmd_newvars: clears variables and resets the stack and other misc state
31 ; cmd_newstack: just reset the stack and other misc state
32 cmd_new bne cmd_new0 ; brif there was an argument - don't wipe things out on syntax error
33 cmd_newraw ldx progtext ; point to start of program
34 clr -1,x ; make sure there's a NUL before the start of the program
35 clr ,x+ ; put a NULL pointer at the start of the program
36 clr ,x+
37 stx vartab ; set start of variables after that
38 cmd_newinptr ldx progtext ;* set input pointer to the NUL before the program; this will cause the
39 leax -1,x ;* the interpreter to drop to immediate mode no matter what it was
40 stx inputptr ;* executing before this call if called from the main loop
41 cmd_newvars ldx memsize ; get top of memory
42 stx stringtab ; clear out string space
43 ldx vartab ; get start of variables
44 stx objecttab ; set start of large objects (arrays) there too (clear vars)
45 stx freestart ; set start of free memory (end of large objects) (clear arrays)
46 cmd_newstack ldx #stringstackend ; reset string stack (string stack counts down)
47 stx stringstackptr
48 ldx ,s ; get return address
49 lds freetop ; reset stack to top of memory
50 clr ,-s ; put a flag to stop stack searches (NEXT, RETURN)
51 sts stackptr ; reset pointer for call stack
52 clr contstmt ; clear "CONT" destination
53 clr contstmt+1
54 jmp ,x ; return to caller
55 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56 ; REM and ' commands; also ELSE comes here since it needs to skip the rest of the line in that case.
57 cmd_else
58 cmd_apos
59 cmd_rem clra ; clear carry
60 ldx curline ; get start of current line
61 beq cmd_stop3 ; brif immediate mode - fall back to caller
62 ldx ,x ; get address of next line
63 leax -1,x ; move back one
64 stx inputptr ; put input pointer there
65 cmd_new0 rts
66 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
67 ; DATA command
68 ;
69 ; need to skip to the end of the current statement, which is either the end of the line OR a colon not included inside
70 ; a quoted string
71 cmd_data ldx inputptr ; get input pointer
72 cmd_data0 lda ,x+ ; get character at pointer
73 beq cmd_data1 ; brif end of line
74 cmpa #': ; end of statement?
75 bne cmd_data2 ; brif not
76 cmd_data1 leax -1,x ; move back to the NUL or colon
77 stx inputptr ; reset input pointer for interpreter
78 rts
79 cmd_data2 cmpa #'" ; start of constant string?
80 bne cmd_data0 ; brif not - process more characters
81 cmd_data3 lda ,x+ ; get next string character
82 beq cmd_data1 ; brif end of line
83 cmpa #'" ; string delimiter?
84 bne cmd_data3 ; brif not - keep going
85 bra cmd_data0 ; process stuff outside string
86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
87 ; RUN command
88 cmd_run ;jsr closeall ; close all files
89 jsr curchar ; what do we have as an argument?
90 bcs cmd_goto ; brif a digit - it's a line number (RUN ###); do GOTO
91 lbne SNERROR ; brif anything else on the line - not legit command
92 ldx progtext ; point to start of program
93 bra cmd_goto0 ; go transfer control to the start of the program
94 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
95 ; GOTO command
96 cmd_goto jsr parse_lineno ; parse the line number
97 cmd_gosub0 jsr prog_findlinecl ; go look up line number
98 bcc cmd_goto0 ; brif line found
99 ULERROR ldb #err_ul ; raise undefined line error
100 jmp ERROR
101 cmd_goto0 stx curline ; make sure we aren't flagging immediate mode
102 leax -1,x ; move input pointer to NUL before destination line
103 stx inputptr ; put input pointer there
104 rts ; resume interpretation at the new location
105 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
106 ; GOSUB command
107 cmd_gosub jsr parse_lineno ; parse the destination line so return location is after the line number
108 ldd #tok_gosub*256+4 ; stack frame details
109 bsr callstack_alloc ; make a stack frame
110 ldx curline ; save current line pointer
111 stx ,u
112 ldx inputptr ; save current input pointer
113 stx 2,u
114 bra cmd_gosub0 ; go finish up as a GOTO
115 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
116 ; RETURN command
117 ; POP command
118 ;
119 ; RETURN will search the call stack for the first GOSUB frame and remove all other placeholders it finds. A frame type
120 ; of 0 will cause it to stop.
121 cmd_pop skip1lda ; set nonzero for POP
122 cmd_return clra ; set zero for RETURN
123 pshs a ; save operation type
124 bsr callstack_first ; get first entry on call stack
125 bne cmd_return1 ; brif there's a frame - don't error
126 RG_ERROR ldb #err_rg ; raise RETURN without GOSUB
127 jmp ERROR
128 cmd_return0 bsr callstack_next ; move to next entry
129 beq RG_ERROR ; brif end of stack - raise error
130 cmd_return1 cmpb #tok_gosub ; do we have a GOSUB frame?
131 bne cmd_return0 ; brif not - try again
132 lda ,s+ ; is it "POP"?
133 bne cmd_return2 ; brif so - don't change flow control but clear stack frame
134 ldx ,u ; get back saved line pointer
135 stx curline
136 ldx 2,u ; get back saved input pointer
137 stx inputptr
138 cmd_return2 bsr callstack_pop ; clean up call stack
139 bra cmd_data ; move to end of statement (move past any "ON GOSUB" entries
140 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
141 ; Point to the first entry on the call stack; yes this is trivial but it points to the payload, not the header. Also
142 ; sets Z if there is nothing on the stack.
143 callstack_first ldu stackptr ; get stack pointer
144 ldb ,u++ ; set flags on frame type and adjust pointer
145 rts
146 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
147 ; Move to the next frame on the call stack; enter with U pointing to a stack frame payload area
148 callstack_next ldb -1,u ; get length of this frame
149 leau b,u ; move to the next frame
150 ldb -2,u ; set flags on frame type code
151 rts
152 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
153 ; Create a stack frame. Enter with the frame type flag in A and the size in B.
154 ;
155 ; The stack frame of size B bytes plus 2 bytes for the length and type flag will be allocated between the actual
156 ; hardware stack and the current call stack pointer. Return with the pointer to the allocated frame in U. As long as
157 ; there are no pointers to anything on the hardware stack, this will allow the stack to be entirely intact after
158 ; the call.
159 callstack_alloc addb #2 ; account for the header bytes
160 pshs a,b ; save the type and length
161 negb ; need a negative offset
162 leax ,s ; point to current bottom of stack
163 leas b,s ; make a hole below the stack
164 leau ,s ; get a pointer to the destination for copying
165 callstack_alloc0
166 lda ,x+ ; copy a byte down
167 sta ,u+
168 cmpx stackptr ; have we reached the top of the stack?
169 blo callstack_alloc0 ; brif not
170 stu stackptr ; save the new call stack pointer
171 puls d ; get back the type and length values
172 std ,u++ ; save type and length
173 rts
174 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
175 ; Pop the call stack to the end of the frame pointed to by U; this will relocate the hardware stack to close the
176 ; newly made gap in memory.
177 callstack_pop leau -2,u ; move back to header
178 ldb 1,u ; get length of frame
179 leax b,u ; point to element after this frame
180 sts ,--s ; save the current bottom of the stack
181 stx stackptr ; save new call stack pointer
182 callstack_pop0 lda ,-u ; copy a byte up
183 sta ,-x
184 cmpu ,s ; at the bottom of the call stack?
185 bhi callstack_pop0 ; brif not
186 leas 2,x ; reset the stack pointer (and lose the saved stack pointer value)
187 rts
188 *pragmapop list