Subversion Repositories Kolibri OS

Rev

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

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