Subversion Repositories Kolibri OS

Rev

Rev 8097 | Rev 9847 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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