Rev 8097 | Rev 9893 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7983 | leency | 1 | (* |
7597 | akron1 | 2 | BSD 2-Clause License |
3 | |||
8859 | leency | 4 | Copyright (c) 2018-2021, Anton Krotov |
7597 | akron1 | 5 | All rights reserved. |
6 | *) |
||
7 | |||
8 | MODULE STATEMENTS; |
||
9 | |||
10 | IMPORT |
||
11 | |||
8859 | leency | 12 | PARS, PROG, SCAN, ARITH, STRINGS, LISTS, IL, X86, AMD64, MSP430, THUMB, RVMxI, |
7983 | leency | 13 | ERRORS, UTILS, AVL := AVLTREES, CONSOLE, C := COLLECTIONS, TARGETS; |
7597 | akron1 | 14 | |
15 | |||
16 | CONST |
||
17 | |||
18 | eCONST = PARS.eCONST; eTYPE = PARS.eTYPE; eVAR = PARS.eVAR; |
||
19 | eEXPR = PARS.eEXPR; eVREC = PARS.eVREC; ePROC = PARS.ePROC; |
||
20 | eVPAR = PARS.eVPAR; ePARAM = PARS.ePARAM; eSTPROC = PARS.eSTPROC; |
||
21 | eSTFUNC = PARS.eSTFUNC; eSYSFUNC = PARS.eSYSFUNC; eSYSPROC = PARS.eSYSPROC; |
||
22 | eIMP = PARS.eIMP; |
||
23 | |||
7693 | akron1 | 24 | errASSERT = 1; errPTR = 2; errDIV = 3; errPROC = 4; |
25 | errGUARD = 5; errIDX = 6; errCASE = 7; errCOPY = 8; |
||
7597 | akron1 | 26 | errCHR = 9; errWCHR = 10; errBYTE = 11; |
27 | |||
28 | chkIDX* = 0; chkGUARD* = 1; chkPTR* = 2; chkCHR* = 3; chkWCHR* = 4; chkBYTE* = 5; |
||
8859 | leency | 29 | chkSTK* = MSP430.chkSTK; (* 6 *) |
7597 | akron1 | 30 | |
8859 | leency | 31 | chkALL* = {chkIDX, chkGUARD, chkPTR, chkCHR, chkWCHR, chkBYTE, chkSTK}; |
7597 | akron1 | 32 | |
33 | |||
34 | TYPE |
||
35 | |||
36 | isXXX = PROCEDURE (e: PARS.EXPR): BOOLEAN; |
||
37 | |||
38 | RANGE = RECORD |
||
39 | |||
40 | a, b: INTEGER |
||
41 | |||
42 | END; |
||
43 | |||
44 | CASE_LABEL = POINTER TO rCASE_LABEL; |
||
45 | |||
46 | rCASE_LABEL = RECORD (AVL.DATA) |
||
47 | |||
48 | range: RANGE; |
||
49 | |||
50 | variant, self: INTEGER; |
||
51 | |||
8097 | maxcodehac | 52 | _type: PROG._TYPE; |
7597 | akron1 | 53 | |
54 | prev: CASE_LABEL |
||
55 | |||
56 | END; |
||
57 | |||
58 | CASE_VARIANT = POINTER TO RECORD (LISTS.ITEM) |
||
59 | |||
7693 | akron1 | 60 | label: INTEGER; |
61 | cmd: IL.COMMAND; |
||
62 | processed: BOOLEAN |
||
7597 | akron1 | 63 | |
64 | END; |
||
65 | |||
66 | |||
67 | VAR |
||
68 | |||
7693 | akron1 | 69 | Options: PROG.OPTIONS; |
7597 | akron1 | 70 | |
7693 | akron1 | 71 | begcall, endcall: IL.COMMAND; |
7597 | akron1 | 72 | |
73 | CaseLabels, CaseVar: C.COLLECTION; |
||
74 | |||
75 | CaseVariants: LISTS.LIST; |
||
76 | |||
7693 | akron1 | 77 | CPU: INTEGER; |
7597 | akron1 | 78 | |
8097 | maxcodehac | 79 | tINTEGER, tBYTE, tCHAR, tWCHAR, tSET, tBOOLEAN, tREAL: PROG._TYPE; |
7693 | akron1 | 80 | |
81 | |||
7597 | akron1 | 82 | PROCEDURE isExpr (e: PARS.EXPR): BOOLEAN; |
83 | RETURN e.obj IN {eCONST, eVAR, eEXPR, eVPAR, ePARAM, eVREC} |
||
84 | END isExpr; |
||
85 | |||
86 | |||
87 | PROCEDURE isVar (e: PARS.EXPR): BOOLEAN; |
||
88 | RETURN e.obj IN {eVAR, eVPAR, ePARAM, eVREC} |
||
89 | END isVar; |
||
90 | |||
91 | |||
92 | PROCEDURE isBoolean (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 93 | RETURN isExpr(e) & (e._type = tBOOLEAN) |
7597 | akron1 | 94 | END isBoolean; |
95 | |||
96 | |||
97 | PROCEDURE isInteger (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 98 | RETURN isExpr(e) & (e._type = tINTEGER) |
7597 | akron1 | 99 | END isInteger; |
100 | |||
101 | |||
102 | PROCEDURE isByte (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 103 | RETURN isExpr(e) & (e._type = tBYTE) |
7597 | akron1 | 104 | END isByte; |
105 | |||
106 | |||
107 | PROCEDURE isInt (e: PARS.EXPR): BOOLEAN; |
||
108 | RETURN isByte(e) OR isInteger(e) |
||
109 | END isInt; |
||
110 | |||
111 | |||
112 | PROCEDURE isReal (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 113 | RETURN isExpr(e) & (e._type = tREAL) |
7597 | akron1 | 114 | END isReal; |
115 | |||
116 | |||
117 | PROCEDURE isSet (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 118 | RETURN isExpr(e) & (e._type = tSET) |
7597 | akron1 | 119 | END isSet; |
120 | |||
121 | |||
122 | PROCEDURE isString (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 123 | RETURN (e.obj = eCONST) & (e._type.typ IN {PROG.tSTRING, PROG.tCHAR}) |
7597 | akron1 | 124 | END isString; |
125 | |||
126 | |||
127 | PROCEDURE isStringW (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 128 | RETURN (e.obj = eCONST) & (e._type.typ IN {PROG.tSTRING, PROG.tCHAR, PROG.tWCHAR}) |
7597 | akron1 | 129 | END isStringW; |
130 | |||
131 | |||
132 | PROCEDURE isChar (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 133 | RETURN isExpr(e) & (e._type = tCHAR) |
7597 | akron1 | 134 | END isChar; |
135 | |||
136 | |||
137 | PROCEDURE isCharW (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 138 | RETURN isExpr(e) & (e._type = tWCHAR) |
7597 | akron1 | 139 | END isCharW; |
140 | |||
141 | |||
142 | PROCEDURE isPtr (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 143 | RETURN isExpr(e) & (e._type.typ = PROG.tPOINTER) |
7597 | akron1 | 144 | END isPtr; |
145 | |||
146 | |||
147 | PROCEDURE isRec (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 148 | RETURN isExpr(e) & (e._type.typ = PROG.tRECORD) |
7597 | akron1 | 149 | END isRec; |
150 | |||
151 | |||
7693 | akron1 | 152 | PROCEDURE isRecPtr (e: PARS.EXPR): BOOLEAN; |
153 | RETURN isRec(e) OR isPtr(e) |
||
154 | END isRecPtr; |
||
155 | |||
156 | |||
7597 | akron1 | 157 | PROCEDURE isArr (e: PARS.EXPR): BOOLEAN; |
8097 | maxcodehac | 158 | RETURN isExpr(e) & (e._type.typ = PROG.tARRAY) |
7597 | akron1 | 159 | END isArr; |
160 | |||
161 | |||
162 | PROCEDURE isProc (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 163 | RETURN isExpr(e) & (e._type.typ = PROG.tPROCEDURE) OR (e.obj IN {ePROC, eIMP}) |
7597 | akron1 | 164 | END isProc; |
165 | |||
166 | |||
167 | PROCEDURE isNil (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 168 | RETURN e._type.typ = PROG.tNIL |
7597 | akron1 | 169 | END isNil; |
170 | |||
171 | |||
7693 | akron1 | 172 | PROCEDURE isCharArray (e: PARS.EXPR): BOOLEAN; |
8097 | maxcodehac | 173 | RETURN isArr(e) & (e._type.base = tCHAR) |
7693 | akron1 | 174 | END isCharArray; |
175 | |||
176 | |||
177 | PROCEDURE isCharArrayW (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 178 | RETURN isArr(e) & (e._type.base = tWCHAR) |
7693 | akron1 | 179 | END isCharArrayW; |
180 | |||
181 | |||
182 | PROCEDURE isCharArrayX (e: PARS.EXPR): BOOLEAN; |
||
183 | RETURN isCharArray(e) OR isCharArrayW(e) |
||
184 | END isCharArrayX; |
||
185 | |||
186 | |||
187 | PROCEDURE getpos (parser: PARS.PARSER; VAR pos: PARS.POSITION); |
||
7597 | akron1 | 188 | BEGIN |
7693 | akron1 | 189 | pos.line := parser.lex.pos.line; |
190 | pos.col := parser.lex.pos.col; |
||
191 | pos.parser := parser |
||
7597 | akron1 | 192 | END getpos; |
193 | |||
194 | |||
7693 | akron1 | 195 | PROCEDURE NextPos (parser: PARS.PARSER; VAR pos: PARS.POSITION); |
7597 | akron1 | 196 | BEGIN |
7693 | akron1 | 197 | PARS.Next(parser); |
198 | getpos(parser, pos) |
||
7597 | akron1 | 199 | END NextPos; |
200 | |||
201 | |||
202 | PROCEDURE strlen (e: PARS.EXPR): INTEGER; |
||
203 | VAR |
||
204 | res: INTEGER; |
||
205 | |||
206 | BEGIN |
||
207 | ASSERT(isString(e)); |
||
8097 | maxcodehac | 208 | IF e._type = tCHAR THEN |
7597 | akron1 | 209 | res := 1 |
210 | ELSE |
||
8859 | leency | 211 | res := LENGTH(e.value.string(SCAN.STRING).s) |
7597 | akron1 | 212 | END |
213 | RETURN res |
||
214 | END strlen; |
||
215 | |||
216 | |||
217 | PROCEDURE _length (s: ARRAY OF CHAR): INTEGER; |
||
218 | VAR |
||
219 | i, res: INTEGER; |
||
220 | |||
221 | BEGIN |
||
222 | i := 0; |
||
223 | res := 0; |
||
224 | WHILE (i < LEN(s)) & (s[i] # 0X) DO |
||
225 | IF (s[i] <= CHR(127)) OR (s[i] >= CHR(192)) THEN |
||
226 | INC(res) |
||
227 | END; |
||
228 | INC(i) |
||
229 | END |
||
230 | |||
231 | RETURN res |
||
232 | END _length; |
||
233 | |||
234 | |||
235 | PROCEDURE utf8strlen (e: PARS.EXPR): INTEGER; |
||
236 | VAR |
||
237 | res: INTEGER; |
||
238 | |||
239 | BEGIN |
||
240 | ASSERT(isStringW(e)); |
||
8097 | maxcodehac | 241 | IF e._type.typ IN {PROG.tCHAR, PROG.tWCHAR} THEN |
7597 | akron1 | 242 | res := 1 |
243 | ELSE |
||
8859 | leency | 244 | res := _length(e.value.string(SCAN.STRING).s) |
7597 | akron1 | 245 | END |
246 | RETURN res |
||
247 | END utf8strlen; |
||
248 | |||
249 | |||
250 | PROCEDURE StrToWChar (s: ARRAY OF CHAR): INTEGER; |
||
251 | VAR |
||
252 | res: ARRAY 2 OF WCHAR; |
||
253 | |||
254 | BEGIN |
||
255 | ASSERT(STRINGS.Utf8To16(s, res) = 1) |
||
256 | RETURN ORD(res[0]) |
||
257 | END StrToWChar; |
||
258 | |||
259 | |||
260 | PROCEDURE isStringW1 (e: PARS.EXPR): BOOLEAN; |
||
8097 | maxcodehac | 261 | RETURN isString(e) & (utf8strlen(e) = 1) & (strlen(e) > 1) |
7597 | akron1 | 262 | END isStringW1; |
263 | |||
264 | |||
8097 | maxcodehac | 265 | PROCEDURE assigncomp (e: PARS.EXPR; t: PROG._TYPE): BOOLEAN; |
7597 | akron1 | 266 | VAR |
267 | res: BOOLEAN; |
||
268 | |||
269 | BEGIN |
||
270 | IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN |
||
7696 | akron1 | 271 | |
8097 | maxcodehac | 272 | IF t = e._type THEN |
7597 | akron1 | 273 | res := TRUE |
274 | ELSIF isInt(e) & (t.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN |
||
7693 | akron1 | 275 | IF (e.obj = eCONST) & (t = tBYTE) THEN |
7597 | akron1 | 276 | res := ARITH.range(e.value, 0, 255) |
277 | ELSE |
||
278 | res := TRUE |
||
279 | END |
||
7696 | akron1 | 280 | ELSIF |
281 | (e.obj = eCONST) & isChar(e) & (t = tWCHAR) |
||
282 | OR isStringW1(e) & (t = tWCHAR) |
||
8097 | maxcodehac | 283 | OR PROG.isBaseOf(t, e._type) |
284 | OR ~PROG.isOpenArray(t) & ~PROG.isOpenArray(e._type) & PROG.isTypeEq(t, e._type) |
||
7696 | akron1 | 285 | OR isNil(e) & (t.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) |
8097 | maxcodehac | 286 | OR PROG.arrcomp(e._type, t) |
7696 | akron1 | 287 | OR isString(e) & (t.typ = PROG.tARRAY) & (t.base = tCHAR) & (t.length > strlen(e)) |
288 | OR isStringW(e) & (t.typ = PROG.tARRAY) & (t.base = tWCHAR) & (t.length > utf8strlen(e)) |
||
289 | THEN |
||
7597 | akron1 | 290 | res := TRUE |
291 | ELSE |
||
292 | res := FALSE |
||
293 | END |
||
294 | ELSE |
||
295 | res := FALSE |
||
296 | END |
||
7696 | akron1 | 297 | |
7597 | akron1 | 298 | RETURN res |
299 | END assigncomp; |
||
300 | |||
301 | |||
302 | PROCEDURE String (e: PARS.EXPR): INTEGER; |
||
303 | VAR |
||
304 | offset: INTEGER; |
||
8859 | leency | 305 | string: SCAN.STRING; |
7597 | akron1 | 306 | |
307 | BEGIN |
||
308 | IF strlen(e) # 1 THEN |
||
8859 | leency | 309 | string := e.value.string(SCAN.STRING); |
7597 | akron1 | 310 | IF string.offset = -1 THEN |
7693 | akron1 | 311 | string.offset := IL.putstr(string.s); |
7597 | akron1 | 312 | END; |
313 | offset := string.offset |
||
314 | ELSE |
||
7693 | akron1 | 315 | offset := IL.putstr1(ARITH.Int(e.value)) |
7597 | akron1 | 316 | END |
317 | |||
318 | RETURN offset |
||
319 | END String; |
||
320 | |||
321 | |||
322 | PROCEDURE StringW (e: PARS.EXPR): INTEGER; |
||
323 | VAR |
||
324 | offset: INTEGER; |
||
8859 | leency | 325 | string: SCAN.STRING; |
7597 | akron1 | 326 | |
327 | BEGIN |
||
328 | IF utf8strlen(e) # 1 THEN |
||
8859 | leency | 329 | string := e.value.string(SCAN.STRING); |
7597 | akron1 | 330 | IF string.offsetW = -1 THEN |
7693 | akron1 | 331 | string.offsetW := IL.putstrW(string.s); |
7597 | akron1 | 332 | END; |
333 | offset := string.offsetW |
||
334 | ELSE |
||
8097 | maxcodehac | 335 | IF e._type.typ IN {PROG.tWCHAR, PROG.tCHAR} THEN |
7693 | akron1 | 336 | offset := IL.putstrW1(ARITH.Int(e.value)) |
8097 | maxcodehac | 337 | ELSE (* e._type.typ = PROG.tSTRING *) |
8859 | leency | 338 | string := e.value.string(SCAN.STRING); |
7597 | akron1 | 339 | IF string.offsetW = -1 THEN |
7693 | akron1 | 340 | string.offsetW := IL.putstrW(string.s); |
7597 | akron1 | 341 | END; |
342 | offset := string.offsetW |
||
343 | END |
||
344 | END |
||
345 | |||
346 | RETURN offset |
||
347 | END StringW; |
||
348 | |||
349 | |||
350 | PROCEDURE CheckRange (range, line, errno: INTEGER); |
||
351 | VAR |
||
352 | label: INTEGER; |
||
353 | |||
354 | BEGIN |
||
7693 | akron1 | 355 | label := IL.NewLabel(); |
356 | IL.AddCmd2(IL.opCHKIDX, label, range); |
||
357 | IL.OnError(line, errno); |
||
358 | IL.SetLabel(label) |
||
7597 | akron1 | 359 | END CheckRange; |
360 | |||
361 | |||
8097 | maxcodehac | 362 | PROCEDURE Float (parser: PARS.PARSER; e: PARS.EXPR); |
7597 | akron1 | 363 | VAR |
8097 | maxcodehac | 364 | pos: PARS.POSITION; |
365 | |||
366 | BEGIN |
||
367 | getpos(parser, pos); |
||
368 | IL.Float(ARITH.Float(e.value), pos.line, pos.col) |
||
369 | END Float; |
||
370 | |||
371 | |||
372 | PROCEDURE assign (parser: PARS.PARSER; e: PARS.EXPR; VarType: PROG._TYPE; line: INTEGER): BOOLEAN; |
||
373 | VAR |
||
7983 | leency | 374 | res: BOOLEAN; |
375 | label: INTEGER; |
||
7597 | akron1 | 376 | |
377 | BEGIN |
||
378 | IF isExpr(e) OR (e.obj IN {ePROC, eIMP}) THEN |
||
379 | res := TRUE; |
||
8097 | maxcodehac | 380 | IF PROG.arrcomp(e._type, VarType) THEN |
7597 | akron1 | 381 | |
382 | IF ~PROG.isOpenArray(VarType) THEN |
||
7693 | akron1 | 383 | IL.Const(VarType.length) |
7597 | akron1 | 384 | END; |
7693 | akron1 | 385 | IL.AddCmd(IL.opCOPYA, VarType.base.size); |
386 | label := IL.NewLabel(); |
||
8859 | leency | 387 | IL.Jmp(IL.opJNZ, label); |
7693 | akron1 | 388 | IL.OnError(line, errCOPY); |
389 | IL.SetLabel(label) |
||
7597 | akron1 | 390 | |
391 | ELSIF isInt(e) & (VarType.typ IN {PROG.tBYTE, PROG.tINTEGER}) THEN |
||
7693 | akron1 | 392 | IF VarType = tINTEGER THEN |
7597 | akron1 | 393 | IF e.obj = eCONST THEN |
7693 | akron1 | 394 | IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) |
7597 | akron1 | 395 | ELSE |
7693 | akron1 | 396 | IL.AddCmd0(IL.opSAVE) |
7597 | akron1 | 397 | END |
398 | ELSE |
||
399 | IF e.obj = eCONST THEN |
||
400 | res := ARITH.range(e.value, 0, 255); |
||
401 | IF res THEN |
||
7693 | akron1 | 402 | IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) |
7597 | akron1 | 403 | END |
404 | ELSE |
||
7693 | akron1 | 405 | IF chkBYTE IN Options.checking THEN |
406 | label := IL.NewLabel(); |
||
407 | IL.AddCmd2(IL.opCHKBYTE, label, 0); |
||
408 | IL.OnError(line, errBYTE); |
||
409 | IL.SetLabel(label) |
||
7597 | akron1 | 410 | END; |
7693 | akron1 | 411 | IL.AddCmd0(IL.opSAVE8) |
7597 | akron1 | 412 | END |
413 | END |
||
7693 | akron1 | 414 | ELSIF isSet(e) & (VarType = tSET) THEN |
7597 | akron1 | 415 | IF e.obj = eCONST THEN |
7693 | akron1 | 416 | IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) |
7597 | akron1 | 417 | ELSE |
7693 | akron1 | 418 | IL.AddCmd0(IL.opSAVE) |
7597 | akron1 | 419 | END |
7693 | akron1 | 420 | ELSIF isBoolean(e) & (VarType = tBOOLEAN) THEN |
7597 | akron1 | 421 | IF e.obj = eCONST THEN |
7693 | akron1 | 422 | IL.AddCmd(IL.opSBOOLC, ARITH.Int(e.value)) |
7597 | akron1 | 423 | ELSE |
7693 | akron1 | 424 | IL.AddCmd0(IL.opSBOOL) |
7597 | akron1 | 425 | END |
7693 | akron1 | 426 | ELSIF isReal(e) & (VarType = tREAL) THEN |
7597 | akron1 | 427 | IF e.obj = eCONST THEN |
8097 | maxcodehac | 428 | Float(parser, e) |
7597 | akron1 | 429 | END; |
7983 | leency | 430 | IL.savef(e.obj = eCONST) |
7693 | akron1 | 431 | ELSIF isChar(e) & (VarType = tCHAR) THEN |
7597 | akron1 | 432 | IF e.obj = eCONST THEN |
7693 | akron1 | 433 | IL.AddCmd(IL.opSAVE8C, ARITH.Int(e.value)) |
7597 | akron1 | 434 | ELSE |
7693 | akron1 | 435 | IL.AddCmd0(IL.opSAVE8) |
7597 | akron1 | 436 | END |
7693 | akron1 | 437 | ELSIF (e.obj = eCONST) & isChar(e) & (VarType = tWCHAR) THEN |
438 | IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) |
||
439 | ELSIF isStringW1(e) & (VarType = tWCHAR) THEN |
||
8859 | leency | 440 | IL.AddCmd(IL.opSAVE16C, StrToWChar(e.value.string(SCAN.STRING).s)) |
7693 | akron1 | 441 | ELSIF isCharW(e) & (VarType = tWCHAR) THEN |
7597 | akron1 | 442 | IF e.obj = eCONST THEN |
7693 | akron1 | 443 | IL.AddCmd(IL.opSAVE16C, ARITH.Int(e.value)) |
7597 | akron1 | 444 | ELSE |
7693 | akron1 | 445 | IL.AddCmd0(IL.opSAVE16) |
7597 | akron1 | 446 | END |
8097 | maxcodehac | 447 | ELSIF PROG.isBaseOf(VarType, e._type) THEN |
7597 | akron1 | 448 | IF VarType.typ = PROG.tPOINTER THEN |
7693 | akron1 | 449 | IL.AddCmd0(IL.opSAVE) |
7597 | akron1 | 450 | ELSE |
7693 | akron1 | 451 | IL.AddCmd(IL.opCOPY, VarType.size) |
7597 | akron1 | 452 | END |
8097 | maxcodehac | 453 | ELSIF (e._type.typ = PROG.tCARD32) & (VarType.typ = PROG.tCARD32) THEN |
7693 | akron1 | 454 | IL.AddCmd0(IL.opSAVE32) |
8097 | maxcodehac | 455 | ELSIF ~PROG.isOpenArray(VarType) & ~PROG.isOpenArray(e._type) & PROG.isTypeEq(VarType, e._type) THEN |
7597 | akron1 | 456 | IF e.obj = ePROC THEN |
7693 | akron1 | 457 | IL.AssignProc(e.ident.proc.label) |
7597 | akron1 | 458 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 459 | IL.AssignImpProc(e.ident._import) |
7597 | akron1 | 460 | ELSE |
461 | IF VarType.typ = PROG.tPROCEDURE THEN |
||
7693 | akron1 | 462 | IL.AddCmd0(IL.opSAVE) |
7597 | akron1 | 463 | ELSE |
7693 | akron1 | 464 | IL.AddCmd(IL.opCOPY, VarType.size) |
7597 | akron1 | 465 | END |
466 | END |
||
467 | ELSIF isNil(e) & (VarType.typ IN {PROG.tPOINTER, PROG.tPROCEDURE}) THEN |
||
7693 | akron1 | 468 | IL.AddCmd(IL.opSAVEC, 0) |
469 | ELSIF isString(e) & ((VarType.typ = PROG.tARRAY) & (VarType.base = tCHAR) & (VarType.length > strlen(e))) THEN |
||
470 | IL.saves(String(e), strlen(e) + 1) |
||
471 | ELSIF isStringW(e) & ((VarType.typ = PROG.tARRAY) & (VarType.base = tWCHAR) & (VarType.length > utf8strlen(e))) THEN |
||
472 | IL.saves(StringW(e), (utf8strlen(e) + 1) * 2) |
||
7597 | akron1 | 473 | ELSE |
474 | res := FALSE |
||
475 | END |
||
476 | ELSE |
||
477 | res := FALSE |
||
478 | END |
||
479 | RETURN res |
||
480 | END assign; |
||
481 | |||
482 | |||
483 | PROCEDURE LoadConst (e: PARS.EXPR); |
||
484 | BEGIN |
||
7693 | akron1 | 485 | IL.Const(ARITH.Int(e.value)) |
7597 | akron1 | 486 | END LoadConst; |
487 | |||
488 | |||
7693 | akron1 | 489 | PROCEDURE paramcomp (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR; p: PROG.PARAM); |
490 | VAR |
||
491 | stroffs: INTEGER; |
||
7597 | akron1 | 492 | |
493 | PROCEDURE arrcomp (e: PARS.EXPR; p: PROG.PARAM): BOOLEAN; |
||
494 | VAR |
||
8097 | maxcodehac | 495 | t1, t2: PROG._TYPE; |
7597 | akron1 | 496 | |
497 | BEGIN |
||
8097 | maxcodehac | 498 | t1 := p._type; |
499 | t2 := e._type; |
||
7597 | akron1 | 500 | WHILE (t2.typ = PROG.tARRAY) & PROG.isOpenArray(t1) DO |
501 | t1 := t1.base; |
||
502 | t2 := t2.base |
||
503 | END |
||
504 | |||
505 | RETURN PROG.isTypeEq(t1, t2) |
||
506 | END arrcomp; |
||
507 | |||
508 | |||
8097 | maxcodehac | 509 | PROCEDURE ArrLen (t: PROG._TYPE; n: INTEGER): INTEGER; |
7597 | akron1 | 510 | VAR |
511 | res: INTEGER; |
||
7983 | leency | 512 | |
7597 | akron1 | 513 | BEGIN |
514 | REPEAT |
||
515 | res := t.length; |
||
516 | t := t.base; |
||
517 | DEC(n) |
||
518 | UNTIL (n < 0) OR (t.typ # PROG.tARRAY); |
||
519 | ASSERT(n < 0) |
||
520 | RETURN res |
||
521 | END ArrLen; |
||
522 | |||
523 | |||
8097 | maxcodehac | 524 | PROCEDURE OpenArray (t, t2: PROG._TYPE); |
7597 | akron1 | 525 | VAR |
7983 | leency | 526 | n, d1, d2: INTEGER; |
527 | |||
7597 | akron1 | 528 | BEGIN |
529 | IF t.length # 0 THEN |
||
7693 | akron1 | 530 | IL.Param1; |
7597 | akron1 | 531 | n := PROG.Dim(t2) - 1; |
532 | WHILE n >= 0 DO |
||
7693 | akron1 | 533 | IL.Const(ArrLen(t, n)); |
534 | IL.Param1; |
||
7597 | akron1 | 535 | DEC(n) |
536 | END |
||
537 | ELSE |
||
538 | d1 := PROG.Dim(t); |
||
539 | d2 := PROG.Dim(t2); |
||
540 | IF d1 # d2 THEN |
||
541 | n := d2 - d1; |
||
542 | WHILE d2 > d1 DO |
||
7693 | akron1 | 543 | IL.Const(ArrLen(t, d2 - 1)); |
7597 | akron1 | 544 | DEC(d2) |
545 | END; |
||
546 | d2 := PROG.Dim(t2); |
||
547 | WHILE n > 0 DO |
||
7693 | akron1 | 548 | IL.AddCmd(IL.opROT, d2); |
7597 | akron1 | 549 | DEC(n) |
550 | END |
||
551 | END; |
||
7693 | akron1 | 552 | IL.AddCmd(IL.opPARAM, PROG.Dim(t2) + 1) |
7597 | akron1 | 553 | END |
554 | END OpenArray; |
||
555 | |||
556 | |||
557 | BEGIN |
||
558 | IF p.vPar THEN |
||
559 | |||
7693 | akron1 | 560 | PARS.check(isVar(e), pos, 93); |
8097 | maxcodehac | 561 | IF p._type.typ = PROG.tRECORD THEN |
562 | PARS.check(PROG.isBaseOf(p._type, e._type), pos, 66); |
||
7597 | akron1 | 563 | IF e.obj = eVREC THEN |
564 | IF e.ident # NIL THEN |
||
7693 | akron1 | 565 | IL.AddCmd(IL.opVADR, e.ident.offset - 1) |
7597 | akron1 | 566 | ELSE |
7693 | akron1 | 567 | IL.AddCmd0(IL.opPUSHT) |
7597 | akron1 | 568 | END |
569 | ELSE |
||
8097 | maxcodehac | 570 | IL.Const(e._type.num) |
7597 | akron1 | 571 | END; |
7693 | akron1 | 572 | IL.AddCmd(IL.opPARAM, 2) |
8097 | maxcodehac | 573 | ELSIF PROG.isOpenArray(p._type) THEN |
7693 | akron1 | 574 | PARS.check(arrcomp(e, p), pos, 66); |
8097 | maxcodehac | 575 | OpenArray(e._type, p._type) |
7597 | akron1 | 576 | ELSE |
8097 | maxcodehac | 577 | PARS.check(PROG.isTypeEq(e._type, p._type), pos, 66); |
7693 | akron1 | 578 | IL.Param1 |
7597 | akron1 | 579 | END; |
7693 | akron1 | 580 | PARS.check(~e.readOnly, pos, 94) |
7597 | akron1 | 581 | |
582 | ELSE |
||
7693 | akron1 | 583 | PARS.check(isExpr(e) OR isProc(e), pos, 66); |
8097 | maxcodehac | 584 | IF PROG.isOpenArray(p._type) THEN |
585 | IF e._type.typ = PROG.tARRAY THEN |
||
7693 | akron1 | 586 | PARS.check(arrcomp(e, p), pos, 66); |
8097 | maxcodehac | 587 | OpenArray(e._type, p._type) |
588 | ELSIF isString(e) & (p._type.typ = PROG.tARRAY) & (p._type.base = tCHAR) THEN |
||
7693 | akron1 | 589 | IL.StrAdr(String(e)); |
590 | IL.Param1; |
||
591 | IL.Const(strlen(e) + 1); |
||
592 | IL.Param1 |
||
8097 | maxcodehac | 593 | ELSIF isStringW(e) & (p._type.typ = PROG.tARRAY) & (p._type.base = tWCHAR) THEN |
7693 | akron1 | 594 | IL.StrAdr(StringW(e)); |
595 | IL.Param1; |
||
596 | IL.Const(utf8strlen(e) + 1); |
||
597 | IL.Param1 |
||
7597 | akron1 | 598 | ELSE |
7693 | akron1 | 599 | PARS.error(pos, 66) |
7597 | akron1 | 600 | END |
601 | ELSE |
||
8097 | maxcodehac | 602 | PARS.check(~PROG.isOpenArray(e._type), pos, 66); |
603 | PARS.check(assigncomp(e, p._type), pos, 66); |
||
7597 | akron1 | 604 | IF e.obj = eCONST THEN |
8097 | maxcodehac | 605 | IF e._type = tREAL THEN |
606 | Float(parser, e); |
||
607 | IL.AddCmd0(IL.opPUSHF) |
||
608 | ELSIF e._type.typ = PROG.tNIL THEN |
||
7693 | akron1 | 609 | IL.Const(0); |
610 | IL.Param1 |
||
8097 | maxcodehac | 611 | ELSIF isStringW1(e) & (p._type = tWCHAR) THEN |
8859 | leency | 612 | IL.Const(StrToWChar(e.value.string(SCAN.STRING).s)); |
7693 | akron1 | 613 | IL.Param1 |
8097 | maxcodehac | 614 | ELSIF (e._type.typ = PROG.tSTRING) OR |
615 | (e._type.typ IN {PROG.tCHAR, PROG.tWCHAR}) & (p._type.typ = PROG.tARRAY) & (p._type.base.typ IN {PROG.tCHAR, PROG.tWCHAR}) THEN |
||
616 | IF p._type.base = tCHAR THEN |
||
7693 | akron1 | 617 | stroffs := String(e); |
618 | IL.StrAdr(stroffs); |
||
8097 | maxcodehac | 619 | IF (CPU = TARGETS.cpuMSP430) & (p._type.size - strlen(e) - 1 > MSP430.IntVectorSize) THEN |
7693 | akron1 | 620 | ERRORS.WarningMsg(pos.line, pos.col, 0) |
621 | END |
||
7597 | akron1 | 622 | ELSE (* WCHAR *) |
7693 | akron1 | 623 | stroffs := StringW(e); |
624 | IL.StrAdr(stroffs) |
||
7597 | akron1 | 625 | END; |
8097 | maxcodehac | 626 | IL.set_dmin(stroffs + p._type.size); |
7693 | akron1 | 627 | IL.Param1 |
7597 | akron1 | 628 | ELSE |
629 | LoadConst(e); |
||
7693 | akron1 | 630 | IL.Param1 |
7597 | akron1 | 631 | END |
632 | ELSIF e.obj = ePROC THEN |
||
7693 | akron1 | 633 | PARS.check(e.ident.global, pos, 85); |
634 | IL.PushProc(e.ident.proc.label); |
||
635 | IL.Param1 |
||
7597 | akron1 | 636 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 637 | IL.PushImpProc(e.ident._import); |
7693 | akron1 | 638 | IL.Param1 |
8097 | maxcodehac | 639 | ELSIF isExpr(e) & (e._type = tREAL) THEN |
640 | IL.AddCmd0(IL.opPUSHF) |
||
7597 | akron1 | 641 | ELSE |
8097 | maxcodehac | 642 | IF (p._type = tBYTE) & (e._type = tINTEGER) & (chkBYTE IN Options.checking) THEN |
7597 | akron1 | 643 | CheckRange(256, pos.line, errBYTE) |
644 | END; |
||
7693 | akron1 | 645 | IL.Param1 |
7597 | akron1 | 646 | END |
647 | END |
||
648 | |||
649 | END |
||
650 | END paramcomp; |
||
651 | |||
652 | |||
7693 | akron1 | 653 | PROCEDURE PExpression (parser: PARS.PARSER; VAR e: PARS.EXPR); |
654 | BEGIN |
||
655 | parser.expression(parser, e) |
||
656 | END PExpression; |
||
657 | |||
658 | |||
7597 | akron1 | 659 | PROCEDURE stProc (parser: PARS.PARSER; VAR e: PARS.EXPR); |
660 | VAR |
||
7983 | leency | 661 | e1, e2: PARS.EXPR; |
662 | pos: PARS.POSITION; |
||
663 | proc, |
||
664 | label, |
||
8097 | maxcodehac | 665 | size, |
7983 | leency | 666 | n, i: INTEGER; |
667 | code: ARITH.VALUE; |
||
668 | wchar, |
||
669 | comma: BOOLEAN; |
||
7597 | akron1 | 670 | cmd1, |
7983 | leency | 671 | cmd2: IL.COMMAND; |
7597 | akron1 | 672 | |
673 | |||
7693 | akron1 | 674 | PROCEDURE varparam (parser: PARS.PARSER; pos: PARS.POSITION; isfunc: isXXX; readOnly: BOOLEAN; VAR e: PARS.EXPR); |
7597 | akron1 | 675 | BEGIN |
676 | parser.designator(parser, e); |
||
7693 | akron1 | 677 | PARS.check(isVar(e), pos, 93); |
678 | PARS.check(isfunc(e), pos, 66); |
||
7597 | akron1 | 679 | IF readOnly THEN |
7693 | akron1 | 680 | PARS.check(~e.readOnly, pos, 94) |
7597 | akron1 | 681 | END |
682 | END varparam; |
||
683 | |||
684 | |||
685 | PROCEDURE shift_minmax (proc: INTEGER): CHAR; |
||
686 | VAR |
||
687 | res: CHAR; |
||
7983 | leency | 688 | |
7597 | akron1 | 689 | BEGIN |
690 | CASE proc OF |
||
691 | |PROG.stASR: res := "A" |
||
692 | |PROG.stLSL: res := "L" |
||
693 | |PROG.stROR: res := "O" |
||
694 | |PROG.stLSR: res := "R" |
||
695 | |PROG.stMIN: res := "m" |
||
696 | |PROG.stMAX: res := "x" |
||
697 | END |
||
698 | RETURN res |
||
699 | END shift_minmax; |
||
700 | |||
701 | |||
702 | BEGIN |
||
703 | ASSERT(e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC}); |
||
7693 | akron1 | 704 | proc := e.stproc; |
7597 | akron1 | 705 | |
7693 | akron1 | 706 | (* IF (proc # PROG.sysNOP) & (proc # PROG.sysEINT) & (proc # PROG.sysDINT) THEN *) |
707 | PARS.checklex(parser, SCAN.lxLROUND); |
||
708 | PARS.Next(parser); |
||
709 | (* END; *) |
||
710 | |||
7597 | akron1 | 711 | getpos(parser, pos); |
712 | |||
713 | IF e.obj IN {eSTPROC, eSYSPROC} THEN |
||
714 | |||
715 | CASE proc OF |
||
716 | |PROG.stASSERT: |
||
7693 | akron1 | 717 | PExpression(parser, e); |
718 | PARS.check(isBoolean(e), pos, 66); |
||
7597 | akron1 | 719 | IF e.obj = eCONST THEN |
720 | IF ~ARITH.getBool(e.value) THEN |
||
7693 | akron1 | 721 | IL.OnError(pos.line, errASSERT) |
7597 | akron1 | 722 | END |
723 | ELSE |
||
7693 | akron1 | 724 | label := IL.NewLabel(); |
8097 | maxcodehac | 725 | IL.not; |
726 | IL.AndOrOpt(label); |
||
7693 | akron1 | 727 | IL.OnError(pos.line, errASSERT); |
728 | IL.SetLabel(label) |
||
7597 | akron1 | 729 | END |
730 | |||
731 | |PROG.stINC, PROG.stDEC: |
||
7693 | akron1 | 732 | IL.pushBegEnd(begcall, endcall); |
7597 | akron1 | 733 | varparam(parser, pos, isInt, TRUE, e); |
8097 | maxcodehac | 734 | IF e._type = tINTEGER THEN |
7597 | akron1 | 735 | IF parser.sym = SCAN.lxCOMMA THEN |
736 | NextPos(parser, pos); |
||
7693 | akron1 | 737 | IL.setlast(begcall); |
738 | PExpression(parser, e2); |
||
739 | IL.setlast(endcall.prev(IL.COMMAND)); |
||
740 | PARS.check(isInt(e2), pos, 66); |
||
7597 | akron1 | 741 | IF e2.obj = eCONST THEN |
7693 | akron1 | 742 | IL.AddCmd(IL.opINCC, ARITH.Int(e2.value) * (ORD(proc = PROG.stINC) * 2 - 1)) |
7597 | akron1 | 743 | ELSE |
7693 | akron1 | 744 | IL.AddCmd0(IL.opINC + ORD(proc = PROG.stDEC)) |
7597 | akron1 | 745 | END |
746 | ELSE |
||
7693 | akron1 | 747 | IL.AddCmd(IL.opINCC, ORD(proc = PROG.stINC) * 2 - 1) |
7597 | akron1 | 748 | END |
8097 | maxcodehac | 749 | ELSE (* e._type = tBYTE *) |
7597 | akron1 | 750 | IF parser.sym = SCAN.lxCOMMA THEN |
751 | NextPos(parser, pos); |
||
7693 | akron1 | 752 | IL.setlast(begcall); |
753 | PExpression(parser, e2); |
||
754 | IL.setlast(endcall.prev(IL.COMMAND)); |
||
755 | PARS.check(isInt(e2), pos, 66); |
||
7597 | akron1 | 756 | IF e2.obj = eCONST THEN |
7693 | akron1 | 757 | IL.AddCmd(IL.opINCCB + ORD(proc = PROG.stDEC), ARITH.Int(e2.value)) |
7597 | akron1 | 758 | ELSE |
7693 | akron1 | 759 | IL.AddCmd0(IL.opINCB + ORD(proc = PROG.stDEC)) |
7597 | akron1 | 760 | END |
761 | ELSE |
||
7693 | akron1 | 762 | IL.AddCmd(IL.opINCCB + ORD(proc = PROG.stDEC), 1) |
7597 | akron1 | 763 | END |
764 | END; |
||
7693 | akron1 | 765 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 766 | |
767 | |PROG.stINCL, PROG.stEXCL: |
||
7693 | akron1 | 768 | IL.pushBegEnd(begcall, endcall); |
7597 | akron1 | 769 | varparam(parser, pos, isSet, TRUE, e); |
770 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
771 | NextPos(parser, pos); |
||
7693 | akron1 | 772 | IL.setlast(begcall); |
773 | PExpression(parser, e2); |
||
774 | IL.setlast(endcall.prev(IL.COMMAND)); |
||
775 | PARS.check(isInt(e2), pos, 66); |
||
7597 | akron1 | 776 | IF e2.obj = eCONST THEN |
7693 | akron1 | 777 | PARS.check(ARITH.range(e2.value, 0, UTILS.target.maxSet), pos, 56); |
778 | IL.AddCmd(IL.opINCLC + ORD(proc = PROG.stEXCL), ARITH.Int(e2.value)) |
||
7597 | akron1 | 779 | ELSE |
7693 | akron1 | 780 | IL.AddCmd0(IL.opINCL + ORD(proc = PROG.stEXCL)) |
7597 | akron1 | 781 | END; |
7693 | akron1 | 782 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 783 | |
784 | |PROG.stNEW: |
||
785 | varparam(parser, pos, isPtr, TRUE, e); |
||
7983 | leency | 786 | IF CPU = TARGETS.cpuMSP430 THEN |
8097 | maxcodehac | 787 | PARS.check(e._type.base.size + 16 < Options.ram, pos, 63) |
7693 | akron1 | 788 | END; |
8097 | maxcodehac | 789 | IL.New(e._type.base.size, e._type.base.num) |
7597 | akron1 | 790 | |
791 | |PROG.stDISPOSE: |
||
792 | varparam(parser, pos, isPtr, TRUE, e); |
||
7693 | akron1 | 793 | IL.AddCmd0(IL.opDISP) |
7597 | akron1 | 794 | |
795 | |PROG.stPACK: |
||
796 | varparam(parser, pos, isReal, TRUE, e); |
||
797 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
798 | NextPos(parser, pos); |
||
7693 | akron1 | 799 | PExpression(parser, e2); |
800 | PARS.check(isInt(e2), pos, 66); |
||
7597 | akron1 | 801 | IF e2.obj = eCONST THEN |
7693 | akron1 | 802 | IL.AddCmd(IL.opPACKC, ARITH.Int(e2.value)) |
7597 | akron1 | 803 | ELSE |
7693 | akron1 | 804 | IL.AddCmd0(IL.opPACK) |
7597 | akron1 | 805 | END |
806 | |||
807 | |PROG.stUNPK: |
||
808 | varparam(parser, pos, isReal, TRUE, e); |
||
809 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
810 | NextPos(parser, pos); |
||
811 | varparam(parser, pos, isInteger, TRUE, e2); |
||
7693 | akron1 | 812 | IL.AddCmd0(IL.opUNPK) |
7597 | akron1 | 813 | |
814 | |PROG.stCOPY: |
||
7693 | akron1 | 815 | IL.pushBegEnd(begcall, endcall); |
816 | PExpression(parser, e); |
||
7597 | akron1 | 817 | IF isString(e) OR isCharArray(e) THEN |
818 | wchar := FALSE |
||
819 | ELSIF isStringW(e) OR isCharArrayW(e) THEN |
||
820 | wchar := TRUE |
||
821 | ELSE |
||
7693 | akron1 | 822 | PARS.error(pos, 66) |
7597 | akron1 | 823 | END; |
824 | |||
8097 | maxcodehac | 825 | IF isCharArrayX(e) & ~PROG.isOpenArray(e._type) THEN |
826 | IL.Const(e._type.length) |
||
7597 | akron1 | 827 | END; |
828 | |||
829 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
830 | NextPos(parser, pos); |
||
7693 | akron1 | 831 | IL.setlast(begcall); |
7597 | akron1 | 832 | |
833 | IF wchar THEN |
||
834 | varparam(parser, pos, isCharArrayW, TRUE, e1) |
||
835 | ELSE |
||
836 | IF e.obj = eCONST THEN |
||
837 | varparam(parser, pos, isCharArrayX, TRUE, e1) |
||
838 | ELSE |
||
839 | varparam(parser, pos, isCharArray, TRUE, e1) |
||
840 | END; |
||
841 | |||
8097 | maxcodehac | 842 | wchar := e1._type.base = tWCHAR |
7597 | akron1 | 843 | END; |
844 | |||
8097 | maxcodehac | 845 | IF ~PROG.isOpenArray(e1._type) THEN |
846 | IL.Const(e1._type.length) |
||
7597 | akron1 | 847 | END; |
848 | |||
7693 | akron1 | 849 | IL.setlast(endcall.prev(IL.COMMAND)); |
850 | |||
7597 | akron1 | 851 | IF e.obj = eCONST THEN |
852 | IF wchar THEN |
||
7693 | akron1 | 853 | IL.StrAdr(StringW(e)); |
854 | IL.Const(utf8strlen(e) + 1) |
||
7597 | akron1 | 855 | ELSE |
7693 | akron1 | 856 | IL.StrAdr(String(e)); |
857 | IL.Const(strlen(e) + 1) |
||
858 | END |
||
859 | END; |
||
8097 | maxcodehac | 860 | IL.AddCmd(IL.opCOPYS, e1._type.base.size); |
7693 | akron1 | 861 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 862 | |
8097 | maxcodehac | 863 | |PROG.sysGET, PROG.sysGET8, PROG.sysGET16, PROG.sysGET32: |
7693 | akron1 | 864 | PExpression(parser, e); |
865 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 866 | PARS.checklex(parser, SCAN.lxCOMMA); |
867 | NextPos(parser, pos); |
||
868 | parser.designator(parser, e2); |
||
7693 | akron1 | 869 | PARS.check(isVar(e2), pos, 93); |
8097 | maxcodehac | 870 | IF proc = PROG.sysGET THEN |
871 | PARS.check(e2._type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66) |
||
872 | ELSE |
||
873 | PARS.check(e2._type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66) |
||
874 | END; |
||
875 | |||
876 | CASE proc OF |
||
877 | |PROG.sysGET: size := e2._type.size |
||
878 | |PROG.sysGET8: size := 1 |
||
879 | |PROG.sysGET16: size := 2 |
||
880 | |PROG.sysGET32: size := 4 |
||
881 | END; |
||
882 | |||
883 | PARS.check(size <= e2._type.size, pos, 66); |
||
884 | |||
7693 | akron1 | 885 | IF e.obj = eCONST THEN |
8097 | maxcodehac | 886 | IL.AddCmd2(IL.opGETC, ARITH.Int(e.value), size) |
7693 | akron1 | 887 | ELSE |
8097 | maxcodehac | 888 | IL.AddCmd(IL.opGET, size) |
7693 | akron1 | 889 | END |
7597 | akron1 | 890 | |
891 | |PROG.sysPUT, PROG.sysPUT8, PROG.sysPUT16, PROG.sysPUT32: |
||
7693 | akron1 | 892 | IL.pushBegEnd(begcall, endcall); |
893 | PExpression(parser, e); |
||
894 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 895 | IF e.obj = eCONST THEN |
896 | LoadConst(e) |
||
897 | END; |
||
898 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
899 | NextPos(parser, pos); |
||
7693 | akron1 | 900 | IL.setlast(begcall); |
901 | PExpression(parser, e2); |
||
902 | PARS.check(isExpr(e2), pos, 66); |
||
7597 | akron1 | 903 | |
904 | IF proc = PROG.sysPUT THEN |
||
8097 | maxcodehac | 905 | PARS.check(e2._type.typ IN PROG.BASICTYPES + {PROG.tPOINTER, PROG.tPROCEDURE}, pos, 66); |
7597 | akron1 | 906 | IF e2.obj = eCONST THEN |
8097 | maxcodehac | 907 | IF e2._type = tREAL THEN |
908 | Float(parser, e2); |
||
7693 | akron1 | 909 | IL.setlast(endcall.prev(IL.COMMAND)); |
7983 | leency | 910 | IL.savef(FALSE) |
7597 | akron1 | 911 | ELSE |
912 | LoadConst(e2); |
||
7693 | akron1 | 913 | IL.setlast(endcall.prev(IL.COMMAND)); |
8097 | maxcodehac | 914 | IL.SysPut(e2._type.size) |
7597 | akron1 | 915 | END |
916 | ELSE |
||
7693 | akron1 | 917 | IL.setlast(endcall.prev(IL.COMMAND)); |
8097 | maxcodehac | 918 | IF e2._type = tREAL THEN |
7983 | leency | 919 | IL.savef(FALSE) |
8097 | maxcodehac | 920 | ELSIF e2._type = tBYTE THEN |
7693 | akron1 | 921 | IL.SysPut(tINTEGER.size) |
7597 | akron1 | 922 | ELSE |
8097 | maxcodehac | 923 | IL.SysPut(e2._type.size) |
7597 | akron1 | 924 | END |
925 | END |
||
926 | |||
927 | ELSIF (proc = PROG.sysPUT8) OR (proc = PROG.sysPUT16) OR (proc = PROG.sysPUT32) THEN |
||
8097 | maxcodehac | 928 | PARS.check(e2._type.typ IN {PROG.tINTEGER, PROG.tBYTE, PROG.tCHAR, PROG.tSET, PROG.tWCHAR, PROG.tCARD32}, pos, 66); |
7597 | akron1 | 929 | IF e2.obj = eCONST THEN |
930 | LoadConst(e2) |
||
931 | END; |
||
7693 | akron1 | 932 | IL.setlast(endcall.prev(IL.COMMAND)); |
933 | CASE proc OF |
||
8097 | maxcodehac | 934 | |PROG.sysPUT8: size := 1 |
935 | |PROG.sysPUT16: size := 2 |
||
936 | |PROG.sysPUT32: size := 4 |
||
937 | END; |
||
938 | IL.SysPut(size) |
||
7597 | akron1 | 939 | |
940 | END; |
||
7693 | akron1 | 941 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 942 | |
943 | |PROG.sysMOVE: |
||
944 | FOR i := 1 TO 2 DO |
||
7693 | akron1 | 945 | PExpression(parser, e); |
946 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 947 | IF e.obj = eCONST THEN |
948 | LoadConst(e) |
||
949 | END; |
||
950 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
951 | NextPos(parser, pos) |
||
952 | END; |
||
953 | |||
7693 | akron1 | 954 | PExpression(parser, e); |
955 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 956 | IF e.obj = eCONST THEN |
957 | LoadConst(e) |
||
958 | END; |
||
7693 | akron1 | 959 | IL.AddCmd0(IL.opMOVE) |
7597 | akron1 | 960 | |
961 | |PROG.sysCOPY: |
||
962 | FOR i := 1 TO 2 DO |
||
963 | parser.designator(parser, e); |
||
7693 | akron1 | 964 | PARS.check(isVar(e), pos, 93); |
8097 | maxcodehac | 965 | n := PROG.Dim(e._type); |
7597 | akron1 | 966 | WHILE n > 0 DO |
7693 | akron1 | 967 | IL.drop; |
7597 | akron1 | 968 | DEC(n) |
969 | END; |
||
970 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
971 | NextPos(parser, pos) |
||
972 | END; |
||
973 | |||
7693 | akron1 | 974 | PExpression(parser, e); |
975 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 976 | IF e.obj = eCONST THEN |
977 | LoadConst(e) |
||
978 | END; |
||
7693 | akron1 | 979 | IL.AddCmd0(IL.opMOVE) |
7597 | akron1 | 980 | |
981 | |PROG.sysCODE: |
||
982 | REPEAT |
||
983 | getpos(parser, pos); |
||
984 | PARS.ConstExpression(parser, code); |
||
7693 | akron1 | 985 | PARS.check(code.typ = ARITH.tINTEGER, pos, 43); |
8097 | maxcodehac | 986 | IF TARGETS.WordSize > TARGETS.InstrSize THEN |
987 | CASE TARGETS.InstrSize OF |
||
988 | |1: PARS.check(ARITH.range(code, 0, 255), pos, 42) |
||
989 | |2: PARS.check(ARITH.range(code, 0, 65535), pos, 110) |
||
990 | END |
||
7693 | akron1 | 991 | END; |
992 | IL.AddCmd(IL.opCODE, ARITH.getInt(code)); |
||
993 | comma := parser.sym = SCAN.lxCOMMA; |
||
994 | IF comma THEN |
||
7597 | akron1 | 995 | PARS.Next(parser) |
996 | ELSE |
||
997 | PARS.checklex(parser, SCAN.lxRROUND) |
||
7693 | akron1 | 998 | END |
999 | UNTIL (parser.sym = SCAN.lxRROUND) & ~comma |
||
1000 | (* |
||
1001 | |PROG.sysNOP, PROG.sysDINT, PROG.sysEINT: |
||
1002 | IF parser.sym = SCAN.lxLROUND THEN |
||
1003 | PARS.Next(parser); |
||
1004 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1005 | PARS.Next(parser) |
||
1006 | END; |
||
1007 | ASSERT(CPU = cpuMSP430); |
||
1008 | CASE proc OF |
||
1009 | |PROG.sysNOP: IL.AddCmd(IL.opCODE, 4303H) |
||
1010 | |PROG.sysDINT: IL.AddCmd(IL.opCODE, 0C232H); IL.AddCmd(IL.opCODE, 4303H) |
||
1011 | |PROG.sysEINT: IL.AddCmd(IL.opCODE, 0D232H) |
||
1012 | END |
||
1013 | *) |
||
7597 | akron1 | 1014 | END; |
1015 | |||
1016 | e.obj := eEXPR; |
||
8097 | maxcodehac | 1017 | e._type := NIL |
7597 | akron1 | 1018 | |
1019 | ELSIF e.obj IN {eSTFUNC, eSYSFUNC} THEN |
||
1020 | |||
1021 | CASE e.stproc OF |
||
1022 | |PROG.stABS: |
||
7693 | akron1 | 1023 | PExpression(parser, e); |
1024 | PARS.check(isInt(e) OR isReal(e), pos, 66); |
||
7597 | akron1 | 1025 | IF e.obj = eCONST THEN |
7693 | akron1 | 1026 | PARS.check(ARITH.abs(e.value), pos, 39) |
7597 | akron1 | 1027 | ELSE |
7693 | akron1 | 1028 | IL.abs(isReal(e)) |
7597 | akron1 | 1029 | END |
1030 | |||
1031 | |PROG.stASR, PROG.stLSL, PROG.stROR, PROG.stLSR, PROG.stMIN, PROG.stMAX: |
||
7693 | akron1 | 1032 | PExpression(parser, e); |
1033 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 1034 | PARS.checklex(parser, SCAN.lxCOMMA); |
1035 | NextPos(parser, pos); |
||
7693 | akron1 | 1036 | PExpression(parser, e2); |
1037 | PARS.check(isInt(e2), pos, 66); |
||
8097 | maxcodehac | 1038 | e._type := tINTEGER; |
7597 | akron1 | 1039 | IF (e.obj = eCONST) & (e2.obj = eCONST) THEN |
1040 | ASSERT(ARITH.opInt(e.value, e2.value, shift_minmax(proc))) |
||
1041 | ELSE |
||
1042 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 1043 | IL.shift_minmax1(shift_minmax(proc), ARITH.Int(e.value)) |
7597 | akron1 | 1044 | ELSIF e2.obj = eCONST THEN |
7693 | akron1 | 1045 | IL.shift_minmax2(shift_minmax(proc), ARITH.Int(e2.value)) |
7597 | akron1 | 1046 | ELSE |
7693 | akron1 | 1047 | IL.shift_minmax(shift_minmax(proc)) |
7597 | akron1 | 1048 | END; |
1049 | e.obj := eEXPR |
||
1050 | END |
||
1051 | |||
1052 | |PROG.stCHR: |
||
7693 | akron1 | 1053 | PExpression(parser, e); |
1054 | PARS.check(isInt(e), pos, 66); |
||
8097 | maxcodehac | 1055 | e._type := tCHAR; |
7597 | akron1 | 1056 | IF e.obj = eCONST THEN |
1057 | ARITH.setChar(e.value, ARITH.getInt(e.value)); |
||
7693 | akron1 | 1058 | PARS.check(ARITH.check(e.value), pos, 107) |
7597 | akron1 | 1059 | ELSE |
7693 | akron1 | 1060 | IF chkCHR IN Options.checking THEN |
7597 | akron1 | 1061 | CheckRange(256, pos.line, errCHR) |
1062 | ELSE |
||
7693 | akron1 | 1063 | IL.AddCmd0(IL.opCHR) |
7597 | akron1 | 1064 | END |
1065 | END |
||
1066 | |||
1067 | |PROG.stWCHR: |
||
7693 | akron1 | 1068 | PExpression(parser, e); |
1069 | PARS.check(isInt(e), pos, 66); |
||
8097 | maxcodehac | 1070 | e._type := tWCHAR; |
7597 | akron1 | 1071 | IF e.obj = eCONST THEN |
1072 | ARITH.setWChar(e.value, ARITH.getInt(e.value)); |
||
7693 | akron1 | 1073 | PARS.check(ARITH.check(e.value), pos, 101) |
7597 | akron1 | 1074 | ELSE |
7693 | akron1 | 1075 | IF chkWCHR IN Options.checking THEN |
7597 | akron1 | 1076 | CheckRange(65536, pos.line, errWCHR) |
1077 | ELSE |
||
7693 | akron1 | 1078 | IL.AddCmd0(IL.opWCHR) |
7597 | akron1 | 1079 | END |
1080 | END |
||
1081 | |||
1082 | |PROG.stFLOOR: |
||
7693 | akron1 | 1083 | PExpression(parser, e); |
1084 | PARS.check(isReal(e), pos, 66); |
||
8097 | maxcodehac | 1085 | e._type := tINTEGER; |
7597 | akron1 | 1086 | IF e.obj = eCONST THEN |
7693 | akron1 | 1087 | PARS.check(ARITH.floor(e.value), pos, 39) |
7597 | akron1 | 1088 | ELSE |
8097 | maxcodehac | 1089 | IL.AddCmd0(IL.opFLOOR) |
7597 | akron1 | 1090 | END |
1091 | |||
1092 | |PROG.stFLT: |
||
7693 | akron1 | 1093 | PExpression(parser, e); |
1094 | PARS.check(isInt(e), pos, 66); |
||
8097 | maxcodehac | 1095 | e._type := tREAL; |
7597 | akron1 | 1096 | IF e.obj = eCONST THEN |
1097 | ARITH.flt(e.value) |
||
1098 | ELSE |
||
8097 | maxcodehac | 1099 | IL.AddCmd2(IL.opFLT, pos.line, pos.col) |
7597 | akron1 | 1100 | END |
1101 | |||
1102 | |PROG.stLEN: |
||
7693 | akron1 | 1103 | cmd1 := IL.getlast(); |
7597 | akron1 | 1104 | varparam(parser, pos, isArr, FALSE, e); |
8097 | maxcodehac | 1105 | IF e._type.length > 0 THEN |
7693 | akron1 | 1106 | cmd2 := IL.getlast(); |
1107 | IL.delete2(cmd1.next, cmd2); |
||
1108 | IL.setlast(cmd1); |
||
8097 | maxcodehac | 1109 | ASSERT(ARITH.setInt(e.value, e._type.length)); |
7597 | akron1 | 1110 | e.obj := eCONST |
1111 | ELSE |
||
8097 | maxcodehac | 1112 | IL.len(PROG.Dim(e._type)) |
7597 | akron1 | 1113 | END; |
8097 | maxcodehac | 1114 | e._type := tINTEGER |
7597 | akron1 | 1115 | |
1116 | |PROG.stLENGTH: |
||
7693 | akron1 | 1117 | PExpression(parser, e); |
7597 | akron1 | 1118 | IF isCharArray(e) THEN |
8097 | maxcodehac | 1119 | IF e._type.length > 0 THEN |
1120 | IL.Const(e._type.length) |
||
7597 | akron1 | 1121 | END; |
7693 | akron1 | 1122 | IL.AddCmd0(IL.opLENGTH) |
7597 | akron1 | 1123 | ELSIF isCharArrayW(e) THEN |
8097 | maxcodehac | 1124 | IF e._type.length > 0 THEN |
1125 | IL.Const(e._type.length) |
||
7597 | akron1 | 1126 | END; |
7693 | akron1 | 1127 | IL.AddCmd0(IL.opLENGTHW) |
7597 | akron1 | 1128 | ELSE |
7693 | akron1 | 1129 | PARS.error(pos, 66); |
7597 | akron1 | 1130 | END; |
8097 | maxcodehac | 1131 | e._type := tINTEGER |
7597 | akron1 | 1132 | |
1133 | |PROG.stODD: |
||
7693 | akron1 | 1134 | PExpression(parser, e); |
1135 | PARS.check(isInt(e), pos, 66); |
||
8097 | maxcodehac | 1136 | e._type := tBOOLEAN; |
7597 | akron1 | 1137 | IF e.obj = eCONST THEN |
1138 | ARITH.odd(e.value) |
||
1139 | ELSE |
||
7983 | leency | 1140 | IL.AddCmd(IL.opMODR, 2) |
7597 | akron1 | 1141 | END |
1142 | |||
1143 | |PROG.stORD: |
||
8859 | leency | 1144 | IL.AddCmd(IL.opPRECALL, 0); |
7693 | akron1 | 1145 | PExpression(parser, e); |
1146 | PARS.check(isChar(e) OR isBoolean(e) OR isSet(e) OR isCharW(e) OR isStringW1(e), pos, 66); |
||
7597 | akron1 | 1147 | IF e.obj = eCONST THEN |
1148 | IF isStringW1(e) THEN |
||
8859 | leency | 1149 | ASSERT(ARITH.setInt(e.value, StrToWChar(e.value.string(SCAN.STRING).s))) |
7597 | akron1 | 1150 | ELSE |
1151 | ARITH.ord(e.value) |
||
1152 | END |
||
1153 | ELSE |
||
1154 | IF isBoolean(e) THEN |
||
8097 | maxcodehac | 1155 | IL._ord |
7597 | akron1 | 1156 | END |
1157 | END; |
||
8097 | maxcodehac | 1158 | e._type := tINTEGER |
7597 | akron1 | 1159 | |
1160 | |PROG.stBITS: |
||
7693 | akron1 | 1161 | PExpression(parser, e); |
1162 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 1163 | IF e.obj = eCONST THEN |
1164 | ARITH.bits(e.value) |
||
1165 | END; |
||
8097 | maxcodehac | 1166 | e._type := tSET |
7597 | akron1 | 1167 | |
1168 | |PROG.sysADR: |
||
1169 | parser.designator(parser, e); |
||
1170 | IF isVar(e) THEN |
||
8097 | maxcodehac | 1171 | n := PROG.Dim(e._type); |
1172 | WHILE n > 0 DO |
||
7693 | akron1 | 1173 | IL.drop; |
7597 | akron1 | 1174 | DEC(n) |
8097 | maxcodehac | 1175 | END |
7597 | akron1 | 1176 | ELSIF e.obj = ePROC THEN |
7693 | akron1 | 1177 | IL.PushProc(e.ident.proc.label) |
7597 | akron1 | 1178 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 1179 | IL.PushImpProc(e.ident._import) |
7597 | akron1 | 1180 | ELSE |
7693 | akron1 | 1181 | PARS.error(pos, 108) |
7597 | akron1 | 1182 | END; |
8097 | maxcodehac | 1183 | e._type := tINTEGER |
7597 | akron1 | 1184 | |
1185 | |PROG.sysSADR: |
||
7693 | akron1 | 1186 | PExpression(parser, e); |
1187 | PARS.check(isString(e), pos, 66); |
||
1188 | IL.StrAdr(String(e)); |
||
8097 | maxcodehac | 1189 | e._type := tINTEGER; |
7597 | akron1 | 1190 | e.obj := eEXPR |
1191 | |||
1192 | |PROG.sysWSADR: |
||
7693 | akron1 | 1193 | PExpression(parser, e); |
1194 | PARS.check(isStringW(e), pos, 66); |
||
1195 | IL.StrAdr(StringW(e)); |
||
8097 | maxcodehac | 1196 | e._type := tINTEGER; |
7597 | akron1 | 1197 | e.obj := eEXPR |
1198 | |||
1199 | |PROG.sysTYPEID: |
||
7693 | akron1 | 1200 | PExpression(parser, e); |
1201 | PARS.check(e.obj = eTYPE, pos, 68); |
||
8097 | maxcodehac | 1202 | IF e._type.typ = PROG.tRECORD THEN |
1203 | ASSERT(ARITH.setInt(e.value, e._type.num)) |
||
1204 | ELSIF e._type.typ = PROG.tPOINTER THEN |
||
1205 | ASSERT(ARITH.setInt(e.value, e._type.base.num)) |
||
7597 | akron1 | 1206 | ELSE |
7693 | akron1 | 1207 | PARS.error(pos, 52) |
7597 | akron1 | 1208 | END; |
1209 | e.obj := eCONST; |
||
8097 | maxcodehac | 1210 | e._type := tINTEGER |
7597 | akron1 | 1211 | |
1212 | |PROG.sysINF: |
||
8097 | maxcodehac | 1213 | IL.AddCmd2(IL.opINF, pos.line, pos.col); |
7597 | akron1 | 1214 | e.obj := eEXPR; |
8097 | maxcodehac | 1215 | e._type := tREAL |
7597 | akron1 | 1216 | |
1217 | |PROG.sysSIZE: |
||
7693 | akron1 | 1218 | PExpression(parser, e); |
1219 | PARS.check(e.obj = eTYPE, pos, 68); |
||
8097 | maxcodehac | 1220 | ASSERT(ARITH.setInt(e.value, e._type.size)); |
7597 | akron1 | 1221 | e.obj := eCONST; |
8097 | maxcodehac | 1222 | e._type := tINTEGER |
7597 | akron1 | 1223 | |
1224 | END |
||
1225 | |||
1226 | END; |
||
1227 | |||
7693 | akron1 | 1228 | (* IF (proc # PROG.sysNOP) & (proc # PROG.sysEINT) & (proc # PROG.sysDINT) THEN *) |
1229 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1230 | PARS.Next(parser); |
||
1231 | (* END; *) |
||
7597 | akron1 | 1232 | |
1233 | IF e.obj # eCONST THEN |
||
1234 | e.obj := eEXPR |
||
1235 | END |
||
1236 | |||
1237 | END stProc; |
||
1238 | |||
1239 | |||
1240 | PROCEDURE ActualParameters (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1241 | VAR |
||
8097 | maxcodehac | 1242 | proc: PROG._TYPE; |
7597 | akron1 | 1243 | param: LISTS.ITEM; |
1244 | e1: PARS.EXPR; |
||
7693 | akron1 | 1245 | pos: PARS.POSITION; |
7597 | akron1 | 1246 | |
1247 | BEGIN |
||
1248 | ASSERT(parser.sym = SCAN.lxLROUND); |
||
1249 | |||
1250 | IF (e.obj IN {ePROC, eIMP}) OR isExpr(e) THEN |
||
8097 | maxcodehac | 1251 | proc := e._type; |
7597 | akron1 | 1252 | PARS.check1(proc.typ = PROG.tPROCEDURE, parser, 86); |
1253 | PARS.Next(parser); |
||
1254 | |||
1255 | param := proc.params.first; |
||
1256 | WHILE param # NIL DO |
||
1257 | getpos(parser, pos); |
||
1258 | |||
7693 | akron1 | 1259 | IL.setlast(begcall); |
7597 | akron1 | 1260 | |
1261 | IF param(PROG.PARAM).vPar THEN |
||
1262 | parser.designator(parser, e1) |
||
1263 | ELSE |
||
7693 | akron1 | 1264 | PExpression(parser, e1) |
7597 | akron1 | 1265 | END; |
1266 | paramcomp(parser, pos, e1, param(PROG.PARAM)); |
||
1267 | param := param.next; |
||
1268 | IF param # NIL THEN |
||
1269 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
1270 | PARS.Next(parser) |
||
1271 | END |
||
1272 | END; |
||
1273 | |||
1274 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1275 | PARS.Next(parser); |
||
1276 | |||
1277 | e.obj := eEXPR; |
||
8097 | maxcodehac | 1278 | e._type := proc.base |
7597 | akron1 | 1279 | |
1280 | ELSIF e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC} THEN |
||
1281 | stProc(parser, e) |
||
1282 | ELSE |
||
1283 | PARS.check1(FALSE, parser, 86) |
||
1284 | END |
||
1285 | |||
1286 | END ActualParameters; |
||
1287 | |||
1288 | |||
1289 | PROCEDURE qualident (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1290 | VAR |
||
8097 | maxcodehac | 1291 | ident: PROG.IDENT; |
1292 | imp: BOOLEAN; |
||
1293 | pos: PARS.POSITION; |
||
7597 | akron1 | 1294 | |
1295 | BEGIN |
||
1296 | PARS.checklex(parser, SCAN.lxIDENT); |
||
1297 | getpos(parser, pos); |
||
8097 | maxcodehac | 1298 | imp := FALSE; |
7693 | akron1 | 1299 | ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE); |
7597 | akron1 | 1300 | PARS.check1(ident # NIL, parser, 48); |
1301 | IF ident.typ = PROG.idMODULE THEN |
||
1302 | PARS.ExpectSym(parser, SCAN.lxPOINT); |
||
1303 | PARS.ExpectSym(parser, SCAN.lxIDENT); |
||
7693 | akron1 | 1304 | ident := PROG.getIdent(ident.unit, parser.lex.ident, FALSE); |
7597 | akron1 | 1305 | PARS.check1((ident # NIL) & ident.export, parser, 48); |
8097 | maxcodehac | 1306 | imp := TRUE |
7597 | akron1 | 1307 | END; |
1308 | PARS.Next(parser); |
||
1309 | |||
1310 | e.readOnly := FALSE; |
||
1311 | e.ident := ident; |
||
1312 | |||
1313 | CASE ident.typ OF |
||
1314 | |PROG.idCONST: |
||
1315 | e.obj := eCONST; |
||
8097 | maxcodehac | 1316 | e._type := ident._type; |
7597 | akron1 | 1317 | e.value := ident.value |
1318 | |PROG.idTYPE: |
||
8097 | maxcodehac | 1319 | e.obj := eTYPE; |
1320 | e._type := ident._type |
||
7597 | akron1 | 1321 | |PROG.idVAR: |
8097 | maxcodehac | 1322 | e.obj := eVAR; |
1323 | e._type := ident._type; |
||
1324 | e.readOnly := imp |
||
7597 | akron1 | 1325 | |PROG.idPROC: |
1326 | e.obj := ePROC; |
||
8097 | maxcodehac | 1327 | e._type := ident._type |
7597 | akron1 | 1328 | |PROG.idIMP: |
1329 | e.obj := eIMP; |
||
8097 | maxcodehac | 1330 | e._type := ident._type |
7597 | akron1 | 1331 | |PROG.idVPAR: |
8097 | maxcodehac | 1332 | e._type := ident._type; |
1333 | IF e._type.typ = PROG.tRECORD THEN |
||
7597 | akron1 | 1334 | e.obj := eVREC |
1335 | ELSE |
||
1336 | e.obj := eVPAR |
||
1337 | END |
||
1338 | |PROG.idPARAM: |
||
8097 | maxcodehac | 1339 | e.obj := ePARAM; |
1340 | e._type := ident._type; |
||
1341 | e.readOnly := (e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) |
||
7597 | akron1 | 1342 | |PROG.idSTPROC: |
1343 | e.obj := eSTPROC; |
||
8097 | maxcodehac | 1344 | e._type := ident._type; |
7597 | akron1 | 1345 | e.stproc := ident.stproc |
1346 | |PROG.idSTFUNC: |
||
1347 | e.obj := eSTFUNC; |
||
8097 | maxcodehac | 1348 | e._type := ident._type; |
7597 | akron1 | 1349 | e.stproc := ident.stproc |
1350 | |PROG.idSYSPROC: |
||
1351 | e.obj := eSYSPROC; |
||
8097 | maxcodehac | 1352 | e._type := ident._type; |
7597 | akron1 | 1353 | e.stproc := ident.stproc |
1354 | |PROG.idSYSFUNC: |
||
7693 | akron1 | 1355 | PARS.check(~parser.constexp, pos, 109); |
7597 | akron1 | 1356 | e.obj := eSYSFUNC; |
8097 | maxcodehac | 1357 | e._type := ident._type; |
7597 | akron1 | 1358 | e.stproc := ident.stproc |
1359 | |PROG.idNONE: |
||
7693 | akron1 | 1360 | PARS.error(pos, 115) |
7597 | akron1 | 1361 | END; |
1362 | |||
1363 | IF isVar(e) THEN |
||
7693 | akron1 | 1364 | PARS.check(e.ident.global OR (e.ident.scopeLvl = parser.unit.scopeLvl), pos, 105) |
7597 | akron1 | 1365 | END |
1366 | |||
1367 | END qualident; |
||
1368 | |||
1369 | |||
7693 | akron1 | 1370 | PROCEDURE deref (pos: PARS.POSITION; e: PARS.EXPR; load: BOOLEAN; error: INTEGER); |
7597 | akron1 | 1371 | VAR |
7983 | leency | 1372 | label: INTEGER; |
7597 | akron1 | 1373 | |
1374 | BEGIN |
||
1375 | IF load THEN |
||
8097 | maxcodehac | 1376 | IL.load(e._type.size) |
7597 | akron1 | 1377 | END; |
1378 | |||
7693 | akron1 | 1379 | IF chkPTR IN Options.checking THEN |
1380 | label := IL.NewLabel(); |
||
8859 | leency | 1381 | IL.Jmp(IL.opJNZ1, label); |
7693 | akron1 | 1382 | IL.OnError(pos.line, error); |
1383 | IL.SetLabel(label) |
||
7597 | akron1 | 1384 | END |
1385 | END deref; |
||
1386 | |||
1387 | |||
1388 | PROCEDURE designator (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1389 | VAR |
||
1390 | field: PROG.FIELD; |
||
7693 | akron1 | 1391 | pos: PARS.POSITION; |
7597 | akron1 | 1392 | t, idx: PARS.EXPR; |
1393 | |||
1394 | |||
1395 | PROCEDURE LoadAdr (e: PARS.EXPR); |
||
1396 | VAR |
||
1397 | offset: INTEGER; |
||
1398 | |||
1399 | PROCEDURE OpenArray (e: PARS.EXPR); |
||
1400 | VAR |
||
1401 | offset, n: INTEGER; |
||
1402 | BEGIN |
||
1403 | offset := e.ident.offset; |
||
8097 | maxcodehac | 1404 | n := PROG.Dim(e._type); |
7597 | akron1 | 1405 | WHILE n >= 0 DO |
7693 | akron1 | 1406 | IL.AddCmd(IL.opVADR, offset); |
7597 | akron1 | 1407 | DEC(offset); |
1408 | DEC(n) |
||
1409 | END |
||
1410 | END OpenArray; |
||
1411 | |||
1412 | |||
1413 | BEGIN |
||
1414 | IF e.obj = eVAR THEN |
||
8097 | maxcodehac | 1415 | offset := PROG.getOffset(e.ident); |
7597 | akron1 | 1416 | IF e.ident.global THEN |
7693 | akron1 | 1417 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 1418 | ELSE |
7693 | akron1 | 1419 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 1420 | END |
1421 | ELSIF e.obj = ePARAM THEN |
||
8097 | maxcodehac | 1422 | IF (e._type.typ = PROG.tRECORD) OR ((e._type.typ = PROG.tARRAY) & (e._type.length > 0)) THEN |
7693 | akron1 | 1423 | IL.AddCmd(IL.opVADR, e.ident.offset) |
8097 | maxcodehac | 1424 | ELSIF PROG.isOpenArray(e._type) THEN |
7597 | akron1 | 1425 | OpenArray(e) |
1426 | ELSE |
||
7693 | akron1 | 1427 | IL.AddCmd(IL.opLADR, e.ident.offset) |
7597 | akron1 | 1428 | END |
1429 | ELSIF e.obj IN {eVPAR, eVREC} THEN |
||
8097 | maxcodehac | 1430 | IF PROG.isOpenArray(e._type) THEN |
7597 | akron1 | 1431 | OpenArray(e) |
1432 | ELSE |
||
7693 | akron1 | 1433 | IL.AddCmd(IL.opVADR, e.ident.offset) |
7597 | akron1 | 1434 | END |
1435 | END |
||
1436 | END LoadAdr; |
||
1437 | |||
1438 | |||
7693 | akron1 | 1439 | PROCEDURE OpenIdx (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR); |
7597 | akron1 | 1440 | VAR |
7983 | leency | 1441 | label, offset, n, k: INTEGER; |
8097 | maxcodehac | 1442 | _type: PROG._TYPE; |
7597 | akron1 | 1443 | |
1444 | BEGIN |
||
1445 | |||
7693 | akron1 | 1446 | IF chkIDX IN Options.checking THEN |
1447 | label := IL.NewLabel(); |
||
1448 | IL.AddCmd2(IL.opCHKIDX2, label, 0); |
||
1449 | IL.OnError(pos.line, errIDX); |
||
1450 | IL.SetLabel(label) |
||
7597 | akron1 | 1451 | ELSE |
7693 | akron1 | 1452 | IL.AddCmd(IL.opCHKIDX2, -1) |
7597 | akron1 | 1453 | END; |
1454 | |||
8097 | maxcodehac | 1455 | _type := PROG.OpenBase(e._type); |
1456 | IF _type.size # 1 THEN |
||
1457 | IL.AddCmd(IL.opMULC, _type.size) |
||
7597 | akron1 | 1458 | END; |
8097 | maxcodehac | 1459 | n := PROG.Dim(e._type) - 1; |
7597 | akron1 | 1460 | k := n; |
1461 | WHILE n > 0 DO |
||
7693 | akron1 | 1462 | IL.AddCmd0(IL.opMUL); |
7597 | akron1 | 1463 | DEC(n) |
1464 | END; |
||
7693 | akron1 | 1465 | IL.AddCmd0(IL.opADD); |
7597 | akron1 | 1466 | offset := e.ident.offset - 1; |
1467 | n := k; |
||
1468 | WHILE n > 0 DO |
||
7693 | akron1 | 1469 | IL.AddCmd(IL.opVADR, offset); |
7597 | akron1 | 1470 | DEC(offset); |
1471 | DEC(n) |
||
1472 | END |
||
1473 | END OpenIdx; |
||
1474 | |||
1475 | |||
1476 | BEGIN |
||
1477 | qualident(parser, e); |
||
1478 | |||
1479 | IF e.obj IN {ePROC, eIMP} THEN |
||
1480 | PROG.UseProc(parser.unit, e.ident.proc) |
||
1481 | END; |
||
1482 | |||
1483 | IF isVar(e) THEN |
||
1484 | LoadAdr(e) |
||
1485 | END; |
||
1486 | |||
1487 | WHILE parser.sym = SCAN.lxPOINT DO |
||
1488 | getpos(parser, pos); |
||
8097 | maxcodehac | 1489 | PARS.check1(isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}), parser, 73); |
1490 | IF e._type.typ = PROG.tPOINTER THEN |
||
7597 | akron1 | 1491 | deref(pos, e, TRUE, errPTR) |
1492 | END; |
||
1493 | PARS.ExpectSym(parser, SCAN.lxIDENT); |
||
8097 | maxcodehac | 1494 | IF e._type.typ = PROG.tPOINTER THEN |
1495 | e._type := e._type.base; |
||
7597 | akron1 | 1496 | e.readOnly := FALSE |
1497 | END; |
||
8097 | maxcodehac | 1498 | field := PROG.getField(e._type, parser.lex.ident, parser.unit); |
7597 | akron1 | 1499 | PARS.check1(field # NIL, parser, 74); |
8097 | maxcodehac | 1500 | e._type := field._type; |
7597 | akron1 | 1501 | IF e.obj = eVREC THEN |
1502 | e.obj := eVPAR |
||
1503 | END; |
||
1504 | IF field.offset # 0 THEN |
||
8097 | maxcodehac | 1505 | IL.AddCmd(IL.opADDC, field.offset) |
7597 | akron1 | 1506 | END; |
1507 | PARS.Next(parser); |
||
1508 | e.ident := NIL |
||
1509 | |||
1510 | ELSIF parser.sym = SCAN.lxLSQUARE DO |
||
1511 | |||
1512 | REPEAT |
||
1513 | |||
1514 | PARS.check1(isArr(e), parser, 75); |
||
1515 | NextPos(parser, pos); |
||
7693 | akron1 | 1516 | PExpression(parser, idx); |
1517 | PARS.check(isInt(idx), pos, 76); |
||
7597 | akron1 | 1518 | |
1519 | IF idx.obj = eCONST THEN |
||
8097 | maxcodehac | 1520 | IF e._type.length > 0 THEN |
1521 | PARS.check(ARITH.range(idx.value, 0, e._type.length - 1), pos, 83); |
||
7597 | akron1 | 1522 | IF ARITH.Int(idx.value) > 0 THEN |
8097 | maxcodehac | 1523 | IL.AddCmd(IL.opADDC, ARITH.Int(idx.value) * e._type.base.size) |
7597 | akron1 | 1524 | END |
1525 | ELSE |
||
7693 | akron1 | 1526 | PARS.check(ARITH.range(idx.value, 0, UTILS.target.maxInt), pos, 83); |
7597 | akron1 | 1527 | LoadConst(idx); |
1528 | OpenIdx(parser, pos, e) |
||
1529 | END |
||
1530 | ELSE |
||
8097 | maxcodehac | 1531 | IF e._type.length > 0 THEN |
7693 | akron1 | 1532 | IF chkIDX IN Options.checking THEN |
8097 | maxcodehac | 1533 | CheckRange(e._type.length, pos.line, errIDX) |
7597 | akron1 | 1534 | END; |
8097 | maxcodehac | 1535 | IF e._type.base.size # 1 THEN |
1536 | IL.AddCmd(IL.opMULC, e._type.base.size) |
||
7597 | akron1 | 1537 | END; |
7693 | akron1 | 1538 | IL.AddCmd0(IL.opADD) |
7597 | akron1 | 1539 | ELSE |
1540 | OpenIdx(parser, pos, e) |
||
1541 | END |
||
1542 | END; |
||
1543 | |||
8097 | maxcodehac | 1544 | e._type := e._type.base |
7597 | akron1 | 1545 | |
1546 | UNTIL parser.sym # SCAN.lxCOMMA; |
||
1547 | |||
1548 | PARS.checklex(parser, SCAN.lxRSQUARE); |
||
1549 | PARS.Next(parser); |
||
8859 | leency | 1550 | IF ~(isArr(e) & (e._type.length = 0) & (parser.sym = SCAN.lxLSQUARE)) THEN |
1551 | e.ident := NIL |
||
1552 | END |
||
7597 | akron1 | 1553 | |
1554 | ELSIF parser.sym = SCAN.lxCARET DO |
||
1555 | getpos(parser, pos); |
||
1556 | PARS.check1(isPtr(e), parser, 77); |
||
1557 | deref(pos, e, TRUE, errPTR); |
||
8097 | maxcodehac | 1558 | e._type := e._type.base; |
7597 | akron1 | 1559 | e.readOnly := FALSE; |
1560 | PARS.Next(parser); |
||
1561 | e.ident := NIL; |
||
1562 | e.obj := eVREC |
||
1563 | |||
8097 | maxcodehac | 1564 | ELSIF (parser.sym = SCAN.lxLROUND) & isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}) DO |
7597 | akron1 | 1565 | |
8097 | maxcodehac | 1566 | IF e._type.typ = PROG.tRECORD THEN |
7597 | akron1 | 1567 | PARS.check1(e.obj = eVREC, parser, 78) |
1568 | END; |
||
1569 | NextPos(parser, pos); |
||
1570 | qualident(parser, t); |
||
7693 | akron1 | 1571 | PARS.check(t.obj = eTYPE, pos, 79); |
7597 | akron1 | 1572 | |
8097 | maxcodehac | 1573 | IF e._type.typ = PROG.tRECORD THEN |
1574 | PARS.check(t._type.typ = PROG.tRECORD, pos, 80); |
||
7693 | akron1 | 1575 | IF chkGUARD IN Options.checking THEN |
7597 | akron1 | 1576 | IF e.ident = NIL THEN |
8097 | maxcodehac | 1577 | IL.TypeGuard(IL.opTYPEGD, t._type.num, pos.line, errGUARD) |
7597 | akron1 | 1578 | ELSE |
7693 | akron1 | 1579 | IL.AddCmd(IL.opVADR, e.ident.offset - 1); |
8097 | maxcodehac | 1580 | IL.TypeGuard(IL.opTYPEGR, t._type.num, pos.line, errGUARD) |
7597 | akron1 | 1581 | END |
1582 | END; |
||
1583 | ELSE |
||
8097 | maxcodehac | 1584 | PARS.check(t._type.typ = PROG.tPOINTER, pos, 81); |
7693 | akron1 | 1585 | IF chkGUARD IN Options.checking THEN |
8097 | maxcodehac | 1586 | IL.TypeGuard(IL.opTYPEGP, t._type.base.num, pos.line, errGUARD) |
7597 | akron1 | 1587 | END |
1588 | END; |
||
1589 | |||
8097 | maxcodehac | 1590 | PARS.check(PROG.isBaseOf(e._type, t._type), pos, 82); |
7597 | akron1 | 1591 | |
8097 | maxcodehac | 1592 | e._type := t._type; |
7597 | akron1 | 1593 | |
1594 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1595 | PARS.Next(parser) |
||
1596 | |||
1597 | END |
||
1598 | |||
1599 | END designator; |
||
1600 | |||
1601 | |||
8097 | maxcodehac | 1602 | PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG._TYPE; isfloat: BOOLEAN; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); |
7597 | akron1 | 1603 | VAR |
7983 | leency | 1604 | cconv, |
1605 | parSize, |
||
1606 | callconv, |
||
1607 | fparSize, |
||
1608 | int, flt, |
||
1609 | stk_par: INTEGER; |
||
7597 | akron1 | 1610 | |
1611 | BEGIN |
||
1612 | cconv := procType.call; |
||
7693 | akron1 | 1613 | parSize := procType.parSize; |
7597 | akron1 | 1614 | |
1615 | IF cconv IN {PROG._win64, PROG.win64} THEN |
||
7693 | akron1 | 1616 | callconv := IL.call_win64; |
1617 | fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, 3, int, flt)), 5) + MIN(parSize, 4) |
||
7597 | akron1 | 1618 | ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN |
7693 | akron1 | 1619 | callconv := IL.call_sysv; |
1620 | fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, PROG.MAXSYSVPARAM - 1, int, flt)), 5) + parSize; |
||
7597 | akron1 | 1621 | stk_par := MAX(0, int - 6) + MAX(0, flt - 8) |
1622 | ELSE |
||
7693 | akron1 | 1623 | callconv := IL.call_stack; |
1624 | fparSize := 0 |
||
7597 | akron1 | 1625 | END; |
7693 | akron1 | 1626 | IL.setlast(begcall); |
8097 | maxcodehac | 1627 | IL.AddCmd(IL.opPRECALL, ORD(isfloat)); |
7597 | akron1 | 1628 | |
8859 | leency | 1629 | IF cconv IN {PROG._ccall, PROG.ccall} THEN |
7693 | akron1 | 1630 | IL.AddCmd(IL.opALIGN16, parSize) |
7597 | akron1 | 1631 | ELSIF cconv IN {PROG._win64, PROG.win64} THEN |
7693 | akron1 | 1632 | IL.AddCmd(IL.opWIN64ALIGN16, parSize) |
7597 | akron1 | 1633 | ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN |
7693 | akron1 | 1634 | IL.AddCmd(IL.opSYSVALIGN16, parSize + stk_par) |
7597 | akron1 | 1635 | END; |
7693 | akron1 | 1636 | IL.setlast(endcall.prev(IL.COMMAND)); |
7597 | akron1 | 1637 | |
1638 | IF e.obj = eIMP THEN |
||
8097 | maxcodehac | 1639 | IL.CallImp(e.ident._import, callconv, fparSize) |
7597 | akron1 | 1640 | ELSIF e.obj = ePROC THEN |
7693 | akron1 | 1641 | IL.Call(e.ident.proc.label, callconv, fparSize) |
7597 | akron1 | 1642 | ELSIF isExpr(e) THEN |
1643 | deref(pos, e, CallStat, errPROC); |
||
7693 | akron1 | 1644 | IL.CallP(callconv, fparSize) |
7597 | akron1 | 1645 | END; |
1646 | |||
8859 | leency | 1647 | IF cconv IN {PROG._ccall, PROG.ccall} THEN |
7693 | akron1 | 1648 | IL.AddCmd(IL.opCLEANUP, parSize); |
1649 | IL.AddCmd0(IL.opPOPSP) |
||
7597 | akron1 | 1650 | ELSIF cconv IN {PROG._win64, PROG.win64} THEN |
7693 | akron1 | 1651 | IL.AddCmd(IL.opCLEANUP, MAX(parSize + parSize MOD 2, 4) + 1); |
1652 | IL.AddCmd0(IL.opPOPSP) |
||
7597 | akron1 | 1653 | ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN |
7693 | akron1 | 1654 | IL.AddCmd(IL.opCLEANUP, parSize + stk_par); |
1655 | IL.AddCmd0(IL.opPOPSP) |
||
8859 | leency | 1656 | ELSIF cconv IN {PROG._cdecl, PROG.cdecl, PROG.default16, PROG.code, PROG._code} THEN |
7693 | akron1 | 1657 | IL.AddCmd(IL.opCLEANUP, parSize) |
7597 | akron1 | 1658 | END; |
1659 | |||
8097 | maxcodehac | 1660 | IF CallStat THEN |
1661 | IL.AddCmd0(IL.opRES); |
||
1662 | IL.drop |
||
1663 | ELSE |
||
7597 | akron1 | 1664 | IF isfloat THEN |
8097 | maxcodehac | 1665 | IL.AddCmd2(IL.opRESF, pos.line, pos.col) |
7597 | akron1 | 1666 | ELSE |
8097 | maxcodehac | 1667 | IL.AddCmd0(IL.opRES) |
7597 | akron1 | 1668 | END |
1669 | END |
||
1670 | END ProcCall; |
||
1671 | |||
1672 | |||
1673 | PROCEDURE expression (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1674 | VAR |
||
7693 | akron1 | 1675 | pos, pos0, pos1: PARS.POSITION; |
8097 | maxcodehac | 1676 | e1: PARS.EXPR; |
1677 | op, cmp, error: INTEGER; |
||
1678 | constant, eq: BOOLEAN; |
||
7597 | akron1 | 1679 | |
1680 | |||
1681 | PROCEDURE relation (sym: INTEGER): BOOLEAN; |
||
1682 | RETURN (sym = SCAN.lxEQ) OR (sym = SCAN.lxNE) OR |
||
1683 | (sym = SCAN.lxLT) OR (sym = SCAN.lxLE) OR |
||
1684 | (sym = SCAN.lxGT) OR (sym = SCAN.lxGE) OR |
||
1685 | (sym = SCAN.lxIN) OR (sym = SCAN.lxIS) |
||
1686 | END relation; |
||
1687 | |||
1688 | |||
1689 | PROCEDURE AddOperator (sym: INTEGER): BOOLEAN; |
||
1690 | RETURN (sym = SCAN.lxPLUS) OR (sym = SCAN.lxMINUS) OR |
||
1691 | (sym = SCAN.lxOR) |
||
1692 | END AddOperator; |
||
1693 | |||
1694 | |||
1695 | PROCEDURE MulOperator (sym: INTEGER): BOOLEAN; |
||
1696 | RETURN (sym = SCAN.lxMUL) OR (sym = SCAN.lxSLASH) OR |
||
1697 | (sym = SCAN.lxDIV) OR (sym = SCAN.lxMOD) OR |
||
1698 | (sym = SCAN.lxAND) |
||
1699 | END MulOperator; |
||
1700 | |||
1701 | |||
1702 | PROCEDURE element (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1703 | VAR |
||
1704 | e1, e2: PARS.EXPR; |
||
7693 | akron1 | 1705 | pos: PARS.POSITION; |
7597 | akron1 | 1706 | range: BOOLEAN; |
1707 | |||
1708 | BEGIN |
||
1709 | range := FALSE; |
||
1710 | getpos(parser, pos); |
||
1711 | expression(parser, e1); |
||
7693 | akron1 | 1712 | PARS.check(isInt(e1), pos, 76); |
7597 | akron1 | 1713 | |
1714 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 1715 | PARS.check(ARITH.range(e1.value, 0, UTILS.target.maxSet), pos, 44) |
7597 | akron1 | 1716 | END; |
1717 | |||
1718 | range := parser.sym = SCAN.lxRANGE; |
||
1719 | |||
1720 | IF range THEN |
||
1721 | NextPos(parser, pos); |
||
1722 | expression(parser, e2); |
||
7693 | akron1 | 1723 | PARS.check(isInt(e2), pos, 76); |
7597 | akron1 | 1724 | |
1725 | IF e2.obj = eCONST THEN |
||
7693 | akron1 | 1726 | PARS.check(ARITH.range(e2.value, 0, UTILS.target.maxSet), pos, 44) |
7597 | akron1 | 1727 | END |
1728 | ELSE |
||
1729 | IF e1.obj = eCONST THEN |
||
1730 | e2 := e1 |
||
1731 | END |
||
1732 | END; |
||
1733 | |||
8097 | maxcodehac | 1734 | e._type := tSET; |
7597 | akron1 | 1735 | |
1736 | IF (e1.obj = eCONST) & (e2.obj = eCONST) THEN |
||
1737 | ARITH.constrSet(e.value, e1.value, e2.value); |
||
1738 | e.obj := eCONST |
||
1739 | ELSE |
||
1740 | IF range THEN |
||
1741 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 1742 | IL.AddCmd(IL.opRSETL, ARITH.Int(e1.value)) |
7597 | akron1 | 1743 | ELSIF e2.obj = eCONST THEN |
7693 | akron1 | 1744 | IL.AddCmd(IL.opRSETR, ARITH.Int(e2.value)) |
7597 | akron1 | 1745 | ELSE |
7693 | akron1 | 1746 | IL.AddCmd0(IL.opRSET) |
7597 | akron1 | 1747 | END |
1748 | ELSE |
||
7693 | akron1 | 1749 | IL.AddCmd0(IL.opRSET1) |
7597 | akron1 | 1750 | END; |
1751 | e.obj := eEXPR |
||
1752 | END |
||
1753 | |||
1754 | END element; |
||
1755 | |||
1756 | |||
1757 | PROCEDURE set (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1758 | VAR |
||
1759 | e1: PARS.EXPR; |
||
1760 | |||
1761 | BEGIN |
||
1762 | ASSERT(parser.sym = SCAN.lxLCURLY); |
||
1763 | |||
1764 | e.obj := eCONST; |
||
8097 | maxcodehac | 1765 | e._type := tSET; |
7597 | akron1 | 1766 | ARITH.emptySet(e.value); |
1767 | |||
1768 | PARS.Next(parser); |
||
1769 | IF parser.sym # SCAN.lxRCURLY THEN |
||
1770 | element(parser, e1); |
||
1771 | |||
1772 | IF e1.obj = eCONST THEN |
||
1773 | ARITH.opSet(e.value, e1.value, "+") |
||
1774 | ELSE |
||
1775 | e.obj := eEXPR |
||
1776 | END; |
||
1777 | |||
1778 | WHILE parser.sym = SCAN.lxCOMMA DO |
||
1779 | PARS.Next(parser); |
||
1780 | element(parser, e1); |
||
1781 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
||
1782 | ARITH.opSet(e.value, e1.value, "+") |
||
1783 | ELSE |
||
1784 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 1785 | IL.AddCmd(IL.opADDSC, ARITH.Int(e.value)) |
7597 | akron1 | 1786 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 1787 | IL.AddCmd(IL.opADDSC, ARITH.Int(e1.value)) |
7597 | akron1 | 1788 | ELSE |
7693 | akron1 | 1789 | IL.AddCmd0(IL.opADDS) |
7597 | akron1 | 1790 | END; |
1791 | e.obj := eEXPR |
||
1792 | END |
||
1793 | END; |
||
1794 | PARS.checklex(parser, SCAN.lxRCURLY) |
||
1795 | END; |
||
1796 | PARS.Next(parser); |
||
1797 | END set; |
||
1798 | |||
1799 | |||
1800 | PROCEDURE factor (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1801 | VAR |
||
1802 | sym: INTEGER; |
||
7693 | akron1 | 1803 | pos: PARS.POSITION; |
7597 | akron1 | 1804 | e1: PARS.EXPR; |
1805 | isfloat: BOOLEAN; |
||
1806 | |||
1807 | |||
7693 | akron1 | 1808 | PROCEDURE LoadVar (e: PARS.EXPR; parser: PARS.PARSER; pos: PARS.POSITION); |
7597 | akron1 | 1809 | BEGIN |
8097 | maxcodehac | 1810 | IF ~(e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) THEN |
1811 | IF e._type = tREAL THEN |
||
1812 | IL.AddCmd2(IL.opLOADF, pos.line, pos.col) |
||
7597 | akron1 | 1813 | ELSE |
8097 | maxcodehac | 1814 | IL.load(e._type.size) |
7597 | akron1 | 1815 | END |
1816 | END |
||
1817 | END LoadVar; |
||
1818 | |||
1819 | |||
1820 | BEGIN |
||
1821 | sym := parser.sym; |
||
1822 | |||
1823 | IF (sym = SCAN.lxINTEGER) OR (sym = SCAN.lxHEX) OR (sym = SCAN.lxFLOAT) OR (sym = SCAN.lxCHAR) OR (sym = SCAN.lxSTRING) THEN |
||
1824 | e.obj := eCONST; |
||
1825 | e.value := parser.lex.value; |
||
8097 | maxcodehac | 1826 | e._type := PROG.getType(e.value.typ); |
7597 | akron1 | 1827 | PARS.Next(parser) |
1828 | |||
1829 | ELSIF sym = SCAN.lxNIL THEN |
||
7693 | akron1 | 1830 | e.obj := eCONST; |
8097 | maxcodehac | 1831 | e._type := PROG.program.stTypes.tNIL; |
7597 | akron1 | 1832 | PARS.Next(parser) |
1833 | |||
1834 | ELSIF (sym = SCAN.lxTRUE) OR (sym = SCAN.lxFALSE) THEN |
||
7693 | akron1 | 1835 | e.obj := eCONST; |
7597 | akron1 | 1836 | ARITH.setbool(e.value, sym = SCAN.lxTRUE); |
8097 | maxcodehac | 1837 | e._type := tBOOLEAN; |
7597 | akron1 | 1838 | PARS.Next(parser) |
1839 | |||
1840 | ELSIF sym = SCAN.lxLCURLY THEN |
||
1841 | set(parser, e) |
||
1842 | |||
1843 | ELSIF sym = SCAN.lxIDENT THEN |
||
1844 | getpos(parser, pos); |
||
1845 | |||
7693 | akron1 | 1846 | IL.pushBegEnd(begcall, endcall); |
7597 | akron1 | 1847 | |
1848 | designator(parser, e); |
||
1849 | IF isVar(e) THEN |
||
1850 | LoadVar(e, parser, pos) |
||
1851 | END; |
||
1852 | IF parser.sym = SCAN.lxLROUND THEN |
||
1853 | e1 := e; |
||
1854 | ActualParameters(parser, e); |
||
8097 | maxcodehac | 1855 | PARS.check(e._type # NIL, pos, 59); |
1856 | isfloat := e._type = tREAL; |
||
7597 | akron1 | 1857 | IF e1.obj IN {ePROC, eIMP} THEN |
8097 | maxcodehac | 1858 | ProcCall(e1, e1.ident._type, isfloat, parser, pos, FALSE) |
7597 | akron1 | 1859 | ELSIF isExpr(e1) THEN |
8097 | maxcodehac | 1860 | ProcCall(e1, e1._type, isfloat, parser, pos, FALSE) |
7597 | akron1 | 1861 | END |
1862 | END; |
||
7693 | akron1 | 1863 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 1864 | |
1865 | ELSIF sym = SCAN.lxLROUND THEN |
||
1866 | PARS.Next(parser); |
||
1867 | expression(parser, e); |
||
1868 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1869 | PARS.Next(parser); |
||
1870 | IF isExpr(e) & (e.obj # eCONST) THEN |
||
1871 | e.obj := eEXPR |
||
1872 | END |
||
1873 | |||
1874 | ELSIF sym = SCAN.lxNOT THEN |
||
1875 | NextPos(parser, pos); |
||
1876 | factor(parser, e); |
||
7693 | akron1 | 1877 | PARS.check(isBoolean(e), pos, 72); |
7597 | akron1 | 1878 | IF e.obj # eCONST THEN |
7693 | akron1 | 1879 | IL.not; |
7597 | akron1 | 1880 | e.obj := eEXPR |
1881 | ELSE |
||
1882 | ASSERT(ARITH.neg(e.value)) |
||
1883 | END |
||
1884 | |||
1885 | ELSE |
||
1886 | PARS.check1(FALSE, parser, 34) |
||
1887 | END |
||
1888 | END factor; |
||
1889 | |||
1890 | |||
1891 | PROCEDURE term (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1892 | VAR |
||
7693 | akron1 | 1893 | pos: PARS.POSITION; |
7597 | akron1 | 1894 | e1: PARS.EXPR; |
7983 | leency | 1895 | op, label, label1: INTEGER; |
7597 | akron1 | 1896 | |
1897 | BEGIN |
||
1898 | factor(parser, e); |
||
1899 | label := -1; |
||
1900 | |||
1901 | WHILE MulOperator(parser.sym) DO |
||
1902 | op := parser.sym; |
||
1903 | getpos(parser, pos); |
||
1904 | PARS.Next(parser); |
||
1905 | |||
1906 | IF op = SCAN.lxAND THEN |
||
1907 | IF ~parser.constexp THEN |
||
1908 | |||
1909 | IF label = -1 THEN |
||
7693 | akron1 | 1910 | label := IL.NewLabel() |
7597 | akron1 | 1911 | END; |
1912 | |||
8859 | leency | 1913 | IF (e.obj = eCONST) & isBoolean(e) THEN |
7693 | akron1 | 1914 | IL.Const(ORD(ARITH.getBool(e.value))) |
1915 | END; |
||
8859 | leency | 1916 | IL.Jmp(IL.opJZ, label) |
7597 | akron1 | 1917 | END |
1918 | END; |
||
1919 | |||
1920 | factor(parser, e1); |
||
1921 | |||
1922 | CASE op OF |
||
1923 | |SCAN.lxMUL: |
||
7693 | akron1 | 1924 | PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); |
7597 | akron1 | 1925 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
1926 | |||
1927 | CASE e.value.typ OF |
||
7693 | akron1 | 1928 | |ARITH.tINTEGER: PARS.check(ARITH.opInt(e.value, e1.value, "*"), pos, 39) |
1929 | |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "*"), pos, 40) |
||
7597 | akron1 | 1930 | |ARITH.tSET: ARITH.opSet(e.value, e1.value, "*") |
1931 | END |
||
1932 | |||
1933 | ELSE |
||
1934 | IF isInt(e) THEN |
||
1935 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 1936 | IL.AddCmd(IL.opMULC, ARITH.Int(e.value)) |
7597 | akron1 | 1937 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 1938 | IL.AddCmd(IL.opMULC, ARITH.Int(e1.value)) |
7597 | akron1 | 1939 | ELSE |
7693 | akron1 | 1940 | IL.AddCmd0(IL.opMUL) |
7597 | akron1 | 1941 | END |
1942 | ELSIF isReal(e) THEN |
||
1943 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 1944 | Float(parser, e) |
7597 | akron1 | 1945 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 1946 | Float(parser, e1) |
7597 | akron1 | 1947 | END; |
8097 | maxcodehac | 1948 | IL.AddCmd0(IL.opMULF) |
7597 | akron1 | 1949 | ELSIF isSet(e) THEN |
1950 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 1951 | IL.AddCmd(IL.opMULSC, ARITH.Int(e.value)) |
7597 | akron1 | 1952 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 1953 | IL.AddCmd(IL.opMULSC, ARITH.Int(e1.value)) |
7597 | akron1 | 1954 | ELSE |
7693 | akron1 | 1955 | IL.AddCmd0(IL.opMULS) |
7597 | akron1 | 1956 | END |
1957 | END; |
||
1958 | e.obj := eEXPR |
||
1959 | END |
||
1960 | |||
1961 | |SCAN.lxSLASH: |
||
7693 | akron1 | 1962 | PARS.check(isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); |
7597 | akron1 | 1963 | IF (e1.obj = eCONST) & isReal(e1) THEN |
7693 | akron1 | 1964 | PARS.check(~ARITH.isZero(e1.value), pos, 45) |
7597 | akron1 | 1965 | END; |
1966 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
||
1967 | |||
1968 | CASE e.value.typ OF |
||
7693 | akron1 | 1969 | |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "/"), pos, 40) |
7597 | akron1 | 1970 | |ARITH.tSET: ARITH.opSet(e.value, e1.value, "/") |
1971 | END |
||
1972 | |||
1973 | ELSE |
||
1974 | IF isReal(e) THEN |
||
1975 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 1976 | Float(parser, e); |
1977 | IL.AddCmd0(IL.opDIVFI) |
||
7597 | akron1 | 1978 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 1979 | Float(parser, e1); |
1980 | IL.AddCmd0(IL.opDIVF) |
||
7597 | akron1 | 1981 | ELSE |
8097 | maxcodehac | 1982 | IL.AddCmd0(IL.opDIVF) |
7597 | akron1 | 1983 | END |
1984 | ELSIF isSet(e) THEN |
||
1985 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 1986 | IL.AddCmd(IL.opDIVSC, ARITH.Int(e.value)) |
7597 | akron1 | 1987 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 1988 | IL.AddCmd(IL.opDIVSC, ARITH.Int(e1.value)) |
7597 | akron1 | 1989 | ELSE |
7693 | akron1 | 1990 | IL.AddCmd0(IL.opDIVS) |
7597 | akron1 | 1991 | END |
1992 | END; |
||
1993 | e.obj := eEXPR |
||
1994 | END |
||
1995 | |||
1996 | |SCAN.lxDIV, SCAN.lxMOD: |
||
7693 | akron1 | 1997 | PARS.check(isInt(e) & isInt(e1), pos, 37); |
7597 | akron1 | 1998 | IF e1.obj = eCONST THEN |
7983 | leency | 1999 | PARS.check(ARITH.Int(e1.value) > 0, pos, 122) |
7597 | akron1 | 2000 | END; |
2001 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
||
2002 | |||
2003 | IF op = SCAN.lxDIV THEN |
||
7693 | akron1 | 2004 | PARS.check(ARITH.opInt(e.value, e1.value, "D"), pos, 39) |
7597 | akron1 | 2005 | ELSE |
2006 | ASSERT(ARITH.opInt(e.value, e1.value, "M")) |
||
2007 | END |
||
2008 | |||
2009 | ELSE |
||
2010 | IF e1.obj # eCONST THEN |
||
7693 | akron1 | 2011 | label1 := IL.NewLabel(); |
8859 | leency | 2012 | IL.Jmp(IL.opJG, label1) |
7597 | akron1 | 2013 | END; |
2014 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2015 | IL.OnError(pos.line, errDIV); |
2016 | IL.SetLabel(label1); |
||
2017 | IL.AddCmd(IL.opDIVL + ORD(op = SCAN.lxMOD), ARITH.Int(e.value)) |
||
7597 | akron1 | 2018 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 2019 | IL.AddCmd(IL.opDIVR + ORD(op = SCAN.lxMOD), ARITH.Int(e1.value)) |
7597 | akron1 | 2020 | ELSE |
7693 | akron1 | 2021 | IL.OnError(pos.line, errDIV); |
2022 | IL.SetLabel(label1); |
||
2023 | IL.AddCmd0(IL.opDIV + ORD(op = SCAN.lxMOD)) |
||
7597 | akron1 | 2024 | END; |
2025 | e.obj := eEXPR |
||
2026 | END |
||
2027 | |||
2028 | |SCAN.lxAND: |
||
7693 | akron1 | 2029 | PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); |
7597 | akron1 | 2030 | |
8859 | leency | 2031 | IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN |
7597 | akron1 | 2032 | ARITH.opBoolean(e.value, e1.value, "&") |
2033 | ELSE |
||
2034 | e.obj := eEXPR; |
||
2035 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 2036 | IL.Const(ORD(ARITH.getBool(e1.value))) |
8097 | maxcodehac | 2037 | END |
7597 | akron1 | 2038 | END |
2039 | |||
2040 | END |
||
2041 | END; |
||
2042 | |||
2043 | IF label # -1 THEN |
||
8097 | maxcodehac | 2044 | label1 := IL.NewLabel(); |
8859 | leency | 2045 | IL.Jmp(IL.opJNZ, label1); |
8097 | maxcodehac | 2046 | IL.SetLabel(label); |
2047 | IL.Const(0); |
||
2048 | IL.drop; |
||
2049 | label := IL.NewLabel(); |
||
8859 | leency | 2050 | IL.Jmp(IL.opJMP, label); |
8097 | maxcodehac | 2051 | IL.SetLabel(label1); |
2052 | IL.Const(1); |
||
2053 | IL.SetLabel(label); |
||
2054 | IL.AddCmd0(IL.opAND) |
||
7597 | akron1 | 2055 | END |
2056 | END term; |
||
2057 | |||
2058 | |||
2059 | PROCEDURE SimpleExpression (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
2060 | VAR |
||
7693 | akron1 | 2061 | pos: PARS.POSITION; |
7597 | akron1 | 2062 | op: INTEGER; |
2063 | e1: PARS.EXPR; |
||
8859 | leency | 2064 | s, s1: SCAN.TEXTSTR; |
7597 | akron1 | 2065 | |
2066 | plus, minus: BOOLEAN; |
||
2067 | |||
8097 | maxcodehac | 2068 | label, label1: INTEGER; |
7597 | akron1 | 2069 | |
2070 | BEGIN |
||
2071 | plus := parser.sym = SCAN.lxPLUS; |
||
2072 | minus := parser.sym = SCAN.lxMINUS; |
||
2073 | |||
2074 | IF plus OR minus THEN |
||
2075 | getpos(parser, pos); |
||
2076 | PARS.Next(parser) |
||
2077 | END; |
||
2078 | |||
2079 | term(parser, e); |
||
2080 | |||
2081 | IF plus OR minus THEN |
||
7693 | akron1 | 2082 | PARS.check(isInt(e) OR isReal(e) OR isSet(e), pos, 36); |
7597 | akron1 | 2083 | |
2084 | IF minus & (e.obj = eCONST) THEN |
||
7693 | akron1 | 2085 | PARS.check(ARITH.neg(e.value), pos, 39) |
7597 | akron1 | 2086 | END; |
2087 | |||
2088 | IF e.obj # eCONST THEN |
||
2089 | IF minus THEN |
||
2090 | IF isInt(e) THEN |
||
7693 | akron1 | 2091 | IL.AddCmd0(IL.opUMINUS) |
7597 | akron1 | 2092 | ELSIF isReal(e) THEN |
7693 | akron1 | 2093 | IL.AddCmd0(IL.opUMINF) |
7597 | akron1 | 2094 | ELSIF isSet(e) THEN |
7693 | akron1 | 2095 | IL.AddCmd0(IL.opUMINS) |
7597 | akron1 | 2096 | END |
2097 | END; |
||
2098 | e.obj := eEXPR |
||
2099 | END |
||
2100 | END; |
||
2101 | |||
2102 | label := -1; |
||
2103 | |||
2104 | WHILE AddOperator(parser.sym) DO |
||
2105 | |||
8097 | maxcodehac | 2106 | op := parser.sym; |
7597 | akron1 | 2107 | getpos(parser, pos); |
2108 | PARS.Next(parser); |
||
2109 | |||
2110 | IF op = SCAN.lxOR THEN |
||
2111 | |||
2112 | IF ~parser.constexp THEN |
||
2113 | |||
2114 | IF label = -1 THEN |
||
7693 | akron1 | 2115 | label := IL.NewLabel() |
7597 | akron1 | 2116 | END; |
2117 | |||
8859 | leency | 2118 | IF (e.obj = eCONST) & isBoolean(e) THEN |
7693 | akron1 | 2119 | IL.Const(ORD(ARITH.getBool(e.value))) |
2120 | END; |
||
8859 | leency | 2121 | IL.Jmp(IL.opJNZ, label) |
7597 | akron1 | 2122 | END |
2123 | |||
2124 | END; |
||
2125 | |||
2126 | term(parser, e1); |
||
2127 | |||
2128 | CASE op OF |
||
2129 | |SCAN.lxPLUS, SCAN.lxMINUS: |
||
2130 | |||
8097 | maxcodehac | 2131 | minus := op = SCAN.lxMINUS; |
2132 | IF minus THEN |
||
2133 | op := ORD("-") |
||
2134 | ELSE |
||
7597 | akron1 | 2135 | op := ORD("+") |
2136 | END; |
||
2137 | |||
8097 | maxcodehac | 2138 | PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1) OR isString(e) & isString(e1) & ~minus, pos, 37); |
7597 | akron1 | 2139 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
2140 | |||
8097 | maxcodehac | 2141 | CASE e.value.typ OF |
2142 | |ARITH.tINTEGER: |
||
2143 | PARS.check(ARITH.opInt(e.value, e1.value, CHR(op)), pos, 39) |
||
2144 | |||
2145 | |ARITH.tREAL: |
||
2146 | PARS.check(ARITH.opFloat(e.value, e1.value, CHR(op)), pos, 40) |
||
2147 | |||
2148 | |ARITH.tSET: |
||
2149 | ARITH.opSet(e.value, e1.value, CHR(op)) |
||
2150 | |||
2151 | |ARITH.tCHAR, ARITH.tSTRING: |
||
2152 | IF e.value.typ = ARITH.tCHAR THEN |
||
2153 | ARITH.charToStr(e.value, s) |
||
2154 | ELSE |
||
8859 | leency | 2155 | s := e.value.string(SCAN.STRING).s |
8097 | maxcodehac | 2156 | END; |
2157 | IF e1.value.typ = ARITH.tCHAR THEN |
||
2158 | ARITH.charToStr(e1.value, s1) |
||
2159 | ELSE |
||
8859 | leency | 2160 | s1 := e1.value.string(SCAN.STRING).s |
8097 | maxcodehac | 2161 | END; |
2162 | PARS.check(ARITH.concat(s, s1), pos, 5); |
||
8859 | leency | 2163 | e.value.string := SCAN.enterStr(s); |
8097 | maxcodehac | 2164 | e.value.typ := ARITH.tSTRING; |
2165 | e._type := PROG.program.stTypes.tSTRING |
||
7597 | akron1 | 2166 | END |
2167 | |||
2168 | ELSE |
||
2169 | IF isInt(e) THEN |
||
2170 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2171 | IL.AddCmd(IL.opADDC - ORD(minus), ARITH.Int(e.value)) |
7597 | akron1 | 2172 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2173 | IL.AddCmd(IL.opADDC + ORD(minus), ARITH.Int(e1.value)) |
7597 | akron1 | 2174 | ELSE |
8097 | maxcodehac | 2175 | IL.AddCmd0(IL.opADD + ORD(minus)) |
7597 | akron1 | 2176 | END |
2177 | ELSIF isReal(e) THEN |
||
2178 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2179 | Float(parser, e); |
2180 | IL.AddCmd0(IL.opADDF - ORD(minus)) |
||
7597 | akron1 | 2181 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2182 | Float(parser, e1); |
2183 | IL.AddCmd0(IL.opADDF + ORD(minus)) |
||
7597 | akron1 | 2184 | ELSE |
8097 | maxcodehac | 2185 | IL.AddCmd0(IL.opADDF + ORD(minus)) |
7597 | akron1 | 2186 | END |
2187 | ELSIF isSet(e) THEN |
||
2188 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2189 | IL.AddCmd(IL.opADDSC - ORD(minus), ARITH.Int(e.value)) |
7597 | akron1 | 2190 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2191 | IL.AddCmd(IL.opADDSC + ORD(minus), ARITH.Int(e1.value)) |
7597 | akron1 | 2192 | ELSE |
8097 | maxcodehac | 2193 | IL.AddCmd0(IL.opADDS + ORD(minus)) |
7597 | akron1 | 2194 | END |
2195 | END; |
||
2196 | e.obj := eEXPR |
||
2197 | END |
||
2198 | |||
2199 | |SCAN.lxOR: |
||
7693 | akron1 | 2200 | PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); |
7597 | akron1 | 2201 | |
8859 | leency | 2202 | IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN |
7597 | akron1 | 2203 | ARITH.opBoolean(e.value, e1.value, "|") |
2204 | ELSE |
||
2205 | e.obj := eEXPR; |
||
2206 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 2207 | IL.Const(ORD(ARITH.getBool(e1.value))) |
8097 | maxcodehac | 2208 | END |
7597 | akron1 | 2209 | END |
2210 | |||
2211 | END |
||
2212 | END; |
||
2213 | |||
2214 | IF label # -1 THEN |
||
8097 | maxcodehac | 2215 | label1 := IL.NewLabel(); |
8859 | leency | 2216 | IL.Jmp(IL.opJZ, label1); |
8097 | maxcodehac | 2217 | IL.SetLabel(label); |
2218 | IL.Const(1); |
||
2219 | IL.drop; |
||
2220 | label := IL.NewLabel(); |
||
8859 | leency | 2221 | IL.Jmp(IL.opJMP, label); |
8097 | maxcodehac | 2222 | IL.SetLabel(label1); |
2223 | IL.Const(0); |
||
2224 | IL.SetLabel(label); |
||
2225 | IL.AddCmd0(IL.opOR) |
||
7597 | akron1 | 2226 | END |
2227 | |||
2228 | END SimpleExpression; |
||
2229 | |||
2230 | |||
2231 | PROCEDURE cmpcode (op: INTEGER): INTEGER; |
||
2232 | VAR |
||
2233 | res: INTEGER; |
||
7693 | akron1 | 2234 | |
7597 | akron1 | 2235 | BEGIN |
2236 | CASE op OF |
||
8097 | maxcodehac | 2237 | |SCAN.lxEQ: res := ARITH.opEQ |
2238 | |SCAN.lxNE: res := ARITH.opNE |
||
2239 | |SCAN.lxLT: res := ARITH.opLT |
||
2240 | |SCAN.lxLE: res := ARITH.opLE |
||
2241 | |SCAN.lxGT: res := ARITH.opGT |
||
2242 | |SCAN.lxGE: res := ARITH.opGE |
||
2243 | |SCAN.lxIN: res := ARITH.opIN |
||
2244 | |SCAN.lxIS: res := ARITH.opIS |
||
7597 | akron1 | 2245 | END |
2246 | |||
2247 | RETURN res |
||
2248 | END cmpcode; |
||
2249 | |||
2250 | |||
7693 | akron1 | 2251 | PROCEDURE invcmpcode (op: INTEGER): INTEGER; |
2252 | VAR |
||
2253 | res: INTEGER; |
||
2254 | |||
2255 | BEGIN |
||
2256 | CASE op OF |
||
8097 | maxcodehac | 2257 | |SCAN.lxEQ: res := ARITH.opEQ |
2258 | |SCAN.lxNE: res := ARITH.opNE |
||
2259 | |SCAN.lxLT: res := ARITH.opGT |
||
2260 | |SCAN.lxLE: res := ARITH.opGE |
||
2261 | |SCAN.lxGT: res := ARITH.opLT |
||
2262 | |SCAN.lxGE: res := ARITH.opLE |
||
2263 | |SCAN.lxIN: res := ARITH.opIN |
||
2264 | |SCAN.lxIS: res := ARITH.opIS |
||
7693 | akron1 | 2265 | END |
2266 | |||
2267 | RETURN res |
||
2268 | END invcmpcode; |
||
2269 | |||
2270 | |||
7597 | akron1 | 2271 | PROCEDURE BoolCmp (eq, val: BOOLEAN); |
2272 | BEGIN |
||
2273 | IF eq = val THEN |
||
7693 | akron1 | 2274 | IL.AddCmd0(IL.opNEC) |
7597 | akron1 | 2275 | ELSE |
7693 | akron1 | 2276 | IL.AddCmd0(IL.opEQC) |
7597 | akron1 | 2277 | END |
2278 | END BoolCmp; |
||
2279 | |||
2280 | |||
2281 | PROCEDURE strcmp (VAR e, e1: PARS.EXPR; op: INTEGER): BOOLEAN; |
||
2282 | VAR |
||
2283 | res: BOOLEAN; |
||
8097 | maxcodehac | 2284 | cmp: INTEGER; |
7597 | akron1 | 2285 | |
2286 | BEGIN |
||
2287 | res := TRUE; |
||
8097 | maxcodehac | 2288 | cmp := cmpcode(op); |
7597 | akron1 | 2289 | |
2290 | IF isString(e) & isCharArray(e1) THEN |
||
7693 | akron1 | 2291 | IL.StrAdr(String(e)); |
2292 | IL.Const(strlen(e) + 1); |
||
2293 | IL.AddCmd0(IL.opEQS + invcmpcode(op)) |
||
7597 | akron1 | 2294 | |
8097 | maxcodehac | 2295 | ELSIF (isString(e) OR isStringW(e)) & isCharArrayW(e1) THEN |
7693 | akron1 | 2296 | IL.StrAdr(StringW(e)); |
2297 | IL.Const(utf8strlen(e) + 1); |
||
2298 | IL.AddCmd0(IL.opEQSW + invcmpcode(op)) |
||
7597 | akron1 | 2299 | |
2300 | ELSIF isCharArray(e) & isString(e1) THEN |
||
7693 | akron1 | 2301 | IL.StrAdr(String(e1)); |
2302 | IL.Const(strlen(e1) + 1); |
||
8097 | maxcodehac | 2303 | IL.AddCmd0(IL.opEQS + cmp) |
7597 | akron1 | 2304 | |
8097 | maxcodehac | 2305 | ELSIF isCharArrayW(e) & (isString(e1) OR isStringW(e1)) THEN |
7693 | akron1 | 2306 | IL.StrAdr(StringW(e1)); |
2307 | IL.Const(utf8strlen(e1) + 1); |
||
8097 | maxcodehac | 2308 | IL.AddCmd0(IL.opEQSW + cmp) |
7597 | akron1 | 2309 | |
2310 | ELSIF isCharArrayW(e) & isCharArrayW(e1) THEN |
||
8097 | maxcodehac | 2311 | IL.AddCmd0(IL.opEQSW + cmp) |
7597 | akron1 | 2312 | |
2313 | ELSIF isCharArray(e) & isCharArray(e1) THEN |
||
8097 | maxcodehac | 2314 | IL.AddCmd0(IL.opEQS + cmp) |
7597 | akron1 | 2315 | |
2316 | ELSIF isString(e) & isString(e1) THEN |
||
2317 | PARS.strcmp(e.value, e1.value, op) |
||
2318 | |||
2319 | ELSE |
||
2320 | res := FALSE |
||
2321 | |||
2322 | END |
||
2323 | |||
2324 | RETURN res |
||
2325 | END strcmp; |
||
2326 | |||
2327 | |||
2328 | BEGIN |
||
2329 | getpos(parser, pos0); |
||
2330 | SimpleExpression(parser, e); |
||
2331 | IF relation(parser.sym) THEN |
||
8097 | maxcodehac | 2332 | IF (isCharArray(e) OR isCharArrayW(e)) & (e._type.length # 0) THEN |
2333 | IL.Const(e._type.length) |
||
7597 | akron1 | 2334 | END; |
8097 | maxcodehac | 2335 | op := parser.sym; |
7597 | akron1 | 2336 | getpos(parser, pos); |
2337 | PARS.Next(parser); |
||
2338 | |||
7693 | akron1 | 2339 | getpos(parser, pos1); |
7597 | akron1 | 2340 | SimpleExpression(parser, e1); |
2341 | |||
8097 | maxcodehac | 2342 | IF (isCharArray(e1) OR isCharArrayW(e1)) & (e1._type.length # 0) THEN |
2343 | IL.Const(e1._type.length) |
||
7597 | akron1 | 2344 | END; |
2345 | |||
2346 | constant := (e.obj = eCONST) & (e1.obj = eCONST); |
||
2347 | error := 0; |
||
8097 | maxcodehac | 2348 | cmp := cmpcode(op); |
7597 | akron1 | 2349 | |
2350 | CASE op OF |
||
2351 | |SCAN.lxEQ, SCAN.lxNE: |
||
8097 | maxcodehac | 2352 | eq := op = SCAN.lxEQ; |
7597 | akron1 | 2353 | IF isInt(e) & isInt(e1) OR isSet(e) & isSet(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR |
2354 | isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR |
||
2355 | isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR |
||
2356 | isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) OR |
||
8097 | maxcodehac | 2357 | isPtr(e) & isPtr(e1) & (PROG.isBaseOf(e._type, e1._type) OR PROG.isBaseOf(e1._type, e._type)) THEN |
7597 | akron1 | 2358 | IF constant THEN |
8097 | maxcodehac | 2359 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2360 | ELSE |
2361 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2362 | IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e.value)) |
7597 | akron1 | 2363 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2364 | IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) |
7597 | akron1 | 2365 | ELSE |
8097 | maxcodehac | 2366 | IL.AddCmd0(IL.opEQ + cmp) |
7597 | akron1 | 2367 | END |
2368 | END |
||
2369 | |||
2370 | ELSIF isStringW1(e) & isCharW(e1) THEN |
||
8859 | leency | 2371 | IL.AddCmd(IL.opEQC + cmp, StrToWChar(e.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2372 | |
2373 | ELSIF isStringW1(e1) & isCharW(e) THEN |
||
8859 | leency | 2374 | IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2375 | |
2376 | ELSIF isBoolean(e) & isBoolean(e1) THEN |
||
2377 | IF constant THEN |
||
8097 | maxcodehac | 2378 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2379 | ELSE |
2380 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2381 | BoolCmp(eq, ARITH.Int(e.value) # 0) |
7597 | akron1 | 2382 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2383 | BoolCmp(eq, ARITH.Int(e1.value) # 0) |
7597 | akron1 | 2384 | ELSE |
8097 | maxcodehac | 2385 | IF eq THEN |
7693 | akron1 | 2386 | IL.AddCmd0(IL.opEQB) |
7597 | akron1 | 2387 | ELSE |
7693 | akron1 | 2388 | IL.AddCmd0(IL.opNEB) |
7597 | akron1 | 2389 | END |
2390 | END |
||
2391 | END |
||
2392 | |||
2393 | ELSIF isReal(e) & isReal(e1) THEN |
||
2394 | IF constant THEN |
||
8097 | maxcodehac | 2395 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2396 | ELSE |
2397 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2398 | Float(parser, e) |
7597 | akron1 | 2399 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2400 | Float(parser, e1) |
7693 | akron1 | 2401 | END; |
8097 | maxcodehac | 2402 | IL.AddCmd0(IL.opEQF + cmp) |
7597 | akron1 | 2403 | END |
2404 | |||
2405 | ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN |
||
2406 | IF ~strcmp(e, e1, op) THEN |
||
7693 | akron1 | 2407 | PARS.error(pos, 37) |
7597 | akron1 | 2408 | END |
2409 | |||
2410 | ELSIF isPtr(e) & isNil(e1) OR isNil(e) & isPtr(e1) THEN |
||
8097 | maxcodehac | 2411 | IL.AddCmd0(IL.opEQC + cmp) |
7597 | akron1 | 2412 | |
2413 | ELSIF isProc(e) & isNil(e1) THEN |
||
2414 | IF e.obj IN {ePROC, eIMP} THEN |
||
7693 | akron1 | 2415 | PARS.check(e.ident.global, pos0, 85); |
7597 | akron1 | 2416 | constant := TRUE; |
2417 | e.obj := eCONST; |
||
8097 | maxcodehac | 2418 | ARITH.setbool(e.value, ~eq) |
7597 | akron1 | 2419 | ELSE |
8097 | maxcodehac | 2420 | IL.AddCmd0(IL.opEQC + cmp) |
7597 | akron1 | 2421 | END |
2422 | |||
2423 | ELSIF isNil(e) & isProc(e1) THEN |
||
2424 | IF e1.obj IN {ePROC, eIMP} THEN |
||
7693 | akron1 | 2425 | PARS.check(e1.ident.global, pos1, 85); |
7597 | akron1 | 2426 | constant := TRUE; |
2427 | e.obj := eCONST; |
||
8097 | maxcodehac | 2428 | ARITH.setbool(e.value, ~eq) |
7597 | akron1 | 2429 | ELSE |
8097 | maxcodehac | 2430 | IL.AddCmd0(IL.opEQC + cmp) |
7597 | akron1 | 2431 | END |
2432 | |||
8097 | maxcodehac | 2433 | ELSIF isProc(e) & isProc(e1) & PROG.isTypeEq(e._type, e1._type) THEN |
7597 | akron1 | 2434 | IF e.obj = ePROC THEN |
7693 | akron1 | 2435 | PARS.check(e.ident.global, pos0, 85) |
7597 | akron1 | 2436 | END; |
2437 | IF e1.obj = ePROC THEN |
||
7693 | akron1 | 2438 | PARS.check(e1.ident.global, pos1, 85) |
7597 | akron1 | 2439 | END; |
2440 | IF (e.obj IN {ePROC, eIMP}) & (e1.obj IN {ePROC, eIMP}) THEN |
||
2441 | constant := TRUE; |
||
2442 | e.obj := eCONST; |
||
8097 | maxcodehac | 2443 | IF eq THEN |
7597 | akron1 | 2444 | ARITH.setbool(e.value, e.ident = e1.ident) |
2445 | ELSE |
||
2446 | ARITH.setbool(e.value, e.ident # e1.ident) |
||
2447 | END |
||
2448 | ELSIF e.obj = ePROC THEN |
||
8097 | maxcodehac | 2449 | IL.ProcCmp(e.ident.proc.label, eq) |
7597 | akron1 | 2450 | ELSIF e1.obj = ePROC THEN |
8097 | maxcodehac | 2451 | IL.ProcCmp(e1.ident.proc.label, eq) |
7597 | akron1 | 2452 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 2453 | IL.ProcImpCmp(e.ident._import, eq) |
7597 | akron1 | 2454 | ELSIF e1.obj = eIMP THEN |
8097 | maxcodehac | 2455 | IL.ProcImpCmp(e1.ident._import, eq) |
7597 | akron1 | 2456 | ELSE |
8097 | maxcodehac | 2457 | IL.AddCmd0(IL.opEQ + cmp) |
7597 | akron1 | 2458 | END |
2459 | |||
2460 | ELSIF isNil(e) & isNil(e1) THEN |
||
2461 | constant := TRUE; |
||
2462 | e.obj := eCONST; |
||
8097 | maxcodehac | 2463 | ARITH.setbool(e.value, eq) |
7597 | akron1 | 2464 | |
2465 | ELSE |
||
7693 | akron1 | 2466 | PARS.error(pos, 37) |
7597 | akron1 | 2467 | END |
2468 | |||
2469 | |SCAN.lxLT, SCAN.lxLE, SCAN.lxGT, SCAN.lxGE: |
||
2470 | IF isInt(e) & isInt(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR |
||
2471 | isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR |
||
2472 | isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR |
||
2473 | isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) THEN |
||
2474 | |||
2475 | IF constant THEN |
||
8097 | maxcodehac | 2476 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2477 | ELSE |
2478 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2479 | IL.AddCmd(IL.opEQC + invcmpcode(op), ARITH.Int(e.value)) |
7597 | akron1 | 2480 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2481 | IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) |
7597 | akron1 | 2482 | ELSE |
8097 | maxcodehac | 2483 | IL.AddCmd0(IL.opEQ + cmp) |
7597 | akron1 | 2484 | END |
2485 | END |
||
2486 | |||
2487 | ELSIF isStringW1(e) & isCharW(e1) THEN |
||
8859 | leency | 2488 | IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2489 | |
2490 | ELSIF isStringW1(e1) & isCharW(e) THEN |
||
8859 | leency | 2491 | IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2492 | |
2493 | ELSIF isReal(e) & isReal(e1) THEN |
||
2494 | IF constant THEN |
||
8097 | maxcodehac | 2495 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2496 | ELSE |
2497 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2498 | Float(parser, e); |
2499 | IL.AddCmd0(IL.opEQF + invcmpcode(op)) |
||
7597 | akron1 | 2500 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2501 | Float(parser, e1); |
2502 | IL.AddCmd0(IL.opEQF + cmp) |
||
7597 | akron1 | 2503 | ELSE |
8097 | maxcodehac | 2504 | IL.AddCmd0(IL.opEQF + cmp) |
7597 | akron1 | 2505 | END |
2506 | END |
||
2507 | |||
2508 | ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN |
||
2509 | IF ~strcmp(e, e1, op) THEN |
||
7693 | akron1 | 2510 | PARS.error(pos, 37) |
7597 | akron1 | 2511 | END |
2512 | |||
2513 | ELSE |
||
7693 | akron1 | 2514 | PARS.error(pos, 37) |
7597 | akron1 | 2515 | END |
2516 | |||
2517 | |SCAN.lxIN: |
||
7693 | akron1 | 2518 | PARS.check(isInt(e) & isSet(e1), pos, 37); |
7597 | akron1 | 2519 | IF e.obj = eCONST THEN |
7693 | akron1 | 2520 | PARS.check(ARITH.range(e.value, 0, UTILS.target.maxSet), pos0, 56) |
7597 | akron1 | 2521 | END; |
2522 | IF constant THEN |
||
8097 | maxcodehac | 2523 | ARITH.relation(e.value, e1.value, ARITH.opIN, error) |
7597 | akron1 | 2524 | ELSE |
2525 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2526 | IL.AddCmd(IL.opINL, ARITH.Int(e.value)) |
7597 | akron1 | 2527 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 2528 | IL.AddCmd(IL.opINR, ARITH.Int(e1.value)) |
7597 | akron1 | 2529 | ELSE |
7693 | akron1 | 2530 | IL.AddCmd0(IL.opIN) |
7597 | akron1 | 2531 | END |
2532 | END |
||
2533 | |||
2534 | |SCAN.lxIS: |
||
7693 | akron1 | 2535 | PARS.check(isRecPtr(e), pos, 73); |
2536 | PARS.check(e1.obj = eTYPE, pos1, 79); |
||
7597 | akron1 | 2537 | |
7693 | akron1 | 2538 | IF isRec(e) THEN |
2539 | PARS.check(e.obj = eVREC, pos0, 78); |
||
8097 | maxcodehac | 2540 | PARS.check(e1._type.typ = PROG.tRECORD, pos1, 80); |
7597 | akron1 | 2541 | IF e.ident = NIL THEN |
8097 | maxcodehac | 2542 | IL.TypeCheck(e1._type.num) |
7597 | akron1 | 2543 | ELSE |
7693 | akron1 | 2544 | IL.AddCmd(IL.opVADR, e.ident.offset - 1); |
8097 | maxcodehac | 2545 | IL.TypeCheckRec(e1._type.num) |
7597 | akron1 | 2546 | END |
2547 | ELSE |
||
8097 | maxcodehac | 2548 | PARS.check(e1._type.typ = PROG.tPOINTER, pos1, 81); |
2549 | IL.TypeCheck(e1._type.base.num) |
||
7597 | akron1 | 2550 | END; |
2551 | |||
8097 | maxcodehac | 2552 | PARS.check(PROG.isBaseOf(e._type, e1._type), pos1, 82) |
7597 | akron1 | 2553 | |
2554 | END; |
||
2555 | |||
2556 | ASSERT(error = 0); |
||
2557 | |||
8097 | maxcodehac | 2558 | e._type := tBOOLEAN; |
7597 | akron1 | 2559 | |
2560 | IF ~constant THEN |
||
2561 | e.obj := eEXPR |
||
2562 | END |
||
2563 | |||
2564 | END |
||
2565 | END expression; |
||
2566 | |||
2567 | |||
2568 | PROCEDURE ElementaryStatement (parser: PARS.PARSER); |
||
2569 | VAR |
||
7983 | leency | 2570 | e, e1: PARS.EXPR; |
2571 | pos: PARS.POSITION; |
||
2572 | line: INTEGER; |
||
2573 | call: BOOLEAN; |
||
7597 | akron1 | 2574 | |
2575 | BEGIN |
||
2576 | getpos(parser, pos); |
||
2577 | |||
7693 | akron1 | 2578 | IL.pushBegEnd(begcall, endcall); |
7597 | akron1 | 2579 | |
2580 | designator(parser, e); |
||
2581 | |||
2582 | IF parser.sym = SCAN.lxASSIGN THEN |
||
2583 | line := parser.lex.pos.line; |
||
7693 | akron1 | 2584 | PARS.check(isVar(e), pos, 93); |
2585 | PARS.check(~e.readOnly, pos, 94); |
||
7597 | akron1 | 2586 | |
7693 | akron1 | 2587 | IL.setlast(begcall); |
7597 | akron1 | 2588 | |
2589 | NextPos(parser, pos); |
||
2590 | expression(parser, e1); |
||
2591 | |||
7693 | akron1 | 2592 | IL.setlast(endcall.prev(IL.COMMAND)); |
7597 | akron1 | 2593 | |
8097 | maxcodehac | 2594 | PARS.check(assign(parser, e1, e._type, line), pos, 91); |
7597 | akron1 | 2595 | IF e1.obj = ePROC THEN |
7693 | akron1 | 2596 | PARS.check(e1.ident.global, pos, 85) |
7597 | akron1 | 2597 | END; |
2598 | call := FALSE |
||
2599 | ELSIF parser.sym = SCAN.lxEQ THEN |
||
2600 | PARS.check1(FALSE, parser, 96) |
||
2601 | ELSIF parser.sym = SCAN.lxLROUND THEN |
||
2602 | e1 := e; |
||
2603 | ActualParameters(parser, e1); |
||
8097 | maxcodehac | 2604 | PARS.check((e1._type = NIL) OR ODD(e._type.call), pos, 92); |
7597 | akron1 | 2605 | call := TRUE |
2606 | ELSE |
||
7693 | akron1 | 2607 | IF e.obj IN {eSYSPROC, eSTPROC} THEN |
2608 | stProc(parser, e); |
||
2609 | call := FALSE |
||
2610 | ELSE |
||
2611 | PARS.check(isProc(e), pos, 86); |
||
8097 | maxcodehac | 2612 | PARS.check((e._type.base = NIL) OR ODD(e._type.call), pos, 92); |
2613 | PARS.check1(e._type.params.first = NIL, parser, 64); |
||
7693 | akron1 | 2614 | call := TRUE |
2615 | END |
||
7597 | akron1 | 2616 | END; |
2617 | |||
2618 | IF call THEN |
||
2619 | IF e.obj IN {ePROC, eIMP} THEN |
||
8097 | maxcodehac | 2620 | ProcCall(e, e.ident._type, FALSE, parser, pos, TRUE) |
7597 | akron1 | 2621 | ELSIF isExpr(e) THEN |
8097 | maxcodehac | 2622 | ProcCall(e, e._type, FALSE, parser, pos, TRUE) |
7597 | akron1 | 2623 | END |
2624 | END; |
||
2625 | |||
7693 | akron1 | 2626 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 2627 | END ElementaryStatement; |
2628 | |||
2629 | |||
8097 | maxcodehac | 2630 | PROCEDURE IfStatement (parser: PARS.PARSER; _if: BOOLEAN); |
7597 | akron1 | 2631 | VAR |
7983 | leency | 2632 | e: PARS.EXPR; |
2633 | pos: PARS.POSITION; |
||
7597 | akron1 | 2634 | |
2635 | label, L: INTEGER; |
||
2636 | |||
2637 | BEGIN |
||
7693 | akron1 | 2638 | L := IL.NewLabel(); |
7597 | akron1 | 2639 | |
8097 | maxcodehac | 2640 | IF ~_if THEN |
8859 | leency | 2641 | IL.AddCmd(IL.opNOP, IL.begin_loop); |
7693 | akron1 | 2642 | IL.SetLabel(L) |
7597 | akron1 | 2643 | END; |
2644 | |||
2645 | REPEAT |
||
2646 | NextPos(parser, pos); |
||
2647 | |||
7693 | akron1 | 2648 | label := IL.NewLabel(); |
7597 | akron1 | 2649 | |
2650 | expression(parser, e); |
||
7693 | akron1 | 2651 | PARS.check(isBoolean(e), pos, 72); |
7597 | akron1 | 2652 | |
2653 | IF e.obj = eCONST THEN |
||
2654 | IF ~ARITH.getBool(e.value) THEN |
||
8859 | leency | 2655 | IL.Jmp(IL.opJMP, label) |
7597 | akron1 | 2656 | END |
2657 | ELSE |
||
8097 | maxcodehac | 2658 | IL.AndOrOpt(label) |
7597 | akron1 | 2659 | END; |
2660 | |||
8097 | maxcodehac | 2661 | IF _if THEN |
7597 | akron1 | 2662 | PARS.checklex(parser, SCAN.lxTHEN) |
2663 | ELSE |
||
2664 | PARS.checklex(parser, SCAN.lxDO) |
||
2665 | END; |
||
2666 | |||
2667 | PARS.Next(parser); |
||
2668 | parser.StatSeq(parser); |
||
2669 | |||
8097 | maxcodehac | 2670 | IF ~_if OR (parser.sym # SCAN.lxEND) THEN |
8859 | leency | 2671 | IL.Jmp(IL.opJMP, L) |
8097 | maxcodehac | 2672 | END; |
7693 | akron1 | 2673 | IL.SetLabel(label) |
7597 | akron1 | 2674 | |
2675 | UNTIL parser.sym # SCAN.lxELSIF; |
||
2676 | |||
8097 | maxcodehac | 2677 | IF _if THEN |
7597 | akron1 | 2678 | IF parser.sym = SCAN.lxELSE THEN |
2679 | PARS.Next(parser); |
||
2680 | parser.StatSeq(parser) |
||
2681 | END; |
||
7693 | akron1 | 2682 | IL.SetLabel(L) |
8097 | maxcodehac | 2683 | ELSE |
8859 | leency | 2684 | IL.AddCmd(IL.opNOP, IL.end_loop) |
7597 | akron1 | 2685 | END; |
2686 | |||
2687 | PARS.checklex(parser, SCAN.lxEND); |
||
2688 | |||
2689 | PARS.Next(parser) |
||
2690 | END IfStatement; |
||
2691 | |||
2692 | |||
2693 | PROCEDURE RepeatStatement (parser: PARS.PARSER); |
||
2694 | VAR |
||
2695 | e: PARS.EXPR; |
||
7693 | akron1 | 2696 | pos: PARS.POSITION; |
7597 | akron1 | 2697 | label: INTEGER; |
8097 | maxcodehac | 2698 | L: IL.COMMAND; |
7597 | akron1 | 2699 | |
2700 | BEGIN |
||
8859 | leency | 2701 | IL.AddCmd(IL.opNOP, IL.begin_loop); |
7597 | akron1 | 2702 | |
7693 | akron1 | 2703 | label := IL.NewLabel(); |
2704 | IL.SetLabel(label); |
||
8097 | maxcodehac | 2705 | L := IL.getlast(); |
7597 | akron1 | 2706 | |
2707 | PARS.Next(parser); |
||
2708 | parser.StatSeq(parser); |
||
2709 | PARS.checklex(parser, SCAN.lxUNTIL); |
||
2710 | NextPos(parser, pos); |
||
2711 | expression(parser, e); |
||
7693 | akron1 | 2712 | PARS.check(isBoolean(e), pos, 72); |
7597 | akron1 | 2713 | |
2714 | IF e.obj = eCONST THEN |
||
2715 | IF ~ARITH.getBool(e.value) THEN |
||
8859 | leency | 2716 | IL.Jmp(IL.opJMP, label) |
7597 | akron1 | 2717 | END |
2718 | ELSE |
||
8097 | maxcodehac | 2719 | IL.AndOrOpt(label); |
2720 | L.param1 := label |
||
7597 | akron1 | 2721 | END; |
2722 | |||
8859 | leency | 2723 | IL.AddCmd(IL.opNOP, IL.end_loop) |
7597 | akron1 | 2724 | END RepeatStatement; |
2725 | |||
2726 | |||
2727 | PROCEDURE LabelCmp (a, b: AVL.DATA): INTEGER; |
||
2728 | VAR |
||
2729 | La, Ra, Lb, Rb, res: INTEGER; |
||
2730 | |||
2731 | BEGIN |
||
2732 | La := a(CASE_LABEL).range.a; |
||
2733 | Ra := a(CASE_LABEL).range.b; |
||
2734 | Lb := b(CASE_LABEL).range.a; |
||
2735 | Rb := b(CASE_LABEL).range.b; |
||
2736 | IF (Ra < Lb) OR (La > Rb) THEN |
||
2737 | res := ORD(La > Lb) - ORD(La < Lb) |
||
2738 | ELSE |
||
2739 | res := 0 |
||
2740 | END |
||
2741 | |||
2742 | RETURN res |
||
2743 | END LabelCmp; |
||
2744 | |||
2745 | |||
2746 | PROCEDURE DestroyLabel (VAR label: AVL.DATA); |
||
2747 | BEGIN |
||
2748 | C.push(CaseLabels, label); |
||
2749 | label := NIL |
||
2750 | END DestroyLabel; |
||
2751 | |||
2752 | |||
7693 | akron1 | 2753 | PROCEDURE NewVariant (label: INTEGER; cmd: IL.COMMAND): CASE_VARIANT; |
7597 | akron1 | 2754 | VAR |
2755 | res: CASE_VARIANT; |
||
2756 | citem: C.ITEM; |
||
2757 | |||
2758 | BEGIN |
||
2759 | citem := C.pop(CaseVar); |
||
2760 | IF citem = NIL THEN |
||
2761 | NEW(res) |
||
2762 | ELSE |
||
2763 | res := citem(CASE_VARIANT) |
||
2764 | END; |
||
2765 | |||
2766 | res.label := label; |
||
2767 | res.cmd := cmd; |
||
2768 | res.processed := FALSE |
||
2769 | |||
2770 | RETURN res |
||
2771 | END NewVariant; |
||
2772 | |||
2773 | |||
2774 | PROCEDURE CaseStatement (parser: PARS.PARSER); |
||
2775 | VAR |
||
7983 | leency | 2776 | e: PARS.EXPR; |
2777 | pos: PARS.POSITION; |
||
7597 | akron1 | 2778 | |
2779 | |||
8097 | maxcodehac | 2780 | PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR _type: PROG._TYPE): INTEGER; |
7597 | akron1 | 2781 | VAR |
7983 | leency | 2782 | a: INTEGER; |
2783 | label: PARS.EXPR; |
||
2784 | pos: PARS.POSITION; |
||
2785 | value: ARITH.VALUE; |
||
7597 | akron1 | 2786 | |
2787 | BEGIN |
||
2788 | getpos(parser, pos); |
||
8097 | maxcodehac | 2789 | _type := NIL; |
7597 | akron1 | 2790 | |
2791 | IF isChar(caseExpr) THEN |
||
2792 | PARS.ConstExpression(parser, value); |
||
7693 | akron1 | 2793 | PARS.check(value.typ = ARITH.tCHAR, pos, 99); |
7597 | akron1 | 2794 | a := ARITH.getInt(value) |
2795 | ELSIF isCharW(caseExpr) THEN |
||
2796 | PARS.ConstExpression(parser, value); |
||
8859 | leency | 2797 | IF (value.typ = ARITH.tSTRING) & (_length(value.string(SCAN.STRING).s) = 1) & (LENGTH(value.string(SCAN.STRING).s) > 1) THEN |
2798 | ASSERT(ARITH.setInt(value, StrToWChar(value.string(SCAN.STRING).s))) |
||
7597 | akron1 | 2799 | ELSE |
7693 | akron1 | 2800 | PARS.check(value.typ IN {ARITH.tWCHAR, ARITH.tCHAR}, pos, 99) |
7597 | akron1 | 2801 | END; |
2802 | a := ARITH.getInt(value) |
||
2803 | ELSIF isInt(caseExpr) THEN |
||
2804 | PARS.ConstExpression(parser, value); |
||
7693 | akron1 | 2805 | PARS.check(value.typ = ARITH.tINTEGER, pos, 99); |
7597 | akron1 | 2806 | a := ARITH.getInt(value) |
2807 | ELSIF isRecPtr(caseExpr) THEN |
||
2808 | qualident(parser, label); |
||
7693 | akron1 | 2809 | PARS.check(label.obj = eTYPE, pos, 79); |
8097 | maxcodehac | 2810 | PARS.check(PROG.isBaseOf(caseExpr._type, label._type), pos, 99); |
7597 | akron1 | 2811 | IF isRec(caseExpr) THEN |
8097 | maxcodehac | 2812 | a := label._type.num |
7597 | akron1 | 2813 | ELSE |
8097 | maxcodehac | 2814 | a := label._type.base.num |
7597 | akron1 | 2815 | END; |
8097 | maxcodehac | 2816 | _type := label._type |
7597 | akron1 | 2817 | END |
2818 | |||
2819 | RETURN a |
||
2820 | END Label; |
||
2821 | |||
2822 | |||
8097 | maxcodehac | 2823 | PROCEDURE CheckType (node: AVL.NODE; _type: PROG._TYPE; parser: PARS.PARSER; pos: PARS.POSITION); |
7597 | akron1 | 2824 | BEGIN |
2825 | IF node # NIL THEN |
||
8097 | maxcodehac | 2826 | PARS.check(~(PROG.isBaseOf(node.data(CASE_LABEL)._type, _type) OR PROG.isBaseOf(_type, node.data(CASE_LABEL)._type)), pos, 100); |
2827 | CheckType(node.left, _type, parser, pos); |
||
2828 | CheckType(node.right, _type, parser, pos) |
||
7597 | akron1 | 2829 | END |
2830 | END CheckType; |
||
2831 | |||
2832 | |||
2833 | PROCEDURE LabelRange (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; variant: INTEGER): AVL.NODE; |
||
2834 | VAR |
||
2835 | label: CASE_LABEL; |
||
2836 | citem: C.ITEM; |
||
7693 | akron1 | 2837 | pos, pos1: PARS.POSITION; |
7597 | akron1 | 2838 | node: AVL.NODE; |
2839 | newnode: BOOLEAN; |
||
2840 | range: RANGE; |
||
2841 | |||
2842 | BEGIN |
||
2843 | citem := C.pop(CaseLabels); |
||
2844 | IF citem = NIL THEN |
||
2845 | NEW(label) |
||
2846 | ELSE |
||
2847 | label := citem(CASE_LABEL) |
||
2848 | END; |
||
2849 | |||
2850 | label.variant := variant; |
||
7693 | akron1 | 2851 | label.self := IL.NewLabel(); |
7597 | akron1 | 2852 | |
2853 | getpos(parser, pos1); |
||
8097 | maxcodehac | 2854 | range.a := Label(parser, caseExpr, label._type); |
7597 | akron1 | 2855 | |
2856 | IF parser.sym = SCAN.lxRANGE THEN |
||
2857 | PARS.check1(~isRecPtr(caseExpr), parser, 53); |
||
2858 | NextPos(parser, pos); |
||
8097 | maxcodehac | 2859 | range.b := Label(parser, caseExpr, label._type); |
7693 | akron1 | 2860 | PARS.check(range.a <= range.b, pos, 103) |
7597 | akron1 | 2861 | ELSE |
2862 | range.b := range.a |
||
2863 | END; |
||
2864 | |||
2865 | label.range := range; |
||
2866 | |||
2867 | IF isRecPtr(caseExpr) THEN |
||
8097 | maxcodehac | 2868 | CheckType(tree, label._type, parser, pos1) |
7597 | akron1 | 2869 | END; |
2870 | tree := AVL.insert(tree, label, LabelCmp, newnode, node); |
||
7693 | akron1 | 2871 | PARS.check(newnode, pos1, 100) |
7597 | akron1 | 2872 | |
2873 | RETURN node |
||
2874 | |||
2875 | END LabelRange; |
||
2876 | |||
2877 | |||
2878 | PROCEDURE CaseLabelList (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; variant: INTEGER): AVL.NODE; |
||
2879 | VAR |
||
2880 | exit: BOOLEAN; |
||
2881 | res: AVL.NODE; |
||
2882 | |||
2883 | BEGIN |
||
2884 | exit := FALSE; |
||
2885 | REPEAT |
||
2886 | res := LabelRange(parser, caseExpr, tree, variant); |
||
2887 | IF parser.sym = SCAN.lxCOMMA THEN |
||
2888 | PARS.check1(~isRecPtr(caseExpr), parser, 53); |
||
2889 | PARS.Next(parser) |
||
2890 | ELSE |
||
2891 | exit := TRUE |
||
2892 | END |
||
2893 | UNTIL exit |
||
2894 | |||
2895 | RETURN res |
||
2896 | END CaseLabelList; |
||
2897 | |||
2898 | |||
8097 | maxcodehac | 2899 | PROCEDURE _case (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; _end: INTEGER); |
7597 | akron1 | 2900 | VAR |
7983 | leency | 2901 | sym: INTEGER; |
8097 | maxcodehac | 2902 | t: PROG._TYPE; |
7983 | leency | 2903 | variant: INTEGER; |
2904 | node: AVL.NODE; |
||
2905 | last: IL.COMMAND; |
||
7597 | akron1 | 2906 | |
2907 | BEGIN |
||
2908 | sym := parser.sym; |
||
2909 | IF sym # SCAN.lxBAR THEN |
||
7693 | akron1 | 2910 | variant := IL.NewLabel(); |
7597 | akron1 | 2911 | node := CaseLabelList(parser, caseExpr, tree, variant); |
2912 | PARS.checklex(parser, SCAN.lxCOLON); |
||
2913 | PARS.Next(parser); |
||
2914 | IF isRecPtr(caseExpr) THEN |
||
8097 | maxcodehac | 2915 | t := caseExpr._type; |
2916 | caseExpr.ident._type := node.data(CASE_LABEL)._type |
||
7597 | akron1 | 2917 | END; |
2918 | |||
7693 | akron1 | 2919 | last := IL.getlast(); |
2920 | IL.SetLabel(variant); |
||
7597 | akron1 | 2921 | |
2922 | IF ~isRecPtr(caseExpr) THEN |
||
2923 | LISTS.push(CaseVariants, NewVariant(variant, last)) |
||
2924 | END; |
||
2925 | |||
2926 | parser.StatSeq(parser); |
||
8859 | leency | 2927 | IL.Jmp(IL.opJMP, _end); |
7597 | akron1 | 2928 | |
2929 | IF isRecPtr(caseExpr) THEN |
||
8097 | maxcodehac | 2930 | caseExpr.ident._type := t |
7597 | akron1 | 2931 | END |
2932 | END |
||
8097 | maxcodehac | 2933 | END _case; |
7597 | akron1 | 2934 | |
2935 | |||
8097 | maxcodehac | 2936 | PROCEDURE Table (node: AVL.NODE; _else: INTEGER); |
7597 | akron1 | 2937 | VAR |
2938 | L, R: INTEGER; |
||
2939 | range: RANGE; |
||
2940 | left, right: AVL.NODE; |
||
7693 | akron1 | 2941 | last: IL.COMMAND; |
7597 | akron1 | 2942 | v: CASE_VARIANT; |
2943 | |||
2944 | BEGIN |
||
2945 | IF node # NIL THEN |
||
2946 | |||
2947 | range := node.data(CASE_LABEL).range; |
||
2948 | |||
2949 | left := node.left; |
||
2950 | IF left # NIL THEN |
||
2951 | L := left.data(CASE_LABEL).self |
||
2952 | ELSE |
||
8097 | maxcodehac | 2953 | L := _else |
7597 | akron1 | 2954 | END; |
2955 | |||
2956 | right := node.right; |
||
2957 | IF right # NIL THEN |
||
2958 | R := right.data(CASE_LABEL).self |
||
2959 | ELSE |
||
8097 | maxcodehac | 2960 | R := _else |
7597 | akron1 | 2961 | END; |
2962 | |||
7693 | akron1 | 2963 | last := IL.getlast(); |
7597 | akron1 | 2964 | |
2965 | v := CaseVariants.last(CASE_VARIANT); |
||
2966 | WHILE (v # NIL) & (v.label # 0) & (v.label # node.data(CASE_LABEL).variant) DO |
||
2967 | v := v.prev(CASE_VARIANT) |
||
2968 | END; |
||
2969 | |||
2970 | ASSERT((v # NIL) & (v.label # 0)); |
||
7693 | akron1 | 2971 | IL.setlast(v.cmd); |
7597 | akron1 | 2972 | |
7693 | akron1 | 2973 | IL.SetLabel(node.data(CASE_LABEL).self); |
8097 | maxcodehac | 2974 | IL._case(range.a, range.b, L, R); |
7597 | akron1 | 2975 | IF v.processed THEN |
8859 | leency | 2976 | IL.Jmp(IL.opJMP, node.data(CASE_LABEL).variant) |
7597 | akron1 | 2977 | END; |
2978 | v.processed := TRUE; |
||
2979 | |||
7693 | akron1 | 2980 | IL.setlast(last); |
7597 | akron1 | 2981 | |
8097 | maxcodehac | 2982 | Table(left, _else); |
2983 | Table(right, _else) |
||
7597 | akron1 | 2984 | END |
2985 | END Table; |
||
2986 | |||
2987 | |||
2988 | PROCEDURE TableT (node: AVL.NODE); |
||
2989 | BEGIN |
||
2990 | IF node # NIL THEN |
||
8097 | maxcodehac | 2991 | IL.AddCmd2(IL.opCASET, node.data(CASE_LABEL).variant, node.data(CASE_LABEL).range.a); |
7597 | akron1 | 2992 | TableT(node.left); |
2993 | TableT(node.right) |
||
2994 | END |
||
2995 | END TableT; |
||
2996 | |||
2997 | |||
7693 | akron1 | 2998 | PROCEDURE ParseCase (parser: PARS.PARSER; e: PARS.EXPR; pos: PARS.POSITION); |
7597 | akron1 | 2999 | VAR |
8097 | maxcodehac | 3000 | table, _end, _else: INTEGER; |
7597 | akron1 | 3001 | tree: AVL.NODE; |
7983 | leency | 3002 | item: LISTS.ITEM; |
7597 | akron1 | 3003 | |
3004 | BEGIN |
||
3005 | LISTS.push(CaseVariants, NewVariant(0, NIL)); |
||
8097 | maxcodehac | 3006 | _end := IL.NewLabel(); |
3007 | _else := IL.NewLabel(); |
||
7693 | akron1 | 3008 | table := IL.NewLabel(); |
3009 | IL.AddCmd(IL.opSWITCH, ORD(isRecPtr(e))); |
||
8859 | leency | 3010 | IL.Jmp(IL.opJMP, table); |
7597 | akron1 | 3011 | |
3012 | tree := NIL; |
||
3013 | |||
8097 | maxcodehac | 3014 | _case(parser, e, tree, _end); |
7597 | akron1 | 3015 | WHILE parser.sym = SCAN.lxBAR DO |
3016 | PARS.Next(parser); |
||
8097 | maxcodehac | 3017 | _case(parser, e, tree, _end) |
7597 | akron1 | 3018 | END; |
3019 | |||
8097 | maxcodehac | 3020 | IL.SetLabel(_else); |
7597 | akron1 | 3021 | IF parser.sym = SCAN.lxELSE THEN |
3022 | PARS.Next(parser); |
||
3023 | parser.StatSeq(parser); |
||
8859 | leency | 3024 | IL.Jmp(IL.opJMP, _end) |
7597 | akron1 | 3025 | ELSE |
7693 | akron1 | 3026 | IL.OnError(pos.line, errCASE) |
7597 | akron1 | 3027 | END; |
3028 | |||
3029 | PARS.checklex(parser, SCAN.lxEND); |
||
3030 | PARS.Next(parser); |
||
3031 | |||
3032 | IF isRecPtr(e) THEN |
||
7693 | akron1 | 3033 | IL.SetLabel(table); |
7597 | akron1 | 3034 | TableT(tree); |
8859 | leency | 3035 | IL.Jmp(IL.opJMP, _else) |
7597 | akron1 | 3036 | ELSE |
3037 | tree.data(CASE_LABEL).self := table; |
||
8097 | maxcodehac | 3038 | Table(tree, _else) |
7597 | akron1 | 3039 | END; |
3040 | |||
3041 | AVL.destroy(tree, DestroyLabel); |
||
8097 | maxcodehac | 3042 | IL.SetLabel(_end); |
7693 | akron1 | 3043 | IL.AddCmd0(IL.opENDSW); |
7597 | akron1 | 3044 | |
3045 | REPEAT |
||
3046 | item := LISTS.pop(CaseVariants); |
||
3047 | C.push(CaseVar, item) |
||
3048 | UNTIL item(CASE_VARIANT).cmd = NIL |
||
3049 | |||
3050 | END ParseCase; |
||
3051 | |||
3052 | |||
3053 | BEGIN |
||
3054 | NextPos(parser, pos); |
||
3055 | expression(parser, e); |
||
7693 | akron1 | 3056 | PARS.check(isInt(e) OR isChar(e) OR isCharW(e) OR isPtr(e) OR isRec(e), pos, 95); |
7597 | akron1 | 3057 | IF isRecPtr(e) THEN |
7693 | akron1 | 3058 | PARS.check(isVar(e), pos, 93); |
3059 | PARS.check(e.ident # NIL, pos, 106) |
||
7597 | akron1 | 3060 | END; |
3061 | IF isRec(e) THEN |
||
7693 | akron1 | 3062 | PARS.check(e.obj = eVREC, pos, 78) |
7597 | akron1 | 3063 | END; |
3064 | |||
3065 | IF e.obj = eCONST THEN |
||
3066 | LoadConst(e) |
||
3067 | ELSIF isRec(e) THEN |
||
7693 | akron1 | 3068 | IL.drop; |
3069 | IL.AddCmd(IL.opLADR, e.ident.offset - 1); |
||
7983 | leency | 3070 | IL.load(TARGETS.WordSize) |
7597 | akron1 | 3071 | ELSIF isPtr(e) THEN |
3072 | deref(pos, e, FALSE, errPTR); |
||
7983 | leency | 3073 | IL.AddCmd(IL.opSUBR, TARGETS.WordSize); |
3074 | IL.load(TARGETS.WordSize) |
||
7597 | akron1 | 3075 | END; |
3076 | |||
3077 | PARS.checklex(parser, SCAN.lxOF); |
||
3078 | PARS.Next(parser); |
||
3079 | ParseCase(parser, e, pos) |
||
3080 | END CaseStatement; |
||
3081 | |||
3082 | |||
3083 | PROCEDURE ForStatement (parser: PARS.PARSER); |
||
3084 | VAR |
||
7693 | akron1 | 3085 | e: PARS.EXPR; |
3086 | pos, pos2: PARS.POSITION; |
||
3087 | step: ARITH.VALUE; |
||
3088 | st: INTEGER; |
||
3089 | ident: PROG.IDENT; |
||
3090 | offset: INTEGER; |
||
3091 | L1, L2: INTEGER; |
||
7597 | akron1 | 3092 | |
3093 | BEGIN |
||
8859 | leency | 3094 | IL.AddCmd(IL.opNOP, IL.begin_loop); |
7597 | akron1 | 3095 | |
7693 | akron1 | 3096 | L1 := IL.NewLabel(); |
3097 | L2 := IL.NewLabel(); |
||
7597 | akron1 | 3098 | |
3099 | PARS.ExpectSym(parser, SCAN.lxIDENT); |
||
7693 | akron1 | 3100 | ident := PROG.getIdent(parser.unit, parser.lex.ident, TRUE); |
7597 | akron1 | 3101 | PARS.check1(ident # NIL, parser, 48); |
3102 | PARS.check1(ident.typ = PROG.idVAR, parser, 93); |
||
8097 | maxcodehac | 3103 | PARS.check1(ident._type = tINTEGER, parser, 97); |
7597 | akron1 | 3104 | PARS.ExpectSym(parser, SCAN.lxASSIGN); |
3105 | NextPos(parser, pos); |
||
3106 | expression(parser, e); |
||
7693 | akron1 | 3107 | PARS.check(isInt(e), pos, 76); |
7597 | akron1 | 3108 | |
8097 | maxcodehac | 3109 | offset := PROG.getOffset(ident); |
7597 | akron1 | 3110 | |
3111 | IF ident.global THEN |
||
7693 | akron1 | 3112 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 3113 | ELSE |
7693 | akron1 | 3114 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 3115 | END; |
3116 | |||
3117 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 3118 | IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) |
7597 | akron1 | 3119 | ELSE |
7693 | akron1 | 3120 | IL.AddCmd0(IL.opSAVE) |
7597 | akron1 | 3121 | END; |
3122 | |||
7693 | akron1 | 3123 | IL.SetLabel(L1); |
7597 | akron1 | 3124 | |
3125 | IF ident.global THEN |
||
7693 | akron1 | 3126 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 3127 | ELSE |
7693 | akron1 | 3128 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 3129 | END; |
8097 | maxcodehac | 3130 | IL.load(ident._type.size); |
7597 | akron1 | 3131 | |
3132 | PARS.checklex(parser, SCAN.lxTO); |
||
7693 | akron1 | 3133 | NextPos(parser, pos2); |
7597 | akron1 | 3134 | expression(parser, e); |
7693 | akron1 | 3135 | PARS.check(isInt(e), pos2, 76); |
7597 | akron1 | 3136 | |
3137 | IF parser.sym = SCAN.lxBY THEN |
||
3138 | NextPos(parser, pos); |
||
3139 | PARS.ConstExpression(parser, step); |
||
7693 | akron1 | 3140 | PARS.check(step.typ = ARITH.tINTEGER, pos, 76); |
7597 | akron1 | 3141 | st := ARITH.getInt(step); |
7693 | akron1 | 3142 | PARS.check(st # 0, pos, 98) |
7597 | akron1 | 3143 | ELSE |
3144 | st := 1 |
||
3145 | END; |
||
3146 | |||
3147 | IF e.obj = eCONST THEN |
||
3148 | IF st > 0 THEN |
||
7693 | akron1 | 3149 | IL.AddCmd(IL.opLEC, ARITH.Int(e.value)); |
3150 | IF ARITH.Int(e.value) = UTILS.target.maxInt THEN |
||
3151 | ERRORS.WarningMsg(pos2.line, pos2.col, 1) |
||
3152 | END |
||
7597 | akron1 | 3153 | ELSE |
7693 | akron1 | 3154 | IL.AddCmd(IL.opGEC, ARITH.Int(e.value)); |
3155 | IF ARITH.Int(e.value) = UTILS.target.minInt THEN |
||
3156 | ERRORS.WarningMsg(pos2.line, pos2.col, 1) |
||
3157 | END |
||
7597 | akron1 | 3158 | END |
3159 | ELSE |
||
3160 | IF st > 0 THEN |
||
7693 | akron1 | 3161 | IL.AddCmd0(IL.opLE) |
7597 | akron1 | 3162 | ELSE |
7693 | akron1 | 3163 | IL.AddCmd0(IL.opGE) |
7597 | akron1 | 3164 | END |
3165 | END; |
||
3166 | |||
8859 | leency | 3167 | IL.Jmp(IL.opJZ, L2); |
7597 | akron1 | 3168 | |
3169 | PARS.checklex(parser, SCAN.lxDO); |
||
3170 | PARS.Next(parser); |
||
3171 | parser.StatSeq(parser); |
||
3172 | |||
3173 | IF ident.global THEN |
||
7693 | akron1 | 3174 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 3175 | ELSE |
7693 | akron1 | 3176 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 3177 | END; |
3178 | |||
7693 | akron1 | 3179 | IL.AddCmd(IL.opINCC, st); |
7597 | akron1 | 3180 | |
8859 | leency | 3181 | IL.Jmp(IL.opJMP, L1); |
7597 | akron1 | 3182 | |
3183 | PARS.checklex(parser, SCAN.lxEND); |
||
3184 | PARS.Next(parser); |
||
3185 | |||
7693 | akron1 | 3186 | IL.SetLabel(L2); |
7597 | akron1 | 3187 | |
8859 | leency | 3188 | IL.AddCmd(IL.opNOP, IL.end_loop) |
7597 | akron1 | 3189 | END ForStatement; |
3190 | |||
3191 | |||
3192 | PROCEDURE statement (parser: PARS.PARSER); |
||
3193 | VAR |
||
3194 | sym: INTEGER; |
||
3195 | |||
3196 | BEGIN |
||
3197 | sym := parser.sym; |
||
3198 | |||
3199 | IF sym = SCAN.lxIDENT THEN |
||
3200 | ElementaryStatement(parser) |
||
3201 | ELSIF sym = SCAN.lxIF THEN |
||
3202 | IfStatement(parser, TRUE) |
||
3203 | ELSIF sym = SCAN.lxWHILE THEN |
||
3204 | IfStatement(parser, FALSE) |
||
3205 | ELSIF sym = SCAN.lxREPEAT THEN |
||
3206 | RepeatStatement(parser) |
||
3207 | ELSIF sym = SCAN.lxCASE THEN |
||
3208 | CaseStatement(parser) |
||
3209 | ELSIF sym = SCAN.lxFOR THEN |
||
3210 | ForStatement(parser) |
||
3211 | END |
||
3212 | END statement; |
||
3213 | |||
3214 | |||
3215 | PROCEDURE StatSeq (parser: PARS.PARSER); |
||
3216 | BEGIN |
||
3217 | statement(parser); |
||
3218 | WHILE parser.sym = SCAN.lxSEMI DO |
||
3219 | PARS.Next(parser); |
||
3220 | statement(parser) |
||
3221 | END |
||
3222 | END StatSeq; |
||
3223 | |||
3224 | |||
8097 | maxcodehac | 3225 | PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG._TYPE; pos: PARS.POSITION): BOOLEAN; |
7597 | akron1 | 3226 | VAR |
3227 | res: BOOLEAN; |
||
3228 | |||
3229 | BEGIN |
||
3230 | res := assigncomp(e, t); |
||
3231 | IF res THEN |
||
3232 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 3233 | IF e._type = tREAL THEN |
3234 | Float(parser, e) |
||
3235 | ELSIF e._type.typ = PROG.tNIL THEN |
||
7693 | akron1 | 3236 | IL.Const(0) |
7597 | akron1 | 3237 | ELSE |
3238 | LoadConst(e) |
||
3239 | END |
||
8097 | maxcodehac | 3240 | ELSIF (e._type = tINTEGER) & (t = tBYTE) & (chkBYTE IN Options.checking) THEN |
7597 | akron1 | 3241 | CheckRange(256, pos.line, errBYTE) |
3242 | ELSIF e.obj = ePROC THEN |
||
7693 | akron1 | 3243 | PARS.check(e.ident.global, pos, 85); |
3244 | IL.PushProc(e.ident.proc.label) |
||
7597 | akron1 | 3245 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 3246 | IL.PushImpProc(e.ident._import) |
7597 | akron1 | 3247 | END |
3248 | END |
||
3249 | |||
3250 | RETURN res |
||
3251 | END chkreturn; |
||
3252 | |||
3253 | |||
3254 | PROCEDURE setrtl; |
||
3255 | VAR |
||
3256 | rtl: PROG.UNIT; |
||
3257 | |||
3258 | |||
8859 | leency | 3259 | PROCEDURE getproc (rtl: PROG.UNIT; name: SCAN.IDSTR; idx: INTEGER); |
7597 | akron1 | 3260 | VAR |
7983 | leency | 3261 | id: PROG.IDENT; |
8859 | leency | 3262 | ident: SCAN.IDENT; |
7597 | akron1 | 3263 | |
3264 | BEGIN |
||
8859 | leency | 3265 | SCAN.setIdent(ident, name); |
3266 | id := PROG.getIdent(rtl, ident, FALSE); |
||
7597 | akron1 | 3267 | |
8097 | maxcodehac | 3268 | IF (id # NIL) & (id._import # NIL) THEN |
3269 | IL.set_rtl(idx, -id._import(IL.IMPORT_PROC).label); |
||
7597 | akron1 | 3270 | id.proc.used := TRUE |
3271 | ELSIF (id # NIL) & (id.proc # NIL) THEN |
||
7696 | akron1 | 3272 | IL.set_rtl(idx, id.proc.label); |
7597 | akron1 | 3273 | id.proc.used := TRUE |
3274 | ELSE |
||
7693 | akron1 | 3275 | ERRORS.WrongRTL(name) |
7597 | akron1 | 3276 | END |
3277 | END getproc; |
||
3278 | |||
3279 | |||
3280 | BEGIN |
||
8097 | maxcodehac | 3281 | rtl := PROG.program.rtl; |
7597 | akron1 | 3282 | ASSERT(rtl # NIL); |
3283 | |||
7983 | leency | 3284 | getproc(rtl, "_strcmp", IL._strcmp); |
3285 | getproc(rtl, "_length", IL._length); |
||
3286 | getproc(rtl, "_arrcpy", IL._arrcpy); |
||
3287 | getproc(rtl, "_is", IL._is); |
||
3288 | getproc(rtl, "_guard", IL._guard); |
||
3289 | getproc(rtl, "_guardrec", IL._guardrec); |
||
3290 | getproc(rtl, "_new", IL._new); |
||
3291 | getproc(rtl, "_rot", IL._rot); |
||
3292 | getproc(rtl, "_strcpy", IL._strcpy); |
||
3293 | getproc(rtl, "_move", IL._move); |
||
3294 | getproc(rtl, "_set", IL._set); |
||
3295 | getproc(rtl, "_set1", IL._set1); |
||
3296 | getproc(rtl, "_lengthw", IL._lengthw); |
||
3297 | getproc(rtl, "_strcmpw", IL._strcmpw); |
||
3298 | getproc(rtl, "_init", IL._init); |
||
3299 | |||
3300 | IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN |
||
3301 | getproc(rtl, "_error", IL._error); |
||
3302 | getproc(rtl, "_divmod", IL._divmod); |
||
3303 | getproc(rtl, "_exit", IL._exit); |
||
3304 | getproc(rtl, "_dispose", IL._dispose); |
||
3305 | getproc(rtl, "_isrec", IL._isrec); |
||
3306 | getproc(rtl, "_dllentry", IL._dllentry); |
||
3307 | getproc(rtl, "_sofinit", IL._sofinit) |
||
8859 | leency | 3308 | ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN |
7983 | leency | 3309 | getproc(rtl, "_fmul", IL._fmul); |
3310 | getproc(rtl, "_fdiv", IL._fdiv); |
||
3311 | getproc(rtl, "_fdivi", IL._fdivi); |
||
3312 | getproc(rtl, "_fadd", IL._fadd); |
||
3313 | getproc(rtl, "_fsub", IL._fsub); |
||
3314 | getproc(rtl, "_fsubi", IL._fsubi); |
||
3315 | getproc(rtl, "_fcmp", IL._fcmp); |
||
3316 | getproc(rtl, "_floor", IL._floor); |
||
3317 | getproc(rtl, "_flt", IL._flt); |
||
3318 | getproc(rtl, "_pack", IL._pack); |
||
8097 | maxcodehac | 3319 | getproc(rtl, "_unpk", IL._unpk); |
8859 | leency | 3320 | IF CPU IN {TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN |
8097 | maxcodehac | 3321 | getproc(rtl, "_error", IL._error) |
3322 | END |
||
7693 | akron1 | 3323 | END |
7597 | akron1 | 3324 | |
3325 | END setrtl; |
||
3326 | |||
3327 | |||
7693 | akron1 | 3328 | PROCEDURE compile* (path, lib_path, modname, outname: PARS.PATH; target: INTEGER; options: PROG.OPTIONS); |
7597 | akron1 | 3329 | VAR |
7693 | akron1 | 3330 | parser: PARS.PARSER; |
7597 | akron1 | 3331 | ext: PARS.PATH; |
3332 | |||
3333 | BEGIN |
||
8097 | maxcodehac | 3334 | tINTEGER := PROG.program.stTypes.tINTEGER; |
3335 | tBYTE := PROG.program.stTypes.tBYTE; |
||
3336 | tCHAR := PROG.program.stTypes.tCHAR; |
||
3337 | tSET := PROG.program.stTypes.tSET; |
||
3338 | tBOOLEAN := PROG.program.stTypes.tBOOLEAN; |
||
3339 | tWCHAR := PROG.program.stTypes.tWCHAR; |
||
3340 | tREAL := PROG.program.stTypes.tREAL; |
||
7693 | akron1 | 3341 | |
3342 | Options := options; |
||
7983 | leency | 3343 | CPU := TARGETS.CPU; |
7693 | akron1 | 3344 | |
7983 | leency | 3345 | ext := UTILS.FILE_EXT; |
7597 | akron1 | 3346 | CaseLabels := C.create(); |
3347 | CaseVar := C.create(); |
||
3348 | |||
3349 | CaseVariants := LISTS.create(NIL); |
||
3350 | LISTS.push(CaseVariants, NewVariant(0, NIL)); |
||
3351 | |||
7983 | leency | 3352 | IL.init(CPU); |
7597 | akron1 | 3353 | |
8097 | maxcodehac | 3354 | IF TARGETS.RTL THEN |
7693 | akron1 | 3355 | parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); |
8859 | leency | 3356 | IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN |
7597 | akron1 | 3357 | parser.parse(parser); |
3358 | PARS.destroy(parser) |
||
3359 | ELSE |
||
7693 | akron1 | 3360 | PARS.destroy(parser); |
3361 | parser := PARS.create(lib_path, lib_path, StatSeq, expression, designator, chkreturn); |
||
8859 | leency | 3362 | IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN |
7693 | akron1 | 3363 | parser.parse(parser); |
3364 | PARS.destroy(parser) |
||
3365 | ELSE |
||
7983 | leency | 3366 | ERRORS.FileNotFound(lib_path, UTILS.RTL_NAME, UTILS.FILE_EXT) |
7693 | akron1 | 3367 | END |
7597 | akron1 | 3368 | END |
3369 | END; |
||
3370 | |||
3371 | parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); |
||
3372 | parser.main := TRUE; |
||
3373 | |||
8859 | leency | 3374 | IF parser.open(parser, modname, UTILS.FILE_EXT) THEN |
7597 | akron1 | 3375 | parser.parse(parser) |
3376 | ELSE |
||
7983 | leency | 3377 | ERRORS.FileNotFound(path, modname, UTILS.FILE_EXT) |
7597 | akron1 | 3378 | END; |
3379 | |||
3380 | PARS.destroy(parser); |
||
3381 | |||
8097 | maxcodehac | 3382 | IF PROG.program.bss > UTILS.MAX_GLOBAL_SIZE THEN |
7693 | akron1 | 3383 | ERRORS.Error(204) |
7597 | akron1 | 3384 | END; |
3385 | |||
8097 | maxcodehac | 3386 | IF TARGETS.RTL THEN |
7693 | akron1 | 3387 | setrtl |
3388 | END; |
||
7597 | akron1 | 3389 | |
8097 | maxcodehac | 3390 | PROG.DelUnused(IL.DelImport); |
7597 | akron1 | 3391 | |
8097 | maxcodehac | 3392 | IL.set_bss(PROG.program.bss); |
7693 | akron1 | 3393 | |
3394 | CASE CPU OF |
||
7983 | leency | 3395 | |TARGETS.cpuAMD64: AMD64.CodeGen(outname, target, options) |
3396 | |TARGETS.cpuX86: X86.CodeGen(outname, target, options) |
||
3397 | |TARGETS.cpuMSP430: MSP430.CodeGen(outname, target, options) |
||
3398 | |TARGETS.cpuTHUMB: THUMB.CodeGen(outname, target, options) |
||
8859 | leency | 3399 | |TARGETS.cpuRVM32I, |
3400 | TARGETS.cpuRVM64I: RVMxI.CodeGen(outname, target, options) |
||
7597 | akron1 | 3401 | END |
7693 | akron1 | 3402 | |
7597 | akron1 | 3403 | END compile; |
3404 | |||
3405 | |||
7983 | leency | 3406 | END STATEMENTS.=>>>=>>>>=>> |