Mercurial > hg > index.cgi
comparison src/interp.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 | 5f8f0b0781e8 |
comparison
equal
deleted
inserted
replaced
73:2d52cd154ed1 | 74:e74d00ac6b79 |
---|---|
1 *pragmapush list | |
2 *pragma list | |
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
4 ; Fetch next input character, skip spaces. This is structured the way it is to avoid burning any register except A | |
5 ; which is used for the returned value. Z will be set if the input character is NUL or a colon. C will be set if the | |
6 ; input character is an ASCII digit. This allows testing Z to identify the end of a command due to either a colon or | |
7 ; the end of a line. | |
8 ; | |
9 ; Compared to Color Basic, the instruction sequence only varies in the handling of the LDA. In Color Basic, the sequence | |
10 ; is an LDA extended followed by a JMP extended. This totals to 9 cycles (5 for LDA, 4 for JMP). In LWBasic, an LDA | |
11 ; with extended indirect addressing is used. This also totals 9 cycles. The only other difference is when a space is | |
12 ; detected where the branch can be direct to the nextchar code instead of having to branch around a direct page JUMP | |
13 ; which saves 3 cycles for the case where a space is detected. In other words, this is only slower by virtue of the | |
14 ; fact that it is called with an extended JSR instead of a direct JSR which causes one extra cycle to be used there | |
15 ; and one extra byte for each call to nextchar or curchar. | |
16 ; | |
17 ; On 6309, native move saves an extra cycle in the LDA sequence using the LDA extended followed by JMP extended | |
18 ; sequence. | |
19 ; | |
20 ; This whole thing could be sped up by keeping the input pointer in a register. However, retaining the ability to | |
21 ; use Y without having to save it first is likely more beneficial. | |
22 nextchar inc inputptr+1 ; bump LSB of input pointer | |
23 bne curchar ; brif no carry | |
24 inc inputptr ; bump MSB | |
25 curchar lda [inputptr] ; read the byte | |
26 cmpa #'9+1 ; clear C if above ASCII digits, Z if colon | |
27 bhs curchar0 ; brif above the ASCII digits | |
28 cmpa #0x20 ; is it a space? | |
29 beq nextchar ; brif so - skip over it | |
30 suba #'0 ; clever way to set C if >= ASCII 0, Z if zero | |
31 suba #-'0 | |
32 curchar0 rts | |
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
34 ; This is exactly the same as nextchar except it doesn't skip spaces. Unfortunately, for efficiency purposes, we need | |
35 ; to actually duplicate code here. | |
36 nextcharraw inc inputptr+1 ; bump LSB of input pointer | |
37 bne curchar ; brif no carry | |
38 inc inputptr ; bump MSB | |
39 curcharraw lda [inputptr] ; fetch the byte | |
40 cmpa #'9+1 ; clear C if above digits, set Z if colon | |
41 bhs curcharraw0 ; brif above digits | |
42 suba #'0 ; clever way to set C if >= ASCII 0, Z if zero | |
43 suba #-'0 | |
44 curcharraw0 rts | |
45 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
46 ; The error handler | |
47 ; | |
48 ; Enter with the error number in B. This routine will do some cleanup and handle any ON ERROR GOTO handler that | |
49 ; may be active. | |
50 ; | |
51 ; Note the error message lookup does not need to be efficient which is why the lookup just runs through the list | |
52 ; of error messages in sequence looking for NUL terminators. The specific handling of B (error number) below avoids | |
53 ; issues if there happen to be error codes above 128. | |
54 ERROR clr filenum ; reset display device to console | |
55 jsr writecondnl ; do a newline if needed (will preserve B) | |
56 ldx #errormsg ; point to error message list | |
57 incb ; account for decb below | |
58 bra ERROR1 ; go search for correct message | |
59 ERROR0 lda ,x+ ; end of message? | |
60 bne ERROR0 ; brif not end of message | |
61 ERROR1 decb ; at the correct one? | |
62 bne ERROR0 ; brif not - skip to next one | |
63 ERROR2 jsr writestrconduc ; output error message | |
64 ldu curline ; are we in immediate mode? | |
65 beq ERROR3 ; brif so | |
66 ldx #inmsg ; point to " in " | |
67 jsr writestrconduc ; output " in " | |
68 ldd 2,u ; get line number | |
69 jsr print_uint16d ; display the line number | |
70 ERROR3 lds freetop ; reset the stack pointer (error routine could be called anywhere) | |
71 clr ,-s ; reset the call stack | |
72 sts stackptr | |
73 ; fall through to immediate mode intentional | |
74 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
75 ; Immediate mode handler | |
76 immediate jsr writecondnl ; do newline if required | |
77 ldx #prompt ; point to prompt string | |
78 jsr console_outstrn | |
79 immediate0 jsr readline ; read input line | |
80 bcs immediate0 ; brif ended with BREAK | |
81 ldx #linebuff ; point to start of line input buffer | |
82 stx inputptr ; set input pointer | |
83 jsr curchar ; skip spaces and set flags | |
84 bcs immediate1 ; brif there's a line number | |
85 tsta ; is there anything there at all (end of line)? | |
86 beq immediate0 ; brif not - read another line | |
87 ldx inputptr ; get the modified input pointer processing above | |
88 jsr tokenize ; tokenize the line at inputptr, return with result at tokebuff and X | |
89 jsr interpretline ; go interpret the tokenized line | |
90 bra immediate ; go handle another line | |
91 immediate1 bsr parse_lineno ; parse the line number | |
92 bsr prog_findline ; go see if the line is in the program | |
93 bne immediate3 ; brif not - no need to delete it | |
94 ldu ,x ; get next line pointer which is where we start the copy from | |
95 leay ,x ; use temp pointer for copying | |
96 immediate2 lda ,u+ ; get source byte | |
97 sta ,y+ ; stash it | |
98 cmpu vartab ; did we reach the end of the program text? | |
99 blo immediate2 ; brif not | |
100 sty vartab ; save new end of program | |
101 immediate3 jsr curchar ; skip any spaces after line number | |
102 tsta ; is it the end of input (don't test for colon) | |
103 beq immediate6 ; brif so - we don't need to insert a line | |
104 pshs x ; save program insert location and line number | |
105 ldx inputptr ; point to line text | |
106 jsr tokenize ; tokenize line, get length to D | |
107 leay ,x ; save tokenized line pointer | |
108 addd #4 ; account for next line pointer and line number | |
109 ldx vartab ; get start of copy location | |
110 leau d,x ; set destination copy location D bytes further up | |
111 stu vartab ; save new end of program | |
112 immediate4 lda ,-x ; get byte from program | |
113 sta ,-u ; stash it above the empty space | |
114 cmpx ,s ; did we reach the insertion point? | |
115 bne immediate4 ; brif not - keep going | |
116 leas 2,s ; clear insertion location | |
117 stu ,x++ ; set next line pointer to not null | |
118 ldd binval ; set the line number for the program | |
119 std ,x++ | |
120 immediate5 lda ,y+ ; get byte from tokenized line | |
121 sta ,x+ ; stash it in the program | |
122 bne immediate5 ; brif not at end of tokenized line (see note for fixlineptrs) | |
123 immediate6 bsr prog_fixlineptrs ; fix up line pointers (all of them) | |
124 ldx vartab ; clear out variables | |
125 stx objecttab | |
126 stx freestart | |
127 bra immediate0 ; go handle more input | |
128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
129 ; Fix up next line pointers. Enter at prog_fixlineptrs to do the entire program. Enter at prog_fixlineptrsx to start | |
130 ; at the line pointered to by X, which MUST NOT point to the end of the program. | |
131 ; | |
132 ; Works by simply scanning for a NUL in the program text after a line header (pointer to next line and line number) | |
133 ; and uses that as the new next line pointer. A NULL next line pointer flags the end of the program. | |
134 ; | |
135 ; Observation: if the program text format is changed such that it can include NULs embedded within a line, this routine | |
136 ; will need to be updated to grok that. | |
137 prog_fixlineptrs | |
138 ldx progtext ; point to start of program | |
139 prog_fixlineptrsx | |
140 ldu ,x ; are we at the end of the program? | |
141 beq prog_findline2 ; brif not (borrow RTS from findline) | |
142 leau 4,x ; point to line text (past pointer and line number) | |
143 prog_fixlineptrs1 | |
144 lda ,u+ ; are we at the end of this line? | |
145 bne prog_fixlineptrs1 ; brif not | |
146 stu ,x ; set the next pointer for the previous line | |
147 leax ,u ; move to the next line | |
148 bra prog_fixlineptrsx ; go handle the next line | |
149 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
150 ; 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 | |
151 ; will point to either the exact matched line *or* the line that would be immediately after the desired line number if | |
152 ; the line had been present, which could be the end of the program. D and U are clobbered. Enter at prog_findlinex to | |
153 ; start searching at the line pointed to by X. Enter at prog_findline to start at the beginning of the program. Enter | |
154 ; with the desired line number in binval. | |
155 prog_findlinecl ldx curline ; get current line pointer | |
156 beq prog_findline ; brif immediate mode | |
157 ldd binval ; get desired line number | |
158 cmpd 2,x ; is the desired line number >= current line? | |
159 beq prog_findline2 ; brif this is the right line (optimizes goto self) | |
160 bhi prog_findlinex ; brif desired line higher: start here instead of program start | |
161 prog_findline ldx progtext ; point to start of program | |
162 prog_findlinex ldu binval ; get line number to search for | |
163 prog_findline0 ldd ,x ; end of program? | |
164 beq prog_findline1 ; brif not | |
165 cmpu 2,x ; does line number match? Z set if so, clear if not; C set not found | |
166 bls prog_findline2 | |
167 ldx ,x ; move to next line | |
168 bra prog_findline0 ; see if we found the line yet | |
169 prog_findline1 coma ; set carry for not found; also clears Z because D is zero from above | |
170 prog_findline2 rts | |
171 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
172 ; Parse a line number and return it in binval; raise syntax error if the line number overflows 16 bits unsigned. | |
173 ; Preserves; registers except D. This will accept the entire 16 bit unsigned number range which is why there is | |
174 ; a BCS after every shift or add. Enter with the input pointer pointing to the number to parse. | |
175 parse_lineno ldd zero ; clear out accumlator but preserve carry flag | |
176 std binval | |
177 jsr curchar ; set flags on current character; skip spaces | |
178 bcc parse_lineno1 ; brif first character wasn't a digit - default to zero | |
179 parse_lineno0 suba #0x30 ; adjust to binary digit | |
180 pshs a ; save digit so we can add it later | |
181 ldd binval ; get accumulated number | |
182 lslb ; multiply accumulator by 10 | |
183 rola ; times 2 | |
184 bcs SNERROR ; brif overflow | |
185 lslb | |
186 rola ; times 4 | |
187 bcs SNERROR ; brif overflow | |
188 addd binval ; times 5 (add orignal value to times 4) | |
189 bcs SNERROR ; brif overflow | |
190 lslb | |
191 rola ; times 10 | |
192 bcs SNERROR ; brif overflow | |
193 addb ,s+ ; add in accumulated digit | |
194 adca #0 | |
195 bcs SNERROR ; brif overflow | |
196 std binval ; save accumulated number | |
197 jsr nextcharraw ; get next input character; DO NOT skip spaces | |
198 bcs parse_lineno0 ; brif it's also a digit | |
199 parse_lineno1 rts | |
200 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
201 ; Main interpretation loop | |
202 ; | |
203 ; Enter at interpret with inputptr pointing to the code stream to interpret. | |
204 ; Enter at interpretline with X pointing to the command stream to interpret which will return to the caller one the | |
205 ; command stream has completed. STOP or BREAK will return with carry set while END or falling off the end of the | |
206 ; code will return with carry clear. In the event of an error, the usual error processing will be done and control | |
207 ; will return to immediate mode with the stack reset. | |
208 interpret jsr breakcheck ; check for BREAK | |
209 bcs cmd_stop0 ; brif BREAK detected - go stop the program | |
210 ldx inputptr ; get interpration address | |
211 stx curstmt ; save address of the current statement (needed for some stuff) | |
212 lda ,x+ ; are we at the end of the line? | |
213 beq interpret0 ; brif so | |
214 cmpa #': ; end of statement? | |
215 beq interpret3 ; brif so - do a statement | |
216 SNERROR ldb #err_sn ; raise a syntax error | |
217 jmp ERROR | |
218 interpret0 sta endflag ; flag the program exit state as "END" (will be zero) | |
219 ldd curline ; were we in immediate mode? | |
220 bne interpret1 ; brif not | |
221 clra ; clear carry to indicate normal exit | |
222 rts ; return to caller | |
223 interpret1 ldd ,x ; are we at the end of the program? | |
224 beq interpret4 ; brif so - bail out | |
225 stx curline ; save pointer to current line | |
226 leax 3,x ; set input pointer one before the start of the line text | |
227 interpret2 stx inputptr | |
228 interpret3 jsr nextchar ; fetch first character of next statement | |
229 beq interpret ; brif end of statement - do the next statement dance | |
230 tsta ; set flags properly for token | |
231 lbpl cmd_let ; brif no command - do assignment (LET command is optional) | |
232 ldx #primaryjump ; point to jump table | |
233 anda #0x7f ; lose bit 7 | |
234 leax a,x ; get half way to the correct offset | |
235 ldx a,x ; get the address the other half of the way from here | |
236 jsr nextchar ; skip past token and set flags | |
237 jsr ,x ; call the routine | |
238 bra interpret ; go handle the next statement dance | |
239 interpret4 bsr cmd_stop1 ; make sure stack is aligned correctly (will not return) | |
240 interpretline clr curline ; blank out current line pointer (for immediate mode) | |
241 clr curline+1 | |
242 leax -1,x ; move back before start of code stream | |
243 bra interpret2 ; go interpret this statement and then continue with stuff | |
244 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
245 ; Check for character in B and raise a syntax error if not found at current input pointer. If it is found, fetch the | |
246 ; next input character. | |
247 syncheckb cmpb [inputptr] ; do we have a syntax match? | |
248 bne SNERROR ; brif not | |
249 jmp nextchar ; return next input character | |
250 *pragmapop list |