Subversion Repositories Kolibri OS

Rev

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

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