Subversion Repositories Kolibri OS

Rev

Rev 9893 | Details | Compare with Previous | Last modification | View Log | RSS feed

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