Initial revision
[ssr] / StraySrc / Libraries / Sapphire / sail / s / value
1 ;
2 ; value.s
3 ;
4 ; Table drive expression evaluator for TermScript
5 ;
6 ; © 1995 Straylight
7 ;
8
9 ;----- Standard Header ------------------------------------------------------
10
11 GET libs:header
12 GET libs:swis
13
14 GET libs:stream
15
16 ;----- External dependencies ------------------------------------------------
17
18 ;----- Main code ------------------------------------------------------------
19
20 AREA |Termscript$$Code|,CODE,READONLY
21
22 ; --- val_readExp ---
23 ;
24 ; On entry: R7, R8, R9 == lookahead token
25 ; R10 == pointer into tokenised buffer
26 ; R11 == evaluation stack pointer
27 ; R12 == anchor pointer
28 ;
29 ; On exit: R7, R8, R9 == lookahead token
30 ; R0, R1 == result of expression
31 ; R10 == moved on to first char after expression
32 ;
33 ; Use: Reads an expression for the current point in the tokenised
34 ; file, and returns it's result. The implementation is
35 ; table driven and should be very fast.
36
37 EXPORT val_readExp
38 val_readExp ROUT
39
40 10val_readExp BL val__operand
41 BLCS val__operator
42 BCS val_readExp
43
44 ; --- Now work out the result ---
45
46 BL val__copyRest ;Copy rest of tokens over
47
48
49 LTORG
50
51 ; --- val__operand ---
52 ;
53 ; On entry: R7, R8, R9 == lookahead token
54 ; R10 == pointer into tokenised buffer
55 ; R11 == evaluation stack pointer
56 ; R12 == anchor pointer
57 ;
58 ; On exit: R0 corrupted
59 ; R7, R8, R9 == lookahead token
60 ; R10 modified appropriately
61 ; CS if operand found,
62 ; CC otherwise
63 ;
64 ; Use: Reads an operand from the input, and does appropriate
65 ; stack like things with it.
66
67 val__operand ROUT
68
69 STMFD R13!,{R14} ;Stack registers
70 00val__operand CMP R9,#'&' ;Start a hex number?
71 BEQ %10val__operand ;Yes -- jump ahead
72 CMP R9,#'%' ;Start of a binary number?
73 BEQ %20val__operand ;Yes -- jump ahead
74 CMP R9,#'!' ;An indirection operand?
75 CMPNE R9,#'?'
76 CMPNE R9,#'$'
77 BEQ %40val__operand ;Yes -- jump ahead
78 CMP R9,#'+' ;Unary operator then?
79 CMPNE R9,#'-'
80 BEQ %50val__operand ;Yes -- jump ahead
81 CMPNE R9,#'(' ;A nice bracket?
82 BEQ %60val__operand ;Yes -- jump ahead
83 SUB R14,R9,#'0' ;Set up for a range check
84 CMP R14,#10 ;Is it a digit?
85 MOVCC R0,#0 ;Yes -- set up accumulator
86 BCC %30val__operand ;Yes -- deal with that
87 B %70val__operand ;Assume it's an identifier
88
89 ; --- Read a hex number ---
90
91 10val__operand BL getToken ;Get another token
92 MOV R0,#0 ;The number so far
93 SUB R14,R9,#'A' ;Check if it's a letter
94 CMP R14,#6 ;But only A-F
95 ADDCC R14,R14,#10 ;If so, add 10 on
96 SUBCS R14,R9,#'0' ;Otherwise check for digit
97 CMPCS R14,#10 ;Make sure it's OK
98 BCC %12val__operand ;And jump head
99 MOV R0,#err_badHex ;Point to error message
100 B error_report ;And return the error
101
102 11val__operand SUB R14,R9,#'A' ;Check if it's a letter
103 CMP R14,#6 ;But only A-F
104 ADDCC R14,R14,#10 ;If so, add 10 on
105 SUBCS R14,R9,#'0' ;Otherwise check for digit
106 CMPCS R14,#10 ;Make sure it's OK
107 BCS %35val__readSimple ;No -- that's it then
108
109 12val__operand ADD R0,R14,R0,LSL #4 ;Multiply by 16 and add digit
110 BL getToken ;Load a character
111 B %11val__readSimple ;Keep on reading more
112
113 ; --- Read a binary number ---
114
115 20val__operand BL getToken ;Get another token
116 MOV R0,#0 ;The number so far
117 SUB R14,R9,#'0' ;Set up for a range check
118 CMP R14,#1 ;Is it a digit
119 BLS %22val__readSimple ;Yes -- jump ahead
120 MOV R0,#err_badBinary ;Point to error message
121 B error_report ;And return the error
122
123 21val__operand SUB R14,R9,#'0' ;Set up for a range check
124 CMP R14,#1 ;Is it a digit
125 BHI %35val__readSimple ;Nope -- jump ahead then
126
127 22val__operand ADC R0,R0,R0 ;Multiply by 2
128 BL getToken ;Load a character
129 B %21val__readSimple ;Keep on reading more
130
131 ; --- Read a decimal number ---
132
133 30val__operand SUB R14,R9,#'0' ;Set up for a range check
134 CMP R14,#10 ;Is it a digit
135 BCS %35val__readSimple ;Nope -- jump ahead then
136
137 32val__operand ADD R0,R0,R0,LSL #2 ;Multiply by 5
138 ADD R0,R14,R0,LSL #1 ;And then by 2 (* 10)
139 BL getToken ;Load the next token
140 B %30val__readSimple ;Keep on reading more
141
142 ; --- Finished reading a number ---
143
144 35val__operand BL val__stackNumber ;Put a number on the stack
145 B %90val__operand ;Jump ahead
146
147 ; --- Read an indirection operator ---
148
149 40val__operand MOV R0,#0 ;Get the offset ready
150 BL val__stackNumber ;Put it on the stack
151 BL val__stackToken ;And put operator on too
152 BL getToken ;Get the next token
153 B %00val__operand ;Need another operand
154
155 ; --- Deal with unary signs ---
156
157 50val__operand CMP R9,#'-' ;Is is a unary minus
158 BLEQ val__stackToken ;Yes -- put it on the stack
159 BL getToken ;Get another token
160 B %00val__operand ;Need another operand
161
162 ; --- We have just read a '(' ---
163
164 60val__operand BL val__stackToken ;Stackit immediately
165 BL getToken ;Get another token
166 B %00val__operand ;Need another operand
167
168 ; --- Assume it's an identifier then ---
169
170 70val__operand ADR R1,sail_misc ;Point to a nice block
171 MOV R0,#vType_integer ;The current variable type
172
173 75val__operand SUBS R14,R9,#'_' ;Is it an underscore?
174 SUBNE R14,R9,#'0' ;Or a number?
175 CMP R14,#10
176 SUBCS R14,R9,#'A' ;Or a capital letter?
177 CMPCS R14,#26
178 SUBCS R14,R9,#'a' ;Or a lowercase letter?
179 CMPCS R14,#26
180 STRCCB R9,[R1],#1 ;Yes -- store it away
181 BLCC getToken ;Read the next byte
182 BCS %95val_readLvalue ;Ouch -- not an identifier
183
184 CMP R9,#'$' ;Is it a dollar sign?
185 MOVEQ R0,#vType_string ;It's a string now
186 CMPNE R9,#'%' ;Or a percentage?
187 STREQB R9,[R2],#1 ;Yes -- store it then
188 CMPNE R9,#' ' ;Just check for a space
189
190 BNE %75val_readLvalue ;Go round for more
191
192 MOV R14,#0 ;The terminator
193 STRB R14,[R1],#0 ;Store that in the var name
194 BL getToken ;Read the next token ready
195
196 ; --- The identifier name is in the buffer ---
197
198 ADR R1,sail_misc ;Point to the name
199 BL var_find ;Try to find the variable
200 MOVCC R0,#err_unknown ;Not there, get the error
201 BCC error_report ;And report a possible error
202
203 LDR R1,[R0,#0] ;Load out the variable type
204 LDR R0,[R0,#4] ;Load out the value
205 CMP R1,#vType_integer ;Is it an integer?
206 BLEQ val__stackInteger ;Yes -- stack it
207 BLNE val__stackString ;No -- it's a string then
208
209 90val__operand LDMFD R13!,{R14} ;Load back registers
210 ORRS PC,R14,#C_flag ;We found an operand
211
212 95val__operand LDMFD R13!,{R14} ;Load back registers
213 BICS PC,R14,#C_flag ;No operand was found
214
215 LTORG
216
217 ; --- val__operator ---
218 ;
219 ; On entry: R7, R8, R9 == lookahead token
220 ; R10 == pointer into tokenised buffer
221 ; R11 == evaluation stack pointer
222 ; R12 == anchor pointer
223 ;
224 ; On exit: R7, R8, R9 == lookahead token
225 ; R10 modified appropriately
226 ; CS if operator found,
227 ; CC otherwise
228 ;
229 ; Use: Reads an operator from the input, and does appropriate
230 ; stack like things with it.
231
232 ROUT
233
234 val__operator STMFD R13!,{R14} ;Stack registers
235 00val__operator CMP R9,#')' ;Is it a close bracket?
236 BEQ %10val__operator ;Yes -- jump ahead
237 ; --- Make sure we recognise it ---
238
239 CMP R9,#'!' ;An indirection operator?
240 CMPNE R9,#'?'
241 CMPNE R7,#tClass__andOp
242 CMPNE R7,#tClass__orOp
243 CMPNE R7,#tClass__addOp
244 CMPNE R7,#tClass__multOp
245 CMPNE R7,#tClass__relOp
246 BNE %95val__operator ;Nope -- just return
247 BL val__stackToken ;Stack this token
248 BL getToken ;Get another one
249 B %90val__operator ;And return success
250
251 ; --- We have read a ')' ---
252
253 BL val__stackToken ;Stack this token
254 BL getToken ;Get another one
255 B %00val__operator ;We expect another operator
256
257 90val__operator LDMFD R13!,{R14} ;Load back registers
258 ORRS PC,R14,#C_flag ;We found an operand
259
260 95val__operator LDMFD R13!,{R14} ;Load back registers
261 BICS PC,R14,#C_flag ;No operand was found
262
263 LTORG
264
265 ;----- Workspace ------------------------------------------------------------
266
267 val__precTable DCD val__andOp-val__precTable
268 DCD 0
269 DCD 0
270 DCD 0
271 DCD val__multOp-val__precTable
272 DCD val__orOp-val__precTable
273 DCD 0
274 DCD val__relOp-val__precTable
275 DCD val__addOp-val__precTable
276 DCD 0
277
278 ; --- The precedence tables ---
279 ;
280 ; Each byte indicates whether or not the given type of
281 ; toke has a higher or lower precedence than another type.
282 ; The order of the bytes is:
283 ;
284 ; and,-,-,-,mult,or,-,-,rel,add,-
285
286 val__andOp DCB 0, 0, 0, 0,-1, 1, 0, 0,-1,-1, 0
287 val__multOp DCB 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0
288 val__orOp DCB -1, 0, 0, 0,-1, 0, 0, 0,-1,-1, 0
289 val__relOp DCB 1, 0, 0, 0,-1, 1, 0, 0, 0,-1, 0
290 val__addOp DCB 1, 0, 0, 0,-1, 1, 0, 0, 1, 0, 0
291
292 ;----- That's all, folks ----------------------------------------------------
293
294 END