Subversion Repositories Kolibri OS

Rev

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

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