comparison src/lwbasic.s @ 75:5f8f0b0781e8

Split some code into separate files for easier management (3) 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 three of the split. Includes a file missing from part one.
author William Astle <lost@l-w.ca>
date Sun, 06 Aug 2023 00:41:26 -0600
parents e74d00ac6b79
children eb2681108660
comparison
equal deleted inserted replaced
74:e74d00ac6b79 75:5f8f0b0781e8
43 include consscr.s 43 include consscr.s
44 include genio.s 44 include genio.s
45 include interp.s 45 include interp.s
46 include progctrl.s 46 include progctrl.s
47 include print.s 47 include print.s
48 48 include error.s
49 include expr.s
50
49 include miscdata.s 51 include miscdata.s
50 *pragmapop list 52 *pragmapop list
51 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52 ; Error messages
53 ;
54 ; Each error begins with a deferr macro invocation which will define a symbol err_slug with the next error number
55 ;
56 ; deferr slug
57 ;
58 ; This is then followed by the error message defined with fcn.
59 ;
60 ; Real error numbers start at 1; 0 is used to indicate no error.
61 *pragmapush list
62 *pragma nolist
63 __errnum set 0
64 deferr macro noexpand
65 err_{1} equ __errnum
66 __errnum set __errnum+1
67 endm
68 *pragmapop list
69 errormsg deferr none
70 fcn 'No error'
71 deferr nf
72 fcn 'NEXT without FOR'
73 deferr sn
74 fcn 'Syntax error'
75 deferr ul
76 fcn 'Undefined line number'
77 deferr rg
78 fcn 'RETURN without GOSUB'
79 deferr ov
80 fcn 'Overflow'
81 deferr tm
82 fcn 'Type mismatch'
83 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
84 ; The LET command which is the default if no token begins a statement
85 cmd_let jmp SNERROR ; not yet implemented
86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
87 ; Expression Evaluation Package
88 ;
89 ; This is the expression evaluator. It handles everything from parsing numbers to dispatching function calls. The main
90 ; entry point is eval_expr which will evaluate an arbitrary expression. It returns as soon as it reaches something it
91 ; doesn't understand as part of an expression.
92 ;
93 ; The special handling for relational operators is required because Basic allows them in all
94 eval_expr clrb ; flag previous operator as minimum precdence (end of expression)
95 eval_expraux jsr eval_term ; evaluate the first term of the expression
96 eval_expr0 jsr curchar ; fetch current input
97 beq eval_expr1 ; brif end of expression - we're done
98 cmpa #tok_or ; is it above operators?
99 bhi eval_expr1 ; brif so
100 suba #tok_plus ; offset to zero for first operator token
101 bcc eval_expr2 ; brif it is an operator
102 eval_expr1 rts
103 eval_expr2 pshs b ; save previous operator precedence
104 ldx #oper_tab ; point to operator table
105 tfr a,b ; shift to B for "ABX"
106 abx ; add three times (3 bytes per entry)
107 abx ; OBS: TFR + ABX + ABX + ABX is faster than LDB + MUL + ABX
108 abx ; now X points to the operator entry in the table
109 ldb ,x ; get precedence of current operation
110 cmpb ,s ; is it higher than the current operation?
111 bhi eval_expr3 ; brif so - process this operator
112 puls b,pc ; return current value to complete previous operation
113 eval_expr3 jsr nextchar ; eat the operator token
114 ldx 1,x ; get handler address of this operator
115 leas -val.size,s ; make room for the result accumulator
116 pshs x ; save handler address for later
117 lda val0+val.type ; get current value type
118 ldx val0 ; get value accumlator contents (6 bytes)
119 ldy val0+2
120 ldu val0+4
121 pshs a,x,y,u ; save it on the stack
122 jsr eval_expraux ; evaluate the following term and higher precedence expressions
123 puls a,x,y,u ; get back saved value
124 stx val1 ; save it to the second value accumulator
125 sty val1+2
126 stu val1+4
127 sta val1+val.type ; save previous value type
128 ldx #val1 ; point to left operand
129 ldu #val0 ; point to right operand
130 leay 2,s ; point to return value location
131 jsr [,s++] ; go handle the operator
132 puls a,x,y,u ; get return value
133 sta val0
134 stx val0+1
135 sty val0+3
136 stu val0+5
137 puls b ; get back the previous operator precedence
138 bra eval_expr0 ; go process another operator or end of expression
139 eval_term jsr curchar ; get current input character
140 beq eval_term0 ; brif end of input - this is an error
141 bcs eval_number ; brif digit - we have a number
142 ; bmi eval_func ; brif we have a token - handle function call
143 cmpa #'. ; decimal point?
144 beq eval_number ; brif so - evaluate number
145 cmpa #'- ; negative sign?
146 beq eval_number ; brif so - evaluate number
147 cmpa #'+ ; positive sign?
148 beq eval_number ; brif so - evaluate number
149 eval_term0 jmp SNERROR ; we have something unrecognized - raise error
150 ; Evaluate a number constant. Currently this only handles 32 bit integers.
151 eval_number ldb #valtype_int ; start with integer value
152 stb val0+val.type ; set return value
153 ldx zero ; blank out the value
154 stx val0
155 stx val0+2
156 stx val0+4
157 bra eval_number1 ; go do the parsing
158 eval_number0 jsr nextchar ; fetch next input
159 beq eval_numberr ; brif end of expression - bail
160 eval_number1 cmpa #'- ; negative (ascii sign)?
161 beq eval_number3 ; brif so
162 cmpa #tok_minus ; negative (operator negative)?
163 bne eval_number2 ; brif not
164 eval_number3 com val0+val.fpsign ; invert sign
165 bra eval_number0 ; deal with next input
166 eval_number2 cmpa #'+ ; unary +?
167 beq eval_number0 ; brif so - skip it
168 eval_number5 cmpa #'. ; decimal point?
169 beq eval_float ; brif decimal - force float
170 cmpa #'0 ; is it a number?
171 blo eval_numberr ; brif below digit
172 cmpa #'9 ; is it still a number?
173 bhi eval_numberr ; brif above digit
174 suba #'0 ; offset to binary digit value
175 pshs a ; save digit value
176 ldx val0+val.int ; get current value for later (for quick multiply by 10)
177 ldd val0+val.int+2
178 pshs d,x ; stored with words swapped on stack for efficiency for later
179 lsl val0+val.int+3 ; times 2
180 rol val0+val.int+2
181 rol val0+val.int+1
182 rol val0+val.int
183 bcs OVERROR ; brif overflowed
184 lsl val0+val.int+3 ; times 4
185 rol val0+val.int+2
186 rol val0+val.int+1
187 rol val0+val.int
188 bcs OVERROR ; brif overflowed
189 ldd val0+val.int+2 ; times 5 (add original value)
190 addd ,s++
191 std val0+val.int+2
192 ldd val0+val.int
193 adcb 1,s
194 adca ,s++
195 std val0+val.int
196 bcs OVERROR
197 lsl val0+val.int+3 ; times 10
198 rol val0+val.int+2
199 rol val0+val.int+1
200 rol val0+val.int
201 bcs OVERROR ; brif overflowed
202 ldd val0+val.int+2 ; get low word
203 addb ,s+ ; add in current digit
204 adca #0
205 std val0+val.int+2
206 ldd val0+val.int
207 adcb #0
208 adca #0
209 std val0+val.int
210 bcs OVERROR ; brif overflowed
211 bpl eval_number4 ; brif we haven't wrapped negative
212 cmpd #0x8000 ; is it valid negative two's complement?
213 bhi OVERROR ; brif not
214 ldd val0+val.int+2 ; is it still valid two's complement (max negative)?
215 bne OVERROR ; brif so
216 eval_number4 jsr nextchar ; fetch next input character
217 bra eval_number5 ; go handle it
218 OVERROR ldb #err_ov ; flag overflow
219 jmp ERROR
220 eval_numberr ldb val0+val.fpsign ; is the number we want negative?
221 beq eval_numberr0 ; brif not
222 jsr val_negint32 ; negate the integer
223 eval_numberr0 rts
224 eval_float jmp SNERROR ; we don't handle floating point yet
225 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
226 ; Operator table
227 ;
228 ; Each entry starts with the precedence value followed by the handler routine. Each handler will receive its left
229 ; operand in val1 and its right operand in val0 and should return its result in val0.
230 oper_tab fcb 0x79 ; addition
231 fdb oper_plus
232 fcb 0x79 ; subtraction
233 fdb oper_minus
234 fcb 0x7b ; multiplication
235 fdb SNERROR
236 fcb 0x7b ; division
237 fdb SNERROR
238 fcb 0x7f ; exponentiation
239 fdb SNERROR
240 fcb 0x64 ; less than
241 fdb SNERROR
242 fcb 0x64 ; equal to
243 fdb SNERROR
244 fcb 0x64 ; greater than
245 fdb SNERROR
246 fcb 0x64 ; less than or equal to
247 fdb SNERROR
248 fcb 0x64 ; greater than or equal to
249 fdb SNERROR
250 fcb 0x64 ; not equal to
251 fdb SNERROR
252 fcb 0x50 ; boolean AND
253 fdb SNERROR
254 fcb 0x46 ; boolean OR
255 fdb SNERROR
256 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 53 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
257 ; Set carry if upper/lower case alpha 54 ; Set carry if upper/lower case alpha
258 setcifalpha cmpa #'z+1 ; is it above lower case Z? 55 setcifalpha cmpa #'z+1 ; is it above lower case Z?
259 bhs setcifalpha0 ; brif so, C clear 56 bhs setcifalpha0 ; brif so, C clear
260 suba #'a ; set C if >= lower case A 57 suba #'a ; set C if >= lower case A