Rev 9893 | 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 | |||
9895 | akron1 | 4 | Copyright (c) 2018-2023, 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: |
||
9895 | akron1 | 1140 | cmd1 := IL.getlast(); |
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 |
||
9895 | akron1 | 1151 | cmd2 := IL.getlast(); |
1152 | IL.setlast(cmd1); |
||
1153 | IL.AddCmd(IL.opPRECALL, 0); |
||
1154 | IL.AddCmd0(IL.opRES); |
||
1155 | IL.drop; |
||
1156 | IL.setlast(cmd2); |
||
8097 | maxcodehac | 1157 | IL._ord |
7597 | akron1 | 1158 | END |
1159 | END; |
||
8097 | maxcodehac | 1160 | e._type := tINTEGER |
7597 | akron1 | 1161 | |
1162 | |PROG.stBITS: |
||
7693 | akron1 | 1163 | PExpression(parser, e); |
1164 | PARS.check(isInt(e), pos, 66); |
||
7597 | akron1 | 1165 | IF e.obj = eCONST THEN |
1166 | ARITH.bits(e.value) |
||
1167 | END; |
||
8097 | maxcodehac | 1168 | e._type := tSET |
7597 | akron1 | 1169 | |
1170 | |PROG.sysADR: |
||
1171 | parser.designator(parser, e); |
||
1172 | IF isVar(e) THEN |
||
8097 | maxcodehac | 1173 | n := PROG.Dim(e._type); |
1174 | WHILE n > 0 DO |
||
7693 | akron1 | 1175 | IL.drop; |
7597 | akron1 | 1176 | DEC(n) |
8097 | maxcodehac | 1177 | END |
7597 | akron1 | 1178 | ELSIF e.obj = ePROC THEN |
7693 | akron1 | 1179 | IL.PushProc(e.ident.proc.label) |
7597 | akron1 | 1180 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 1181 | IL.PushImpProc(e.ident._import) |
7597 | akron1 | 1182 | ELSE |
7693 | akron1 | 1183 | PARS.error(pos, 108) |
7597 | akron1 | 1184 | END; |
8097 | maxcodehac | 1185 | e._type := tINTEGER |
7597 | akron1 | 1186 | |
1187 | |PROG.sysSADR: |
||
7693 | akron1 | 1188 | PExpression(parser, e); |
1189 | PARS.check(isString(e), pos, 66); |
||
1190 | IL.StrAdr(String(e)); |
||
8097 | maxcodehac | 1191 | e._type := tINTEGER; |
7597 | akron1 | 1192 | e.obj := eEXPR |
1193 | |||
1194 | |PROG.sysWSADR: |
||
7693 | akron1 | 1195 | PExpression(parser, e); |
1196 | PARS.check(isStringW(e), pos, 66); |
||
1197 | IL.StrAdr(StringW(e)); |
||
8097 | maxcodehac | 1198 | e._type := tINTEGER; |
7597 | akron1 | 1199 | e.obj := eEXPR |
1200 | |||
1201 | |PROG.sysTYPEID: |
||
7693 | akron1 | 1202 | PExpression(parser, e); |
1203 | PARS.check(e.obj = eTYPE, pos, 68); |
||
8097 | maxcodehac | 1204 | IF e._type.typ = PROG.tRECORD THEN |
1205 | ASSERT(ARITH.setInt(e.value, e._type.num)) |
||
1206 | ELSIF e._type.typ = PROG.tPOINTER THEN |
||
1207 | ASSERT(ARITH.setInt(e.value, e._type.base.num)) |
||
7597 | akron1 | 1208 | ELSE |
7693 | akron1 | 1209 | PARS.error(pos, 52) |
7597 | akron1 | 1210 | END; |
1211 | e.obj := eCONST; |
||
8097 | maxcodehac | 1212 | e._type := tINTEGER |
7597 | akron1 | 1213 | |
1214 | |PROG.sysINF: |
||
8097 | maxcodehac | 1215 | IL.AddCmd2(IL.opINF, pos.line, pos.col); |
7597 | akron1 | 1216 | e.obj := eEXPR; |
8097 | maxcodehac | 1217 | e._type := tREAL |
7597 | akron1 | 1218 | |
1219 | |PROG.sysSIZE: |
||
7693 | akron1 | 1220 | PExpression(parser, e); |
1221 | PARS.check(e.obj = eTYPE, pos, 68); |
||
8097 | maxcodehac | 1222 | ASSERT(ARITH.setInt(e.value, e._type.size)); |
7597 | akron1 | 1223 | e.obj := eCONST; |
8097 | maxcodehac | 1224 | e._type := tINTEGER |
7597 | akron1 | 1225 | |
1226 | END |
||
1227 | |||
1228 | END; |
||
1229 | |||
7693 | akron1 | 1230 | (* IF (proc # PROG.sysNOP) & (proc # PROG.sysEINT) & (proc # PROG.sysDINT) THEN *) |
1231 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1232 | PARS.Next(parser); |
||
1233 | (* END; *) |
||
7597 | akron1 | 1234 | |
1235 | IF e.obj # eCONST THEN |
||
1236 | e.obj := eEXPR |
||
1237 | END |
||
1238 | |||
1239 | END stProc; |
||
1240 | |||
1241 | |||
1242 | PROCEDURE ActualParameters (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1243 | VAR |
||
8097 | maxcodehac | 1244 | proc: PROG._TYPE; |
7597 | akron1 | 1245 | param: LISTS.ITEM; |
1246 | e1: PARS.EXPR; |
||
7693 | akron1 | 1247 | pos: PARS.POSITION; |
7597 | akron1 | 1248 | |
1249 | BEGIN |
||
1250 | ASSERT(parser.sym = SCAN.lxLROUND); |
||
1251 | |||
1252 | IF (e.obj IN {ePROC, eIMP}) OR isExpr(e) THEN |
||
8097 | maxcodehac | 1253 | proc := e._type; |
7597 | akron1 | 1254 | PARS.check1(proc.typ = PROG.tPROCEDURE, parser, 86); |
1255 | PARS.Next(parser); |
||
1256 | |||
1257 | param := proc.params.first; |
||
1258 | WHILE param # NIL DO |
||
1259 | getpos(parser, pos); |
||
1260 | |||
7693 | akron1 | 1261 | IL.setlast(begcall); |
7597 | akron1 | 1262 | |
1263 | IF param(PROG.PARAM).vPar THEN |
||
1264 | parser.designator(parser, e1) |
||
1265 | ELSE |
||
7693 | akron1 | 1266 | PExpression(parser, e1) |
7597 | akron1 | 1267 | END; |
1268 | paramcomp(parser, pos, e1, param(PROG.PARAM)); |
||
1269 | param := param.next; |
||
1270 | IF param # NIL THEN |
||
1271 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
1272 | PARS.Next(parser) |
||
1273 | END |
||
1274 | END; |
||
1275 | |||
1276 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1277 | PARS.Next(parser); |
||
1278 | |||
1279 | e.obj := eEXPR; |
||
8097 | maxcodehac | 1280 | e._type := proc.base |
7597 | akron1 | 1281 | |
1282 | ELSIF e.obj IN {eSTPROC, eSTFUNC, eSYSPROC, eSYSFUNC} THEN |
||
1283 | stProc(parser, e) |
||
1284 | ELSE |
||
1285 | PARS.check1(FALSE, parser, 86) |
||
1286 | END |
||
1287 | |||
1288 | END ActualParameters; |
||
1289 | |||
1290 | |||
1291 | PROCEDURE qualident (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1292 | VAR |
||
8097 | maxcodehac | 1293 | ident: PROG.IDENT; |
1294 | imp: BOOLEAN; |
||
1295 | pos: PARS.POSITION; |
||
7597 | akron1 | 1296 | |
1297 | BEGIN |
||
1298 | PARS.checklex(parser, SCAN.lxIDENT); |
||
1299 | getpos(parser, pos); |
||
8097 | maxcodehac | 1300 | imp := FALSE; |
7693 | akron1 | 1301 | ident := PROG.getIdent(parser.unit, parser.lex.ident, FALSE); |
7597 | akron1 | 1302 | PARS.check1(ident # NIL, parser, 48); |
1303 | IF ident.typ = PROG.idMODULE THEN |
||
1304 | PARS.ExpectSym(parser, SCAN.lxPOINT); |
||
1305 | PARS.ExpectSym(parser, SCAN.lxIDENT); |
||
7693 | akron1 | 1306 | ident := PROG.getIdent(ident.unit, parser.lex.ident, FALSE); |
7597 | akron1 | 1307 | PARS.check1((ident # NIL) & ident.export, parser, 48); |
8097 | maxcodehac | 1308 | imp := TRUE |
7597 | akron1 | 1309 | END; |
1310 | PARS.Next(parser); |
||
1311 | |||
1312 | e.readOnly := FALSE; |
||
1313 | e.ident := ident; |
||
1314 | |||
1315 | CASE ident.typ OF |
||
1316 | |PROG.idCONST: |
||
1317 | e.obj := eCONST; |
||
8097 | maxcodehac | 1318 | e._type := ident._type; |
7597 | akron1 | 1319 | e.value := ident.value |
1320 | |PROG.idTYPE: |
||
8097 | maxcodehac | 1321 | e.obj := eTYPE; |
1322 | e._type := ident._type |
||
7597 | akron1 | 1323 | |PROG.idVAR: |
8097 | maxcodehac | 1324 | e.obj := eVAR; |
1325 | e._type := ident._type; |
||
1326 | e.readOnly := imp |
||
7597 | akron1 | 1327 | |PROG.idPROC: |
1328 | e.obj := ePROC; |
||
8097 | maxcodehac | 1329 | e._type := ident._type |
7597 | akron1 | 1330 | |PROG.idIMP: |
1331 | e.obj := eIMP; |
||
8097 | maxcodehac | 1332 | e._type := ident._type |
7597 | akron1 | 1333 | |PROG.idVPAR: |
8097 | maxcodehac | 1334 | e._type := ident._type; |
1335 | IF e._type.typ = PROG.tRECORD THEN |
||
7597 | akron1 | 1336 | e.obj := eVREC |
1337 | ELSE |
||
1338 | e.obj := eVPAR |
||
1339 | END |
||
1340 | |PROG.idPARAM: |
||
8097 | maxcodehac | 1341 | e.obj := ePARAM; |
1342 | e._type := ident._type; |
||
1343 | e.readOnly := (e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) |
||
7597 | akron1 | 1344 | |PROG.idSTPROC: |
1345 | e.obj := eSTPROC; |
||
8097 | maxcodehac | 1346 | e._type := ident._type; |
7597 | akron1 | 1347 | e.stproc := ident.stproc |
1348 | |PROG.idSTFUNC: |
||
1349 | e.obj := eSTFUNC; |
||
8097 | maxcodehac | 1350 | e._type := ident._type; |
7597 | akron1 | 1351 | e.stproc := ident.stproc |
1352 | |PROG.idSYSPROC: |
||
1353 | e.obj := eSYSPROC; |
||
8097 | maxcodehac | 1354 | e._type := ident._type; |
7597 | akron1 | 1355 | e.stproc := ident.stproc |
1356 | |PROG.idSYSFUNC: |
||
7693 | akron1 | 1357 | PARS.check(~parser.constexp, pos, 109); |
7597 | akron1 | 1358 | e.obj := eSYSFUNC; |
8097 | maxcodehac | 1359 | e._type := ident._type; |
7597 | akron1 | 1360 | e.stproc := ident.stproc |
1361 | |PROG.idNONE: |
||
7693 | akron1 | 1362 | PARS.error(pos, 115) |
7597 | akron1 | 1363 | END; |
1364 | |||
1365 | IF isVar(e) THEN |
||
7693 | akron1 | 1366 | PARS.check(e.ident.global OR (e.ident.scopeLvl = parser.unit.scopeLvl), pos, 105) |
7597 | akron1 | 1367 | END |
1368 | |||
1369 | END qualident; |
||
1370 | |||
1371 | |||
7693 | akron1 | 1372 | PROCEDURE deref (pos: PARS.POSITION; e: PARS.EXPR; load: BOOLEAN; error: INTEGER); |
7597 | akron1 | 1373 | VAR |
7983 | leency | 1374 | label: INTEGER; |
7597 | akron1 | 1375 | |
1376 | BEGIN |
||
1377 | IF load THEN |
||
8097 | maxcodehac | 1378 | IL.load(e._type.size) |
7597 | akron1 | 1379 | END; |
1380 | |||
7693 | akron1 | 1381 | IF chkPTR IN Options.checking THEN |
1382 | label := IL.NewLabel(); |
||
8859 | leency | 1383 | IL.Jmp(IL.opJNZ1, label); |
7693 | akron1 | 1384 | IL.OnError(pos.line, error); |
1385 | IL.SetLabel(label) |
||
7597 | akron1 | 1386 | END |
1387 | END deref; |
||
1388 | |||
1389 | |||
1390 | PROCEDURE designator (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1391 | VAR |
||
1392 | field: PROG.FIELD; |
||
7693 | akron1 | 1393 | pos: PARS.POSITION; |
7597 | akron1 | 1394 | t, idx: PARS.EXPR; |
9893 | akron1 | 1395 | sysVal: BOOLEAN; |
1396 | n: INTEGER; |
||
7597 | akron1 | 1397 | |
1398 | |||
1399 | PROCEDURE LoadAdr (e: PARS.EXPR); |
||
1400 | VAR |
||
1401 | offset: INTEGER; |
||
1402 | |||
1403 | PROCEDURE OpenArray (e: PARS.EXPR); |
||
1404 | VAR |
||
1405 | offset, n: INTEGER; |
||
1406 | BEGIN |
||
1407 | offset := e.ident.offset; |
||
8097 | maxcodehac | 1408 | n := PROG.Dim(e._type); |
7597 | akron1 | 1409 | WHILE n >= 0 DO |
7693 | akron1 | 1410 | IL.AddCmd(IL.opVADR, offset); |
7597 | akron1 | 1411 | DEC(offset); |
1412 | DEC(n) |
||
1413 | END |
||
1414 | END OpenArray; |
||
1415 | |||
1416 | |||
1417 | BEGIN |
||
1418 | IF e.obj = eVAR THEN |
||
8097 | maxcodehac | 1419 | offset := PROG.getOffset(e.ident); |
7597 | akron1 | 1420 | IF e.ident.global THEN |
7693 | akron1 | 1421 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 1422 | ELSE |
7693 | akron1 | 1423 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 1424 | END |
1425 | ELSIF e.obj = ePARAM THEN |
||
8097 | maxcodehac | 1426 | IF (e._type.typ = PROG.tRECORD) OR ((e._type.typ = PROG.tARRAY) & (e._type.length > 0)) THEN |
7693 | akron1 | 1427 | IL.AddCmd(IL.opVADR, e.ident.offset) |
8097 | maxcodehac | 1428 | ELSIF PROG.isOpenArray(e._type) THEN |
7597 | akron1 | 1429 | OpenArray(e) |
1430 | ELSE |
||
7693 | akron1 | 1431 | IL.AddCmd(IL.opLADR, e.ident.offset) |
7597 | akron1 | 1432 | END |
1433 | ELSIF e.obj IN {eVPAR, eVREC} THEN |
||
8097 | maxcodehac | 1434 | IF PROG.isOpenArray(e._type) THEN |
7597 | akron1 | 1435 | OpenArray(e) |
1436 | ELSE |
||
7693 | akron1 | 1437 | IL.AddCmd(IL.opVADR, e.ident.offset) |
7597 | akron1 | 1438 | END |
1439 | END |
||
1440 | END LoadAdr; |
||
1441 | |||
1442 | |||
7693 | akron1 | 1443 | PROCEDURE OpenIdx (parser: PARS.PARSER; pos: PARS.POSITION; e: PARS.EXPR); |
7597 | akron1 | 1444 | VAR |
7983 | leency | 1445 | label, offset, n, k: INTEGER; |
8097 | maxcodehac | 1446 | _type: PROG._TYPE; |
7597 | akron1 | 1447 | |
1448 | BEGIN |
||
7693 | akron1 | 1449 | IF chkIDX IN Options.checking THEN |
1450 | label := IL.NewLabel(); |
||
1451 | IL.AddCmd2(IL.opCHKIDX2, label, 0); |
||
1452 | IL.OnError(pos.line, errIDX); |
||
1453 | IL.SetLabel(label) |
||
7597 | akron1 | 1454 | ELSE |
7693 | akron1 | 1455 | IL.AddCmd(IL.opCHKIDX2, -1) |
7597 | akron1 | 1456 | END; |
1457 | |||
8097 | maxcodehac | 1458 | _type := PROG.OpenBase(e._type); |
1459 | IF _type.size # 1 THEN |
||
1460 | IL.AddCmd(IL.opMULC, _type.size) |
||
7597 | akron1 | 1461 | END; |
8097 | maxcodehac | 1462 | n := PROG.Dim(e._type) - 1; |
7597 | akron1 | 1463 | k := n; |
1464 | WHILE n > 0 DO |
||
7693 | akron1 | 1465 | IL.AddCmd0(IL.opMUL); |
7597 | akron1 | 1466 | DEC(n) |
1467 | END; |
||
7693 | akron1 | 1468 | IL.AddCmd0(IL.opADD); |
7597 | akron1 | 1469 | offset := e.ident.offset - 1; |
1470 | n := k; |
||
1471 | WHILE n > 0 DO |
||
7693 | akron1 | 1472 | IL.AddCmd(IL.opVADR, offset); |
7597 | akron1 | 1473 | DEC(offset); |
1474 | DEC(n) |
||
1475 | END |
||
1476 | END OpenIdx; |
||
1477 | |||
1478 | |||
1479 | BEGIN |
||
1480 | qualident(parser, e); |
||
9893 | akron1 | 1481 | sysVal := (e.obj = eSYSPROC) & (e.stproc = PROG.sysVAL); |
1482 | IF sysVal THEN |
||
1483 | PARS.checklex(parser, SCAN.lxLROUND); |
||
1484 | PARS.Next(parser); |
||
1485 | getpos(parser, pos); |
||
1486 | designator(parser, e); |
||
1487 | PARS.check(isVar(e), pos, 93); |
||
1488 | IF PROG.isOpenArray(e._type) THEN |
||
1489 | n := PROG.Dim(e._type); |
||
1490 | WHILE n > 0 DO |
||
1491 | IL.drop; |
||
1492 | DEC(n) |
||
1493 | END |
||
1494 | END; |
||
1495 | PARS.checklex(parser, SCAN.lxCOMMA); |
||
1496 | PARS.Next(parser); |
||
1497 | getpos(parser, pos); |
||
1498 | qualident(parser, t); |
||
1499 | PARS.check(t.obj = eTYPE, pos, 79); |
||
1500 | e._type := t._type; |
||
1501 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1502 | PARS.Next(parser) |
||
1503 | END; |
||
7597 | akron1 | 1504 | |
1505 | IF e.obj IN {ePROC, eIMP} THEN |
||
1506 | PROG.UseProc(parser.unit, e.ident.proc) |
||
1507 | END; |
||
1508 | |||
9893 | akron1 | 1509 | IF isVar(e) & ~sysVal THEN |
7597 | akron1 | 1510 | LoadAdr(e) |
1511 | END; |
||
1512 | |||
1513 | WHILE parser.sym = SCAN.lxPOINT DO |
||
1514 | getpos(parser, pos); |
||
8097 | maxcodehac | 1515 | PARS.check1(isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}), parser, 73); |
1516 | IF e._type.typ = PROG.tPOINTER THEN |
||
7597 | akron1 | 1517 | deref(pos, e, TRUE, errPTR) |
1518 | END; |
||
1519 | PARS.ExpectSym(parser, SCAN.lxIDENT); |
||
8097 | maxcodehac | 1520 | IF e._type.typ = PROG.tPOINTER THEN |
1521 | e._type := e._type.base; |
||
7597 | akron1 | 1522 | e.readOnly := FALSE |
1523 | END; |
||
8097 | maxcodehac | 1524 | field := PROG.getField(e._type, parser.lex.ident, parser.unit); |
7597 | akron1 | 1525 | PARS.check1(field # NIL, parser, 74); |
8097 | maxcodehac | 1526 | e._type := field._type; |
7597 | akron1 | 1527 | IF e.obj = eVREC THEN |
1528 | e.obj := eVPAR |
||
1529 | END; |
||
1530 | IF field.offset # 0 THEN |
||
8097 | maxcodehac | 1531 | IL.AddCmd(IL.opADDC, field.offset) |
7597 | akron1 | 1532 | END; |
1533 | PARS.Next(parser); |
||
1534 | e.ident := NIL |
||
1535 | |||
1536 | ELSIF parser.sym = SCAN.lxLSQUARE DO |
||
1537 | |||
1538 | REPEAT |
||
1539 | |||
1540 | PARS.check1(isArr(e), parser, 75); |
||
1541 | NextPos(parser, pos); |
||
7693 | akron1 | 1542 | PExpression(parser, idx); |
1543 | PARS.check(isInt(idx), pos, 76); |
||
7597 | akron1 | 1544 | |
1545 | IF idx.obj = eCONST THEN |
||
8097 | maxcodehac | 1546 | IF e._type.length > 0 THEN |
1547 | PARS.check(ARITH.range(idx.value, 0, e._type.length - 1), pos, 83); |
||
7597 | akron1 | 1548 | IF ARITH.Int(idx.value) > 0 THEN |
8097 | maxcodehac | 1549 | IL.AddCmd(IL.opADDC, ARITH.Int(idx.value) * e._type.base.size) |
7597 | akron1 | 1550 | END |
1551 | ELSE |
||
7693 | akron1 | 1552 | PARS.check(ARITH.range(idx.value, 0, UTILS.target.maxInt), pos, 83); |
7597 | akron1 | 1553 | LoadConst(idx); |
1554 | OpenIdx(parser, pos, e) |
||
1555 | END |
||
1556 | ELSE |
||
8097 | maxcodehac | 1557 | IF e._type.length > 0 THEN |
7693 | akron1 | 1558 | IF chkIDX IN Options.checking THEN |
8097 | maxcodehac | 1559 | CheckRange(e._type.length, pos.line, errIDX) |
7597 | akron1 | 1560 | END; |
8097 | maxcodehac | 1561 | IF e._type.base.size # 1 THEN |
1562 | IL.AddCmd(IL.opMULC, e._type.base.size) |
||
7597 | akron1 | 1563 | END; |
7693 | akron1 | 1564 | IL.AddCmd0(IL.opADD) |
7597 | akron1 | 1565 | ELSE |
1566 | OpenIdx(parser, pos, e) |
||
1567 | END |
||
1568 | END; |
||
1569 | |||
8097 | maxcodehac | 1570 | e._type := e._type.base |
7597 | akron1 | 1571 | |
1572 | UNTIL parser.sym # SCAN.lxCOMMA; |
||
1573 | |||
1574 | PARS.checklex(parser, SCAN.lxRSQUARE); |
||
1575 | PARS.Next(parser); |
||
8859 | leency | 1576 | IF ~(isArr(e) & (e._type.length = 0) & (parser.sym = SCAN.lxLSQUARE)) THEN |
1577 | e.ident := NIL |
||
1578 | END |
||
7597 | akron1 | 1579 | |
1580 | ELSIF parser.sym = SCAN.lxCARET DO |
||
1581 | getpos(parser, pos); |
||
1582 | PARS.check1(isPtr(e), parser, 77); |
||
1583 | deref(pos, e, TRUE, errPTR); |
||
8097 | maxcodehac | 1584 | e._type := e._type.base; |
7597 | akron1 | 1585 | e.readOnly := FALSE; |
1586 | PARS.Next(parser); |
||
1587 | e.ident := NIL; |
||
1588 | e.obj := eVREC |
||
1589 | |||
8097 | maxcodehac | 1590 | ELSIF (parser.sym = SCAN.lxLROUND) & isExpr(e) & (e._type.typ IN {PROG.tRECORD, PROG.tPOINTER}) DO |
7597 | akron1 | 1591 | |
8097 | maxcodehac | 1592 | IF e._type.typ = PROG.tRECORD THEN |
7597 | akron1 | 1593 | PARS.check1(e.obj = eVREC, parser, 78) |
1594 | END; |
||
1595 | NextPos(parser, pos); |
||
1596 | qualident(parser, t); |
||
7693 | akron1 | 1597 | PARS.check(t.obj = eTYPE, pos, 79); |
7597 | akron1 | 1598 | |
8097 | maxcodehac | 1599 | IF e._type.typ = PROG.tRECORD THEN |
1600 | PARS.check(t._type.typ = PROG.tRECORD, pos, 80); |
||
7693 | akron1 | 1601 | IF chkGUARD IN Options.checking THEN |
7597 | akron1 | 1602 | IF e.ident = NIL THEN |
8097 | maxcodehac | 1603 | IL.TypeGuard(IL.opTYPEGD, t._type.num, pos.line, errGUARD) |
7597 | akron1 | 1604 | ELSE |
7693 | akron1 | 1605 | IL.AddCmd(IL.opVADR, e.ident.offset - 1); |
8097 | maxcodehac | 1606 | IL.TypeGuard(IL.opTYPEGR, t._type.num, pos.line, errGUARD) |
7597 | akron1 | 1607 | END |
1608 | END; |
||
1609 | ELSE |
||
8097 | maxcodehac | 1610 | PARS.check(t._type.typ = PROG.tPOINTER, pos, 81); |
7693 | akron1 | 1611 | IF chkGUARD IN Options.checking THEN |
8097 | maxcodehac | 1612 | IL.TypeGuard(IL.opTYPEGP, t._type.base.num, pos.line, errGUARD) |
7597 | akron1 | 1613 | END |
1614 | END; |
||
1615 | |||
8097 | maxcodehac | 1616 | PARS.check(PROG.isBaseOf(e._type, t._type), pos, 82); |
7597 | akron1 | 1617 | |
8097 | maxcodehac | 1618 | e._type := t._type; |
7597 | akron1 | 1619 | |
1620 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1621 | PARS.Next(parser) |
||
1622 | |||
1623 | END |
||
1624 | |||
1625 | END designator; |
||
1626 | |||
1627 | |||
8097 | maxcodehac | 1628 | PROCEDURE ProcCall (e: PARS.EXPR; procType: PROG._TYPE; isfloat: BOOLEAN; parser: PARS.PARSER; pos: PARS.POSITION; CallStat: BOOLEAN); |
7597 | akron1 | 1629 | VAR |
7983 | leency | 1630 | cconv, |
1631 | parSize, |
||
1632 | callconv, |
||
1633 | fparSize, |
||
1634 | int, flt, |
||
1635 | stk_par: INTEGER; |
||
7597 | akron1 | 1636 | |
1637 | BEGIN |
||
1638 | cconv := procType.call; |
||
7693 | akron1 | 1639 | parSize := procType.parSize; |
7597 | akron1 | 1640 | |
1641 | IF cconv IN {PROG._win64, PROG.win64} THEN |
||
7693 | akron1 | 1642 | callconv := IL.call_win64; |
1643 | fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, 3, int, flt)), 5) + MIN(parSize, 4) |
||
7597 | akron1 | 1644 | ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN |
7693 | akron1 | 1645 | callconv := IL.call_sysv; |
1646 | fparSize := LSL(ORD(PROG.getFloatParamsPos(procType, PROG.MAXSYSVPARAM - 1, int, flt)), 5) + parSize; |
||
7597 | akron1 | 1647 | stk_par := MAX(0, int - 6) + MAX(0, flt - 8) |
9847 | akron1 | 1648 | ELSIF cconv IN {PROG.fastcall, PROG._fastcall} THEN |
1649 | IF parSize = 0 THEN |
||
1650 | callconv := IL.call_stack |
||
1651 | ELSIF parSize = 1 THEN |
||
1652 | callconv := IL.call_fast1 |
||
1653 | ELSIF parSize >= 2 THEN |
||
1654 | callconv := IL.call_fast2 |
||
1655 | END; |
||
1656 | fparSize := 0 |
||
7597 | akron1 | 1657 | ELSE |
7693 | akron1 | 1658 | callconv := IL.call_stack; |
1659 | fparSize := 0 |
||
7597 | akron1 | 1660 | END; |
7693 | akron1 | 1661 | IL.setlast(begcall); |
8097 | maxcodehac | 1662 | IL.AddCmd(IL.opPRECALL, ORD(isfloat)); |
7597 | akron1 | 1663 | |
8859 | leency | 1664 | IF cconv IN {PROG._ccall, PROG.ccall} THEN |
7693 | akron1 | 1665 | IL.AddCmd(IL.opALIGN16, parSize) |
7597 | akron1 | 1666 | ELSIF cconv IN {PROG._win64, PROG.win64} THEN |
7693 | akron1 | 1667 | IL.AddCmd(IL.opWIN64ALIGN16, parSize) |
7597 | akron1 | 1668 | ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN |
7693 | akron1 | 1669 | IL.AddCmd(IL.opSYSVALIGN16, parSize + stk_par) |
7597 | akron1 | 1670 | END; |
7693 | akron1 | 1671 | IL.setlast(endcall.prev(IL.COMMAND)); |
7597 | akron1 | 1672 | |
1673 | IF e.obj = eIMP THEN |
||
8097 | maxcodehac | 1674 | IL.CallImp(e.ident._import, callconv, fparSize) |
7597 | akron1 | 1675 | ELSIF e.obj = ePROC THEN |
7693 | akron1 | 1676 | IL.Call(e.ident.proc.label, callconv, fparSize) |
7597 | akron1 | 1677 | ELSIF isExpr(e) THEN |
1678 | deref(pos, e, CallStat, errPROC); |
||
7693 | akron1 | 1679 | IL.CallP(callconv, fparSize) |
7597 | akron1 | 1680 | END; |
1681 | |||
8859 | leency | 1682 | IF cconv IN {PROG._ccall, PROG.ccall} THEN |
7693 | akron1 | 1683 | IL.AddCmd(IL.opCLEANUP, parSize); |
1684 | IL.AddCmd0(IL.opPOPSP) |
||
7597 | akron1 | 1685 | ELSIF cconv IN {PROG._win64, PROG.win64} THEN |
7693 | akron1 | 1686 | IL.AddCmd(IL.opCLEANUP, MAX(parSize + parSize MOD 2, 4) + 1); |
1687 | IL.AddCmd0(IL.opPOPSP) |
||
7597 | akron1 | 1688 | ELSIF cconv IN {PROG._systemv, PROG.systemv} THEN |
7693 | akron1 | 1689 | IL.AddCmd(IL.opCLEANUP, parSize + stk_par); |
1690 | IL.AddCmd0(IL.opPOPSP) |
||
8859 | leency | 1691 | ELSIF cconv IN {PROG._cdecl, PROG.cdecl, PROG.default16, PROG.code, PROG._code} THEN |
7693 | akron1 | 1692 | IL.AddCmd(IL.opCLEANUP, parSize) |
7597 | akron1 | 1693 | END; |
1694 | |||
8097 | maxcodehac | 1695 | IF CallStat THEN |
1696 | IL.AddCmd0(IL.opRES); |
||
1697 | IL.drop |
||
1698 | ELSE |
||
7597 | akron1 | 1699 | IF isfloat THEN |
8097 | maxcodehac | 1700 | IL.AddCmd2(IL.opRESF, pos.line, pos.col) |
7597 | akron1 | 1701 | ELSE |
8097 | maxcodehac | 1702 | IL.AddCmd0(IL.opRES) |
7597 | akron1 | 1703 | END |
1704 | END |
||
1705 | END ProcCall; |
||
1706 | |||
1707 | |||
1708 | PROCEDURE expression (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1709 | VAR |
||
7693 | akron1 | 1710 | pos, pos0, pos1: PARS.POSITION; |
8097 | maxcodehac | 1711 | e1: PARS.EXPR; |
1712 | op, cmp, error: INTEGER; |
||
1713 | constant, eq: BOOLEAN; |
||
7597 | akron1 | 1714 | |
1715 | |||
1716 | PROCEDURE relation (sym: INTEGER): BOOLEAN; |
||
1717 | RETURN (sym = SCAN.lxEQ) OR (sym = SCAN.lxNE) OR |
||
1718 | (sym = SCAN.lxLT) OR (sym = SCAN.lxLE) OR |
||
1719 | (sym = SCAN.lxGT) OR (sym = SCAN.lxGE) OR |
||
1720 | (sym = SCAN.lxIN) OR (sym = SCAN.lxIS) |
||
1721 | END relation; |
||
1722 | |||
1723 | |||
1724 | PROCEDURE AddOperator (sym: INTEGER): BOOLEAN; |
||
1725 | RETURN (sym = SCAN.lxPLUS) OR (sym = SCAN.lxMINUS) OR |
||
1726 | (sym = SCAN.lxOR) |
||
1727 | END AddOperator; |
||
1728 | |||
1729 | |||
1730 | PROCEDURE MulOperator (sym: INTEGER): BOOLEAN; |
||
1731 | RETURN (sym = SCAN.lxMUL) OR (sym = SCAN.lxSLASH) OR |
||
1732 | (sym = SCAN.lxDIV) OR (sym = SCAN.lxMOD) OR |
||
1733 | (sym = SCAN.lxAND) |
||
1734 | END MulOperator; |
||
1735 | |||
1736 | |||
1737 | PROCEDURE element (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1738 | VAR |
||
1739 | e1, e2: PARS.EXPR; |
||
7693 | akron1 | 1740 | pos: PARS.POSITION; |
7597 | akron1 | 1741 | range: BOOLEAN; |
1742 | |||
1743 | BEGIN |
||
1744 | range := FALSE; |
||
1745 | getpos(parser, pos); |
||
1746 | expression(parser, e1); |
||
7693 | akron1 | 1747 | PARS.check(isInt(e1), pos, 76); |
7597 | akron1 | 1748 | |
1749 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 1750 | PARS.check(ARITH.range(e1.value, 0, UTILS.target.maxSet), pos, 44) |
7597 | akron1 | 1751 | END; |
1752 | |||
1753 | range := parser.sym = SCAN.lxRANGE; |
||
1754 | |||
1755 | IF range THEN |
||
1756 | NextPos(parser, pos); |
||
1757 | expression(parser, e2); |
||
7693 | akron1 | 1758 | PARS.check(isInt(e2), pos, 76); |
7597 | akron1 | 1759 | |
1760 | IF e2.obj = eCONST THEN |
||
7693 | akron1 | 1761 | PARS.check(ARITH.range(e2.value, 0, UTILS.target.maxSet), pos, 44) |
7597 | akron1 | 1762 | END |
1763 | ELSE |
||
1764 | IF e1.obj = eCONST THEN |
||
1765 | e2 := e1 |
||
1766 | END |
||
1767 | END; |
||
1768 | |||
8097 | maxcodehac | 1769 | e._type := tSET; |
7597 | akron1 | 1770 | |
1771 | IF (e1.obj = eCONST) & (e2.obj = eCONST) THEN |
||
1772 | ARITH.constrSet(e.value, e1.value, e2.value); |
||
1773 | e.obj := eCONST |
||
1774 | ELSE |
||
1775 | IF range THEN |
||
1776 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 1777 | IL.AddCmd(IL.opRSETL, ARITH.Int(e1.value)) |
7597 | akron1 | 1778 | ELSIF e2.obj = eCONST THEN |
7693 | akron1 | 1779 | IL.AddCmd(IL.opRSETR, ARITH.Int(e2.value)) |
7597 | akron1 | 1780 | ELSE |
7693 | akron1 | 1781 | IL.AddCmd0(IL.opRSET) |
7597 | akron1 | 1782 | END |
1783 | ELSE |
||
7693 | akron1 | 1784 | IL.AddCmd0(IL.opRSET1) |
7597 | akron1 | 1785 | END; |
1786 | e.obj := eEXPR |
||
1787 | END |
||
1788 | |||
1789 | END element; |
||
1790 | |||
1791 | |||
1792 | PROCEDURE set (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1793 | VAR |
||
1794 | e1: PARS.EXPR; |
||
1795 | |||
1796 | BEGIN |
||
1797 | ASSERT(parser.sym = SCAN.lxLCURLY); |
||
1798 | |||
1799 | e.obj := eCONST; |
||
8097 | maxcodehac | 1800 | e._type := tSET; |
7597 | akron1 | 1801 | ARITH.emptySet(e.value); |
1802 | |||
1803 | PARS.Next(parser); |
||
1804 | IF parser.sym # SCAN.lxRCURLY THEN |
||
1805 | element(parser, e1); |
||
1806 | |||
1807 | IF e1.obj = eCONST THEN |
||
1808 | ARITH.opSet(e.value, e1.value, "+") |
||
1809 | ELSE |
||
1810 | e.obj := eEXPR |
||
1811 | END; |
||
1812 | |||
1813 | WHILE parser.sym = SCAN.lxCOMMA DO |
||
1814 | PARS.Next(parser); |
||
1815 | element(parser, e1); |
||
1816 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
||
1817 | ARITH.opSet(e.value, e1.value, "+") |
||
1818 | ELSE |
||
1819 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 1820 | IL.AddCmd(IL.opADDSC, ARITH.Int(e.value)) |
7597 | akron1 | 1821 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 1822 | IL.AddCmd(IL.opADDSC, ARITH.Int(e1.value)) |
7597 | akron1 | 1823 | ELSE |
7693 | akron1 | 1824 | IL.AddCmd0(IL.opADDS) |
7597 | akron1 | 1825 | END; |
1826 | e.obj := eEXPR |
||
1827 | END |
||
1828 | END; |
||
1829 | PARS.checklex(parser, SCAN.lxRCURLY) |
||
1830 | END; |
||
1831 | PARS.Next(parser); |
||
1832 | END set; |
||
1833 | |||
1834 | |||
1835 | PROCEDURE factor (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1836 | VAR |
||
1837 | sym: INTEGER; |
||
7693 | akron1 | 1838 | pos: PARS.POSITION; |
7597 | akron1 | 1839 | e1: PARS.EXPR; |
1840 | isfloat: BOOLEAN; |
||
1841 | |||
1842 | |||
7693 | akron1 | 1843 | PROCEDURE LoadVar (e: PARS.EXPR; parser: PARS.PARSER; pos: PARS.POSITION); |
7597 | akron1 | 1844 | BEGIN |
8097 | maxcodehac | 1845 | IF ~(e._type.typ IN {PROG.tRECORD, PROG.tARRAY}) THEN |
1846 | IF e._type = tREAL THEN |
||
1847 | IL.AddCmd2(IL.opLOADF, pos.line, pos.col) |
||
7597 | akron1 | 1848 | ELSE |
8097 | maxcodehac | 1849 | IL.load(e._type.size) |
7597 | akron1 | 1850 | END |
1851 | END |
||
1852 | END LoadVar; |
||
1853 | |||
1854 | |||
1855 | BEGIN |
||
1856 | sym := parser.sym; |
||
1857 | |||
1858 | IF (sym = SCAN.lxINTEGER) OR (sym = SCAN.lxHEX) OR (sym = SCAN.lxFLOAT) OR (sym = SCAN.lxCHAR) OR (sym = SCAN.lxSTRING) THEN |
||
1859 | e.obj := eCONST; |
||
1860 | e.value := parser.lex.value; |
||
8097 | maxcodehac | 1861 | e._type := PROG.getType(e.value.typ); |
7597 | akron1 | 1862 | PARS.Next(parser) |
1863 | |||
1864 | ELSIF sym = SCAN.lxNIL THEN |
||
7693 | akron1 | 1865 | e.obj := eCONST; |
8097 | maxcodehac | 1866 | e._type := PROG.program.stTypes.tNIL; |
7597 | akron1 | 1867 | PARS.Next(parser) |
1868 | |||
1869 | ELSIF (sym = SCAN.lxTRUE) OR (sym = SCAN.lxFALSE) THEN |
||
7693 | akron1 | 1870 | e.obj := eCONST; |
7597 | akron1 | 1871 | ARITH.setbool(e.value, sym = SCAN.lxTRUE); |
8097 | maxcodehac | 1872 | e._type := tBOOLEAN; |
7597 | akron1 | 1873 | PARS.Next(parser) |
1874 | |||
1875 | ELSIF sym = SCAN.lxLCURLY THEN |
||
1876 | set(parser, e) |
||
1877 | |||
1878 | ELSIF sym = SCAN.lxIDENT THEN |
||
1879 | getpos(parser, pos); |
||
1880 | |||
7693 | akron1 | 1881 | IL.pushBegEnd(begcall, endcall); |
7597 | akron1 | 1882 | |
1883 | designator(parser, e); |
||
1884 | IF isVar(e) THEN |
||
1885 | LoadVar(e, parser, pos) |
||
1886 | END; |
||
1887 | IF parser.sym = SCAN.lxLROUND THEN |
||
1888 | e1 := e; |
||
1889 | ActualParameters(parser, e); |
||
8097 | maxcodehac | 1890 | PARS.check(e._type # NIL, pos, 59); |
1891 | isfloat := e._type = tREAL; |
||
7597 | akron1 | 1892 | IF e1.obj IN {ePROC, eIMP} THEN |
8097 | maxcodehac | 1893 | ProcCall(e1, e1.ident._type, isfloat, parser, pos, FALSE) |
7597 | akron1 | 1894 | ELSIF isExpr(e1) THEN |
8097 | maxcodehac | 1895 | ProcCall(e1, e1._type, isfloat, parser, pos, FALSE) |
7597 | akron1 | 1896 | END |
1897 | END; |
||
7693 | akron1 | 1898 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 1899 | |
1900 | ELSIF sym = SCAN.lxLROUND THEN |
||
1901 | PARS.Next(parser); |
||
1902 | expression(parser, e); |
||
1903 | PARS.checklex(parser, SCAN.lxRROUND); |
||
1904 | PARS.Next(parser); |
||
1905 | IF isExpr(e) & (e.obj # eCONST) THEN |
||
1906 | e.obj := eEXPR |
||
1907 | END |
||
1908 | |||
1909 | ELSIF sym = SCAN.lxNOT THEN |
||
1910 | NextPos(parser, pos); |
||
1911 | factor(parser, e); |
||
7693 | akron1 | 1912 | PARS.check(isBoolean(e), pos, 72); |
7597 | akron1 | 1913 | IF e.obj # eCONST THEN |
7693 | akron1 | 1914 | IL.not; |
7597 | akron1 | 1915 | e.obj := eEXPR |
1916 | ELSE |
||
1917 | ASSERT(ARITH.neg(e.value)) |
||
1918 | END |
||
1919 | |||
1920 | ELSE |
||
1921 | PARS.check1(FALSE, parser, 34) |
||
1922 | END |
||
1923 | END factor; |
||
1924 | |||
1925 | |||
1926 | PROCEDURE term (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
1927 | VAR |
||
7693 | akron1 | 1928 | pos: PARS.POSITION; |
7597 | akron1 | 1929 | e1: PARS.EXPR; |
7983 | leency | 1930 | op, label, label1: INTEGER; |
7597 | akron1 | 1931 | |
1932 | BEGIN |
||
1933 | factor(parser, e); |
||
1934 | label := -1; |
||
1935 | |||
1936 | WHILE MulOperator(parser.sym) DO |
||
1937 | op := parser.sym; |
||
1938 | getpos(parser, pos); |
||
1939 | PARS.Next(parser); |
||
1940 | |||
1941 | IF op = SCAN.lxAND THEN |
||
1942 | IF ~parser.constexp THEN |
||
1943 | |||
1944 | IF label = -1 THEN |
||
7693 | akron1 | 1945 | label := IL.NewLabel() |
7597 | akron1 | 1946 | END; |
1947 | |||
8859 | leency | 1948 | IF (e.obj = eCONST) & isBoolean(e) THEN |
7693 | akron1 | 1949 | IL.Const(ORD(ARITH.getBool(e.value))) |
1950 | END; |
||
8859 | leency | 1951 | IL.Jmp(IL.opJZ, label) |
7597 | akron1 | 1952 | END |
1953 | END; |
||
1954 | |||
1955 | factor(parser, e1); |
||
1956 | |||
1957 | CASE op OF |
||
1958 | |SCAN.lxMUL: |
||
7693 | akron1 | 1959 | PARS.check(isInt(e) & isInt(e1) OR isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); |
7597 | akron1 | 1960 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
1961 | |||
1962 | CASE e.value.typ OF |
||
7693 | akron1 | 1963 | |ARITH.tINTEGER: PARS.check(ARITH.opInt(e.value, e1.value, "*"), pos, 39) |
1964 | |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "*"), pos, 40) |
||
7597 | akron1 | 1965 | |ARITH.tSET: ARITH.opSet(e.value, e1.value, "*") |
1966 | END |
||
1967 | |||
1968 | ELSE |
||
1969 | IF isInt(e) THEN |
||
1970 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 1971 | IL.AddCmd(IL.opMULC, ARITH.Int(e.value)) |
7597 | akron1 | 1972 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 1973 | IL.AddCmd(IL.opMULC, ARITH.Int(e1.value)) |
7597 | akron1 | 1974 | ELSE |
7693 | akron1 | 1975 | IL.AddCmd0(IL.opMUL) |
7597 | akron1 | 1976 | END |
1977 | ELSIF isReal(e) THEN |
||
1978 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 1979 | Float(parser, e) |
7597 | akron1 | 1980 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 1981 | Float(parser, e1) |
7597 | akron1 | 1982 | END; |
8097 | maxcodehac | 1983 | IL.AddCmd0(IL.opMULF) |
7597 | akron1 | 1984 | ELSIF isSet(e) THEN |
1985 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 1986 | IL.AddCmd(IL.opMULSC, ARITH.Int(e.value)) |
7597 | akron1 | 1987 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 1988 | IL.AddCmd(IL.opMULSC, ARITH.Int(e1.value)) |
7597 | akron1 | 1989 | ELSE |
7693 | akron1 | 1990 | IL.AddCmd0(IL.opMULS) |
7597 | akron1 | 1991 | END |
1992 | END; |
||
1993 | e.obj := eEXPR |
||
1994 | END |
||
1995 | |||
1996 | |SCAN.lxSLASH: |
||
7693 | akron1 | 1997 | PARS.check(isReal(e) & isReal(e1) OR isSet(e) & isSet(e1), pos, 37); |
7597 | akron1 | 1998 | IF (e1.obj = eCONST) & isReal(e1) THEN |
7693 | akron1 | 1999 | PARS.check(~ARITH.isZero(e1.value), pos, 45) |
7597 | akron1 | 2000 | END; |
2001 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
||
2002 | |||
2003 | CASE e.value.typ OF |
||
7693 | akron1 | 2004 | |ARITH.tREAL: PARS.check(ARITH.opFloat(e.value, e1.value, "/"), pos, 40) |
7597 | akron1 | 2005 | |ARITH.tSET: ARITH.opSet(e.value, e1.value, "/") |
2006 | END |
||
2007 | |||
2008 | ELSE |
||
2009 | IF isReal(e) THEN |
||
2010 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2011 | Float(parser, e); |
2012 | IL.AddCmd0(IL.opDIVFI) |
||
7597 | akron1 | 2013 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2014 | Float(parser, e1); |
2015 | IL.AddCmd0(IL.opDIVF) |
||
7597 | akron1 | 2016 | ELSE |
8097 | maxcodehac | 2017 | IL.AddCmd0(IL.opDIVF) |
7597 | akron1 | 2018 | END |
2019 | ELSIF isSet(e) THEN |
||
2020 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2021 | IL.AddCmd(IL.opDIVSC, ARITH.Int(e.value)) |
7597 | akron1 | 2022 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 2023 | IL.AddCmd(IL.opDIVSC, ARITH.Int(e1.value)) |
7597 | akron1 | 2024 | ELSE |
7693 | akron1 | 2025 | IL.AddCmd0(IL.opDIVS) |
7597 | akron1 | 2026 | END |
2027 | END; |
||
2028 | e.obj := eEXPR |
||
2029 | END |
||
2030 | |||
2031 | |SCAN.lxDIV, SCAN.lxMOD: |
||
7693 | akron1 | 2032 | PARS.check(isInt(e) & isInt(e1), pos, 37); |
7597 | akron1 | 2033 | IF e1.obj = eCONST THEN |
7983 | leency | 2034 | PARS.check(ARITH.Int(e1.value) > 0, pos, 122) |
7597 | akron1 | 2035 | END; |
2036 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
||
2037 | |||
2038 | IF op = SCAN.lxDIV THEN |
||
7693 | akron1 | 2039 | PARS.check(ARITH.opInt(e.value, e1.value, "D"), pos, 39) |
7597 | akron1 | 2040 | ELSE |
2041 | ASSERT(ARITH.opInt(e.value, e1.value, "M")) |
||
2042 | END |
||
2043 | |||
2044 | ELSE |
||
2045 | IF e1.obj # eCONST THEN |
||
7693 | akron1 | 2046 | label1 := IL.NewLabel(); |
8859 | leency | 2047 | IL.Jmp(IL.opJG, label1) |
7597 | akron1 | 2048 | END; |
2049 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2050 | IL.OnError(pos.line, errDIV); |
2051 | IL.SetLabel(label1); |
||
2052 | IL.AddCmd(IL.opDIVL + ORD(op = SCAN.lxMOD), ARITH.Int(e.value)) |
||
7597 | akron1 | 2053 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 2054 | IL.AddCmd(IL.opDIVR + ORD(op = SCAN.lxMOD), ARITH.Int(e1.value)) |
7597 | akron1 | 2055 | ELSE |
7693 | akron1 | 2056 | IL.OnError(pos.line, errDIV); |
2057 | IL.SetLabel(label1); |
||
2058 | IL.AddCmd0(IL.opDIV + ORD(op = SCAN.lxMOD)) |
||
7597 | akron1 | 2059 | END; |
2060 | e.obj := eEXPR |
||
2061 | END |
||
2062 | |||
2063 | |SCAN.lxAND: |
||
7693 | akron1 | 2064 | PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); |
7597 | akron1 | 2065 | |
8859 | leency | 2066 | IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN |
7597 | akron1 | 2067 | ARITH.opBoolean(e.value, e1.value, "&") |
2068 | ELSE |
||
2069 | e.obj := eEXPR; |
||
2070 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 2071 | IL.Const(ORD(ARITH.getBool(e1.value))) |
8097 | maxcodehac | 2072 | END |
7597 | akron1 | 2073 | END |
2074 | |||
2075 | END |
||
2076 | END; |
||
2077 | |||
2078 | IF label # -1 THEN |
||
8097 | maxcodehac | 2079 | label1 := IL.NewLabel(); |
8859 | leency | 2080 | IL.Jmp(IL.opJNZ, label1); |
8097 | maxcodehac | 2081 | IL.SetLabel(label); |
2082 | IL.Const(0); |
||
2083 | IL.drop; |
||
2084 | label := IL.NewLabel(); |
||
8859 | leency | 2085 | IL.Jmp(IL.opJMP, label); |
8097 | maxcodehac | 2086 | IL.SetLabel(label1); |
2087 | IL.Const(1); |
||
2088 | IL.SetLabel(label); |
||
2089 | IL.AddCmd0(IL.opAND) |
||
7597 | akron1 | 2090 | END |
2091 | END term; |
||
2092 | |||
2093 | |||
2094 | PROCEDURE SimpleExpression (parser: PARS.PARSER; VAR e: PARS.EXPR); |
||
2095 | VAR |
||
7693 | akron1 | 2096 | pos: PARS.POSITION; |
7597 | akron1 | 2097 | op: INTEGER; |
2098 | e1: PARS.EXPR; |
||
8859 | leency | 2099 | s, s1: SCAN.TEXTSTR; |
7597 | akron1 | 2100 | |
2101 | plus, minus: BOOLEAN; |
||
2102 | |||
8097 | maxcodehac | 2103 | label, label1: INTEGER; |
7597 | akron1 | 2104 | |
2105 | BEGIN |
||
2106 | plus := parser.sym = SCAN.lxPLUS; |
||
2107 | minus := parser.sym = SCAN.lxMINUS; |
||
2108 | |||
2109 | IF plus OR minus THEN |
||
2110 | getpos(parser, pos); |
||
2111 | PARS.Next(parser) |
||
2112 | END; |
||
2113 | |||
2114 | term(parser, e); |
||
2115 | |||
2116 | IF plus OR minus THEN |
||
7693 | akron1 | 2117 | PARS.check(isInt(e) OR isReal(e) OR isSet(e), pos, 36); |
7597 | akron1 | 2118 | |
2119 | IF minus & (e.obj = eCONST) THEN |
||
7693 | akron1 | 2120 | PARS.check(ARITH.neg(e.value), pos, 39) |
7597 | akron1 | 2121 | END; |
2122 | |||
2123 | IF e.obj # eCONST THEN |
||
2124 | IF minus THEN |
||
2125 | IF isInt(e) THEN |
||
7693 | akron1 | 2126 | IL.AddCmd0(IL.opUMINUS) |
7597 | akron1 | 2127 | ELSIF isReal(e) THEN |
7693 | akron1 | 2128 | IL.AddCmd0(IL.opUMINF) |
7597 | akron1 | 2129 | ELSIF isSet(e) THEN |
7693 | akron1 | 2130 | IL.AddCmd0(IL.opUMINS) |
7597 | akron1 | 2131 | END |
2132 | END; |
||
2133 | e.obj := eEXPR |
||
2134 | END |
||
2135 | END; |
||
2136 | |||
2137 | label := -1; |
||
2138 | |||
2139 | WHILE AddOperator(parser.sym) DO |
||
2140 | |||
8097 | maxcodehac | 2141 | op := parser.sym; |
7597 | akron1 | 2142 | getpos(parser, pos); |
2143 | PARS.Next(parser); |
||
2144 | |||
2145 | IF op = SCAN.lxOR THEN |
||
2146 | |||
2147 | IF ~parser.constexp THEN |
||
2148 | |||
2149 | IF label = -1 THEN |
||
7693 | akron1 | 2150 | label := IL.NewLabel() |
7597 | akron1 | 2151 | END; |
2152 | |||
8859 | leency | 2153 | IF (e.obj = eCONST) & isBoolean(e) THEN |
7693 | akron1 | 2154 | IL.Const(ORD(ARITH.getBool(e.value))) |
2155 | END; |
||
8859 | leency | 2156 | IL.Jmp(IL.opJNZ, label) |
7597 | akron1 | 2157 | END |
2158 | |||
2159 | END; |
||
2160 | |||
2161 | term(parser, e1); |
||
2162 | |||
2163 | CASE op OF |
||
2164 | |SCAN.lxPLUS, SCAN.lxMINUS: |
||
2165 | |||
8097 | maxcodehac | 2166 | minus := op = SCAN.lxMINUS; |
2167 | IF minus THEN |
||
2168 | op := ORD("-") |
||
2169 | ELSE |
||
7597 | akron1 | 2170 | op := ORD("+") |
2171 | END; |
||
2172 | |||
8097 | maxcodehac | 2173 | 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 | 2174 | IF (e.obj = eCONST) & (e1.obj = eCONST) THEN |
2175 | |||
8097 | maxcodehac | 2176 | CASE e.value.typ OF |
2177 | |ARITH.tINTEGER: |
||
2178 | PARS.check(ARITH.opInt(e.value, e1.value, CHR(op)), pos, 39) |
||
2179 | |||
2180 | |ARITH.tREAL: |
||
2181 | PARS.check(ARITH.opFloat(e.value, e1.value, CHR(op)), pos, 40) |
||
2182 | |||
2183 | |ARITH.tSET: |
||
2184 | ARITH.opSet(e.value, e1.value, CHR(op)) |
||
2185 | |||
2186 | |ARITH.tCHAR, ARITH.tSTRING: |
||
2187 | IF e.value.typ = ARITH.tCHAR THEN |
||
2188 | ARITH.charToStr(e.value, s) |
||
2189 | ELSE |
||
8859 | leency | 2190 | s := e.value.string(SCAN.STRING).s |
8097 | maxcodehac | 2191 | END; |
2192 | IF e1.value.typ = ARITH.tCHAR THEN |
||
2193 | ARITH.charToStr(e1.value, s1) |
||
2194 | ELSE |
||
8859 | leency | 2195 | s1 := e1.value.string(SCAN.STRING).s |
8097 | maxcodehac | 2196 | END; |
2197 | PARS.check(ARITH.concat(s, s1), pos, 5); |
||
8859 | leency | 2198 | e.value.string := SCAN.enterStr(s); |
8097 | maxcodehac | 2199 | e.value.typ := ARITH.tSTRING; |
2200 | e._type := PROG.program.stTypes.tSTRING |
||
7597 | akron1 | 2201 | END |
2202 | |||
2203 | ELSE |
||
2204 | IF isInt(e) THEN |
||
2205 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2206 | IL.AddCmd(IL.opADDC - ORD(minus), ARITH.Int(e.value)) |
7597 | akron1 | 2207 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2208 | IL.AddCmd(IL.opADDC + ORD(minus), ARITH.Int(e1.value)) |
7597 | akron1 | 2209 | ELSE |
8097 | maxcodehac | 2210 | IL.AddCmd0(IL.opADD + ORD(minus)) |
7597 | akron1 | 2211 | END |
2212 | ELSIF isReal(e) THEN |
||
2213 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2214 | Float(parser, e); |
2215 | IL.AddCmd0(IL.opADDF - ORD(minus)) |
||
7597 | akron1 | 2216 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2217 | Float(parser, e1); |
2218 | IL.AddCmd0(IL.opADDF + ORD(minus)) |
||
7597 | akron1 | 2219 | ELSE |
8097 | maxcodehac | 2220 | IL.AddCmd0(IL.opADDF + ORD(minus)) |
7597 | akron1 | 2221 | END |
2222 | ELSIF isSet(e) THEN |
||
2223 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2224 | IL.AddCmd(IL.opADDSC - ORD(minus), ARITH.Int(e.value)) |
7597 | akron1 | 2225 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2226 | IL.AddCmd(IL.opADDSC + ORD(minus), ARITH.Int(e1.value)) |
7597 | akron1 | 2227 | ELSE |
8097 | maxcodehac | 2228 | IL.AddCmd0(IL.opADDS + ORD(minus)) |
7597 | akron1 | 2229 | END |
2230 | END; |
||
2231 | e.obj := eEXPR |
||
2232 | END |
||
2233 | |||
2234 | |SCAN.lxOR: |
||
7693 | akron1 | 2235 | PARS.check(isBoolean(e) & isBoolean(e1), pos, 37); |
7597 | akron1 | 2236 | |
8859 | leency | 2237 | IF (e.obj = eCONST) & (e1.obj = eCONST) & parser.constexp THEN |
7597 | akron1 | 2238 | ARITH.opBoolean(e.value, e1.value, "|") |
2239 | ELSE |
||
2240 | e.obj := eEXPR; |
||
2241 | IF e1.obj = eCONST THEN |
||
7693 | akron1 | 2242 | IL.Const(ORD(ARITH.getBool(e1.value))) |
8097 | maxcodehac | 2243 | END |
7597 | akron1 | 2244 | END |
2245 | |||
2246 | END |
||
2247 | END; |
||
2248 | |||
2249 | IF label # -1 THEN |
||
8097 | maxcodehac | 2250 | label1 := IL.NewLabel(); |
8859 | leency | 2251 | IL.Jmp(IL.opJZ, label1); |
8097 | maxcodehac | 2252 | IL.SetLabel(label); |
2253 | IL.Const(1); |
||
2254 | IL.drop; |
||
2255 | label := IL.NewLabel(); |
||
8859 | leency | 2256 | IL.Jmp(IL.opJMP, label); |
8097 | maxcodehac | 2257 | IL.SetLabel(label1); |
2258 | IL.Const(0); |
||
2259 | IL.SetLabel(label); |
||
2260 | IL.AddCmd0(IL.opOR) |
||
7597 | akron1 | 2261 | END |
2262 | |||
2263 | END SimpleExpression; |
||
2264 | |||
2265 | |||
2266 | PROCEDURE cmpcode (op: INTEGER): INTEGER; |
||
2267 | VAR |
||
2268 | res: INTEGER; |
||
7693 | akron1 | 2269 | |
7597 | akron1 | 2270 | BEGIN |
2271 | CASE op OF |
||
8097 | maxcodehac | 2272 | |SCAN.lxEQ: res := ARITH.opEQ |
2273 | |SCAN.lxNE: res := ARITH.opNE |
||
2274 | |SCAN.lxLT: res := ARITH.opLT |
||
2275 | |SCAN.lxLE: res := ARITH.opLE |
||
2276 | |SCAN.lxGT: res := ARITH.opGT |
||
2277 | |SCAN.lxGE: res := ARITH.opGE |
||
2278 | |SCAN.lxIN: res := ARITH.opIN |
||
2279 | |SCAN.lxIS: res := ARITH.opIS |
||
7597 | akron1 | 2280 | END |
2281 | |||
2282 | RETURN res |
||
2283 | END cmpcode; |
||
2284 | |||
2285 | |||
7693 | akron1 | 2286 | PROCEDURE invcmpcode (op: INTEGER): INTEGER; |
2287 | VAR |
||
2288 | res: INTEGER; |
||
2289 | |||
2290 | BEGIN |
||
2291 | CASE op OF |
||
8097 | maxcodehac | 2292 | |SCAN.lxEQ: res := ARITH.opEQ |
2293 | |SCAN.lxNE: res := ARITH.opNE |
||
2294 | |SCAN.lxLT: res := ARITH.opGT |
||
2295 | |SCAN.lxLE: res := ARITH.opGE |
||
2296 | |SCAN.lxGT: res := ARITH.opLT |
||
2297 | |SCAN.lxGE: res := ARITH.opLE |
||
2298 | |SCAN.lxIN: res := ARITH.opIN |
||
2299 | |SCAN.lxIS: res := ARITH.opIS |
||
7693 | akron1 | 2300 | END |
2301 | |||
2302 | RETURN res |
||
2303 | END invcmpcode; |
||
2304 | |||
2305 | |||
7597 | akron1 | 2306 | PROCEDURE BoolCmp (eq, val: BOOLEAN); |
2307 | BEGIN |
||
2308 | IF eq = val THEN |
||
7693 | akron1 | 2309 | IL.AddCmd0(IL.opNEC) |
7597 | akron1 | 2310 | ELSE |
7693 | akron1 | 2311 | IL.AddCmd0(IL.opEQC) |
7597 | akron1 | 2312 | END |
2313 | END BoolCmp; |
||
2314 | |||
2315 | |||
2316 | PROCEDURE strcmp (VAR e, e1: PARS.EXPR; op: INTEGER): BOOLEAN; |
||
2317 | VAR |
||
2318 | res: BOOLEAN; |
||
8097 | maxcodehac | 2319 | cmp: INTEGER; |
7597 | akron1 | 2320 | |
2321 | BEGIN |
||
2322 | res := TRUE; |
||
8097 | maxcodehac | 2323 | cmp := cmpcode(op); |
7597 | akron1 | 2324 | |
2325 | IF isString(e) & isCharArray(e1) THEN |
||
7693 | akron1 | 2326 | IL.StrAdr(String(e)); |
2327 | IL.Const(strlen(e) + 1); |
||
2328 | IL.AddCmd0(IL.opEQS + invcmpcode(op)) |
||
7597 | akron1 | 2329 | |
8097 | maxcodehac | 2330 | ELSIF (isString(e) OR isStringW(e)) & isCharArrayW(e1) THEN |
7693 | akron1 | 2331 | IL.StrAdr(StringW(e)); |
2332 | IL.Const(utf8strlen(e) + 1); |
||
2333 | IL.AddCmd0(IL.opEQSW + invcmpcode(op)) |
||
7597 | akron1 | 2334 | |
2335 | ELSIF isCharArray(e) & isString(e1) THEN |
||
7693 | akron1 | 2336 | IL.StrAdr(String(e1)); |
2337 | IL.Const(strlen(e1) + 1); |
||
8097 | maxcodehac | 2338 | IL.AddCmd0(IL.opEQS + cmp) |
7597 | akron1 | 2339 | |
8097 | maxcodehac | 2340 | ELSIF isCharArrayW(e) & (isString(e1) OR isStringW(e1)) THEN |
7693 | akron1 | 2341 | IL.StrAdr(StringW(e1)); |
2342 | IL.Const(utf8strlen(e1) + 1); |
||
8097 | maxcodehac | 2343 | IL.AddCmd0(IL.opEQSW + cmp) |
7597 | akron1 | 2344 | |
2345 | ELSIF isCharArrayW(e) & isCharArrayW(e1) THEN |
||
8097 | maxcodehac | 2346 | IL.AddCmd0(IL.opEQSW + cmp) |
7597 | akron1 | 2347 | |
2348 | ELSIF isCharArray(e) & isCharArray(e1) THEN |
||
8097 | maxcodehac | 2349 | IL.AddCmd0(IL.opEQS + cmp) |
7597 | akron1 | 2350 | |
2351 | ELSIF isString(e) & isString(e1) THEN |
||
2352 | PARS.strcmp(e.value, e1.value, op) |
||
2353 | |||
2354 | ELSE |
||
2355 | res := FALSE |
||
2356 | |||
2357 | END |
||
2358 | |||
2359 | RETURN res |
||
2360 | END strcmp; |
||
2361 | |||
2362 | |||
2363 | BEGIN |
||
2364 | getpos(parser, pos0); |
||
2365 | SimpleExpression(parser, e); |
||
2366 | IF relation(parser.sym) THEN |
||
8097 | maxcodehac | 2367 | IF (isCharArray(e) OR isCharArrayW(e)) & (e._type.length # 0) THEN |
2368 | IL.Const(e._type.length) |
||
7597 | akron1 | 2369 | END; |
8097 | maxcodehac | 2370 | op := parser.sym; |
7597 | akron1 | 2371 | getpos(parser, pos); |
2372 | PARS.Next(parser); |
||
2373 | |||
7693 | akron1 | 2374 | getpos(parser, pos1); |
7597 | akron1 | 2375 | SimpleExpression(parser, e1); |
2376 | |||
8097 | maxcodehac | 2377 | IF (isCharArray(e1) OR isCharArrayW(e1)) & (e1._type.length # 0) THEN |
2378 | IL.Const(e1._type.length) |
||
7597 | akron1 | 2379 | END; |
2380 | |||
2381 | constant := (e.obj = eCONST) & (e1.obj = eCONST); |
||
2382 | error := 0; |
||
8097 | maxcodehac | 2383 | cmp := cmpcode(op); |
7597 | akron1 | 2384 | |
2385 | CASE op OF |
||
2386 | |SCAN.lxEQ, SCAN.lxNE: |
||
8097 | maxcodehac | 2387 | eq := op = SCAN.lxEQ; |
7597 | akron1 | 2388 | IF isInt(e) & isInt(e1) OR isSet(e) & isSet(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR |
2389 | isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR |
||
2390 | isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR |
||
2391 | isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) OR |
||
8097 | maxcodehac | 2392 | isPtr(e) & isPtr(e1) & (PROG.isBaseOf(e._type, e1._type) OR PROG.isBaseOf(e1._type, e._type)) THEN |
7597 | akron1 | 2393 | IF constant THEN |
8097 | maxcodehac | 2394 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2395 | ELSE |
2396 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2397 | IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e.value)) |
7597 | akron1 | 2398 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2399 | IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) |
7597 | akron1 | 2400 | ELSE |
8097 | maxcodehac | 2401 | IL.AddCmd0(IL.opEQ + cmp) |
7597 | akron1 | 2402 | END |
2403 | END |
||
2404 | |||
2405 | ELSIF isStringW1(e) & isCharW(e1) THEN |
||
8859 | leency | 2406 | IL.AddCmd(IL.opEQC + cmp, StrToWChar(e.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2407 | |
2408 | ELSIF isStringW1(e1) & isCharW(e) THEN |
||
8859 | leency | 2409 | IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2410 | |
2411 | ELSIF isBoolean(e) & isBoolean(e1) THEN |
||
2412 | IF constant THEN |
||
8097 | maxcodehac | 2413 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2414 | ELSE |
2415 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2416 | BoolCmp(eq, ARITH.Int(e.value) # 0) |
7597 | akron1 | 2417 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2418 | BoolCmp(eq, ARITH.Int(e1.value) # 0) |
7597 | akron1 | 2419 | ELSE |
8097 | maxcodehac | 2420 | IF eq THEN |
7693 | akron1 | 2421 | IL.AddCmd0(IL.opEQB) |
7597 | akron1 | 2422 | ELSE |
7693 | akron1 | 2423 | IL.AddCmd0(IL.opNEB) |
7597 | akron1 | 2424 | END |
2425 | END |
||
2426 | END |
||
2427 | |||
2428 | ELSIF isReal(e) & isReal(e1) THEN |
||
2429 | IF constant THEN |
||
8097 | maxcodehac | 2430 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2431 | ELSE |
2432 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2433 | Float(parser, e) |
7597 | akron1 | 2434 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2435 | Float(parser, e1) |
7693 | akron1 | 2436 | END; |
8097 | maxcodehac | 2437 | IL.AddCmd0(IL.opEQF + cmp) |
7597 | akron1 | 2438 | END |
2439 | |||
2440 | ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN |
||
2441 | IF ~strcmp(e, e1, op) THEN |
||
7693 | akron1 | 2442 | PARS.error(pos, 37) |
7597 | akron1 | 2443 | END |
2444 | |||
2445 | ELSIF isPtr(e) & isNil(e1) OR isNil(e) & isPtr(e1) THEN |
||
8097 | maxcodehac | 2446 | IL.AddCmd0(IL.opEQC + cmp) |
7597 | akron1 | 2447 | |
2448 | ELSIF isProc(e) & isNil(e1) THEN |
||
2449 | IF e.obj IN {ePROC, eIMP} THEN |
||
7693 | akron1 | 2450 | PARS.check(e.ident.global, pos0, 85); |
7597 | akron1 | 2451 | constant := TRUE; |
2452 | e.obj := eCONST; |
||
8097 | maxcodehac | 2453 | ARITH.setbool(e.value, ~eq) |
7597 | akron1 | 2454 | ELSE |
8097 | maxcodehac | 2455 | IL.AddCmd0(IL.opEQC + cmp) |
7597 | akron1 | 2456 | END |
2457 | |||
2458 | ELSIF isNil(e) & isProc(e1) THEN |
||
2459 | IF e1.obj IN {ePROC, eIMP} THEN |
||
7693 | akron1 | 2460 | PARS.check(e1.ident.global, pos1, 85); |
7597 | akron1 | 2461 | constant := TRUE; |
2462 | e.obj := eCONST; |
||
8097 | maxcodehac | 2463 | ARITH.setbool(e.value, ~eq) |
7597 | akron1 | 2464 | ELSE |
8097 | maxcodehac | 2465 | IL.AddCmd0(IL.opEQC + cmp) |
7597 | akron1 | 2466 | END |
2467 | |||
8097 | maxcodehac | 2468 | ELSIF isProc(e) & isProc(e1) & PROG.isTypeEq(e._type, e1._type) THEN |
7597 | akron1 | 2469 | IF e.obj = ePROC THEN |
7693 | akron1 | 2470 | PARS.check(e.ident.global, pos0, 85) |
7597 | akron1 | 2471 | END; |
2472 | IF e1.obj = ePROC THEN |
||
7693 | akron1 | 2473 | PARS.check(e1.ident.global, pos1, 85) |
7597 | akron1 | 2474 | END; |
2475 | IF (e.obj IN {ePROC, eIMP}) & (e1.obj IN {ePROC, eIMP}) THEN |
||
2476 | constant := TRUE; |
||
2477 | e.obj := eCONST; |
||
8097 | maxcodehac | 2478 | IF eq THEN |
7597 | akron1 | 2479 | ARITH.setbool(e.value, e.ident = e1.ident) |
2480 | ELSE |
||
2481 | ARITH.setbool(e.value, e.ident # e1.ident) |
||
2482 | END |
||
2483 | ELSIF e.obj = ePROC THEN |
||
8097 | maxcodehac | 2484 | IL.ProcCmp(e.ident.proc.label, eq) |
7597 | akron1 | 2485 | ELSIF e1.obj = ePROC THEN |
8097 | maxcodehac | 2486 | IL.ProcCmp(e1.ident.proc.label, eq) |
7597 | akron1 | 2487 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 2488 | IL.ProcImpCmp(e.ident._import, eq) |
7597 | akron1 | 2489 | ELSIF e1.obj = eIMP THEN |
8097 | maxcodehac | 2490 | IL.ProcImpCmp(e1.ident._import, eq) |
7597 | akron1 | 2491 | ELSE |
8097 | maxcodehac | 2492 | IL.AddCmd0(IL.opEQ + cmp) |
7597 | akron1 | 2493 | END |
2494 | |||
2495 | ELSIF isNil(e) & isNil(e1) THEN |
||
2496 | constant := TRUE; |
||
2497 | e.obj := eCONST; |
||
8097 | maxcodehac | 2498 | ARITH.setbool(e.value, eq) |
7597 | akron1 | 2499 | |
2500 | ELSE |
||
7693 | akron1 | 2501 | PARS.error(pos, 37) |
7597 | akron1 | 2502 | END |
2503 | |||
2504 | |SCAN.lxLT, SCAN.lxLE, SCAN.lxGT, SCAN.lxGE: |
||
2505 | IF isInt(e) & isInt(e1) OR isChar(e) & isChar(e1) OR isCharW(e) & isCharW(e1) OR |
||
2506 | isCharW(e) & isChar(e1) & (e1.obj = eCONST) OR isCharW(e1) & isChar(e) & (e.obj = eCONST) OR |
||
2507 | isCharW(e1) & (e1.obj = eCONST) & isChar(e) & (e.obj = eCONST) OR |
||
2508 | isCharW(e) & (e.obj = eCONST) & isChar(e1) & (e1.obj = eCONST) THEN |
||
2509 | |||
2510 | IF constant THEN |
||
8097 | maxcodehac | 2511 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2512 | ELSE |
2513 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2514 | IL.AddCmd(IL.opEQC + invcmpcode(op), ARITH.Int(e.value)) |
7597 | akron1 | 2515 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2516 | IL.AddCmd(IL.opEQC + cmp, ARITH.Int(e1.value)) |
7597 | akron1 | 2517 | ELSE |
8097 | maxcodehac | 2518 | IL.AddCmd0(IL.opEQ + cmp) |
7597 | akron1 | 2519 | END |
2520 | END |
||
2521 | |||
2522 | ELSIF isStringW1(e) & isCharW(e1) THEN |
||
8859 | leency | 2523 | IL.AddCmd(IL.opEQC + invcmpcode(op), StrToWChar(e.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2524 | |
2525 | ELSIF isStringW1(e1) & isCharW(e) THEN |
||
8859 | leency | 2526 | IL.AddCmd(IL.opEQC + cmp, StrToWChar(e1.value.string(SCAN.STRING).s)) |
7597 | akron1 | 2527 | |
2528 | ELSIF isReal(e) & isReal(e1) THEN |
||
2529 | IF constant THEN |
||
8097 | maxcodehac | 2530 | ARITH.relation(e.value, e1.value, cmp, error) |
7597 | akron1 | 2531 | ELSE |
2532 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 2533 | Float(parser, e); |
2534 | IL.AddCmd0(IL.opEQF + invcmpcode(op)) |
||
7597 | akron1 | 2535 | ELSIF e1.obj = eCONST THEN |
8097 | maxcodehac | 2536 | Float(parser, e1); |
2537 | IL.AddCmd0(IL.opEQF + cmp) |
||
7597 | akron1 | 2538 | ELSE |
8097 | maxcodehac | 2539 | IL.AddCmd0(IL.opEQF + cmp) |
7597 | akron1 | 2540 | END |
2541 | END |
||
2542 | |||
2543 | ELSIF (isStringW(e) OR isCharArrayX(e)) & (isStringW(e1) OR isCharArrayX(e1)) THEN |
||
2544 | IF ~strcmp(e, e1, op) THEN |
||
7693 | akron1 | 2545 | PARS.error(pos, 37) |
7597 | akron1 | 2546 | END |
2547 | |||
2548 | ELSE |
||
7693 | akron1 | 2549 | PARS.error(pos, 37) |
7597 | akron1 | 2550 | END |
2551 | |||
2552 | |SCAN.lxIN: |
||
7693 | akron1 | 2553 | PARS.check(isInt(e) & isSet(e1), pos, 37); |
7597 | akron1 | 2554 | IF e.obj = eCONST THEN |
7693 | akron1 | 2555 | PARS.check(ARITH.range(e.value, 0, UTILS.target.maxSet), pos0, 56) |
7597 | akron1 | 2556 | END; |
2557 | IF constant THEN |
||
8097 | maxcodehac | 2558 | ARITH.relation(e.value, e1.value, ARITH.opIN, error) |
7597 | akron1 | 2559 | ELSE |
2560 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 2561 | IL.AddCmd(IL.opINL, ARITH.Int(e.value)) |
7597 | akron1 | 2562 | ELSIF e1.obj = eCONST THEN |
7693 | akron1 | 2563 | IL.AddCmd(IL.opINR, ARITH.Int(e1.value)) |
7597 | akron1 | 2564 | ELSE |
7693 | akron1 | 2565 | IL.AddCmd0(IL.opIN) |
7597 | akron1 | 2566 | END |
2567 | END |
||
2568 | |||
2569 | |SCAN.lxIS: |
||
7693 | akron1 | 2570 | PARS.check(isRecPtr(e), pos, 73); |
2571 | PARS.check(e1.obj = eTYPE, pos1, 79); |
||
7597 | akron1 | 2572 | |
7693 | akron1 | 2573 | IF isRec(e) THEN |
2574 | PARS.check(e.obj = eVREC, pos0, 78); |
||
8097 | maxcodehac | 2575 | PARS.check(e1._type.typ = PROG.tRECORD, pos1, 80); |
7597 | akron1 | 2576 | IF e.ident = NIL THEN |
8097 | maxcodehac | 2577 | IL.TypeCheck(e1._type.num) |
7597 | akron1 | 2578 | ELSE |
7693 | akron1 | 2579 | IL.AddCmd(IL.opVADR, e.ident.offset - 1); |
8097 | maxcodehac | 2580 | IL.TypeCheckRec(e1._type.num) |
7597 | akron1 | 2581 | END |
2582 | ELSE |
||
8097 | maxcodehac | 2583 | PARS.check(e1._type.typ = PROG.tPOINTER, pos1, 81); |
2584 | IL.TypeCheck(e1._type.base.num) |
||
7597 | akron1 | 2585 | END; |
2586 | |||
8097 | maxcodehac | 2587 | PARS.check(PROG.isBaseOf(e._type, e1._type), pos1, 82) |
7597 | akron1 | 2588 | |
2589 | END; |
||
2590 | |||
2591 | ASSERT(error = 0); |
||
2592 | |||
8097 | maxcodehac | 2593 | e._type := tBOOLEAN; |
7597 | akron1 | 2594 | |
2595 | IF ~constant THEN |
||
2596 | e.obj := eEXPR |
||
2597 | END |
||
2598 | |||
2599 | END |
||
2600 | END expression; |
||
2601 | |||
2602 | |||
2603 | PROCEDURE ElementaryStatement (parser: PARS.PARSER); |
||
2604 | VAR |
||
7983 | leency | 2605 | e, e1: PARS.EXPR; |
2606 | pos: PARS.POSITION; |
||
2607 | line: INTEGER; |
||
2608 | call: BOOLEAN; |
||
7597 | akron1 | 2609 | |
2610 | BEGIN |
||
2611 | getpos(parser, pos); |
||
2612 | |||
7693 | akron1 | 2613 | IL.pushBegEnd(begcall, endcall); |
7597 | akron1 | 2614 | |
2615 | designator(parser, e); |
||
2616 | |||
2617 | IF parser.sym = SCAN.lxASSIGN THEN |
||
2618 | line := parser.lex.pos.line; |
||
7693 | akron1 | 2619 | PARS.check(isVar(e), pos, 93); |
2620 | PARS.check(~e.readOnly, pos, 94); |
||
7597 | akron1 | 2621 | |
7693 | akron1 | 2622 | IL.setlast(begcall); |
7597 | akron1 | 2623 | |
2624 | NextPos(parser, pos); |
||
2625 | expression(parser, e1); |
||
9893 | akron1 | 2626 | IF (e._type.typ = PROG.tBYTE) & (e1.obj # eCONST) & (e1._type.typ = PROG.tINTEGER) & (chkBYTE IN Options.checking) THEN |
2627 | CheckRange(256, pos.line, errBYTE) |
||
2628 | END; |
||
7597 | akron1 | 2629 | |
7693 | akron1 | 2630 | IL.setlast(endcall.prev(IL.COMMAND)); |
7597 | akron1 | 2631 | |
8097 | maxcodehac | 2632 | PARS.check(assign(parser, e1, e._type, line), pos, 91); |
7597 | akron1 | 2633 | IF e1.obj = ePROC THEN |
7693 | akron1 | 2634 | PARS.check(e1.ident.global, pos, 85) |
7597 | akron1 | 2635 | END; |
2636 | call := FALSE |
||
2637 | ELSIF parser.sym = SCAN.lxEQ THEN |
||
2638 | PARS.check1(FALSE, parser, 96) |
||
2639 | ELSIF parser.sym = SCAN.lxLROUND THEN |
||
2640 | e1 := e; |
||
2641 | ActualParameters(parser, e1); |
||
8097 | maxcodehac | 2642 | PARS.check((e1._type = NIL) OR ODD(e._type.call), pos, 92); |
7597 | akron1 | 2643 | call := TRUE |
2644 | ELSE |
||
7693 | akron1 | 2645 | IF e.obj IN {eSYSPROC, eSTPROC} THEN |
2646 | stProc(parser, e); |
||
2647 | call := FALSE |
||
2648 | ELSE |
||
2649 | PARS.check(isProc(e), pos, 86); |
||
8097 | maxcodehac | 2650 | PARS.check((e._type.base = NIL) OR ODD(e._type.call), pos, 92); |
2651 | PARS.check1(e._type.params.first = NIL, parser, 64); |
||
7693 | akron1 | 2652 | call := TRUE |
2653 | END |
||
7597 | akron1 | 2654 | END; |
2655 | |||
2656 | IF call THEN |
||
2657 | IF e.obj IN {ePROC, eIMP} THEN |
||
8097 | maxcodehac | 2658 | ProcCall(e, e.ident._type, FALSE, parser, pos, TRUE) |
7597 | akron1 | 2659 | ELSIF isExpr(e) THEN |
8097 | maxcodehac | 2660 | ProcCall(e, e._type, FALSE, parser, pos, TRUE) |
7597 | akron1 | 2661 | END |
2662 | END; |
||
2663 | |||
7693 | akron1 | 2664 | IL.popBegEnd(begcall, endcall) |
7597 | akron1 | 2665 | END ElementaryStatement; |
2666 | |||
2667 | |||
8097 | maxcodehac | 2668 | PROCEDURE IfStatement (parser: PARS.PARSER; _if: BOOLEAN); |
7597 | akron1 | 2669 | VAR |
7983 | leency | 2670 | e: PARS.EXPR; |
2671 | pos: PARS.POSITION; |
||
7597 | akron1 | 2672 | |
2673 | label, L: INTEGER; |
||
2674 | |||
2675 | BEGIN |
||
7693 | akron1 | 2676 | L := IL.NewLabel(); |
7597 | akron1 | 2677 | |
8097 | maxcodehac | 2678 | IF ~_if THEN |
8859 | leency | 2679 | IL.AddCmd(IL.opNOP, IL.begin_loop); |
7693 | akron1 | 2680 | IL.SetLabel(L) |
7597 | akron1 | 2681 | END; |
2682 | |||
2683 | REPEAT |
||
2684 | NextPos(parser, pos); |
||
2685 | |||
7693 | akron1 | 2686 | label := IL.NewLabel(); |
7597 | akron1 | 2687 | |
2688 | expression(parser, e); |
||
7693 | akron1 | 2689 | PARS.check(isBoolean(e), pos, 72); |
7597 | akron1 | 2690 | |
2691 | IF e.obj = eCONST THEN |
||
2692 | IF ~ARITH.getBool(e.value) THEN |
||
8859 | leency | 2693 | IL.Jmp(IL.opJMP, label) |
7597 | akron1 | 2694 | END |
2695 | ELSE |
||
8097 | maxcodehac | 2696 | IL.AndOrOpt(label) |
7597 | akron1 | 2697 | END; |
2698 | |||
8097 | maxcodehac | 2699 | IF _if THEN |
7597 | akron1 | 2700 | PARS.checklex(parser, SCAN.lxTHEN) |
2701 | ELSE |
||
2702 | PARS.checklex(parser, SCAN.lxDO) |
||
2703 | END; |
||
2704 | |||
2705 | PARS.Next(parser); |
||
2706 | parser.StatSeq(parser); |
||
2707 | |||
8097 | maxcodehac | 2708 | IF ~_if OR (parser.sym # SCAN.lxEND) THEN |
8859 | leency | 2709 | IL.Jmp(IL.opJMP, L) |
8097 | maxcodehac | 2710 | END; |
7693 | akron1 | 2711 | IL.SetLabel(label) |
7597 | akron1 | 2712 | |
2713 | UNTIL parser.sym # SCAN.lxELSIF; |
||
2714 | |||
8097 | maxcodehac | 2715 | IF _if THEN |
7597 | akron1 | 2716 | IF parser.sym = SCAN.lxELSE THEN |
2717 | PARS.Next(parser); |
||
2718 | parser.StatSeq(parser) |
||
2719 | END; |
||
7693 | akron1 | 2720 | IL.SetLabel(L) |
8097 | maxcodehac | 2721 | ELSE |
8859 | leency | 2722 | IL.AddCmd(IL.opNOP, IL.end_loop) |
7597 | akron1 | 2723 | END; |
2724 | |||
2725 | PARS.checklex(parser, SCAN.lxEND); |
||
2726 | |||
2727 | PARS.Next(parser) |
||
2728 | END IfStatement; |
||
2729 | |||
2730 | |||
2731 | PROCEDURE RepeatStatement (parser: PARS.PARSER); |
||
2732 | VAR |
||
2733 | e: PARS.EXPR; |
||
7693 | akron1 | 2734 | pos: PARS.POSITION; |
7597 | akron1 | 2735 | label: INTEGER; |
8097 | maxcodehac | 2736 | L: IL.COMMAND; |
7597 | akron1 | 2737 | |
2738 | BEGIN |
||
8859 | leency | 2739 | IL.AddCmd(IL.opNOP, IL.begin_loop); |
7597 | akron1 | 2740 | |
7693 | akron1 | 2741 | label := IL.NewLabel(); |
2742 | IL.SetLabel(label); |
||
8097 | maxcodehac | 2743 | L := IL.getlast(); |
7597 | akron1 | 2744 | |
2745 | PARS.Next(parser); |
||
2746 | parser.StatSeq(parser); |
||
2747 | PARS.checklex(parser, SCAN.lxUNTIL); |
||
2748 | NextPos(parser, pos); |
||
2749 | expression(parser, e); |
||
7693 | akron1 | 2750 | PARS.check(isBoolean(e), pos, 72); |
7597 | akron1 | 2751 | |
2752 | IF e.obj = eCONST THEN |
||
2753 | IF ~ARITH.getBool(e.value) THEN |
||
8859 | leency | 2754 | IL.Jmp(IL.opJMP, label) |
7597 | akron1 | 2755 | END |
2756 | ELSE |
||
8097 | maxcodehac | 2757 | IL.AndOrOpt(label); |
2758 | L.param1 := label |
||
7597 | akron1 | 2759 | END; |
2760 | |||
8859 | leency | 2761 | IL.AddCmd(IL.opNOP, IL.end_loop) |
7597 | akron1 | 2762 | END RepeatStatement; |
2763 | |||
2764 | |||
2765 | PROCEDURE LabelCmp (a, b: AVL.DATA): INTEGER; |
||
2766 | VAR |
||
2767 | La, Ra, Lb, Rb, res: INTEGER; |
||
2768 | |||
2769 | BEGIN |
||
2770 | La := a(CASE_LABEL).range.a; |
||
2771 | Ra := a(CASE_LABEL).range.b; |
||
2772 | Lb := b(CASE_LABEL).range.a; |
||
2773 | Rb := b(CASE_LABEL).range.b; |
||
2774 | IF (Ra < Lb) OR (La > Rb) THEN |
||
2775 | res := ORD(La > Lb) - ORD(La < Lb) |
||
2776 | ELSE |
||
2777 | res := 0 |
||
2778 | END |
||
2779 | |||
2780 | RETURN res |
||
2781 | END LabelCmp; |
||
2782 | |||
2783 | |||
2784 | PROCEDURE DestroyLabel (VAR label: AVL.DATA); |
||
2785 | BEGIN |
||
2786 | C.push(CaseLabels, label); |
||
2787 | label := NIL |
||
2788 | END DestroyLabel; |
||
2789 | |||
2790 | |||
7693 | akron1 | 2791 | PROCEDURE NewVariant (label: INTEGER; cmd: IL.COMMAND): CASE_VARIANT; |
7597 | akron1 | 2792 | VAR |
2793 | res: CASE_VARIANT; |
||
2794 | citem: C.ITEM; |
||
2795 | |||
2796 | BEGIN |
||
2797 | citem := C.pop(CaseVar); |
||
2798 | IF citem = NIL THEN |
||
2799 | NEW(res) |
||
2800 | ELSE |
||
2801 | res := citem(CASE_VARIANT) |
||
2802 | END; |
||
2803 | |||
2804 | res.label := label; |
||
2805 | res.cmd := cmd; |
||
2806 | res.processed := FALSE |
||
2807 | |||
2808 | RETURN res |
||
2809 | END NewVariant; |
||
2810 | |||
2811 | |||
2812 | PROCEDURE CaseStatement (parser: PARS.PARSER); |
||
2813 | VAR |
||
7983 | leency | 2814 | e: PARS.EXPR; |
2815 | pos: PARS.POSITION; |
||
7597 | akron1 | 2816 | |
2817 | |||
8097 | maxcodehac | 2818 | PROCEDURE Label (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR _type: PROG._TYPE): INTEGER; |
7597 | akron1 | 2819 | VAR |
7983 | leency | 2820 | a: INTEGER; |
2821 | label: PARS.EXPR; |
||
2822 | pos: PARS.POSITION; |
||
2823 | value: ARITH.VALUE; |
||
7597 | akron1 | 2824 | |
2825 | BEGIN |
||
2826 | getpos(parser, pos); |
||
8097 | maxcodehac | 2827 | _type := NIL; |
7597 | akron1 | 2828 | |
2829 | IF isChar(caseExpr) THEN |
||
2830 | PARS.ConstExpression(parser, value); |
||
7693 | akron1 | 2831 | PARS.check(value.typ = ARITH.tCHAR, pos, 99); |
7597 | akron1 | 2832 | a := ARITH.getInt(value) |
2833 | ELSIF isCharW(caseExpr) THEN |
||
2834 | PARS.ConstExpression(parser, value); |
||
8859 | leency | 2835 | IF (value.typ = ARITH.tSTRING) & (_length(value.string(SCAN.STRING).s) = 1) & (LENGTH(value.string(SCAN.STRING).s) > 1) THEN |
2836 | ASSERT(ARITH.setInt(value, StrToWChar(value.string(SCAN.STRING).s))) |
||
7597 | akron1 | 2837 | ELSE |
7693 | akron1 | 2838 | PARS.check(value.typ IN {ARITH.tWCHAR, ARITH.tCHAR}, pos, 99) |
7597 | akron1 | 2839 | END; |
2840 | a := ARITH.getInt(value) |
||
2841 | ELSIF isInt(caseExpr) THEN |
||
2842 | PARS.ConstExpression(parser, value); |
||
7693 | akron1 | 2843 | PARS.check(value.typ = ARITH.tINTEGER, pos, 99); |
7597 | akron1 | 2844 | a := ARITH.getInt(value) |
2845 | ELSIF isRecPtr(caseExpr) THEN |
||
2846 | qualident(parser, label); |
||
7693 | akron1 | 2847 | PARS.check(label.obj = eTYPE, pos, 79); |
8097 | maxcodehac | 2848 | PARS.check(PROG.isBaseOf(caseExpr._type, label._type), pos, 99); |
7597 | akron1 | 2849 | IF isRec(caseExpr) THEN |
8097 | maxcodehac | 2850 | a := label._type.num |
7597 | akron1 | 2851 | ELSE |
8097 | maxcodehac | 2852 | a := label._type.base.num |
7597 | akron1 | 2853 | END; |
8097 | maxcodehac | 2854 | _type := label._type |
7597 | akron1 | 2855 | END |
2856 | |||
2857 | RETURN a |
||
2858 | END Label; |
||
2859 | |||
2860 | |||
8097 | maxcodehac | 2861 | PROCEDURE CheckType (node: AVL.NODE; _type: PROG._TYPE; parser: PARS.PARSER; pos: PARS.POSITION); |
7597 | akron1 | 2862 | BEGIN |
2863 | IF node # NIL THEN |
||
8097 | maxcodehac | 2864 | PARS.check(~(PROG.isBaseOf(node.data(CASE_LABEL)._type, _type) OR PROG.isBaseOf(_type, node.data(CASE_LABEL)._type)), pos, 100); |
2865 | CheckType(node.left, _type, parser, pos); |
||
2866 | CheckType(node.right, _type, parser, pos) |
||
7597 | akron1 | 2867 | END |
2868 | END CheckType; |
||
2869 | |||
2870 | |||
2871 | PROCEDURE LabelRange (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; variant: INTEGER): AVL.NODE; |
||
2872 | VAR |
||
2873 | label: CASE_LABEL; |
||
2874 | citem: C.ITEM; |
||
7693 | akron1 | 2875 | pos, pos1: PARS.POSITION; |
7597 | akron1 | 2876 | node: AVL.NODE; |
2877 | newnode: BOOLEAN; |
||
2878 | range: RANGE; |
||
2879 | |||
2880 | BEGIN |
||
2881 | citem := C.pop(CaseLabels); |
||
2882 | IF citem = NIL THEN |
||
2883 | NEW(label) |
||
2884 | ELSE |
||
2885 | label := citem(CASE_LABEL) |
||
2886 | END; |
||
2887 | |||
2888 | label.variant := variant; |
||
7693 | akron1 | 2889 | label.self := IL.NewLabel(); |
7597 | akron1 | 2890 | |
2891 | getpos(parser, pos1); |
||
8097 | maxcodehac | 2892 | range.a := Label(parser, caseExpr, label._type); |
7597 | akron1 | 2893 | |
2894 | IF parser.sym = SCAN.lxRANGE THEN |
||
2895 | PARS.check1(~isRecPtr(caseExpr), parser, 53); |
||
2896 | NextPos(parser, pos); |
||
8097 | maxcodehac | 2897 | range.b := Label(parser, caseExpr, label._type); |
7693 | akron1 | 2898 | PARS.check(range.a <= range.b, pos, 103) |
7597 | akron1 | 2899 | ELSE |
2900 | range.b := range.a |
||
2901 | END; |
||
2902 | |||
2903 | label.range := range; |
||
2904 | |||
2905 | IF isRecPtr(caseExpr) THEN |
||
8097 | maxcodehac | 2906 | CheckType(tree, label._type, parser, pos1) |
7597 | akron1 | 2907 | END; |
2908 | tree := AVL.insert(tree, label, LabelCmp, newnode, node); |
||
7693 | akron1 | 2909 | PARS.check(newnode, pos1, 100) |
7597 | akron1 | 2910 | |
2911 | RETURN node |
||
2912 | |||
2913 | END LabelRange; |
||
2914 | |||
2915 | |||
2916 | PROCEDURE CaseLabelList (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; variant: INTEGER): AVL.NODE; |
||
2917 | VAR |
||
2918 | exit: BOOLEAN; |
||
2919 | res: AVL.NODE; |
||
2920 | |||
2921 | BEGIN |
||
2922 | exit := FALSE; |
||
2923 | REPEAT |
||
2924 | res := LabelRange(parser, caseExpr, tree, variant); |
||
2925 | IF parser.sym = SCAN.lxCOMMA THEN |
||
2926 | PARS.check1(~isRecPtr(caseExpr), parser, 53); |
||
2927 | PARS.Next(parser) |
||
2928 | ELSE |
||
2929 | exit := TRUE |
||
2930 | END |
||
2931 | UNTIL exit |
||
2932 | |||
2933 | RETURN res |
||
2934 | END CaseLabelList; |
||
2935 | |||
2936 | |||
8097 | maxcodehac | 2937 | PROCEDURE _case (parser: PARS.PARSER; caseExpr: PARS.EXPR; VAR tree: AVL.NODE; _end: INTEGER); |
7597 | akron1 | 2938 | VAR |
7983 | leency | 2939 | sym: INTEGER; |
8097 | maxcodehac | 2940 | t: PROG._TYPE; |
7983 | leency | 2941 | variant: INTEGER; |
2942 | node: AVL.NODE; |
||
2943 | last: IL.COMMAND; |
||
7597 | akron1 | 2944 | |
2945 | BEGIN |
||
2946 | sym := parser.sym; |
||
2947 | IF sym # SCAN.lxBAR THEN |
||
7693 | akron1 | 2948 | variant := IL.NewLabel(); |
7597 | akron1 | 2949 | node := CaseLabelList(parser, caseExpr, tree, variant); |
2950 | PARS.checklex(parser, SCAN.lxCOLON); |
||
2951 | PARS.Next(parser); |
||
2952 | IF isRecPtr(caseExpr) THEN |
||
8097 | maxcodehac | 2953 | t := caseExpr._type; |
2954 | caseExpr.ident._type := node.data(CASE_LABEL)._type |
||
7597 | akron1 | 2955 | END; |
2956 | |||
7693 | akron1 | 2957 | last := IL.getlast(); |
2958 | IL.SetLabel(variant); |
||
7597 | akron1 | 2959 | |
2960 | IF ~isRecPtr(caseExpr) THEN |
||
2961 | LISTS.push(CaseVariants, NewVariant(variant, last)) |
||
2962 | END; |
||
2963 | |||
2964 | parser.StatSeq(parser); |
||
8859 | leency | 2965 | IL.Jmp(IL.opJMP, _end); |
7597 | akron1 | 2966 | |
2967 | IF isRecPtr(caseExpr) THEN |
||
8097 | maxcodehac | 2968 | caseExpr.ident._type := t |
7597 | akron1 | 2969 | END |
2970 | END |
||
8097 | maxcodehac | 2971 | END _case; |
7597 | akron1 | 2972 | |
2973 | |||
8097 | maxcodehac | 2974 | PROCEDURE Table (node: AVL.NODE; _else: INTEGER); |
7597 | akron1 | 2975 | VAR |
2976 | L, R: INTEGER; |
||
2977 | range: RANGE; |
||
2978 | left, right: AVL.NODE; |
||
7693 | akron1 | 2979 | last: IL.COMMAND; |
7597 | akron1 | 2980 | v: CASE_VARIANT; |
2981 | |||
2982 | BEGIN |
||
2983 | IF node # NIL THEN |
||
2984 | |||
2985 | range := node.data(CASE_LABEL).range; |
||
2986 | |||
2987 | left := node.left; |
||
2988 | IF left # NIL THEN |
||
2989 | L := left.data(CASE_LABEL).self |
||
2990 | ELSE |
||
8097 | maxcodehac | 2991 | L := _else |
7597 | akron1 | 2992 | END; |
2993 | |||
2994 | right := node.right; |
||
2995 | IF right # NIL THEN |
||
2996 | R := right.data(CASE_LABEL).self |
||
2997 | ELSE |
||
8097 | maxcodehac | 2998 | R := _else |
7597 | akron1 | 2999 | END; |
3000 | |||
7693 | akron1 | 3001 | last := IL.getlast(); |
7597 | akron1 | 3002 | |
3003 | v := CaseVariants.last(CASE_VARIANT); |
||
3004 | WHILE (v # NIL) & (v.label # 0) & (v.label # node.data(CASE_LABEL).variant) DO |
||
3005 | v := v.prev(CASE_VARIANT) |
||
3006 | END; |
||
3007 | |||
3008 | ASSERT((v # NIL) & (v.label # 0)); |
||
7693 | akron1 | 3009 | IL.setlast(v.cmd); |
7597 | akron1 | 3010 | |
7693 | akron1 | 3011 | IL.SetLabel(node.data(CASE_LABEL).self); |
8097 | maxcodehac | 3012 | IL._case(range.a, range.b, L, R); |
7597 | akron1 | 3013 | IF v.processed THEN |
8859 | leency | 3014 | IL.Jmp(IL.opJMP, node.data(CASE_LABEL).variant) |
7597 | akron1 | 3015 | END; |
3016 | v.processed := TRUE; |
||
3017 | |||
7693 | akron1 | 3018 | IL.setlast(last); |
7597 | akron1 | 3019 | |
8097 | maxcodehac | 3020 | Table(left, _else); |
3021 | Table(right, _else) |
||
7597 | akron1 | 3022 | END |
3023 | END Table; |
||
3024 | |||
3025 | |||
3026 | PROCEDURE TableT (node: AVL.NODE); |
||
3027 | BEGIN |
||
3028 | IF node # NIL THEN |
||
8097 | maxcodehac | 3029 | IL.AddCmd2(IL.opCASET, node.data(CASE_LABEL).variant, node.data(CASE_LABEL).range.a); |
7597 | akron1 | 3030 | TableT(node.left); |
3031 | TableT(node.right) |
||
3032 | END |
||
3033 | END TableT; |
||
3034 | |||
3035 | |||
7693 | akron1 | 3036 | PROCEDURE ParseCase (parser: PARS.PARSER; e: PARS.EXPR; pos: PARS.POSITION); |
7597 | akron1 | 3037 | VAR |
8097 | maxcodehac | 3038 | table, _end, _else: INTEGER; |
7597 | akron1 | 3039 | tree: AVL.NODE; |
7983 | leency | 3040 | item: LISTS.ITEM; |
7597 | akron1 | 3041 | |
3042 | BEGIN |
||
3043 | LISTS.push(CaseVariants, NewVariant(0, NIL)); |
||
8097 | maxcodehac | 3044 | _end := IL.NewLabel(); |
3045 | _else := IL.NewLabel(); |
||
7693 | akron1 | 3046 | table := IL.NewLabel(); |
3047 | IL.AddCmd(IL.opSWITCH, ORD(isRecPtr(e))); |
||
8859 | leency | 3048 | IL.Jmp(IL.opJMP, table); |
7597 | akron1 | 3049 | |
3050 | tree := NIL; |
||
3051 | |||
8097 | maxcodehac | 3052 | _case(parser, e, tree, _end); |
7597 | akron1 | 3053 | WHILE parser.sym = SCAN.lxBAR DO |
3054 | PARS.Next(parser); |
||
8097 | maxcodehac | 3055 | _case(parser, e, tree, _end) |
7597 | akron1 | 3056 | END; |
3057 | |||
8097 | maxcodehac | 3058 | IL.SetLabel(_else); |
7597 | akron1 | 3059 | IF parser.sym = SCAN.lxELSE THEN |
3060 | PARS.Next(parser); |
||
3061 | parser.StatSeq(parser); |
||
8859 | leency | 3062 | IL.Jmp(IL.opJMP, _end) |
7597 | akron1 | 3063 | ELSE |
7693 | akron1 | 3064 | IL.OnError(pos.line, errCASE) |
7597 | akron1 | 3065 | END; |
3066 | |||
3067 | PARS.checklex(parser, SCAN.lxEND); |
||
3068 | PARS.Next(parser); |
||
3069 | |||
3070 | IF isRecPtr(e) THEN |
||
7693 | akron1 | 3071 | IL.SetLabel(table); |
7597 | akron1 | 3072 | TableT(tree); |
8859 | leency | 3073 | IL.Jmp(IL.opJMP, _else) |
7597 | akron1 | 3074 | ELSE |
3075 | tree.data(CASE_LABEL).self := table; |
||
8097 | maxcodehac | 3076 | Table(tree, _else) |
7597 | akron1 | 3077 | END; |
3078 | |||
3079 | AVL.destroy(tree, DestroyLabel); |
||
8097 | maxcodehac | 3080 | IL.SetLabel(_end); |
7693 | akron1 | 3081 | IL.AddCmd0(IL.opENDSW); |
7597 | akron1 | 3082 | |
3083 | REPEAT |
||
3084 | item := LISTS.pop(CaseVariants); |
||
3085 | C.push(CaseVar, item) |
||
3086 | UNTIL item(CASE_VARIANT).cmd = NIL |
||
3087 | |||
3088 | END ParseCase; |
||
3089 | |||
3090 | |||
3091 | BEGIN |
||
3092 | NextPos(parser, pos); |
||
3093 | expression(parser, e); |
||
7693 | akron1 | 3094 | PARS.check(isInt(e) OR isChar(e) OR isCharW(e) OR isPtr(e) OR isRec(e), pos, 95); |
7597 | akron1 | 3095 | IF isRecPtr(e) THEN |
7693 | akron1 | 3096 | PARS.check(isVar(e), pos, 93); |
3097 | PARS.check(e.ident # NIL, pos, 106) |
||
7597 | akron1 | 3098 | END; |
3099 | IF isRec(e) THEN |
||
7693 | akron1 | 3100 | PARS.check(e.obj = eVREC, pos, 78) |
7597 | akron1 | 3101 | END; |
3102 | |||
3103 | IF e.obj = eCONST THEN |
||
3104 | LoadConst(e) |
||
3105 | ELSIF isRec(e) THEN |
||
7693 | akron1 | 3106 | IL.drop; |
3107 | IL.AddCmd(IL.opLADR, e.ident.offset - 1); |
||
7983 | leency | 3108 | IL.load(TARGETS.WordSize) |
7597 | akron1 | 3109 | ELSIF isPtr(e) THEN |
3110 | deref(pos, e, FALSE, errPTR); |
||
7983 | leency | 3111 | IL.AddCmd(IL.opSUBR, TARGETS.WordSize); |
3112 | IL.load(TARGETS.WordSize) |
||
7597 | akron1 | 3113 | END; |
3114 | |||
3115 | PARS.checklex(parser, SCAN.lxOF); |
||
3116 | PARS.Next(parser); |
||
3117 | ParseCase(parser, e, pos) |
||
3118 | END CaseStatement; |
||
3119 | |||
3120 | |||
3121 | PROCEDURE ForStatement (parser: PARS.PARSER); |
||
3122 | VAR |
||
7693 | akron1 | 3123 | e: PARS.EXPR; |
3124 | pos, pos2: PARS.POSITION; |
||
3125 | step: ARITH.VALUE; |
||
3126 | st: INTEGER; |
||
3127 | ident: PROG.IDENT; |
||
3128 | offset: INTEGER; |
||
3129 | L1, L2: INTEGER; |
||
7597 | akron1 | 3130 | |
3131 | BEGIN |
||
8859 | leency | 3132 | IL.AddCmd(IL.opNOP, IL.begin_loop); |
7597 | akron1 | 3133 | |
7693 | akron1 | 3134 | L1 := IL.NewLabel(); |
3135 | L2 := IL.NewLabel(); |
||
7597 | akron1 | 3136 | |
3137 | PARS.ExpectSym(parser, SCAN.lxIDENT); |
||
7693 | akron1 | 3138 | ident := PROG.getIdent(parser.unit, parser.lex.ident, TRUE); |
7597 | akron1 | 3139 | PARS.check1(ident # NIL, parser, 48); |
3140 | PARS.check1(ident.typ = PROG.idVAR, parser, 93); |
||
8097 | maxcodehac | 3141 | PARS.check1(ident._type = tINTEGER, parser, 97); |
7597 | akron1 | 3142 | PARS.ExpectSym(parser, SCAN.lxASSIGN); |
3143 | NextPos(parser, pos); |
||
3144 | expression(parser, e); |
||
7693 | akron1 | 3145 | PARS.check(isInt(e), pos, 76); |
7597 | akron1 | 3146 | |
8097 | maxcodehac | 3147 | offset := PROG.getOffset(ident); |
7597 | akron1 | 3148 | |
3149 | IF ident.global THEN |
||
7693 | akron1 | 3150 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 3151 | ELSE |
7693 | akron1 | 3152 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 3153 | END; |
3154 | |||
3155 | IF e.obj = eCONST THEN |
||
7693 | akron1 | 3156 | IL.AddCmd(IL.opSAVEC, ARITH.Int(e.value)) |
7597 | akron1 | 3157 | ELSE |
7693 | akron1 | 3158 | IL.AddCmd0(IL.opSAVE) |
7597 | akron1 | 3159 | END; |
3160 | |||
7693 | akron1 | 3161 | IL.SetLabel(L1); |
7597 | akron1 | 3162 | |
3163 | IF ident.global THEN |
||
7693 | akron1 | 3164 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 3165 | ELSE |
7693 | akron1 | 3166 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 3167 | END; |
8097 | maxcodehac | 3168 | IL.load(ident._type.size); |
7597 | akron1 | 3169 | |
3170 | PARS.checklex(parser, SCAN.lxTO); |
||
7693 | akron1 | 3171 | NextPos(parser, pos2); |
7597 | akron1 | 3172 | expression(parser, e); |
7693 | akron1 | 3173 | PARS.check(isInt(e), pos2, 76); |
7597 | akron1 | 3174 | |
3175 | IF parser.sym = SCAN.lxBY THEN |
||
3176 | NextPos(parser, pos); |
||
3177 | PARS.ConstExpression(parser, step); |
||
7693 | akron1 | 3178 | PARS.check(step.typ = ARITH.tINTEGER, pos, 76); |
7597 | akron1 | 3179 | st := ARITH.getInt(step); |
7693 | akron1 | 3180 | PARS.check(st # 0, pos, 98) |
7597 | akron1 | 3181 | ELSE |
3182 | st := 1 |
||
3183 | END; |
||
3184 | |||
3185 | IF e.obj = eCONST THEN |
||
3186 | IF st > 0 THEN |
||
7693 | akron1 | 3187 | IL.AddCmd(IL.opLEC, ARITH.Int(e.value)); |
3188 | IF ARITH.Int(e.value) = UTILS.target.maxInt THEN |
||
3189 | ERRORS.WarningMsg(pos2.line, pos2.col, 1) |
||
3190 | END |
||
7597 | akron1 | 3191 | ELSE |
7693 | akron1 | 3192 | IL.AddCmd(IL.opGEC, ARITH.Int(e.value)); |
3193 | IF ARITH.Int(e.value) = UTILS.target.minInt THEN |
||
3194 | ERRORS.WarningMsg(pos2.line, pos2.col, 1) |
||
3195 | END |
||
7597 | akron1 | 3196 | END |
3197 | ELSE |
||
3198 | IF st > 0 THEN |
||
7693 | akron1 | 3199 | IL.AddCmd0(IL.opLE) |
7597 | akron1 | 3200 | ELSE |
7693 | akron1 | 3201 | IL.AddCmd0(IL.opGE) |
7597 | akron1 | 3202 | END |
3203 | END; |
||
3204 | |||
8859 | leency | 3205 | IL.Jmp(IL.opJZ, L2); |
7597 | akron1 | 3206 | |
3207 | PARS.checklex(parser, SCAN.lxDO); |
||
3208 | PARS.Next(parser); |
||
3209 | parser.StatSeq(parser); |
||
3210 | |||
3211 | IF ident.global THEN |
||
7693 | akron1 | 3212 | IL.AddCmd(IL.opGADR, offset) |
7597 | akron1 | 3213 | ELSE |
7693 | akron1 | 3214 | IL.AddCmd(IL.opLADR, -offset) |
7597 | akron1 | 3215 | END; |
3216 | |||
7693 | akron1 | 3217 | IL.AddCmd(IL.opINCC, st); |
7597 | akron1 | 3218 | |
8859 | leency | 3219 | IL.Jmp(IL.opJMP, L1); |
7597 | akron1 | 3220 | |
3221 | PARS.checklex(parser, SCAN.lxEND); |
||
3222 | PARS.Next(parser); |
||
3223 | |||
7693 | akron1 | 3224 | IL.SetLabel(L2); |
7597 | akron1 | 3225 | |
8859 | leency | 3226 | IL.AddCmd(IL.opNOP, IL.end_loop) |
7597 | akron1 | 3227 | END ForStatement; |
3228 | |||
3229 | |||
3230 | PROCEDURE statement (parser: PARS.PARSER); |
||
3231 | VAR |
||
3232 | sym: INTEGER; |
||
3233 | |||
3234 | BEGIN |
||
3235 | sym := parser.sym; |
||
3236 | |||
3237 | IF sym = SCAN.lxIDENT THEN |
||
3238 | ElementaryStatement(parser) |
||
3239 | ELSIF sym = SCAN.lxIF THEN |
||
3240 | IfStatement(parser, TRUE) |
||
3241 | ELSIF sym = SCAN.lxWHILE THEN |
||
3242 | IfStatement(parser, FALSE) |
||
3243 | ELSIF sym = SCAN.lxREPEAT THEN |
||
3244 | RepeatStatement(parser) |
||
3245 | ELSIF sym = SCAN.lxCASE THEN |
||
3246 | CaseStatement(parser) |
||
3247 | ELSIF sym = SCAN.lxFOR THEN |
||
3248 | ForStatement(parser) |
||
3249 | END |
||
3250 | END statement; |
||
3251 | |||
3252 | |||
3253 | PROCEDURE StatSeq (parser: PARS.PARSER); |
||
3254 | BEGIN |
||
3255 | statement(parser); |
||
3256 | WHILE parser.sym = SCAN.lxSEMI DO |
||
3257 | PARS.Next(parser); |
||
3258 | statement(parser) |
||
3259 | END |
||
3260 | END StatSeq; |
||
3261 | |||
3262 | |||
8097 | maxcodehac | 3263 | PROCEDURE chkreturn (parser: PARS.PARSER; e: PARS.EXPR; t: PROG._TYPE; pos: PARS.POSITION): BOOLEAN; |
7597 | akron1 | 3264 | VAR |
3265 | res: BOOLEAN; |
||
3266 | |||
3267 | BEGIN |
||
3268 | res := assigncomp(e, t); |
||
3269 | IF res THEN |
||
3270 | IF e.obj = eCONST THEN |
||
8097 | maxcodehac | 3271 | IF e._type = tREAL THEN |
3272 | Float(parser, e) |
||
3273 | ELSIF e._type.typ = PROG.tNIL THEN |
||
7693 | akron1 | 3274 | IL.Const(0) |
7597 | akron1 | 3275 | ELSE |
3276 | LoadConst(e) |
||
3277 | END |
||
8097 | maxcodehac | 3278 | ELSIF (e._type = tINTEGER) & (t = tBYTE) & (chkBYTE IN Options.checking) THEN |
7597 | akron1 | 3279 | CheckRange(256, pos.line, errBYTE) |
3280 | ELSIF e.obj = ePROC THEN |
||
7693 | akron1 | 3281 | PARS.check(e.ident.global, pos, 85); |
3282 | IL.PushProc(e.ident.proc.label) |
||
7597 | akron1 | 3283 | ELSIF e.obj = eIMP THEN |
8097 | maxcodehac | 3284 | IL.PushImpProc(e.ident._import) |
7597 | akron1 | 3285 | END |
3286 | END |
||
3287 | |||
3288 | RETURN res |
||
3289 | END chkreturn; |
||
3290 | |||
3291 | |||
3292 | PROCEDURE setrtl; |
||
3293 | VAR |
||
3294 | rtl: PROG.UNIT; |
||
3295 | |||
3296 | |||
8859 | leency | 3297 | PROCEDURE getproc (rtl: PROG.UNIT; name: SCAN.IDSTR; idx: INTEGER); |
7597 | akron1 | 3298 | VAR |
7983 | leency | 3299 | id: PROG.IDENT; |
8859 | leency | 3300 | ident: SCAN.IDENT; |
7597 | akron1 | 3301 | |
3302 | BEGIN |
||
8859 | leency | 3303 | SCAN.setIdent(ident, name); |
3304 | id := PROG.getIdent(rtl, ident, FALSE); |
||
7597 | akron1 | 3305 | |
8097 | maxcodehac | 3306 | IF (id # NIL) & (id._import # NIL) THEN |
3307 | IL.set_rtl(idx, -id._import(IL.IMPORT_PROC).label); |
||
7597 | akron1 | 3308 | id.proc.used := TRUE |
3309 | ELSIF (id # NIL) & (id.proc # NIL) THEN |
||
7696 | akron1 | 3310 | IL.set_rtl(idx, id.proc.label); |
7597 | akron1 | 3311 | id.proc.used := TRUE |
3312 | ELSE |
||
7693 | akron1 | 3313 | ERRORS.WrongRTL(name) |
7597 | akron1 | 3314 | END |
3315 | END getproc; |
||
3316 | |||
3317 | |||
3318 | BEGIN |
||
8097 | maxcodehac | 3319 | rtl := PROG.program.rtl; |
7597 | akron1 | 3320 | ASSERT(rtl # NIL); |
3321 | |||
7983 | leency | 3322 | getproc(rtl, "_strcmp", IL._strcmp); |
3323 | getproc(rtl, "_length", IL._length); |
||
3324 | getproc(rtl, "_arrcpy", IL._arrcpy); |
||
3325 | getproc(rtl, "_is", IL._is); |
||
3326 | getproc(rtl, "_guard", IL._guard); |
||
3327 | getproc(rtl, "_guardrec", IL._guardrec); |
||
3328 | getproc(rtl, "_new", IL._new); |
||
3329 | getproc(rtl, "_rot", IL._rot); |
||
3330 | getproc(rtl, "_strcpy", IL._strcpy); |
||
3331 | getproc(rtl, "_move", IL._move); |
||
3332 | getproc(rtl, "_set", IL._set); |
||
3333 | getproc(rtl, "_set1", IL._set1); |
||
3334 | getproc(rtl, "_lengthw", IL._lengthw); |
||
3335 | getproc(rtl, "_strcmpw", IL._strcmpw); |
||
3336 | getproc(rtl, "_init", IL._init); |
||
3337 | |||
3338 | IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN |
||
3339 | getproc(rtl, "_error", IL._error); |
||
3340 | getproc(rtl, "_divmod", IL._divmod); |
||
3341 | getproc(rtl, "_exit", IL._exit); |
||
3342 | getproc(rtl, "_dispose", IL._dispose); |
||
3343 | getproc(rtl, "_isrec", IL._isrec); |
||
3344 | getproc(rtl, "_dllentry", IL._dllentry); |
||
3345 | getproc(rtl, "_sofinit", IL._sofinit) |
||
8859 | leency | 3346 | ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN |
7983 | leency | 3347 | getproc(rtl, "_fmul", IL._fmul); |
3348 | getproc(rtl, "_fdiv", IL._fdiv); |
||
3349 | getproc(rtl, "_fdivi", IL._fdivi); |
||
3350 | getproc(rtl, "_fadd", IL._fadd); |
||
3351 | getproc(rtl, "_fsub", IL._fsub); |
||
3352 | getproc(rtl, "_fsubi", IL._fsubi); |
||
3353 | getproc(rtl, "_fcmp", IL._fcmp); |
||
3354 | getproc(rtl, "_floor", IL._floor); |
||
3355 | getproc(rtl, "_flt", IL._flt); |
||
3356 | getproc(rtl, "_pack", IL._pack); |
||
8097 | maxcodehac | 3357 | getproc(rtl, "_unpk", IL._unpk); |
8859 | leency | 3358 | IF CPU IN {TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN |
8097 | maxcodehac | 3359 | getproc(rtl, "_error", IL._error) |
3360 | END |
||
7693 | akron1 | 3361 | END |
7597 | akron1 | 3362 | |
3363 | END setrtl; |
||
3364 | |||
3365 | |||
7693 | akron1 | 3366 | PROCEDURE compile* (path, lib_path, modname, outname: PARS.PATH; target: INTEGER; options: PROG.OPTIONS); |
7597 | akron1 | 3367 | VAR |
7693 | akron1 | 3368 | parser: PARS.PARSER; |
7597 | akron1 | 3369 | ext: PARS.PATH; |
3370 | |||
3371 | BEGIN |
||
8097 | maxcodehac | 3372 | tINTEGER := PROG.program.stTypes.tINTEGER; |
3373 | tBYTE := PROG.program.stTypes.tBYTE; |
||
3374 | tCHAR := PROG.program.stTypes.tCHAR; |
||
3375 | tSET := PROG.program.stTypes.tSET; |
||
3376 | tBOOLEAN := PROG.program.stTypes.tBOOLEAN; |
||
3377 | tWCHAR := PROG.program.stTypes.tWCHAR; |
||
3378 | tREAL := PROG.program.stTypes.tREAL; |
||
7693 | akron1 | 3379 | |
3380 | Options := options; |
||
7983 | leency | 3381 | CPU := TARGETS.CPU; |
7693 | akron1 | 3382 | |
7983 | leency | 3383 | ext := UTILS.FILE_EXT; |
7597 | akron1 | 3384 | CaseLabels := C.create(); |
3385 | CaseVar := C.create(); |
||
3386 | |||
3387 | CaseVariants := LISTS.create(NIL); |
||
3388 | LISTS.push(CaseVariants, NewVariant(0, NIL)); |
||
3389 | |||
7983 | leency | 3390 | IL.init(CPU); |
7597 | akron1 | 3391 | |
8097 | maxcodehac | 3392 | IF TARGETS.RTL THEN |
7693 | akron1 | 3393 | parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); |
8859 | leency | 3394 | IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN |
7597 | akron1 | 3395 | parser.parse(parser); |
3396 | PARS.destroy(parser) |
||
3397 | ELSE |
||
7693 | akron1 | 3398 | PARS.destroy(parser); |
3399 | parser := PARS.create(lib_path, lib_path, StatSeq, expression, designator, chkreturn); |
||
8859 | leency | 3400 | IF parser.open(parser, UTILS.RTL_NAME, UTILS.FILE_EXT) THEN |
7693 | akron1 | 3401 | parser.parse(parser); |
3402 | PARS.destroy(parser) |
||
3403 | ELSE |
||
7983 | leency | 3404 | ERRORS.FileNotFound(lib_path, UTILS.RTL_NAME, UTILS.FILE_EXT) |
7693 | akron1 | 3405 | END |
7597 | akron1 | 3406 | END |
3407 | END; |
||
3408 | |||
3409 | parser := PARS.create(path, lib_path, StatSeq, expression, designator, chkreturn); |
||
3410 | parser.main := TRUE; |
||
3411 | |||
8859 | leency | 3412 | IF parser.open(parser, modname, UTILS.FILE_EXT) THEN |
7597 | akron1 | 3413 | parser.parse(parser) |
3414 | ELSE |
||
7983 | leency | 3415 | ERRORS.FileNotFound(path, modname, UTILS.FILE_EXT) |
7597 | akron1 | 3416 | END; |
3417 | |||
3418 | PARS.destroy(parser); |
||
3419 | |||
8097 | maxcodehac | 3420 | IF PROG.program.bss > UTILS.MAX_GLOBAL_SIZE THEN |
7693 | akron1 | 3421 | ERRORS.Error(204) |
7597 | akron1 | 3422 | END; |
3423 | |||
8097 | maxcodehac | 3424 | IF TARGETS.RTL THEN |
7693 | akron1 | 3425 | setrtl |
3426 | END; |
||
7597 | akron1 | 3427 | |
8097 | maxcodehac | 3428 | PROG.DelUnused(IL.DelImport); |
7597 | akron1 | 3429 | |
8097 | maxcodehac | 3430 | IL.set_bss(PROG.program.bss); |
7693 | akron1 | 3431 | |
3432 | CASE CPU OF |
||
7983 | leency | 3433 | |TARGETS.cpuAMD64: AMD64.CodeGen(outname, target, options) |
3434 | |TARGETS.cpuX86: X86.CodeGen(outname, target, options) |
||
3435 | |TARGETS.cpuMSP430: MSP430.CodeGen(outname, target, options) |
||
3436 | |TARGETS.cpuTHUMB: THUMB.CodeGen(outname, target, options) |
||
8859 | leency | 3437 | |TARGETS.cpuRVM32I, |
3438 | TARGETS.cpuRVM64I: RVMxI.CodeGen(outname, target, options) |
||
7597 | akron1 | 3439 | END |
7693 | akron1 | 3440 | |
7597 | akron1 | 3441 | END compile; |
3442 | |||
3443 | |||
7983 | leency | 3444 | END STATEMENTS.=>>>=>>>>=>> |