Subversion Repositories Kolibri OS

Rev

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

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