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