Subversion Repositories Kolibri OS

Rev

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

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