Просмотр исходного кода

lower L7: CASE chunking, VAL, qualified calls, VAR actuals, proc values

More of the compiler session now lowers correctly (first divergence
moved from M2S.Get to AST.AddTxt):

- CASE: the arm list was capped at AST.MaxChild (8), silently dropping
  alternatives in a >8-arm CASE (M2S.Get).  CaseStat/CaseAlt now build a
  chunked arm sequence (AstAppend) and LowerCase follows the chunks.
- VAL(T, e): added to LowerBuiltinExpr with the same widen/narrow/convert
  chain as the grammar.
- Qualified calls (M.FileIO.ReadBytes) now resolve through Lower's own
  proc tables instead of SymTab (scopes are closed); CalleeAlias returns
  the base name so the mangled symbol stays <base>_<uid>.
- VAR actuals: LowerExprFull records value->address with NoteAddr,
  mirroring the grammar's Design.  AddrOfVal can no longer rely on the
  grammar's notes because its 256-entry ring wraps during a whole-session
  emit.
- Bare procedures used as values (CurrentCh := CharAt): Resolve now
  recognises the proc table and LowerProcAddr emits the code address.
  Sibling method names fall through to the THIS-binding path.

Suite 204/204; FIXPOINT OK (3,711,028 bytes), session 0 errors.

Remaining: Lower's flat symbol table collides on common names (s, i)
across procedures, so e.g. HIGH(s) in AST.AddTxt picks up another
procedure's `s`.  Proper scope tracking is the next step.
Eric Streit 6 дней назад
Родитель
Сommit
132a981e04
3 измененных файлов с 1946 добавлено и 1840 удалено
  1. 155 57
      compiler/src/Lower.mod
  2. 13 9
      compiler/src/M2.atg
  3. 1778 1774
      compiler/src/M2.lst

+ 155 - 57
compiler/src/Lower.mod

@@ -220,6 +220,15 @@ PROCEDURE Resolve (nm: ARRAY OF CHAR; VAR k: INTEGER;
     IF SymTab.Lookup(nm) THEN k := SymTab.SymKind(nm); t := SymTab.SymType(nm);
       RETURN TRUE
     END;
+    (* A bare procedure used as a value: it lives in the proc table.
+       Sibling method names must fall through so LowerDesign can bind
+       THIS, so exclude methods of the open class implementation. *)
+    IF FindProc(nm) >= 0 THEN
+      IF (curImplCls = SymTab.InvalidType)
+         OR NOT SymTab.MethodExists(curImplCls, nm) THEN
+        k := SymTab.KindProc; t := SymTab.InvalidType; RETURN TRUE
+      END
+    END;
     RETURN FALSE
   END Resolve;
 
@@ -541,7 +550,8 @@ PROCEDURE CanMethodCall (n: AST.Node): BOOLEAN;
 
 PROCEDURE CalleeAlias (call: AST.Node; VAR mal: SymTab.Name): BOOLEAN;
 (* Callee is `M.P` (module-qualified): materialize the export alias. *)
-  VAR d, sel: AST.Node; nm, fn: SymTab.Name; k: INTEGER; t: SymTab.TypeIndex;
+  VAR d, sel: AST.Node; nm, fn, al: SymTab.Name; k: INTEGER;
+      t: SymTab.TypeIndex;
   BEGIN
     d := AST.Child(call, 0);
     IF (AST.Kind(d) # AST.NkDesignator) OR (AST.NChild(d) # 2) THEN
@@ -553,7 +563,11 @@ PROCEDURE CalleeAlias (call: AST.Node; VAR mal: SymTab.Name): BOOLEAN;
     IF NOT Resolve(nm, k, t) THEN RETURN FALSE END;
     IF k # SymTab.KindModule THEN RETURN FALSE END;
     Name(AST.Child(sel, 0), fn);
-    RETURN SymTab.MaterializeAlias(nm, fn, mal)
+    IF NOT SymTab.MaterializeAlias(nm, fn, al) THEN RETURN FALSE END;
+    (* Lower's proc table is keyed by the base name (the mangled symbol
+       is <base>_<uid>), so return fn, not the materialized alias. *)
+    CopyN(fn, mal);
+    RETURN TRUE
   END CalleeAlias;
 
 PROCEDURE IsQualifiedCall (n: AST.Node): BOOLEAN;
@@ -1006,11 +1020,15 @@ PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
     qual := CalleeAlias(n, nm);
     ind := FALSE;
     IF qual THEN
-      uid := SymTab.ProcUid(nm); res := SymTab.ProcRes(nm);
-      depth := SymTab.ProcDepthOf(nm); ext := SymTab.IsExternal(nm);
-      np := SymTab.ProcNPar(nm);
-      IF ext THEN QbeGen.CopyOp(nm, mg) ELSE QbeGen.Mangled(nm, uid, mg) END;
-      QbeGen.CallBegin(mg, res, depth, ext)
+      (* A qualified callee (M.P) resolves to the real name; use Lower's
+         tables, not SymTab, whose scopes are closed by now. *)
+      IF ProcInfo(nm, uid, res, depth, ext, np) THEN
+        IF ext THEN QbeGen.CopyOp(nm, mg) ELSE QbeGen.Mangled(nm, uid, mg) END;
+        QbeGen.CallBegin(mg, res, depth, ext)
+      ELSE
+        res := SymTab.InvalidType;
+        QbeGen.CallBegin(nm, res, 0, FALSE)
+      END
     ELSE
       CalleeName(n, nm);
       IF FindSym(nm, ck, ct)
@@ -1043,9 +1061,6 @@ PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
       IF ind THEN
         ft := SymTab.ProcTypeParamType(ct, i - 1);
         isV := SymTab.ProcTypeParamIsVar(ct, i - 1)
-      ELSIF qual THEN
-        ft := SymTab.ParamType(nm, i - 1);
-        isV := SymTab.ParamIsVar(nm, i - 1)
       ELSE
         IF NOT ParamInfo(nm, i - 1, ft, isV, pn) THEN END
       END;
@@ -1078,6 +1093,7 @@ PROCEDURE IsBuiltin (nm: ARRAY OF CHAR): BOOLEAN;
         OR SymTab.Equal(nm, "CHR") OR SymTab.Equal(nm, "ORD")
         OR SymTab.Equal(nm, "SIZE") OR SymTab.Equal(nm, "TSIZE")
         OR SymTab.Equal(nm, "LEN") OR SymTab.Equal(nm, "HIGH")
+        OR SymTab.Equal(nm, "VAL")
         OR SymTab.Equal(nm, "MIN") OR SymTab.Equal(nm, "MAX")
         OR SymTab.Equal(nm, "SHIFT") OR SymTab.Equal(nm, "ROTATE")
         OR SymTab.Equal(nm, "ADR")
@@ -1089,8 +1105,9 @@ PROCEDURE IsBuiltin (nm: ARRAY OF CHAR): BOOLEAN;
 PROCEDURE LowerBuiltinExpr (n: AST.Node; nm: SymTab.Name;
                             VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal);
 (* Value builtins (Fact). *)
-  VAR et, et2, dt: SymTab.TypeIndex; qa, qt, q2, qd: QbeGen.QVal;
-      k, lo, hi: INTEGER; qn: SymTab.Name; sfx: BOOLEAN; isMax: BOOLEAN;
+  VAR et, et2, dt, vt: SymTab.TypeIndex; qa, qt, q2, qd: QbeGen.QVal;
+      k, lo, hi, c1, c2: INTEGER; qn, vn: SymTab.Name; sfx: BOOLEAN;
+      isMax: BOOLEAN;
   BEGIN
     IF SymTab.Equal(nm, "ABS") THEN
       LowerExpr(AST.Child(n, 1), et, q);
@@ -1139,6 +1156,29 @@ PROCEDURE LowerBuiltinExpr (n: AST.Node; nm: SymTab.Name;
       ELSE
         t := SymTab.InvalidType; QbeGen.CopyOp("0", q)
       END
+    ELSIF SymTab.Equal(nm, "VAL") THEN
+      Name(AST.Child(n, 1), vn);
+      IF NOT SymTab.Lookup(vn) THEN
+        t := SymTab.InvalidType; QbeGen.CopyOp("0", q)
+      ELSE
+        vt := SymTab.SymType(vn);
+        LowerExpr(AST.Child(n, 2), et, q);
+        c1 := SymTab.ClassOf(et); c2 := SymTab.ClassOf(vt);
+        IF (c1 = SymTab.ClInt) AND (c2 = SymTab.ClLong) THEN
+          QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q); t := vt
+        ELSIF (c1 = SymTab.ClLong) AND (c2 = SymTab.ClInt) THEN
+          QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q); t := vt
+        ELSIF (c1 = SymTab.ClInt) AND (c2 = SymTab.ClReal) THEN
+          QbeGen.ConvIR(q, qa); QbeGen.CopyOp(qa, q); t := vt
+        ELSIF (c1 = SymTab.ClLong) AND (c2 = SymTab.ClReal) THEN
+          QbeGen.ConvLR(q, qa); QbeGen.CopyOp(qa, q); t := vt
+        ELSIF (c1 = SymTab.ClReal) AND (c2 = SymTab.ClInt) THEN
+          QbeGen.ConvRI(q, qa); QbeGen.CopyOp(qa, q); t := vt
+        ELSIF (c1 = SymTab.ClReal) AND (c2 = SymTab.ClLong) THEN
+          QbeGen.ConvRL(q, qa); QbeGen.CopyOp(qa, q); t := vt
+        ELSE t := vt   (* same representation: no-op *)
+        END
+      END
     ELSIF SymTab.Equal(nm, "SHIFT") OR SymTab.Equal(nm, "ROTATE") THEN
       LowerExpr(AST.Child(n, 1), et, q);
       LowerExpr(AST.Child(n, 2), et2, q2);
@@ -1354,58 +1394,85 @@ PROCEDURE LowerMethodCall (n: AST.Node; VAR t: SymTab.TypeIndex;
   END LowerMethodCall;
 
 PROCEDURE LowerCase (n: AST.Node);
-(* CASE as a compare-chain (mirrors CaseStat/CaseAlt/CaseLabel). *)
-  VAR i, j: CARDINAL; arm, lab: AST.Node; tsel, t2, t3: SymTab.TypeIndex;
+(* CASE as a compare-chain (mirrors CaseStat/CaseAlt/CaseLabel).  The
+   arm list is chunked (AstAppend) so a CASE with more than MaxChild
+   alternatives is not truncated. *)
+  VAR i, j: CARDINAL; arm, lab, seq, next: AST.Node;
+      tsel, t2, t3: SymTab.TypeIndex;
       qsel, q2, q3, qc, qd, qe, lEnd, lBody, lAfter, lNext: QbeGen.QVal;
   BEGIN
     LowerExpr(AST.Child(n, 0), tsel, qsel);
     QbeGen.NewLabel(lEnd);
-    i := 1;
-    WHILE i < AST.NChild(n) DO
-      arm := AST.Child(n, i);
-      IF AST.Op(arm) = 1 THEN
-        (* ELSE arm: emitted after the alternatives *)
-      ELSE
-        QbeGen.NewLabel(lBody); QbeGen.NewLabel(lAfter);
-        j := 0;
-        WHILE j + 1 < AST.NChild(arm) DO
-          lab := AST.Child(arm, j);
-          IF AST.Kind(lab) = AST.NkSubrange THEN
-            LowerExpr(AST.Child(lab, 0), t2, q2);
-            QbeGen.NewLabel(lNext);
-            QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE);
-            QbeGen.Jnz(qc, lBody, lNext);
-            QbeGen.EmitLabel(lNext);
-            LowerExpr(AST.Child(lab, 1), t3, q3);
-            QbeGen.Cmp(SymTab.OpGe, qsel, q2, qc, FALSE);
-            QbeGen.Cmp(SymTab.OpLe, qsel, q3, qd, FALSE);
-            QbeGen.NewTemp(qe);
-            QbeGen.Op3("and", qe, qc, qd, FALSE);
-            QbeGen.NewLabel(lNext);
-            QbeGen.Jnz(qe, lBody, lNext);
-            QbeGen.EmitLabel(lNext)
-          ELSE
-            LowerExpr(lab, t2, q2);
-            QbeGen.NewLabel(lNext);
-            QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE);
-            QbeGen.Jnz(qc, lBody, lNext);
-            QbeGen.EmitLabel(lNext)
+    (* pass 1: alternatives (ELSE arms come after) *)
+    seq := AST.Child(n, 1);
+    WHILE seq # AST.NoNode DO
+      i := 0;
+      WHILE i < AST.NChild(seq) DO
+        arm := AST.Child(seq, i);
+        IF AST.Kind(arm) = AST.NkBlock THEN
+          (* continuation chunk *)
+        ELSIF AST.Op(arm) = 1 THEN
+          (* ELSE arm: emitted in pass 2 *)
+        ELSE
+          QbeGen.NewLabel(lBody); QbeGen.NewLabel(lAfter);
+          j := 0;
+          WHILE j + 1 < AST.NChild(arm) DO
+            lab := AST.Child(arm, j);
+            IF AST.Kind(lab) = AST.NkSubrange THEN
+              LowerExpr(AST.Child(lab, 0), t2, q2);
+              QbeGen.NewLabel(lNext);
+              QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE);
+              QbeGen.Jnz(qc, lBody, lNext);
+              QbeGen.EmitLabel(lNext);
+              LowerExpr(AST.Child(lab, 1), t3, q3);
+              QbeGen.Cmp(SymTab.OpGe, qsel, q2, qc, FALSE);
+              QbeGen.Cmp(SymTab.OpLe, qsel, q3, qd, FALSE);
+              QbeGen.NewTemp(qe);
+              QbeGen.Op3("and", qe, qc, qd, FALSE);
+              QbeGen.NewLabel(lNext);
+              QbeGen.Jnz(qe, lBody, lNext);
+              QbeGen.EmitLabel(lNext)
+            ELSE
+              LowerExpr(lab, t2, q2);
+              QbeGen.NewLabel(lNext);
+              QbeGen.Cmp(SymTab.OpEq, qsel, q2, qc, FALSE);
+              QbeGen.Jnz(qc, lBody, lNext);
+              QbeGen.EmitLabel(lNext)
+            END;
+            INC(j)
           END;
-          INC(j)
+          QbeGen.Jmp(lAfter);
+          QbeGen.EmitLabel(lBody);
+          LowerStmt(AST.Child(arm, AST.NChild(arm) - 1));
+          QbeGen.Jmp(lEnd);
+          QbeGen.EmitLabel(lAfter)
         END;
-        QbeGen.Jmp(lAfter);
-        QbeGen.EmitLabel(lBody);
-        LowerStmt(AST.Child(arm, AST.NChild(arm) - 1));
-        QbeGen.Jmp(lEnd);
-        QbeGen.EmitLabel(lAfter)
+        INC(i)
       END;
-      INC(i)
+      next := AST.NoNode;
+      IF AST.NChild(seq) > 0 THEN
+        next := AST.Child(seq, AST.NChild(seq) - 1);
+        IF AST.Kind(next) # AST.NkBlock THEN next := AST.NoNode END
+      END;
+      seq := next
     END;
-    i := 1;
-    WHILE i < AST.NChild(n) DO
-      arm := AST.Child(n, i);
-      IF AST.Op(arm) = 1 THEN LowerStmt(AST.Child(arm, 0)) END;
-      INC(i)
+    (* pass 2: ELSE arms *)
+    seq := AST.Child(n, 1);
+    WHILE seq # AST.NoNode DO
+      i := 0;
+      WHILE i < AST.NChild(seq) DO
+        arm := AST.Child(seq, i);
+        IF (AST.Kind(arm) # AST.NkBlock) AND (AST.Op(arm) = 1) THEN
+          LowerStmt(AST.Child(arm, 0))
+        END;
+        INC(i)
+      END;
+      next := AST.NoNode;
+      IF AST.NChild(seq) > 0 THEN
+        next := AST.Child(seq, AST.NChild(seq) - 1);
+        IF AST.Kind(next) # AST.NkBlock THEN next := AST.NoNode END
+      END;
+      seq := next
     END;
     QbeGen.EmitLabel(lEnd)
   END LowerCase;
@@ -1428,11 +1495,24 @@ PROCEDURE LowerWith (n: AST.Node);
     WHILE withTop > 0 DO DEC(withTop); QbeGen.PopWith END
   END LowerWith;
 
+PROCEDURE LowerProcAddr (nm: ARRAY OF CHAR; VAR q: QbeGen.QVal);
+(* Code address of a procedure used as a value (assign to a procedure
+   variable): $<base>_<uid>, or the plain C link for external procs. *)
+  VAR uid, depth, np: CARDINAL; res: SymTab.TypeIndex; ext: BOOLEAN;
+      mg: QbeGen.QVal;
+  BEGIN
+    IF ProcInfo(nm, uid, res, depth, ext, np) THEN
+      IF ext THEN QbeGen.CopyOp(nm, mg) ELSE QbeGen.Mangled(nm, uid, mg) END;
+      QbeGen.ProcAddr(mg, q)
+    ELSE QbeGen.CopyOp("0", q)
+    END
+  END LowerProcAddr;
+
 PROCEDURE LowerExprFull (n: AST.Node; VAR t: SymTab.TypeIndex;
                          VAR q: QbeGen.QVal; VAR k: INTEGER;
                          VAR qn: SymTab.Name; VAR sfx: BOOLEAN;
                          asAddr: BOOLEAN);
-  VAR t2: SymTab.TypeIndex; q2, qt, qf, qs, qr: QbeGen.QVal;
+  VAR t2: SymTab.TypeIndex; q2, qt, qf, qs, qr, qaddr: QbeGen.QVal;
       lNext, lFalse, lTrue, lDone: QbeGen.QVal;
       kind, op, rop: INTEGER;
       folded, isR, isCh: BOOLEAN;
@@ -1442,7 +1522,25 @@ PROCEDURE LowerExprFull (n: AST.Node; VAR t: SymTab.TypeIndex;
   BEGIN
     IF AST.Kind(n) = AST.NkDesignator THEN
       LowerDesign(n, t, k, q, qn, sfx);
+      IF k = SymTab.KindProc THEN
+        (* bare procedure used as a value: its code address *)
+        LowerProcAddr(qn, q);
+        RETURN
+      END;
+      (* Record value->address for VAR actuals, mirroring the grammar's
+         Design.  AddrOfVal cannot rely on the grammar's notes: its ring
+         (256) wraps long before a whole-session emit finishes. *)
+      IF sfx THEN QbeGen.CopyOp(q, qaddr) ELSE QbeGen.AddrOf(qn, qaddr) END;
       IF NOT asAddr THEN FinalLoad(t, sfx, q) END;
+      IF (k = SymTab.KindVar) OR (k = SymTab.KindParam)
+         OR (k = SymTab.KindField) THEN
+        QbeGen.NoteAddr(q, qaddr)
+      ELSIF sfx AND (t # SymTab.InvalidType)
+         AND ((SymTab.ClassOf(t) = SymTab.ClArray)
+              OR (SymTab.ClassOf(t) = SymTab.ClSet)
+              OR (SymTab.ClassOf(t) = SymTab.ClRecord)) THEN
+        QbeGen.NoteAddr(q, qaddr)
+      END;
       RETURN
     END;
     k := -1; qn[0] := CHR(0); sfx := FALSE;

+ 13 - 9
compiler/src/M2.atg

@@ -2058,26 +2058,30 @@ PRODUCTIONS
                                            QbeGen.EmitLabel(lEnd); .) .
   CaseStat                              (. VAR tsel: SymTab.TypeIndex;
                                              qsel, lEnd: QbeGen.QVal;
-                                             arm, astNode: AST.Node; .)
+                                             arm, astNode, astArms,
+                                             astArmsTail: AST.Node; .)
     = "CASE" Expr<tsel, qsel>           (. astNode := AST.MakeNode(AST.NkCase);
                                            AST.SetChild(astNode, 0, astCur);
+                                           astArms := AST.NoNode;
+                                           astArmsTail := AST.NoNode;
                                            QbeGen.NewLabel(lEnd); .)
-      "OF" CaseAlt<tsel, qsel, lEnd, astNode>
-      { "|" CaseAlt<tsel, qsel, lEnd, astNode> }
+      "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
+      { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
       [ "ELSE"                          (. astStmt := AST.NoNode; .)
         [ StatSeq ]                     (. arm := AST.MakeNode(AST.NkCaseArm);
                                            AST.SetOp(arm, 1);
                                            AST.SetChild(arm, 0, astStmt);
-                                           AST.SetChild(astNode,
-                                             AST.NChild(astNode), arm); .) ]
-      "END"                             (. astStmt := astNode;
+                                           AstAppend(AST.NkBlock,
+                                             astArms, astArmsTail, arm); .) ]
+      "END"                             (. AST.SetChild(astNode, 1, astArms);
+                                           astStmt := astNode;
                                            QbeGen.EmitLabel(lEnd); .) .
   (* Compare-chain lowering: each alternative ends its match-tests
      with "jmp lAfter", so the no-match fallthrough skips the body:
      "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
      lAfter:". Falls into the next alternative, ELSE, or END. *)
   CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
-          lEnd: QbeGen.QVal; cnode: AST.Node>
+          lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
                                         (. VAR lBody, lAfter: QbeGen.QVal;
                                              arm: AST.Node; .)
     =                                   (. arm := AST.MakeNode(AST.NkCaseArm);
@@ -2090,8 +2094,8 @@ PRODUCTIONS
                                            QbeGen.EmitLabel(lBody); .)
       [ StatSeq ]                       (. AST.SetChild(arm, AST.NChild(arm),
                                            astStmt);
-                                           AST.SetChild(cnode,
-                                             AST.NChild(cnode), arm);
+                                           AstAppend(AST.NkBlock,
+                                             arms, armsTail, arm);
                                            QbeGen.Jmp(lEnd);
                                            QbeGen.EmitLabel(lAfter); .) .
   CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;

+ 1778 - 1774
compiler/src/M2.lst

@@ -2076,1796 +2076,1800 @@ Listing:
  2058                                             QbeGen.EmitLabel(lEnd); .) .
  2059    CaseStat                              (. VAR tsel: SymTab.TypeIndex;
  2060                                               qsel, lEnd: QbeGen.QVal;
- 2061                                               arm, astNode: AST.Node; .)
- 2062      = "CASE" Expr<tsel, qsel>           (. astNode := AST.MakeNode(AST.NkCase);
- 2063                                             AST.SetChild(astNode, 0, astCur);
- 2064                                             QbeGen.NewLabel(lEnd); .)
- 2065        "OF" CaseAlt<tsel, qsel, lEnd, astNode>
- 2066        { "|" CaseAlt<tsel, qsel, lEnd, astNode> }
- 2067        [ "ELSE"                          (. astStmt := AST.NoNode; .)
- 2068          [ StatSeq ]                     (. arm := AST.MakeNode(AST.NkCaseArm);
- 2069                                             AST.SetOp(arm, 1);
- 2070                                             AST.SetChild(arm, 0, astStmt);
- 2071                                             AST.SetChild(astNode,
- 2072                                               AST.NChild(astNode), arm); .) ]
- 2073        "END"                             (. astStmt := astNode;
- 2074                                             QbeGen.EmitLabel(lEnd); .) .
- 2075    (* Compare-chain lowering: each alternative ends its match-tests
- 2076       with "jmp lAfter", so the no-match fallthrough skips the body:
- 2077       "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
- 2078       lAfter:". Falls into the next alternative, ELSE, or END. *)
- 2079    CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
- 2080            lEnd: QbeGen.QVal; cnode: AST.Node>
- 2081                                          (. VAR lBody, lAfter: QbeGen.QVal;
- 2082                                               arm: AST.Node; .)
- 2083      =                                   (. arm := AST.MakeNode(AST.NkCaseArm);
- 2084                                             QbeGen.NewLabel(lBody);
- 2085                                             QbeGen.NewLabel(lAfter); .)
- 2086        CaseLabel<tsel, qsel, lBody, arm>
- 2087        { "," CaseLabel<tsel, qsel, lBody, arm> }
- 2088        ":"                               (. astStmt := AST.NoNode;
- 2089                                             QbeGen.Jmp(lAfter);
- 2090                                             QbeGen.EmitLabel(lBody); .)
- 2091        [ StatSeq ]                       (. AST.SetChild(arm, AST.NChild(arm),
- 2092                                             astStmt);
- 2093                                             AST.SetChild(cnode,
- 2094                                               AST.NChild(cnode), arm);
- 2095                                             QbeGen.Jmp(lEnd);
- 2096                                             QbeGen.EmitLabel(lAfter); .) .
- 2097    CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
- 2098              lBody: QbeGen.QVal; arm: AST.Node>
- 2099                                          (. VAR t2, t3: SymTab.TypeIndex;
- 2100                                               q2, q3, qc, qd, qe:
- 2101                                                 QbeGen.QVal;
- 2102                                               astLab: AST.Node;
- 2103                                               lNext: QbeGen.QVal; .)
- 2104      = Expr<t2, q2> (. astLab := astCur;
- 2105                                             IF (t2 #
- 2106                                               SymTab.InvalidType)
- 2107   AND (tsel #
- 2108                                                 SymTab.InvalidType)
- 2109   AND ((SymTab.ClassOf(t2) =
- 2110                                                  SymTab.ClSet)
- 2111                                                 OR (SymTab.ClassOf(tsel) =
- 2112                                                     SymTab.ClSet)) THEN
- 2113                                               SemError(230)
- 2114                                             ELSIF (t2 #
- 2115                                               SymTab.InvalidType)
- 2116   AND (tsel #
- 2117                                                 SymTab.InvalidType)
- 2118   AND NOT SymTab.EqCheck(t2,
- 2119                                                   tsel) THEN
- 2120                                               SemError(213) END;
- 2121                                             IF NOT QbeGen.IsImm(q2) THEN
- 2122                                               SemError(230);
- 2123                                               QbeGen.CopyOp("0", q2)
- 2124                                             END;
- 2125                                             QbeGen.NewLabel(lNext);
- 2126                                             QbeGen.Cmp(SymTab.OpEq,
- 2127                                               qsel, q2, qc, FALSE);
- 2128                                             QbeGen.Jnz(qc, lBody, lNext);
- 2129                                             QbeGen.EmitLabel(lNext); .)
- 2130        [ ".." Expr<t3, q3>               (. astLab := AST.MakeBin(
- 2131                                               AST.NkSubrange, 0, astLab, astCur);
- 2132                                             IF (t3 #
- 2133                                               SymTab.InvalidType)
- 2134   AND (tsel #
- 2135                                                 SymTab.InvalidType)
- 2136   AND NOT SymTab.EqCheck(t3,
- 2137                                                   tsel) THEN
- 2138                                               SemError(213) END;
- 2139                                             IF NOT QbeGen.IsImm(q3) THEN
- 2140                                               SemError(230);
- 2141                                               QbeGen.CopyOp("0", q3)
- 2142                                             END;
- 2143                                             QbeGen.Cmp(SymTab.OpGe,
- 2144                                               qsel, q2, qc, FALSE);
- 2145                                             QbeGen.Cmp(SymTab.OpLe,
- 2146                                               qsel, q3, qd, FALSE);
- 2147                                             QbeGen.NewTemp(qe);
- 2148                                             QbeGen.Op3("and", qe, qc, qd,
- 2149                                               FALSE);
- 2150                                             QbeGen.NewLabel(lNext);
- 2151                                             QbeGen.Jnz(qe, lBody, lNext);
- 2152                                             QbeGen.EmitLabel(lNext); .) ]
- 2153                                          (. AST.SetChild(arm,
- 2154                                               AST.NChild(arm), astLab); .) .
- 2155    ReturnStat                            (. VAR t: SymTab.TypeIndex;
- 2156                                               q, qt: QbeGen.QVal;
- 2157                                               res: SymTab.TypeIndex;
- 2158                                               hadE, conv: BOOLEAN;
- 2159                                               astVal, astNode: AST.Node; .)
- 2160      = "RETURN"                          (. hadE := FALSE; astStmt := AST.NoNode; .)
- 2161        [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
- 2162                                          (. astNode := AST.MakeNode(AST.NkReturn);
- 2163                                             IF hadE THEN
- 2164                                               AST.SetChild(astNode, 0, astVal)
- 2165                                             END;
- 2166                                             astStmt := astNode;
- 2167                                             conv := FALSE;
- 2168                                             IF NOT SymTab.InProc() THEN
- 2169                                               SemError(232)
- 2170                                             ELSE res := SymTab.CurRes();
- 2171                                               IF NOT hadE THEN
- 2172                                                 IF res #
- 2173                                                    SymTab.InvalidType THEN
- 2174                                                   SemError(232)
- 2175                                                 ELSE QbeGen.EmitRet(q,
- 2176                                                   FALSE)
- 2177                                                 END
- 2178                                               ELSIF (res =
- 2179                                                      SymTab.InvalidType)
- 2180                                                  OR (t #
- 2181                                                      SymTab.InvalidType)
- 2182   AND NOT SymTab.Assignable(t,
- 2183                                                       res) THEN
- 2184                                                 SemError(232)
- 2185                                               ELSE
- 2186                                                 conv := (SymTab.ClassOf(
- 2187                                                   res) = SymTab.ClReal)
- 2188   AND SymTab.IsIntFamily(t);
- 2189                                                 IF conv THEN
- 2190                                                   QbeGen.ConvIR(q, qt);
- 2191                                                   QbeGen.EmitRet(qt, TRUE)
- 2192                                                 ELSE QbeGen.EmitRet(q, TRUE)
- 2193                                                 END
- 2194                                               END
- 2195                                             END; .) .
- 2196    HaltStat                              (. VAR t: SymTab.TypeIndex;
- 2197                                               q: QbeGen.QVal;
- 2198                                               astVal, astNode: AST.Node; .)
- 2199      = "HALT" (. astVal := AST.NoNode; .)
- 2200        [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
- 2201                                          (. astNode := AST.MakeNode(AST.NkHalt);
- 2202                                             IF astVal # AST.NoNode THEN
- 2203                                               AST.SetChild(astNode, 0, astVal)
- 2204                                             END;
- 2205                                             astStmt := astNode;
- 2206                                             QbeGen.HaltQ; .) .
- 2207    (* Designator: scalar loads, array addresses, and index suffixes.
- 2208       Each index descends one level (bounds-checked, trap on breach);
- 2209       nested levels reload the inner descriptor address. q ends as the
- 2210       value (scalars), the descriptor address (plain arrays), or the
- 2211       element address (indexed); sfx marks the indexed form. *)
- 2212    Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
- 2213           VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
- 2214                                          (. VAR n, fn, mal: SymTab.Name;
- 2215                                               cls: INTEGER;
- 2216                                               ic: SymTab.TypeIndex;
- 2217                                               curT, it, eT, bt:
- 2218                                                 SymTab.TypeIndex;
- 2219                                               iq, ql, qlo, qhi, qe:
- 2220                                                 QbeGen.QVal;
- 2221                                               lo, hi: INTEGER;
- 2222                                               fo: INTEGER;
- 2223                                               isOpen: BOOLEAN;
- 2224                                               qb, cv: QbeGen.QVal;
- 2225                                               fid, fref, slot: INTEGER;
- 2226                                               r: BOOLEAN;
- 2227                                                astDes, astSel: AST.Node; .)
- 2228      = GetIdent<n>                       (. methCls := SymTab.InvalidType;
- 2229                                             QbeGen.CopyOp(n, qn);
- 2230                                             sfx := FALSE;
- 2231                                             fid := 0; fref := 0; slot := 0;
- 2232                                             IF NOT SymTab.Lookup(n) THEN
- 2233                                               (* a bare method name inside
- 2234                                                  a CLASS IMPLEMENTATION
- 2235                                                  is a sibling call on
- 2236                                                  THIS *)
- 2237                                               ic := SymTab.CurImplClass();
- 2238                                               IF (ic #
- 2239                                                  SymTab.InvalidType)
- 2240    AND SymTab.MethodExists(ic, n) THEN
- 2241                                                 sfx := FALSE;
- 2242                                                 QbeGen.ThisBase(q);
- 2243                                                 QbeGen.ArmRecv(q);
- 2244                                                 methCls := ic;
- 2245                                                 k := SymTab.KindProc;
- 2246                                                 t := SymTab.InvalidType
- 2247                                               ELSIF SymTab.InProc() THEN
- 2248                                                 (* not declared yet: a
- 2249                                                    forward reference to a
- 2250                                                    module-level variable
- 2251                                                    declared further down. *)
- 2252                                                 k := SymTab.KindVar;
- 2253                                                 r := SymTab.FwdVarRef(n, k,
- 2254                                                   fref, t);
- 2255                                                 slot := QbeGen.FwdDesignator();
- 2256                                                 FwdVarNote(fref, slot);
- 2257                                                 fid := slot;
- 2258                                                 QbeGen.FwdAddrOper(fid, q);
- 2259                                                 sfx := TRUE
- 2260                                               ELSE
- 2261                                                 SemError(201);
- 2262                                                 t :=
- 2263                                                   SymTab.InvalidType;
- 2264                                                 k := -1;
- 2265                                                 QbeGen.CopyOp("0", q)
- 2266                                               END
- 2267                                             ELSE
- 2268                                               t := SymTab.SymType(n);
- 2269                                               k := SymTab.SymKind(n);
- 2270                                               IF k = SymTab.KindConst THEN
- 2271                                                 IF SymTab.Equal(n,
- 2272                                                    "TRUE") THEN
- 2273                                                   t := SymTab.BoolType();
- 2274                                                   QbeGen.CopyOp("1", q)
- 2275                                                 ELSIF SymTab.Equal(n,
- 2276                                                    "FALSE") THEN
+ 2061                                               arm, astNode, astArms,
+ 2062                                               astArmsTail: AST.Node; .)
+ 2063      = "CASE" Expr<tsel, qsel>           (. astNode := AST.MakeNode(AST.NkCase);
+ 2064                                             AST.SetChild(astNode, 0, astCur);
+ 2065                                             astArms := AST.NoNode;
+ 2066                                             astArmsTail := AST.NoNode;
+ 2067                                             QbeGen.NewLabel(lEnd); .)
+ 2068        "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
+ 2069        { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
+ 2070        [ "ELSE"                          (. astStmt := AST.NoNode; .)
+ 2071          [ StatSeq ]                     (. arm := AST.MakeNode(AST.NkCaseArm);
+ 2072                                             AST.SetOp(arm, 1);
+ 2073                                             AST.SetChild(arm, 0, astStmt);
+ 2074                                             AstAppend(AST.NkBlock,
+ 2075                                               astArms, astArmsTail, arm); .) ]
+ 2076        "END"                             (. AST.SetChild(astNode, 1, astArms);
+ 2077                                             astStmt := astNode;
+ 2078                                             QbeGen.EmitLabel(lEnd); .) .
+ 2079    (* Compare-chain lowering: each alternative ends its match-tests
+ 2080       with "jmp lAfter", so the no-match fallthrough skips the body:
+ 2081       "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
+ 2082       lAfter:". Falls into the next alternative, ELSE, or END. *)
+ 2083    CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
+ 2084            lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
+ 2085                                          (. VAR lBody, lAfter: QbeGen.QVal;
+ 2086                                               arm: AST.Node; .)
+ 2087      =                                   (. arm := AST.MakeNode(AST.NkCaseArm);
+ 2088                                             QbeGen.NewLabel(lBody);
+ 2089                                             QbeGen.NewLabel(lAfter); .)
+ 2090        CaseLabel<tsel, qsel, lBody, arm>
+ 2091        { "," CaseLabel<tsel, qsel, lBody, arm> }
+ 2092        ":"                               (. astStmt := AST.NoNode;
+ 2093                                             QbeGen.Jmp(lAfter);
+ 2094                                             QbeGen.EmitLabel(lBody); .)
+ 2095        [ StatSeq ]                       (. AST.SetChild(arm, AST.NChild(arm),
+ 2096                                             astStmt);
+ 2097                                             AstAppend(AST.NkBlock,
+ 2098                                               arms, armsTail, arm);
+ 2099                                             QbeGen.Jmp(lEnd);
+ 2100                                             QbeGen.EmitLabel(lAfter); .) .
+ 2101    CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
+ 2102              lBody: QbeGen.QVal; arm: AST.Node>
+ 2103                                          (. VAR t2, t3: SymTab.TypeIndex;
+ 2104                                               q2, q3, qc, qd, qe:
+ 2105                                                 QbeGen.QVal;
+ 2106                                               astLab: AST.Node;
+ 2107                                               lNext: QbeGen.QVal; .)
+ 2108      = Expr<t2, q2> (. astLab := astCur;
+ 2109                                             IF (t2 #
+ 2110                                               SymTab.InvalidType)
+ 2111   AND (tsel #
+ 2112                                                 SymTab.InvalidType)
+ 2113   AND ((SymTab.ClassOf(t2) =
+ 2114                                                  SymTab.ClSet)
+ 2115                                                 OR (SymTab.ClassOf(tsel) =
+ 2116                                                     SymTab.ClSet)) THEN
+ 2117                                               SemError(230)
+ 2118                                             ELSIF (t2 #
+ 2119                                               SymTab.InvalidType)
+ 2120   AND (tsel #
+ 2121                                                 SymTab.InvalidType)
+ 2122   AND NOT SymTab.EqCheck(t2,
+ 2123                                                   tsel) THEN
+ 2124                                               SemError(213) END;
+ 2125                                             IF NOT QbeGen.IsImm(q2) THEN
+ 2126                                               SemError(230);
+ 2127                                               QbeGen.CopyOp("0", q2)
+ 2128                                             END;
+ 2129                                             QbeGen.NewLabel(lNext);
+ 2130                                             QbeGen.Cmp(SymTab.OpEq,
+ 2131                                               qsel, q2, qc, FALSE);
+ 2132                                             QbeGen.Jnz(qc, lBody, lNext);
+ 2133                                             QbeGen.EmitLabel(lNext); .)
+ 2134        [ ".." Expr<t3, q3>               (. astLab := AST.MakeBin(
+ 2135                                               AST.NkSubrange, 0, astLab, astCur);
+ 2136                                             IF (t3 #
+ 2137                                               SymTab.InvalidType)
+ 2138   AND (tsel #
+ 2139                                                 SymTab.InvalidType)
+ 2140   AND NOT SymTab.EqCheck(t3,
+ 2141                                                   tsel) THEN
+ 2142                                               SemError(213) END;
+ 2143                                             IF NOT QbeGen.IsImm(q3) THEN
+ 2144                                               SemError(230);
+ 2145                                               QbeGen.CopyOp("0", q3)
+ 2146                                             END;
+ 2147                                             QbeGen.Cmp(SymTab.OpGe,
+ 2148                                               qsel, q2, qc, FALSE);
+ 2149                                             QbeGen.Cmp(SymTab.OpLe,
+ 2150                                               qsel, q3, qd, FALSE);
+ 2151                                             QbeGen.NewTemp(qe);
+ 2152                                             QbeGen.Op3("and", qe, qc, qd,
+ 2153                                               FALSE);
+ 2154                                             QbeGen.NewLabel(lNext);
+ 2155                                             QbeGen.Jnz(qe, lBody, lNext);
+ 2156                                             QbeGen.EmitLabel(lNext); .) ]
+ 2157                                          (. AST.SetChild(arm,
+ 2158                                               AST.NChild(arm), astLab); .) .
+ 2159    ReturnStat                            (. VAR t: SymTab.TypeIndex;
+ 2160                                               q, qt: QbeGen.QVal;
+ 2161                                               res: SymTab.TypeIndex;
+ 2162                                               hadE, conv: BOOLEAN;
+ 2163                                               astVal, astNode: AST.Node; .)
+ 2164      = "RETURN"                          (. hadE := FALSE; astStmt := AST.NoNode; .)
+ 2165        [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
+ 2166                                          (. astNode := AST.MakeNode(AST.NkReturn);
+ 2167                                             IF hadE THEN
+ 2168                                               AST.SetChild(astNode, 0, astVal)
+ 2169                                             END;
+ 2170                                             astStmt := astNode;
+ 2171                                             conv := FALSE;
+ 2172                                             IF NOT SymTab.InProc() THEN
+ 2173                                               SemError(232)
+ 2174                                             ELSE res := SymTab.CurRes();
+ 2175                                               IF NOT hadE THEN
+ 2176                                                 IF res #
+ 2177                                                    SymTab.InvalidType THEN
+ 2178                                                   SemError(232)
+ 2179                                                 ELSE QbeGen.EmitRet(q,
+ 2180                                                   FALSE)
+ 2181                                                 END
+ 2182                                               ELSIF (res =
+ 2183                                                      SymTab.InvalidType)
+ 2184                                                  OR (t #
+ 2185                                                      SymTab.InvalidType)
+ 2186   AND NOT SymTab.Assignable(t,
+ 2187                                                       res) THEN
+ 2188                                                 SemError(232)
+ 2189                                               ELSE
+ 2190                                                 conv := (SymTab.ClassOf(
+ 2191                                                   res) = SymTab.ClReal)
+ 2192   AND SymTab.IsIntFamily(t);
+ 2193                                                 IF conv THEN
+ 2194                                                   QbeGen.ConvIR(q, qt);
+ 2195                                                   QbeGen.EmitRet(qt, TRUE)
+ 2196                                                 ELSE QbeGen.EmitRet(q, TRUE)
+ 2197                                                 END
+ 2198                                               END
+ 2199                                             END; .) .
+ 2200    HaltStat                              (. VAR t: SymTab.TypeIndex;
+ 2201                                               q: QbeGen.QVal;
+ 2202                                               astVal, astNode: AST.Node; .)
+ 2203      = "HALT" (. astVal := AST.NoNode; .)
+ 2204        [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
+ 2205                                          (. astNode := AST.MakeNode(AST.NkHalt);
+ 2206                                             IF astVal # AST.NoNode THEN
+ 2207                                               AST.SetChild(astNode, 0, astVal)
+ 2208                                             END;
+ 2209                                             astStmt := astNode;
+ 2210                                             QbeGen.HaltQ; .) .
+ 2211    (* Designator: scalar loads, array addresses, and index suffixes.
+ 2212       Each index descends one level (bounds-checked, trap on breach);
+ 2213       nested levels reload the inner descriptor address. q ends as the
+ 2214       value (scalars), the descriptor address (plain arrays), or the
+ 2215       element address (indexed); sfx marks the indexed form. *)
+ 2216    Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
+ 2217           VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
+ 2218                                          (. VAR n, fn, mal: SymTab.Name;
+ 2219                                               cls: INTEGER;
+ 2220                                               ic: SymTab.TypeIndex;
+ 2221                                               curT, it, eT, bt:
+ 2222                                                 SymTab.TypeIndex;
+ 2223                                               iq, ql, qlo, qhi, qe:
+ 2224                                                 QbeGen.QVal;
+ 2225                                               lo, hi: INTEGER;
+ 2226                                               fo: INTEGER;
+ 2227                                               isOpen: BOOLEAN;
+ 2228                                               qb, cv: QbeGen.QVal;
+ 2229                                               fid, fref, slot: INTEGER;
+ 2230                                               r: BOOLEAN;
+ 2231                                                astDes, astSel: AST.Node; .)
+ 2232      = GetIdent<n>                       (. methCls := SymTab.InvalidType;
+ 2233                                             QbeGen.CopyOp(n, qn);
+ 2234                                             sfx := FALSE;
+ 2235                                             fid := 0; fref := 0; slot := 0;
+ 2236                                             IF NOT SymTab.Lookup(n) THEN
+ 2237                                               (* a bare method name inside
+ 2238                                                  a CLASS IMPLEMENTATION
+ 2239                                                  is a sibling call on
+ 2240                                                  THIS *)
+ 2241                                               ic := SymTab.CurImplClass();
+ 2242                                               IF (ic #
+ 2243                                                  SymTab.InvalidType)
+ 2244    AND SymTab.MethodExists(ic, n) THEN
+ 2245                                                 sfx := FALSE;
+ 2246                                                 QbeGen.ThisBase(q);
+ 2247                                                 QbeGen.ArmRecv(q);
+ 2248                                                 methCls := ic;
+ 2249                                                 k := SymTab.KindProc;
+ 2250                                                 t := SymTab.InvalidType
+ 2251                                               ELSIF SymTab.InProc() THEN
+ 2252                                                 (* not declared yet: a
+ 2253                                                    forward reference to a
+ 2254                                                    module-level variable
+ 2255                                                    declared further down. *)
+ 2256                                                 k := SymTab.KindVar;
+ 2257                                                 r := SymTab.FwdVarRef(n, k,
+ 2258                                                   fref, t);
+ 2259                                                 slot := QbeGen.FwdDesignator();
+ 2260                                                 FwdVarNote(fref, slot);
+ 2261                                                 fid := slot;
+ 2262                                                 QbeGen.FwdAddrOper(fid, q);
+ 2263                                                 sfx := TRUE
+ 2264                                               ELSE
+ 2265                                                 SemError(201);
+ 2266                                                 t :=
+ 2267                                                   SymTab.InvalidType;
+ 2268                                                 k := -1;
+ 2269                                                 QbeGen.CopyOp("0", q)
+ 2270                                               END
+ 2271                                             ELSE
+ 2272                                               t := SymTab.SymType(n);
+ 2273                                               k := SymTab.SymKind(n);
+ 2274                                               IF k = SymTab.KindConst THEN
+ 2275                                                 IF SymTab.Equal(n,
+ 2276                                                    "TRUE") THEN
  2277                                                   t := SymTab.BoolType();
- 2278                                                   QbeGen.CopyOp("0", q)
+ 2278                                                   QbeGen.CopyOp("1", q)
  2279                                                 ELSIF SymTab.Equal(n,
- 2280                                                    "NIL") THEN
- 2281                                                   QbeGen.CopyOp("0", q)
- 2282                                                 ELSE
- 2283                                                   cls :=
- 2284                                                     SymTab.ClassOf(t);
- 2285                                                   IF (t #
- 2286                                                       SymTab.InvalidType)
- 2287   AND ((cls = SymTab.ClInt)
- 2288                                                      OR (cls
- 2289                                                          = SymTab.ClChar)
- 2290                                                      OR (cls
- 2291                                                          = SymTab.ClEnum)
+ 2280                                                    "FALSE") THEN
+ 2281                                                   t := SymTab.BoolType();
+ 2282                                                   QbeGen.CopyOp("0", q)
+ 2283                                                 ELSIF SymTab.Equal(n,
+ 2284                                                    "NIL") THEN
+ 2285                                                   QbeGen.CopyOp("0", q)
+ 2286                                                 ELSE
+ 2287                                                   cls :=
+ 2288                                                     SymTab.ClassOf(t);
+ 2289                                                   IF (t #
+ 2290                                                       SymTab.InvalidType)
+ 2291   AND ((cls = SymTab.ClInt)
  2292                                                      OR (cls
- 2293                                                          = SymTab.ClReal)
+ 2293                                                          = SymTab.ClChar)
  2294                                                      OR (cls
- 2295                                                          = SymTab.ClLong)
+ 2295                                                          = SymTab.ClEnum)
  2296                                                      OR (cls
- 2297                                                          = SymTab.ClNil)) THEN
- 2298                                                     IF cls = SymTab.ClNil THEN
- 2299                                                       QbeGen.CopyOp("0", q)
- 2300                                                     ELSIF ((cls
- 2301                                                         = SymTab.ClInt)
- 2302                                                       OR (cls
- 2303                                                         = SymTab.ClChar)
- 2304                                                       OR (cls
- 2305                                                         = SymTab.ClEnum)
+ 2297                                                          = SymTab.ClReal)
+ 2298                                                      OR (cls
+ 2299                                                          = SymTab.ClLong)
+ 2300                                                      OR (cls
+ 2301                                                          = SymTab.ClNil)) THEN
+ 2302                                                     IF cls = SymTab.ClNil THEN
+ 2303                                                       QbeGen.CopyOp("0", q)
+ 2304                                                     ELSIF ((cls
+ 2305                                                         = SymTab.ClInt)
  2306                                                       OR (cls
- 2307                                                         = SymTab.ClLong))
- 2308    AND SymTab.GetSymVal(n, cv)
- 2309    AND QbeGen.IsImm(cv) THEN
- 2310                                                       QbeGen.CopyOp(cv, q)
- 2311                                                     ELSE
- 2312                                                       QbeGen.LoadVar(n,
- 2313                                                         cls = SymTab.ClReal,
- 2314                                                         q)
- 2315                                                     END
- 2316                                                   ELSIF (cls = SymTab.ClArray)
- 2317                                                      OR (cls = SymTab.ClRecord)
- 2318                                                      OR (cls = SymTab.ClClass)
- 2319                                                      OR (cls = SymTab.ClStr)
- 2320                                                      OR (cls = SymTab.ClUStr) THEN
- 2321                                                     (* aggregate constant:
- 2322                                                        its value IS the
- 2323                                                        descriptor address *)
- 2324                                                     IF SymTab.GetSymVal(n, cv) THEN
- 2325                                                       QbeGen.CopyOp(cv, q)
- 2326                                                     ELSE
- 2327                                                       QbeGen.CopyOp("0", q)
- 2328                                                     END
- 2329                                                   ELSE
- 2330                                                     IF t #
- 2331                                                        SymTab.InvalidType THEN
- 2332                                                       SemError(230)
- 2333                                                     END;
- 2334                                                     QbeGen.CopyOp("0", q)
- 2335                                                   END
- 2336                                                 END
- 2337                                               ELSIF (k = SymTab.KindVar)
- 2338                                                  OR (k = SymTab.KindParam) THEN
- 2339                                                 cls :=
- 2340                                                   SymTab.ClassOf(t);
- 2341                                                 IF (cls = SymTab.ClInt)
- 2342                                                    OR (cls = SymTab.ClBool)
- 2343                                                    OR (cls = SymTab.ClChar)
- 2344                                                    OR (cls = SymTab.ClUChar)
- 2345                                                    OR (cls = SymTab.ClEnum)
- 2346                                                    OR (cls
- 2347                                                        = SymTab.ClReal) THEN
- 2348                                                   QbeGen.LoadVar(n,
- 2349                                                     cls = SymTab.ClReal, q)
- 2350                                                 ELSIF (cls = SymTab.ClPtr)
- 2351                                                    OR (cls = SymTab.ClProc) THEN
- 2352                                                   QbeGen.LoadPtr(n, q)
- 2353                                                 ELSIF cls = SymTab.ClLong THEN
- 2354                                                   QbeGen.LoadLong(n, q)
- 2355                                                 ELSIF (cls
- 2356                                                         = SymTab.ClArray)
- 2357                                                    OR (cls
- 2358                                                        = SymTab.ClSet)
- 2359                                                    OR (cls
- 2360                                                        = SymTab.ClRecord)
+ 2307                                                         = SymTab.ClChar)
+ 2308                                                       OR (cls
+ 2309                                                         = SymTab.ClEnum)
+ 2310                                                       OR (cls
+ 2311                                                         = SymTab.ClLong))
+ 2312    AND SymTab.GetSymVal(n, cv)
+ 2313    AND QbeGen.IsImm(cv) THEN
+ 2314                                                       QbeGen.CopyOp(cv, q)
+ 2315                                                     ELSE
+ 2316                                                       QbeGen.LoadVar(n,
+ 2317                                                         cls = SymTab.ClReal,
+ 2318                                                         q)
+ 2319                                                     END
+ 2320                                                   ELSIF (cls = SymTab.ClArray)
+ 2321                                                      OR (cls = SymTab.ClRecord)
+ 2322                                                      OR (cls = SymTab.ClClass)
+ 2323                                                      OR (cls = SymTab.ClStr)
+ 2324                                                      OR (cls = SymTab.ClUStr) THEN
+ 2325                                                     (* aggregate constant:
+ 2326                                                        its value IS the
+ 2327                                                        descriptor address *)
+ 2328                                                     IF SymTab.GetSymVal(n, cv) THEN
+ 2329                                                       QbeGen.CopyOp(cv, q)
+ 2330                                                     ELSE
+ 2331                                                       QbeGen.CopyOp("0", q)
+ 2332                                                     END
+ 2333                                                   ELSE
+ 2334                                                     IF t #
+ 2335                                                        SymTab.InvalidType THEN
+ 2336                                                       SemError(230)
+ 2337                                                     END;
+ 2338                                                     QbeGen.CopyOp("0", q)
+ 2339                                                   END
+ 2340                                                 END
+ 2341                                               ELSIF (k = SymTab.KindVar)
+ 2342                                                  OR (k = SymTab.KindParam) THEN
+ 2343                                                 cls :=
+ 2344                                                   SymTab.ClassOf(t);
+ 2345                                                 IF (cls = SymTab.ClInt)
+ 2346                                                    OR (cls = SymTab.ClBool)
+ 2347                                                    OR (cls = SymTab.ClChar)
+ 2348                                                    OR (cls = SymTab.ClUChar)
+ 2349                                                    OR (cls = SymTab.ClEnum)
+ 2350                                                    OR (cls
+ 2351                                                        = SymTab.ClReal) THEN
+ 2352                                                   QbeGen.LoadVar(n,
+ 2353                                                     cls = SymTab.ClReal, q)
+ 2354                                                 ELSIF (cls = SymTab.ClPtr)
+ 2355                                                    OR (cls = SymTab.ClProc) THEN
+ 2356                                                   QbeGen.LoadPtr(n, q)
+ 2357                                                 ELSIF cls = SymTab.ClLong THEN
+ 2358                                                   QbeGen.LoadLong(n, q)
+ 2359                                                 ELSIF (cls
+ 2360                                                         = SymTab.ClArray)
  2361                                                    OR (cls
- 2362                                                        = SymTab.ClUStr)
+ 2362                                                        = SymTab.ClSet)
  2363                                                    OR (cls
- 2364                                                        = SymTab.ClClass) THEN
- 2365                                                   QbeGen.AddrOf(n, q)
- 2366                                                 ELSE SemError(230);
- 2367                                                   QbeGen.CopyOp("0", q)
- 2368                                                 END
- 2369                                               ELSE QbeGen.CopyOp("0", q);
- 2370                                                 IF k = SymTab.KindImport THEN
- 2371                                                   SemError(230)
- 2372                                                 ELSIF k =
- 2373                                                    SymTab.KindProc THEN
- 2374                                                   (* bare procedure name:
- 2375                                                      a following ArgList
- 2376                                                      makes it a call;
- 2377                                                      otherwise Fact
- 2378                                                      reports 230 *)
- 2379                                                 ELSE
- 2380                                                   IF k = SymTab.KindField THEN
- 2381                                                     IF QbeGen.TopWith(qb) THEN
- 2382                                                       fo :=
- 2383                                                         SymTab.FieldOffset(
- 2384                                                         SymTab.FieldOwner(n),
- 2385                                                         n);
- 2386                                                       QbeGen.FieldAddr(qb,
- 2387                                                         fo, q);
- 2388                                                       sfx := TRUE
- 2389                                                     ELSE SemError(230);
- 2390                                                       QbeGen.CopyOp("0", q)
- 2391                                                     END
- 2392                                                   END
- 2393                                                 END
- 2394                                               END
- 2395                                             END; .)
- 2396        (. astDes := AST.MakeNode(AST.NkDesignator);
- 2397           AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
- 2398        { "[" Expr<it, iq>
- 2399                                          (. AST.SetChild(astDes, AST.NChild(astDes),
- 2400               AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
- 2401                                             ELSIF SymTab.ClassOf(t) #
- 2402                                                   SymTab.ClArray THEN
- 2403                                               SemError(217);
- 2404                                               t := SymTab.InvalidType
- 2405                                             ELSIF NOT SymTab.IsIntFamily(it)
- 2406   AND (SymTab.ClassOf(it) #
- 2407                                                   SymTab.ClChar)
- 2408   AND (SymTab.ClassOf(it) #
- 2409                                                   SymTab.ClEnum) THEN
- 2410                                               SemError(218);
- 2411                                               t := SymTab.InvalidType
- 2412                                             ELSE
- 2413                                               QbeGen.WidenIndex(iq, ql);
- 2414                                               isOpen :=
- 2415                                                 SymTab.IsOpenArray(t);
- 2416                                               IF isOpen THEN
- 2417                                                 QbeGen.CopyOp("0", qlo);
- 2418                                                 IF SymTab.IsCharArray(t)
- 2419    OR SymTab.IsUCharArray(t) THEN
- 2420                                                   QbeGen.OpenHiChar(q, qhi)
- 2421                                                 ELSE QbeGen.OpenHi(q, qhi)
- 2422                                                 END
- 2423                                               ELSE
- 2424                                                 lo := SymTab.ArrayLo(t);
- 2425                                                 hi := SymTab.ArrayHi(t);
- 2426                                                 IF SymTab.IsCharArray(t)
- 2427    OR SymTab.IsUCharArray(t) THEN
- 2428                                                   hi := hi + 1
- 2429                                                 END;
- 2430                                                 QbeGen.IntStr(lo, qlo);
- 2431                                                 QbeGen.IntStr(hi, qhi)
- 2432                                               END;
- 2433                                               QbeGen.CheckRange(ql, qlo,
- 2434                                                 qhi);
- 2435                                               eT := SymTab.ArrayElem(t);
- 2436                                               QbeGen.ElemAddr(q, ql, qlo,
- 2437                                                 t, qe);
- 2438                                               IF SymTab.ClassOf(eT) =
- 2439                                                  SymTab.ClArray THEN
- 2440                                                 QbeGen.ElemLoad(qe, eT, q)
- 2441                                               ELSE QbeGen.CopyOp(qe, q)
- 2442                                               END;
- 2443                                               t := eT; sfx := TRUE
- 2444                                             END; .)
- 2445          { "," Expr<it, iq>
- 2446                                          (. AST.SetChild(astDes, AST.NChild(astDes),
- 2447               AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
- 2448                                             ELSIF SymTab.ClassOf(t) #
- 2449                                                   SymTab.ClArray THEN
- 2450                                               SemError(217);
- 2451                                               t := SymTab.InvalidType
- 2452                                             ELSIF NOT SymTab.IsIntFamily(it)
- 2453   AND (SymTab.ClassOf(it) #
- 2454                                                   SymTab.ClChar)
- 2455   AND (SymTab.ClassOf(it) #
- 2456                                                   SymTab.ClEnum) THEN
- 2457                                               SemError(218);
- 2458                                               t := SymTab.InvalidType
- 2459                                             ELSE
- 2460                                               QbeGen.WidenIndex(iq, ql);
- 2461                                               isOpen :=
- 2462                                                 SymTab.IsOpenArray(t);
- 2463                                               IF isOpen THEN
- 2464                                                 QbeGen.CopyOp("0", qlo);
- 2465                                                 IF SymTab.IsCharArray(t)
- 2466    OR SymTab.IsUCharArray(t) THEN
- 2467                                                   QbeGen.OpenHiChar(q, qhi)
- 2468                                                 ELSE QbeGen.OpenHi(q, qhi)
- 2469                                                 END
- 2470                                               ELSE
- 2471                                                 lo := SymTab.ArrayLo(t);
- 2472                                                 hi := SymTab.ArrayHi(t);
- 2473                                                 IF SymTab.IsCharArray(t)
- 2474    OR SymTab.IsUCharArray(t) THEN
- 2475                                                   hi := hi + 1
- 2476                                                 END;
- 2477                                                 QbeGen.IntStr(lo, qlo);
- 2478                                                 QbeGen.IntStr(hi, qhi)
- 2479                                               END;
- 2480                                               QbeGen.CheckRange(ql, qlo,
- 2481                                                 qhi);
- 2482                                               eT := SymTab.ArrayElem(t);
- 2483                                               QbeGen.ElemAddr(q, ql, qlo,
- 2484                                                 t, qe);
- 2485                                               IF SymTab.ClassOf(eT) =
- 2486                                                  SymTab.ClArray THEN
- 2487                                                 QbeGen.ElemLoad(qe, eT, q)
- 2488                                               ELSE QbeGen.CopyOp(qe, q)
- 2489                                               END;
- 2490                                               t := eT; sfx := TRUE
- 2491                                             END; .) }
- 2492          "]"
- 2493        | "." GetIdent<fn>
- 2494                                          (. astSel := AST.MakeNode(AST.NkSelector);
- 2495               AST.SetOp(astSel, AST.SelField);
- 2496               AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
- 2497               AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
- 2498                                               (* qualified L.x: materialize
- 2499                                                  the export, then load it *)
- 2500                                               IF NOT SymTab.MaterializeAlias(n,
- 2501                                                    fn, mal) THEN
- 2502                                                 SemError(201);
- 2503                                                 t := SymTab.InvalidType;
- 2504                                                 QbeGen.CopyOp("0", q)
- 2505                                               ELSE
- 2506                                                 QbeGen.CopyOp(mal, qn);
- 2507                                                 t := SymTab.SymType(mal);
- 2508                                                 k := SymTab.SymKind(mal);
- 2509                                                 sfx := FALSE;
- 2510                                                 IF k = SymTab.KindProc THEN
- 2511                                                   (* call: ArgList supplies
- 2512                                                      the value *)
- 2513                                                   QbeGen.CopyOp("0", q)
- 2514                                                 ELSIF NOT QbeGen.LoadDesignator(
- 2515                                                      mal, t, k, q) THEN
- 2516                                                   SemError(230);
+ 2364                                                        = SymTab.ClRecord)
+ 2365                                                    OR (cls
+ 2366                                                        = SymTab.ClUStr)
+ 2367                                                    OR (cls
+ 2368                                                        = SymTab.ClClass) THEN
+ 2369                                                   QbeGen.AddrOf(n, q)
+ 2370                                                 ELSE SemError(230);
+ 2371                                                   QbeGen.CopyOp("0", q)
+ 2372                                                 END
+ 2373                                               ELSE QbeGen.CopyOp("0", q);
+ 2374                                                 IF k = SymTab.KindImport THEN
+ 2375                                                   SemError(230)
+ 2376                                                 ELSIF k =
+ 2377                                                    SymTab.KindProc THEN
+ 2378                                                   (* bare procedure name:
+ 2379                                                      a following ArgList
+ 2380                                                      makes it a call;
+ 2381                                                      otherwise Fact
+ 2382                                                      reports 230 *)
+ 2383                                                 ELSE
+ 2384                                                   IF k = SymTab.KindField THEN
+ 2385                                                     IF QbeGen.TopWith(qb) THEN
+ 2386                                                       fo :=
+ 2387                                                         SymTab.FieldOffset(
+ 2388                                                         SymTab.FieldOwner(n),
+ 2389                                                         n);
+ 2390                                                       QbeGen.FieldAddr(qb,
+ 2391                                                         fo, q);
+ 2392                                                       sfx := TRUE
+ 2393                                                     ELSE SemError(230);
+ 2394                                                       QbeGen.CopyOp("0", q)
+ 2395                                                     END
+ 2396                                                   END
+ 2397                                                 END
+ 2398                                               END
+ 2399                                             END; .)
+ 2400        (. astDes := AST.MakeNode(AST.NkDesignator);
+ 2401           AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
+ 2402        { "[" Expr<it, iq>
+ 2403                                          (. AST.SetChild(astDes, AST.NChild(astDes),
+ 2404               AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
+ 2405                                             ELSIF SymTab.ClassOf(t) #
+ 2406                                                   SymTab.ClArray THEN
+ 2407                                               SemError(217);
+ 2408                                               t := SymTab.InvalidType
+ 2409                                             ELSIF NOT SymTab.IsIntFamily(it)
+ 2410   AND (SymTab.ClassOf(it) #
+ 2411                                                   SymTab.ClChar)
+ 2412   AND (SymTab.ClassOf(it) #
+ 2413                                                   SymTab.ClEnum) THEN
+ 2414                                               SemError(218);
+ 2415                                               t := SymTab.InvalidType
+ 2416                                             ELSE
+ 2417                                               QbeGen.WidenIndex(iq, ql);
+ 2418                                               isOpen :=
+ 2419                                                 SymTab.IsOpenArray(t);
+ 2420                                               IF isOpen THEN
+ 2421                                                 QbeGen.CopyOp("0", qlo);
+ 2422                                                 IF SymTab.IsCharArray(t)
+ 2423    OR SymTab.IsUCharArray(t) THEN
+ 2424                                                   QbeGen.OpenHiChar(q, qhi)
+ 2425                                                 ELSE QbeGen.OpenHi(q, qhi)
+ 2426                                                 END
+ 2427                                               ELSE
+ 2428                                                 lo := SymTab.ArrayLo(t);
+ 2429                                                 hi := SymTab.ArrayHi(t);
+ 2430                                                 IF SymTab.IsCharArray(t)
+ 2431    OR SymTab.IsUCharArray(t) THEN
+ 2432                                                   hi := hi + 1
+ 2433                                                 END;
+ 2434                                                 QbeGen.IntStr(lo, qlo);
+ 2435                                                 QbeGen.IntStr(hi, qhi)
+ 2436                                               END;
+ 2437                                               QbeGen.CheckRange(ql, qlo,
+ 2438                                                 qhi);
+ 2439                                               eT := SymTab.ArrayElem(t);
+ 2440                                               QbeGen.ElemAddr(q, ql, qlo,
+ 2441                                                 t, qe);
+ 2442                                               IF SymTab.ClassOf(eT) =
+ 2443                                                  SymTab.ClArray THEN
+ 2444                                                 QbeGen.ElemLoad(qe, eT, q)
+ 2445                                               ELSE QbeGen.CopyOp(qe, q)
+ 2446                                               END;
+ 2447                                               t := eT; sfx := TRUE
+ 2448                                             END; .)
+ 2449          { "," Expr<it, iq>
+ 2450                                          (. AST.SetChild(astDes, AST.NChild(astDes),
+ 2451               AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
+ 2452                                             ELSIF SymTab.ClassOf(t) #
+ 2453                                                   SymTab.ClArray THEN
+ 2454                                               SemError(217);
+ 2455                                               t := SymTab.InvalidType
+ 2456                                             ELSIF NOT SymTab.IsIntFamily(it)
+ 2457   AND (SymTab.ClassOf(it) #
+ 2458                                                   SymTab.ClChar)
+ 2459   AND (SymTab.ClassOf(it) #
+ 2460                                                   SymTab.ClEnum) THEN
+ 2461                                               SemError(218);
+ 2462                                               t := SymTab.InvalidType
+ 2463                                             ELSE
+ 2464                                               QbeGen.WidenIndex(iq, ql);
+ 2465                                               isOpen :=
+ 2466                                                 SymTab.IsOpenArray(t);
+ 2467                                               IF isOpen THEN
+ 2468                                                 QbeGen.CopyOp("0", qlo);
+ 2469                                                 IF SymTab.IsCharArray(t)
+ 2470    OR SymTab.IsUCharArray(t) THEN
+ 2471                                                   QbeGen.OpenHiChar(q, qhi)
+ 2472                                                 ELSE QbeGen.OpenHi(q, qhi)
+ 2473                                                 END
+ 2474                                               ELSE
+ 2475                                                 lo := SymTab.ArrayLo(t);
+ 2476                                                 hi := SymTab.ArrayHi(t);
+ 2477                                                 IF SymTab.IsCharArray(t)
+ 2478    OR SymTab.IsUCharArray(t) THEN
+ 2479                                                   hi := hi + 1
+ 2480                                                 END;
+ 2481                                                 QbeGen.IntStr(lo, qlo);
+ 2482                                                 QbeGen.IntStr(hi, qhi)
+ 2483                                               END;
+ 2484                                               QbeGen.CheckRange(ql, qlo,
+ 2485                                                 qhi);
+ 2486                                               eT := SymTab.ArrayElem(t);
+ 2487                                               QbeGen.ElemAddr(q, ql, qlo,
+ 2488                                                 t, qe);
+ 2489                                               IF SymTab.ClassOf(eT) =
+ 2490                                                  SymTab.ClArray THEN
+ 2491                                                 QbeGen.ElemLoad(qe, eT, q)
+ 2492                                               ELSE QbeGen.CopyOp(qe, q)
+ 2493                                               END;
+ 2494                                               t := eT; sfx := TRUE
+ 2495                                             END; .) }
+ 2496          "]"
+ 2497        | "." GetIdent<fn>
+ 2498                                          (. astSel := AST.MakeNode(AST.NkSelector);
+ 2499               AST.SetOp(astSel, AST.SelField);
+ 2500               AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
+ 2501               AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
+ 2502                                               (* qualified L.x: materialize
+ 2503                                                  the export, then load it *)
+ 2504                                               IF NOT SymTab.MaterializeAlias(n,
+ 2505                                                    fn, mal) THEN
+ 2506                                                 SemError(201);
+ 2507                                                 t := SymTab.InvalidType;
+ 2508                                                 QbeGen.CopyOp("0", q)
+ 2509                                               ELSE
+ 2510                                                 QbeGen.CopyOp(mal, qn);
+ 2511                                                 t := SymTab.SymType(mal);
+ 2512                                                 k := SymTab.SymKind(mal);
+ 2513                                                 sfx := FALSE;
+ 2514                                                 IF k = SymTab.KindProc THEN
+ 2515                                                   (* call: ArgList supplies
+ 2516                                                      the value *)
  2517                                                   QbeGen.CopyOp("0", q)
- 2518                                                 END
- 2519                                               END
- 2520                                             ELSIF t = SymTab.InvalidType THEN
- 2521                                             ELSIF (SymTab.ClassOf(t) #
- 2522                                                    SymTab.ClRecord)
- 2523   AND (SymTab.ClassOf(t) #
- 2524                                                   SymTab.ClClass) THEN
- 2525                                               SemError(215);
- 2526                                               t := SymTab.InvalidType
- 2527                                             ELSIF (SymTab.ClassOf(t) =
- 2528                                                    SymTab.ClClass)
- 2529    AND SymTab.MethodExists(t, fn) THEN
- 2530                                               (* obj.Method: bind the
- 2531                                                  method and pass obj as
- 2532                                                  the hidden receiver; q
- 2533                                                  already holds the
- 2534                                                  object's address *)
- 2535                                               QbeGen.ArmRecv(q);
- 2536                                               QbeGen.CopyOp(fn, n);
- 2537                                               QbeGen.CopyOp(fn, qn);
- 2538                                               methCls := t;
- 2539                                               k := SymTab.KindProc;
- 2540                                               t := SymTab.InvalidType
- 2541                                             ELSIF NOT SymTab.FieldExists(t,
- 2542                                                      fn) THEN
- 2543                                               SemError(216);
+ 2518                                                 ELSIF NOT QbeGen.LoadDesignator(
+ 2519                                                      mal, t, k, q) THEN
+ 2520                                                   SemError(230);
+ 2521                                                   QbeGen.CopyOp("0", q)
+ 2522                                                 END
+ 2523                                               END
+ 2524                                             ELSIF t = SymTab.InvalidType THEN
+ 2525                                             ELSIF (SymTab.ClassOf(t) #
+ 2526                                                    SymTab.ClRecord)
+ 2527   AND (SymTab.ClassOf(t) #
+ 2528                                                   SymTab.ClClass) THEN
+ 2529                                               SemError(215);
+ 2530                                               t := SymTab.InvalidType
+ 2531                                             ELSIF (SymTab.ClassOf(t) =
+ 2532                                                    SymTab.ClClass)
+ 2533    AND SymTab.MethodExists(t, fn) THEN
+ 2534                                               (* obj.Method: bind the
+ 2535                                                  method and pass obj as
+ 2536                                                  the hidden receiver; q
+ 2537                                                  already holds the
+ 2538                                                  object's address *)
+ 2539                                               QbeGen.ArmRecv(q);
+ 2540                                               QbeGen.CopyOp(fn, n);
+ 2541                                               QbeGen.CopyOp(fn, qn);
+ 2542                                               methCls := t;
+ 2543                                               k := SymTab.KindProc;
  2544                                               t := SymTab.InvalidType
- 2545                                             ELSE
- 2546                                               fo := SymTab.FieldOffset(t,
- 2547                                                 fn);
- 2548                                               t := SymTab.FieldType(t, fn);
- 2549                                               QbeGen.FieldAddr(q, fo, qe);
- 2550                                               (* array fields are inline:
- 2551                                                  the field address is the
- 2552                                                  descriptor, like records *)
- 2553                                               QbeGen.CopyOp(qe, q);
- 2554                                               sfx := TRUE
- 2555                                             END; .)
- 2556        | "^"
- 2557                                          (. astSel := AST.MakeNode(AST.NkSelector);
- 2558               AST.SetOp(astSel, AST.SelDeref);
- 2559               AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
- 2560                                             ELSIF SymTab.ClassOf(t) #
- 2561                                                   SymTab.ClPtr THEN
- 2562                                               SemError(219);
- 2563                                               t := SymTab.InvalidType
- 2564                                             ELSE
- 2565                                               bt := SymTab.PtrBase(t);
- 2566                                               IF bt = SymTab.InvalidType THEN
- 2567                                               ELSE
- 2568                                                 IF sfx THEN
- 2569                                                   QbeGen.ElemLoad(q, t,
- 2570                                                     qb);
- 2571                                                   QbeGen.CopyOp(qb, q)
- 2572                                                 END;
- 2573                                                 t := bt;
- 2574                                                 (* q holds the pointee
- 2575                                                    address: Fact loads
- 2576                                                    scalars/pointers and uses
- 2577                                                    the address for
- 2578                                                    aggregates; the VAR-actual
- 2579                                                    note is q itself. *)
- 2580                                                 sfx := TRUE
- 2581                                               END
- 2582                                             END; .) } (. astCur := astDes; .) .
- 2583    (* Result suffix (ISO component after a function call): `F()^`,
- 2584       `F()[i]`, `F().field`.  The call result is in t/q with sfx FALSE
- 2585       (a value, or a descriptor address for aggregates); each component
- 2586       descends one level exactly like the Design components. *)
- 2587    ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
- 2588               VAR sfx: BOOLEAN; VAR node: AST.Node>          (. VAR it, eT, bt: SymTab.TypeIndex;
- 2589                                               iq, ql, qlo, qhi, qe, qb:
- 2590                                                 QbeGen.QVal;
- 2591                                               lo, hi, fo: INTEGER;
- 2592                                               isOpen: BOOLEAN;
- 2593                                               fname: SymTab.Name;
- 2594                                               astWrap, astSel: AST.Node; .)
- 2595      = "[" Expr<it, iq>
- 2596                                          (. IF AST.Kind(node) # AST.NkDesignator THEN
- 2597                                               astWrap := AST.MakeNode(
- 2598                                                 AST.NkDesignator);
- 2599                                               AST.SetChild(astWrap, 0, node);
- 2600                                               node := astWrap
- 2601                                             END;
- 2602                                             AST.SetChild(node, AST.NChild(node),
- 2603                                               AST.MakeUn(AST.NkSelector,
- 2604                                                 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
- 2605                                             ELSIF SymTab.ClassOf(t) #
- 2606                                                   SymTab.ClArray THEN
- 2607                                               SemError(217);
- 2608                                               t := SymTab.InvalidType
- 2609                                             ELSIF NOT SymTab.IsIntFamily(it)
- 2610    AND (SymTab.ClassOf(it) # SymTab.ClChar)
- 2611    AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
- 2612                                               SemError(218);
- 2613                                               t := SymTab.InvalidType
- 2614                                             ELSE
- 2615                                               QbeGen.WidenIndex(iq, ql);
- 2616                                               isOpen :=
- 2617                                                 SymTab.IsOpenArray(t);
- 2618                                               IF isOpen THEN
- 2619                                                 QbeGen.CopyOp("0", qlo);
- 2620                                                 IF SymTab.IsCharArray(t)
- 2621    OR SymTab.IsUCharArray(t) THEN
- 2622                                                   QbeGen.OpenHiChar(q, qhi)
- 2623                                                 ELSE QbeGen.OpenHi(q, qhi)
- 2624                                                 END
- 2625                                               ELSE
- 2626                                                 lo := SymTab.ArrayLo(t);
- 2627                                                 hi := SymTab.ArrayHi(t);
- 2628                                                 IF SymTab.IsCharArray(t)
- 2629    OR SymTab.IsUCharArray(t) THEN
- 2630                                                   hi := hi + 1
- 2631                                                 END;
- 2632                                                 QbeGen.IntStr(lo, qlo);
- 2633                                                 QbeGen.IntStr(hi, qhi)
- 2634                                               END;
- 2635                                               QbeGen.CheckRange(ql, qlo,
- 2636                                                 qhi);
- 2637                                               eT := SymTab.ArrayElem(t);
- 2638                                               QbeGen.ElemAddr(q, ql, qlo,
- 2639                                                 t, qe);
- 2640                                               IF SymTab.ClassOf(eT) =
- 2641                                                  SymTab.ClArray THEN
- 2642                                                 QbeGen.ElemLoad(qe, eT, q)
- 2643                                               ELSE QbeGen.CopyOp(qe, q)
- 2644                                               END;
- 2645                                               t := eT; sfx := TRUE
- 2646                                             END; .)
- 2647        "]"
- 2648      | "." GetIdent<fname>
- 2649                                          (. IF AST.Kind(node) # AST.NkDesignator THEN
- 2650                                               astWrap := AST.MakeNode(
- 2651                                                 AST.NkDesignator);
- 2652                                               AST.SetChild(astWrap, 0, node);
- 2653                                               node := astWrap
- 2654                                             END;
- 2655                                             AST.SetChild(node, AST.NChild(node),
- 2656                                               AST.MakeUn(AST.NkSelector,
- 2657                                                 AST.SelField,
- 2658                                                 AST.MakeLeaf(AST.NkIdent,
- 2659                                                   fname))); IF t = SymTab.InvalidType THEN
- 2660                                             ELSIF (SymTab.ClassOf(t) #
- 2661                                                    SymTab.ClRecord)
- 2662    AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
- 2663                                               SemError(215);
- 2664                                               t := SymTab.InvalidType
- 2665                                             ELSIF NOT SymTab.FieldExists(t,
- 2666                                                      fname) THEN
- 2667                                               SemError(216);
+ 2545                                             ELSIF NOT SymTab.FieldExists(t,
+ 2546                                                      fn) THEN
+ 2547                                               SemError(216);
+ 2548                                               t := SymTab.InvalidType
+ 2549                                             ELSE
+ 2550                                               fo := SymTab.FieldOffset(t,
+ 2551                                                 fn);
+ 2552                                               t := SymTab.FieldType(t, fn);
+ 2553                                               QbeGen.FieldAddr(q, fo, qe);
+ 2554                                               (* array fields are inline:
+ 2555                                                  the field address is the
+ 2556                                                  descriptor, like records *)
+ 2557                                               QbeGen.CopyOp(qe, q);
+ 2558                                               sfx := TRUE
+ 2559                                             END; .)
+ 2560        | "^"
+ 2561                                          (. astSel := AST.MakeNode(AST.NkSelector);
+ 2562               AST.SetOp(astSel, AST.SelDeref);
+ 2563               AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
+ 2564                                             ELSIF SymTab.ClassOf(t) #
+ 2565                                                   SymTab.ClPtr THEN
+ 2566                                               SemError(219);
+ 2567                                               t := SymTab.InvalidType
+ 2568                                             ELSE
+ 2569                                               bt := SymTab.PtrBase(t);
+ 2570                                               IF bt = SymTab.InvalidType THEN
+ 2571                                               ELSE
+ 2572                                                 IF sfx THEN
+ 2573                                                   QbeGen.ElemLoad(q, t,
+ 2574                                                     qb);
+ 2575                                                   QbeGen.CopyOp(qb, q)
+ 2576                                                 END;
+ 2577                                                 t := bt;
+ 2578                                                 (* q holds the pointee
+ 2579                                                    address: Fact loads
+ 2580                                                    scalars/pointers and uses
+ 2581                                                    the address for
+ 2582                                                    aggregates; the VAR-actual
+ 2583                                                    note is q itself. *)
+ 2584                                                 sfx := TRUE
+ 2585                                               END
+ 2586                                             END; .) } (. astCur := astDes; .) .
+ 2587    (* Result suffix (ISO component after a function call): `F()^`,
+ 2588       `F()[i]`, `F().field`.  The call result is in t/q with sfx FALSE
+ 2589       (a value, or a descriptor address for aggregates); each component
+ 2590       descends one level exactly like the Design components. *)
+ 2591    ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
+ 2592               VAR sfx: BOOLEAN; VAR node: AST.Node>          (. VAR it, eT, bt: SymTab.TypeIndex;
+ 2593                                               iq, ql, qlo, qhi, qe, qb:
+ 2594                                                 QbeGen.QVal;
+ 2595                                               lo, hi, fo: INTEGER;
+ 2596                                               isOpen: BOOLEAN;
+ 2597                                               fname: SymTab.Name;
+ 2598                                               astWrap, astSel: AST.Node; .)
+ 2599      = "[" Expr<it, iq>
+ 2600                                          (. IF AST.Kind(node) # AST.NkDesignator THEN
+ 2601                                               astWrap := AST.MakeNode(
+ 2602                                                 AST.NkDesignator);
+ 2603                                               AST.SetChild(astWrap, 0, node);
+ 2604                                               node := astWrap
+ 2605                                             END;
+ 2606                                             AST.SetChild(node, AST.NChild(node),
+ 2607                                               AST.MakeUn(AST.NkSelector,
+ 2608                                                 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
+ 2609                                             ELSIF SymTab.ClassOf(t) #
+ 2610                                                   SymTab.ClArray THEN
+ 2611                                               SemError(217);
+ 2612                                               t := SymTab.InvalidType
+ 2613                                             ELSIF NOT SymTab.IsIntFamily(it)
+ 2614    AND (SymTab.ClassOf(it) # SymTab.ClChar)
+ 2615    AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
+ 2616                                               SemError(218);
+ 2617                                               t := SymTab.InvalidType
+ 2618                                             ELSE
+ 2619                                               QbeGen.WidenIndex(iq, ql);
+ 2620                                               isOpen :=
+ 2621                                                 SymTab.IsOpenArray(t);
+ 2622                                               IF isOpen THEN
+ 2623                                                 QbeGen.CopyOp("0", qlo);
+ 2624                                                 IF SymTab.IsCharArray(t)
+ 2625    OR SymTab.IsUCharArray(t) THEN
+ 2626                                                   QbeGen.OpenHiChar(q, qhi)
+ 2627                                                 ELSE QbeGen.OpenHi(q, qhi)
+ 2628                                                 END
+ 2629                                               ELSE
+ 2630                                                 lo := SymTab.ArrayLo(t);
+ 2631                                                 hi := SymTab.ArrayHi(t);
+ 2632                                                 IF SymTab.IsCharArray(t)
+ 2633    OR SymTab.IsUCharArray(t) THEN
+ 2634                                                   hi := hi + 1
+ 2635                                                 END;
+ 2636                                                 QbeGen.IntStr(lo, qlo);
+ 2637                                                 QbeGen.IntStr(hi, qhi)
+ 2638                                               END;
+ 2639                                               QbeGen.CheckRange(ql, qlo,
+ 2640                                                 qhi);
+ 2641                                               eT := SymTab.ArrayElem(t);
+ 2642                                               QbeGen.ElemAddr(q, ql, qlo,
+ 2643                                                 t, qe);
+ 2644                                               IF SymTab.ClassOf(eT) =
+ 2645                                                  SymTab.ClArray THEN
+ 2646                                                 QbeGen.ElemLoad(qe, eT, q)
+ 2647                                               ELSE QbeGen.CopyOp(qe, q)
+ 2648                                               END;
+ 2649                                               t := eT; sfx := TRUE
+ 2650                                             END; .)
+ 2651        "]"
+ 2652      | "." GetIdent<fname>
+ 2653                                          (. IF AST.Kind(node) # AST.NkDesignator THEN
+ 2654                                               astWrap := AST.MakeNode(
+ 2655                                                 AST.NkDesignator);
+ 2656                                               AST.SetChild(astWrap, 0, node);
+ 2657                                               node := astWrap
+ 2658                                             END;
+ 2659                                             AST.SetChild(node, AST.NChild(node),
+ 2660                                               AST.MakeUn(AST.NkSelector,
+ 2661                                                 AST.SelField,
+ 2662                                                 AST.MakeLeaf(AST.NkIdent,
+ 2663                                                   fname))); IF t = SymTab.InvalidType THEN
+ 2664                                             ELSIF (SymTab.ClassOf(t) #
+ 2665                                                    SymTab.ClRecord)
+ 2666    AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
+ 2667                                               SemError(215);
  2668                                               t := SymTab.InvalidType
- 2669                                             ELSE
- 2670                                               fo := SymTab.FieldOffset(t,
- 2671                                                 fname);
- 2672                                               t := SymTab.FieldType(t, fname);
- 2673                                               QbeGen.FieldAddr(q, fo, qe);
- 2674                                               QbeGen.CopyOp(qe, q);
- 2675                                               sfx := TRUE
- 2676                                             END; .)
- 2677      | "^"                               (. IF AST.Kind(node) # AST.NkDesignator THEN
- 2678                                               astWrap := AST.MakeNode(
- 2679                                                 AST.NkDesignator);
- 2680                                               AST.SetChild(astWrap, 0, node);
- 2681                                               node := astWrap
- 2682                                             END;
- 2683                                             astSel := AST.MakeNode(AST.NkSelector);
- 2684                                             AST.SetOp(astSel, AST.SelDeref);
- 2685                                             AST.SetChild(node,
- 2686                                               AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
- 2687                                             ELSIF SymTab.ClassOf(t) #
- 2688                                                   SymTab.ClPtr THEN
- 2689                                               SemError(219);
- 2690                                               t := SymTab.InvalidType
- 2691                                             ELSE
- 2692                                               bt := SymTab.PtrBase(t);
- 2693                                               IF bt # SymTab.InvalidType THEN
- 2694                                                 IF sfx THEN
- 2695                                                   QbeGen.ElemLoad(q, t, qb);
- 2696                                                   QbeGen.CopyOp(qb, q)
- 2697                                                 END;
- 2698                                                 t := bt; sfx := TRUE
- 2699                                               END
- 2700                                             END; .) .
- 2701    Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 2702                                          (. VAR t2: SymTab.TypeIndex;
- 2703                                               op: INTEGER;
- 2704                                               q2, qt, wl: QbeGen.QVal;
- 2705                                                astA, astB: AST.Node;
- 2706                                                astOp: INTEGER;
- 2707                                                astMade: BOOLEAN;
- 2708                                               isR: BOOLEAN; .)
- 2709      = SimExpr<t, q>                     (. astA := astCur; astMade := FALSE; .)
- 2710        [ Rel<op> SimExpr<t2, q2>
- 2711          (. astB := astCur; astMade := TRUE;
- 2712              astOp := AST.OpEq;
- 2713              IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
- 2714              ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
- 2715              ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
- 2716              ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
- 2717              ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
- 2718              ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
- 2719              ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
- 2720              END;
- 2721              IF op = SymTab.OpIn THEN
- 2722               IF SymTab.InCheck(t, t2) THEN
- 2723                 IF (t = SymTab.InvalidType)
- 2724                    OR (t2 = SymTab.InvalidType) THEN
- 2725                   t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
- 2726                 ELSE
- 2727                   QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
- 2728                     SymTab.SetCount(t2), qt);
- 2729                   t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2730                 END
- 2731               ELSE SemError(222); t := SymTab.InvalidType;
- 2732                 QbeGen.CopyOp("0", q)
- 2733               END
- 2734             ELSIF SymTab.RelCheck(t, t2, op) THEN
- 2735               IF (t = SymTab.InvalidType)
- 2736                  OR (t2 = SymTab.InvalidType) THEN
- 2737                 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
- 2738               ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
- 2739                  OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
- 2740                 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
- 2741                   QbeGen.Cmp(op, q, q2, qt, FALSE);
- 2742                   t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2743                 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
- 2744   AND (op # SymTab.OpNeq2) THEN
- 2745                   SemError(213); t := SymTab.InvalidType;
- 2746                   QbeGen.CopyOp("0", q)
- 2747                 ELSE
- 2748                   QbeGen.CmpL(op, q, q2, qt);
- 2749                   t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2750                 END
- 2751               ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
- 2752                  OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 2753                 QbeGen.CmpSet(op, q, q2,
- 2754                   SymTab.SetWords(t), SymTab.SetWords(t2), qt);
- 2755                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2756               ELSIF SymTab.StrCompat(t, t2) THEN
- 2757                 QbeGen.StrEq(op, q, q2, qt);
- 2758                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2759               ELSIF SymTab.IsLongFamily(t)
- 2760                  OR SymTab.IsLongFamily(t2) THEN
- 2761                 IF SymTab.IsIntFamily(t) THEN
- 2762                   QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
- 2763                 END;
- 2764                 IF SymTab.IsIntFamily(t2) THEN
- 2765                   QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
- 2766                 END;
- 2767                 QbeGen.CmpLong(op, q, q2, qt);
- 2768                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2769               ELSE
- 2770                 isR := SymTab.ClassOf(t) = SymTab.ClReal;
- 2771                 t := SymTab.BoolType();
- 2772                 QbeGen.Cmp(op, q, q2, qt, isR);
- 2773                 QbeGen.CopyOp(qt, q)
- 2774               END
- 2775             ELSE SemError(213); t := SymTab.InvalidType;
- 2776                QbeGen.CopyOp("0", q)
- 2777              END;
- 2778              astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
- 2779         (. IF NOT astMade THEN astCur := astA END; .) .
- 2780    Rel<VAR op: INTEGER>
- 2781      = "="                               (. op := SymTab.OpEq; .)
- 2782      | "#"                               (. op := SymTab.OpNeq1; .)
- 2783      | "<"                               (. op := SymTab.OpLt; .)
- 2784      | "<="                              (. op := SymTab.OpLe; .)
- 2785      | ">"                               (. op := SymTab.OpGt; .)
- 2786      | ">="                              (. op := SymTab.OpGe; .)
- 2787      | "IN"                              (. op := SymTab.OpIn; .) .
- 2788    SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 2789                                          (. VAR t2, res2, lt, rt:
- 2790                                                 SymTab.TypeIndex;
- 2791                                               op: INTEGER;
- 2792                                               q2, qt, wq, qf, q2a, q2b:
- 2793                                                 QbeGen.QVal;
- 2794                                               neg, isR, isL, folded:
- 2795                                                 BOOLEAN;
- 2796                                               fok: BOOLEAN;
- 2797                                               lw, rw, mw: CARDINAL;
- 2798                                               lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
- 2799                                                astA, astB: AST.Node;
- 2800                                                astSign, astOp: INTEGER; .)
- 2801      =                                   (. neg := FALSE; astSign := 0; .)
- 2802        [ "+"                         (. neg := TRUE; astSign := 1; .)
- 2803        | "-"                         (. neg := TRUE; astSign := -1; .) ]
- 2804        Term<t, q> (. astA := astCur; IF neg THEN
- 2805                                             IF QbeGen.IsImm(q) THEN
- 2806                                               QbeGen.NegFold(q, q)
- 2807                                             ELSE QbeGen.NewTemp(qt);
- 2808                                               QbeGen.NegQ(q, qt,
- 2809                                                 SymTab.ClassOf(t)
- 2810                                                 = SymTab.ClReal);
- 2811                                               QbeGen.CopyOp(qt, q)
- 2812                                             END
- 2813                                           END;
- 2814                                           IF astSign < 0 THEN
- 2815                                             astCur := AST.MakeUn(
- 2816                                               AST.NkUnary, AST.OpSub, astA);
- 2817                                             astA := astCur
- 2818                                           END; .)
- 2819        { AddOp<op>                       (. IF op = SymTab.OpOr THEN
- 2820                                               QbeGen.DelayBegin END; .)
- 2821          Term<t2, q2> (. astB := astCur; IF op = SymTab.OpOr THEN
- 2822                                               QbeGen.DelayEnd END; .)
- 2823          (. astOp := AST.OpAdd;
- 2824             IF op = SymTab.OpSub THEN astOp := AST.OpSub
- 2825             ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
- 2826             astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
- 2827             astCur := astA;
- 2828             IF op = SymTab.OpOr THEN
- 2829               (* short-circuit: if q is true the RHS is skipped *)
- 2830               IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
- 2831                 t := SymTab.BoolType()
- 2832               ELSE SemError(212); t := SymTab.InvalidType END;
- 2833               IF t # SymTab.InvalidType THEN
- 2834                 QbeGen.Slot4(qs);
- 2835                 QbeGen.NewLabel(lTrue);
- 2836                 QbeGen.NewLabel(lNext);
- 2837                 QbeGen.NewLabel(lDone);
- 2838                 QbeGen.Jnz(q, lTrue, lNext);
- 2839                 QbeGen.EmitLabel(lTrue);
- 2840                 QbeGen.StoreW(qs, "1");
- 2841                 QbeGen.Jmp(lDone);
- 2842                 QbeGen.EmitLabel(lNext);
- 2843                 QbeGen.DelayFlush;
- 2844                 QbeGen.StoreW(qs, q2);
+ 2669                                             ELSIF NOT SymTab.FieldExists(t,
+ 2670                                                      fname) THEN
+ 2671                                               SemError(216);
+ 2672                                               t := SymTab.InvalidType
+ 2673                                             ELSE
+ 2674                                               fo := SymTab.FieldOffset(t,
+ 2675                                                 fname);
+ 2676                                               t := SymTab.FieldType(t, fname);
+ 2677                                               QbeGen.FieldAddr(q, fo, qe);
+ 2678                                               QbeGen.CopyOp(qe, q);
+ 2679                                               sfx := TRUE
+ 2680                                             END; .)
+ 2681      | "^"                               (. IF AST.Kind(node) # AST.NkDesignator THEN
+ 2682                                               astWrap := AST.MakeNode(
+ 2683                                                 AST.NkDesignator);
+ 2684                                               AST.SetChild(astWrap, 0, node);
+ 2685                                               node := astWrap
+ 2686                                             END;
+ 2687                                             astSel := AST.MakeNode(AST.NkSelector);
+ 2688                                             AST.SetOp(astSel, AST.SelDeref);
+ 2689                                             AST.SetChild(node,
+ 2690                                               AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
+ 2691                                             ELSIF SymTab.ClassOf(t) #
+ 2692                                                   SymTab.ClPtr THEN
+ 2693                                               SemError(219);
+ 2694                                               t := SymTab.InvalidType
+ 2695                                             ELSE
+ 2696                                               bt := SymTab.PtrBase(t);
+ 2697                                               IF bt # SymTab.InvalidType THEN
+ 2698                                                 IF sfx THEN
+ 2699                                                   QbeGen.ElemLoad(q, t, qb);
+ 2700                                                   QbeGen.CopyOp(qb, q)
+ 2701                                                 END;
+ 2702                                                 t := bt; sfx := TRUE
+ 2703                                               END
+ 2704                                             END; .) .
+ 2705    Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 2706                                          (. VAR t2: SymTab.TypeIndex;
+ 2707                                               op: INTEGER;
+ 2708                                               q2, qt, wl: QbeGen.QVal;
+ 2709                                                astA, astB: AST.Node;
+ 2710                                                astOp: INTEGER;
+ 2711                                                astMade: BOOLEAN;
+ 2712                                               isR: BOOLEAN; .)
+ 2713      = SimExpr<t, q>                     (. astA := astCur; astMade := FALSE; .)
+ 2714        [ Rel<op> SimExpr<t2, q2>
+ 2715          (. astB := astCur; astMade := TRUE;
+ 2716              astOp := AST.OpEq;
+ 2717              IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
+ 2718              ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
+ 2719              ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
+ 2720              ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
+ 2721              ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
+ 2722              ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
+ 2723              ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
+ 2724              END;
+ 2725              IF op = SymTab.OpIn THEN
+ 2726               IF SymTab.InCheck(t, t2) THEN
+ 2727                 IF (t = SymTab.InvalidType)
+ 2728                    OR (t2 = SymTab.InvalidType) THEN
+ 2729                   t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
+ 2730                 ELSE
+ 2731                   QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
+ 2732                     SymTab.SetCount(t2), qt);
+ 2733                   t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2734                 END
+ 2735               ELSE SemError(222); t := SymTab.InvalidType;
+ 2736                 QbeGen.CopyOp("0", q)
+ 2737               END
+ 2738             ELSIF SymTab.RelCheck(t, t2, op) THEN
+ 2739               IF (t = SymTab.InvalidType)
+ 2740                  OR (t2 = SymTab.InvalidType) THEN
+ 2741                 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
+ 2742               ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
+ 2743                  OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
+ 2744                 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
+ 2745                   QbeGen.Cmp(op, q, q2, qt, FALSE);
+ 2746                   t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2747                 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
+ 2748   AND (op # SymTab.OpNeq2) THEN
+ 2749                   SemError(213); t := SymTab.InvalidType;
+ 2750                   QbeGen.CopyOp("0", q)
+ 2751                 ELSE
+ 2752                   QbeGen.CmpL(op, q, q2, qt);
+ 2753                   t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2754                 END
+ 2755               ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
+ 2756                  OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 2757                 QbeGen.CmpSet(op, q, q2,
+ 2758                   SymTab.SetWords(t), SymTab.SetWords(t2), qt);
+ 2759                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2760               ELSIF SymTab.StrCompat(t, t2) THEN
+ 2761                 QbeGen.StrEq(op, q, q2, qt);
+ 2762                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2763               ELSIF SymTab.IsLongFamily(t)
+ 2764                  OR SymTab.IsLongFamily(t2) THEN
+ 2765                 IF SymTab.IsIntFamily(t) THEN
+ 2766                   QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
+ 2767                 END;
+ 2768                 IF SymTab.IsIntFamily(t2) THEN
+ 2769                   QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
+ 2770                 END;
+ 2771                 QbeGen.CmpLong(op, q, q2, qt);
+ 2772                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2773               ELSE
+ 2774                 isR := SymTab.ClassOf(t) = SymTab.ClReal;
+ 2775                 t := SymTab.BoolType();
+ 2776                 QbeGen.Cmp(op, q, q2, qt, isR);
+ 2777                 QbeGen.CopyOp(qt, q)
+ 2778               END
+ 2779             ELSE SemError(213); t := SymTab.InvalidType;
+ 2780                QbeGen.CopyOp("0", q)
+ 2781              END;
+ 2782              astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
+ 2783         (. IF NOT astMade THEN astCur := astA END; .) .
+ 2784    Rel<VAR op: INTEGER>
+ 2785      = "="                               (. op := SymTab.OpEq; .)
+ 2786      | "#"                               (. op := SymTab.OpNeq1; .)
+ 2787      | "<"                               (. op := SymTab.OpLt; .)
+ 2788      | "<="                              (. op := SymTab.OpLe; .)
+ 2789      | ">"                               (. op := SymTab.OpGt; .)
+ 2790      | ">="                              (. op := SymTab.OpGe; .)
+ 2791      | "IN"                              (. op := SymTab.OpIn; .) .
+ 2792    SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 2793                                          (. VAR t2, res2, lt, rt:
+ 2794                                                 SymTab.TypeIndex;
+ 2795                                               op: INTEGER;
+ 2796                                               q2, qt, wq, qf, q2a, q2b:
+ 2797                                                 QbeGen.QVal;
+ 2798                                               neg, isR, isL, folded:
+ 2799                                                 BOOLEAN;
+ 2800                                               fok: BOOLEAN;
+ 2801                                               lw, rw, mw: CARDINAL;
+ 2802                                               lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
+ 2803                                                astA, astB: AST.Node;
+ 2804                                                astSign, astOp: INTEGER; .)
+ 2805      =                                   (. neg := FALSE; astSign := 0; .)
+ 2806        [ "+"                         (. neg := TRUE; astSign := 1; .)
+ 2807        | "-"                         (. neg := TRUE; astSign := -1; .) ]
+ 2808        Term<t, q> (. astA := astCur; IF neg THEN
+ 2809                                             IF QbeGen.IsImm(q) THEN
+ 2810                                               QbeGen.NegFold(q, q)
+ 2811                                             ELSE QbeGen.NewTemp(qt);
+ 2812                                               QbeGen.NegQ(q, qt,
+ 2813                                                 SymTab.ClassOf(t)
+ 2814                                                 = SymTab.ClReal);
+ 2815                                               QbeGen.CopyOp(qt, q)
+ 2816                                             END
+ 2817                                           END;
+ 2818                                           IF astSign < 0 THEN
+ 2819                                             astCur := AST.MakeUn(
+ 2820                                               AST.NkUnary, AST.OpSub, astA);
+ 2821                                             astA := astCur
+ 2822                                           END; .)
+ 2823        { AddOp<op>                       (. IF op = SymTab.OpOr THEN
+ 2824                                               QbeGen.DelayBegin END; .)
+ 2825          Term<t2, q2> (. astB := astCur; IF op = SymTab.OpOr THEN
+ 2826                                               QbeGen.DelayEnd END; .)
+ 2827          (. astOp := AST.OpAdd;
+ 2828             IF op = SymTab.OpSub THEN astOp := AST.OpSub
+ 2829             ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
+ 2830             astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
+ 2831             astCur := astA;
+ 2832             IF op = SymTab.OpOr THEN
+ 2833               (* short-circuit: if q is true the RHS is skipped *)
+ 2834               IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
+ 2835                 t := SymTab.BoolType()
+ 2836               ELSE SemError(212); t := SymTab.InvalidType END;
+ 2837               IF t # SymTab.InvalidType THEN
+ 2838                 QbeGen.Slot4(qs);
+ 2839                 QbeGen.NewLabel(lTrue);
+ 2840                 QbeGen.NewLabel(lNext);
+ 2841                 QbeGen.NewLabel(lDone);
+ 2842                 QbeGen.Jnz(q, lTrue, lNext);
+ 2843                 QbeGen.EmitLabel(lTrue);
+ 2844                 QbeGen.StoreW(qs, "1");
  2845                 QbeGen.Jmp(lDone);
- 2846                 QbeGen.EmitLabel(lDone);
- 2847                 QbeGen.LoadW(qs, qr);
- 2848                 QbeGen.CopyOp(qr, q)
- 2849               ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
- 2850               END
- 2851             ELSIF (op = SymTab.OpAdd)
- 2852               AND (SymTab.UStrCompat(t, t2)
- 2853                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
- 2854                   AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
- 2855                 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
- 2856                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
+ 2846                 QbeGen.EmitLabel(lNext);
+ 2847                 QbeGen.DelayFlush;
+ 2848                 QbeGen.StoreW(qs, q2);
+ 2849                 QbeGen.Jmp(lDone);
+ 2850                 QbeGen.EmitLabel(lDone);
+ 2851                 QbeGen.LoadW(qs, qr);
+ 2852                 QbeGen.CopyOp(qr, q)
+ 2853               ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
+ 2854               END
+ 2855             ELSIF (op = SymTab.OpAdd)
+ 2856               AND (SymTab.UStrCompat(t, t2)
  2857                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
- 2858                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
- 2859               (* UString concatenation: a UCHAR operand becomes a
- 2860                  1-codepoint UString; the result is a descriptor in the
- 2861                  shim's concat buffer.  Work on copies so neither
- 2862                  operand is clobbered. *)
- 2863               IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
- 2864                 QbeGen.CopyOp(q, q2a)
- 2865               ELSE
- 2866                 QbeGen.UStrFrom(q, q2a)
- 2867               END;
- 2868               IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
- 2869                 QbeGen.UStrCat(q2a, q2, qt)
- 2870               ELSE
- 2871                 QbeGen.UStrFrom(q2, q2b);
- 2872                 QbeGen.UStrCat(q2a, q2b, qt)
- 2873               END;
- 2874               t := SymTab.NewUStr();
- 2875               QbeGen.CopyOp(qt, q)
- 2876             ELSIF (op = SymTab.OpAdd)
- 2877               AND (SymTab.StrCompat(t, t2)
- 2878                 OR (SymTab.IsStrType(t)
- 2879                   AND (SymTab.ClassOf(t2) = SymTab.ClChar))
- 2880                 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
- 2881                   AND SymTab.IsStrType(t2))) THEN
- 2882               (* string concatenation; a CHAR operand becomes a
- 2883                  1-character string literal.  When both operands are
- 2884                  constants, fold to a single string literal so a
- 2885                  constructor element stays compile-time. *)
- 2886               QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
- 2887                 qt, fok);
- 2888               IF NOT fok THEN
- 2889                 IF SymTab.StrCompat(t, t2) THEN
- 2890                   QbeGen.StrCat(q, q2, qt)
- 2891                 ELSIF SymTab.IsStrType(t) THEN
- 2892                   QbeGen.DeclCharStr(q2, qs);
- 2893                   QbeGen.StrCat(q, qs, qt)
- 2894                 ELSE
- 2895                   QbeGen.DeclCharStr(q, qs);
- 2896                   QbeGen.StrCat(qs, q2, qt)
- 2897                 END
- 2898               END;
- 2899               t := SymTab.NewStr();
- 2900               QbeGen.CopyOp(qt, q)
- 2901             ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
- 2902   AND (SymTab.ClassOf(t) = SymTab.ClSet)
- 2903   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 2904               lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
- 2905               mw := lw;
- 2906               IF rw > mw THEN mw := rw END;
- 2907               IF op = SymTab.OpAdd THEN
- 2908                 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
- 2909               ELSE
- 2910                 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
- 2911               END;
- 2912               t := SymTab.NewSet(
- 2913                      SymTab.NewSubR(0,
- 2914                        VAL(INTEGER, mw) * 32 - 1));
- 2915               QbeGen.CopyOp(qt, q)
- 2916             ELSE
- 2917               IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
- 2918                 lt := t; rt := t2; t := res2
- 2919               ELSE SemError(211); t := SymTab.InvalidType END;
- 2920               IF t # SymTab.InvalidType THEN
- 2921                 isL := SymTab.IsLongFamily(t);
- 2922                 isR := SymTab.ClassOf(t) = SymTab.ClReal;
- 2923                 folded := FALSE;
- 2924                 IF (NOT isL) AND (NOT isR)
- 2925    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
- 2926                   IF op = SymTab.OpAdd THEN
- 2927                     folded := QbeGen.Fold2(0, q, q2, qf)
- 2928                   ELSE
- 2929                     folded := QbeGen.Fold2(1, q, q2, qf)
- 2930                   END
- 2931                 END;
- 2932                 IF folded THEN QbeGen.CopyOp(qf, q)
- 2933                 ELSE
- 2934                 IF isL THEN
- 2935                   IF SymTab.IsIntFamily(lt) THEN
- 2936                     QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
- 2937                   END;
- 2938                   IF SymTab.IsIntFamily(rt) THEN
- 2939                     QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
- 2940                   END;
- 2941                   QbeGen.NewTemp(qt);
- 2942                   IF op = SymTab.OpAdd THEN
- 2943                     QbeGen.Op3L("add", qt, q, q2)
- 2944                   ELSE
- 2945                     QbeGen.Op3L("sub", qt, q, q2)
- 2946                   END
- 2947                 ELSE
- 2948                   QbeGen.NewTemp(qt);
- 2949                   IF op = SymTab.OpAdd THEN
- 2950                     QbeGen.Op3("add", qt, q, q2, isR)
- 2951                   ELSE
- 2952                     QbeGen.Op3("sub", qt, q, q2, isR)
- 2953                   END
- 2954                 END;
- 2955                 QbeGen.CopyOp(qt, q)
- 2956                 END
- 2957               ELSE QbeGen.CopyOp("0", q)
- 2958               END
- 2959             END; .) } .
- 2960    AddOp<VAR op: INTEGER>
- 2961      = "+"                               (. op := SymTab.OpAdd; .)
- 2962      | "-"                               (. op := SymTab.OpSub; .)
- 2963      | "OR"                              (. op := SymTab.OpOr; .) .
- 2964    Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 2965                                          (. VAR t2, res2, lt, rt:
- 2966                                                 SymTab.TypeIndex;
- 2967                                               op: INTEGER;
- 2968                                               q2, qt, wq, qf:
- 2969                                                 QbeGen.QVal;
- 2970                                               isR, isL, folded: BOOLEAN;
- 2971                                               lw, rw, mw: CARDINAL;
- 2972                                               lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
- 2973                                                astA, astB: AST.Node;
- 2974                                                astOp: INTEGER; .)
- 2975      = Fact<t, q> (. astA := astCur; .) { MulOp<op>            (. IF op = SymTab.OpAnd THEN
- 2976                                               QbeGen.DelayBegin END; .)
- 2977          Fact<t2, q2> (. astB := astCur; IF op = SymTab.OpAnd THEN
- 2978                                                QbeGen.DelayEnd END; .)
- 2979        (. astOp := AST.OpMul;
- 2980           IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
- 2981           ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
- 2982           ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
- 2983           ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
- 2984           astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
- 2985           astCur := astA;
- 2986           IF op = SymTab.OpAnd THEN
- 2987             (* short-circuit: if q is false the RHS is skipped *)
- 2988             IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
- 2989               t := SymTab.BoolType()
- 2990             ELSE SemError(212); t := SymTab.InvalidType END;
- 2991             IF t # SymTab.InvalidType THEN
- 2992               QbeGen.Slot4(qs);
- 2993               QbeGen.NewLabel(lNext);
- 2994               QbeGen.NewLabel(lFalse);
- 2995               QbeGen.NewLabel(lDone);
- 2996               QbeGen.Jnz(q, lNext, lFalse);
- 2997               QbeGen.EmitLabel(lNext);
- 2998               QbeGen.DelayFlush;
- 2999               QbeGen.StoreW(qs, q2);
- 3000               QbeGen.Jmp(lDone);
- 3001               QbeGen.EmitLabel(lFalse);
- 3002               QbeGen.StoreW(qs, "0");
- 3003               QbeGen.Jmp(lDone);
- 3004               QbeGen.EmitLabel(lDone);
- 3005               QbeGen.LoadW(qs, qr);
- 3006               QbeGen.CopyOp(qr, q)
- 3007             ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
- 3008             END
- 3009           ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
- 3010   AND (SymTab.ClassOf(t) = SymTab.ClSet)
- 3011   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 3012             lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
- 3013             mw := lw;
- 3014             IF rw > mw THEN mw := rw END;
- 3015             IF op = SymTab.OpTimes THEN
- 3016               QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
- 3017             ELSE
- 3018               QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
- 3019             END;
- 3020             t := SymTab.NewSet(
- 3021                    SymTab.NewSubR(0,
- 3022                      VAL(INTEGER, mw) * 32 - 1));
- 3023             QbeGen.CopyOp(qt, q)
- 3024           ELSE
- 3025             IF SymTab.ArithCheck(t, t2,
- 3026                  (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
- 3027                  res2) THEN
- 3028               lt := t; rt := t2; t := res2
- 3029             ELSE SemError(211); t := SymTab.InvalidType END;
- 3030             IF t # SymTab.InvalidType THEN
- 3031               isL := SymTab.IsLongFamily(t);
- 3032               isR := SymTab.ClassOf(t) = SymTab.ClReal;
- 3033               folded := FALSE;
- 3034               IF (NOT isL) AND (NOT isR)
- 3035    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
- 3036                 IF op = SymTab.OpTimes THEN
- 3037                   folded := QbeGen.Fold2(2, q, q2, qf)
- 3038                 ELSIF op = SymTab.OpDiv THEN
- 3039                   folded := QbeGen.Fold2(3, q, q2, qf)
- 3040                 ELSIF op = SymTab.OpMod THEN
- 3041                   folded := QbeGen.Fold2(4, q, q2, qf)
- 3042                 END
- 3043               END;
- 3044               IF folded THEN QbeGen.CopyOp(qf, q)
- 3045               ELSE
- 3046               IF isL THEN
- 3047                 IF SymTab.IsIntFamily(lt) THEN
- 3048                   QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
- 3049                 END;
- 3050                 IF SymTab.IsIntFamily(rt) THEN
- 3051                   QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
- 3052                 END;
- 3053                 QbeGen.NewTemp(qt);
- 3054                 IF op = SymTab.OpTimes THEN
- 3055                   QbeGen.Op3L("mul", qt, q, q2)
- 3056                 ELSIF (op = SymTab.OpDiv)
- 3057                    OR (op = SymTab.OpSlash) THEN
- 3058                   QbeGen.Op3L("div", qt, q, q2)
- 3059                 ELSE
- 3060                   QbeGen.Op3L("rem", qt, q, q2)
- 3061                 END
- 3062               ELSE
- 3063                 QbeGen.NewTemp(qt);
- 3064                 IF op = SymTab.OpTimes THEN
- 3065                   QbeGen.Op3("mul", qt, q, q2, isR)
- 3066                 ELSIF (op = SymTab.OpDiv)
- 3067                    OR (op = SymTab.OpSlash) THEN
- 3068                   QbeGen.Op3("div", qt, q, q2, isR)
- 3069                 ELSE
- 3070                   QbeGen.Op3("rem", qt, q, q2, isR)
- 3071                 END
- 3072               END;
- 3073               QbeGen.CopyOp(qt, q)
- 3074               END
- 3075             ELSE QbeGen.CopyOp("0", q)
- 3076             END
- 3077           END; .) } .
- 3078    MulOp<VAR op: INTEGER>
- 3079      = "*"                               (. op := SymTab.OpTimes; .)
- 3080      | "/"                               (. op := SymTab.OpSlash; .)
- 3081      | "DIV"                             (. op := SymTab.OpDiv; .)
- 3082      | "MOD"                             (. op := SymTab.OpMod; .)
- 3083      | ( "AND" | "&" )                   (. op := SymTab.OpAnd; .) .
- 3084    Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 3085                                          (. VAR s: ARRAY [0 .. 255] OF CHAR;
- 3086                                               et, dt, t2, st, ct2, et2:
- 3087                                                 SymTab.TypeIndex;
- 3088                                               dk: INTEGER;
- 3089                                               qd, q2, sq, qa, qm0, qr, qt:
- 3090                                                 QbeGen.QVal;
- 3091                                               qn, vn: SymTab.Name;
- 3092                                               vt: SymTab.TypeIndex;
- 3093                                               c1, c2: INTEGER;
- 3094                                               lo, hi: INTEGER;
- 3095                                               isMax: BOOLEAN;
- 3096                                               called, isHigh, sfx, isCh,
- 3097                                               isU, uok, isStr: BOOLEAN;
- 3098                                               ucp: INTEGER; astIsLit: BOOLEAN;
- 3099                                                astD: AST.Node;
- 3100                                                astCall: BOOLEAN;
- 3101                                                astNode, astNot: AST.Node;
- 3102                                                j: CARDINAL;
- 3103                                                astArg2: AST.Node;
- 3104                                                astBrace: AST.Node;
- 3105                                                astRes: AST.Node; .)
- 3106      = (. astIsLit := FALSE; .)
- 3107      ( integer                           (. LexString(s);
- 3108                                             QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
- 3109                                             t := SymTab.IntType(); .)
- 3110      | charConst                         (. LexString(s);
- 3111                                             QbeGen.NormLit(s, q, isCh);
- 3112                                             IF twoPhase THEN
- 3113                                               astIsLit := TRUE;
- 3114                                               astCur := AST.MakeLeaf(
- 3115                                                 AST.NkCharLit, s)
- 3116                                             END;
- 3117                                             t := SymTab.CharType(); .)
- 3118      | real                              (. LexString(s);
- 3119                                             QbeGen.NormReal(s, q);
- 3120                                             IF twoPhase THEN
- 3121                                               astIsLit := TRUE;
- 3122                                               astCur := AST.MakeLeaf(
- 3123                                                 AST.NkRealLit, s)
- 3124                                             END;
- 3125                                             t := SymTab.RealType(); .)
- 3126      | string                            (. LexString(s);
- 3127                                             IF twoPhase THEN
- 3128                                               astIsLit := TRUE;
- 3129                                               astCur := AST.MakeLeaf(
- 3130                                                 AST.NkStrLit, s)
- 3131                                             END;
- 3132                                             IF SymTab.StrLen(s) = 3 THEN
- 3133                                               t := SymTab.CharType();
- 3134                                               QbeGen.IntStr(
- 3135                                                 QbeGen.CharVal(s), q)
- 3136                                             ELSE t := SymTab.NewStr();
- 3137                                               QbeGen.DeclStr(s, q);
- 3138                                               (* a literal's value IS its
- 3139                                                  static descriptor address *)
- 3140                                               QbeGen.NoteAddr(q, q)
- 3141                                             END; .)
- 3142      | ustring                           (. LexString(s);
- 3143                                             IF twoPhase THEN
- 3144                                               astIsLit := TRUE;
- 3145                                               astCur := AST.MakeLeaf(
- 3146                                                 AST.NkStrLit, s)
- 3147                                             END;
- 3148                                             QbeGen.DeclUStr(s, q, isU, ucp,
- 3149                                               uok);
- 3150                                             IF NOT uok THEN
- 3151                                               SemError(234);
- 3152                                               t := SymTab.InvalidType
- 3153                                             ELSIF isU THEN
- 3154                                               t := SymTab.UCharType();
- 3155                                               QbeGen.IntStr(ucp, q)
- 3156                                             ELSE
- 3157                                               t := SymTab.NewUStr();
- 3158                                               QbeGen.NoteAddr(q, q)
- 3159                                             END; .)
- 3160      | Design<dt, dk, qd, qn, sfx>       (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
- 3161                                             astNArgs := 0; called := FALSE;
- 3162                                             t := dt;
- 3163                                             IF sfx THEN
- 3164                                               IF dt =
- 3165                                                  SymTab.InvalidType THEN
- 3166                                                 QbeGen.CopyOp("0", q)
- 3167                                               ELSIF (SymTab.ClassOf(dt) =
- 3168                                                      SymTab.ClRecord)
- 3169                                                  OR (SymTab.ClassOf(dt) =
- 3170                                                      SymTab.ClSet)
- 3171                                                  OR (SymTab.ClassOf(dt) =
- 3172                                                      SymTab.ClArray)
+ 2858                   AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
+ 2859                 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
+ 2860                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
+ 2861                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
+ 2862                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
+ 2863               (* UString concatenation: a UCHAR operand becomes a
+ 2864                  1-codepoint UString; the result is a descriptor in the
+ 2865                  shim's concat buffer.  Work on copies so neither
+ 2866                  operand is clobbered. *)
+ 2867               IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
+ 2868                 QbeGen.CopyOp(q, q2a)
+ 2869               ELSE
+ 2870                 QbeGen.UStrFrom(q, q2a)
+ 2871               END;
+ 2872               IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
+ 2873                 QbeGen.UStrCat(q2a, q2, qt)
+ 2874               ELSE
+ 2875                 QbeGen.UStrFrom(q2, q2b);
+ 2876                 QbeGen.UStrCat(q2a, q2b, qt)
+ 2877               END;
+ 2878               t := SymTab.NewUStr();
+ 2879               QbeGen.CopyOp(qt, q)
+ 2880             ELSIF (op = SymTab.OpAdd)
+ 2881               AND (SymTab.StrCompat(t, t2)
+ 2882                 OR (SymTab.IsStrType(t)
+ 2883                   AND (SymTab.ClassOf(t2) = SymTab.ClChar))
+ 2884                 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
+ 2885                   AND SymTab.IsStrType(t2))) THEN
+ 2886               (* string concatenation; a CHAR operand becomes a
+ 2887                  1-character string literal.  When both operands are
+ 2888                  constants, fold to a single string literal so a
+ 2889                  constructor element stays compile-time. *)
+ 2890               QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
+ 2891                 qt, fok);
+ 2892               IF NOT fok THEN
+ 2893                 IF SymTab.StrCompat(t, t2) THEN
+ 2894                   QbeGen.StrCat(q, q2, qt)
+ 2895                 ELSIF SymTab.IsStrType(t) THEN
+ 2896                   QbeGen.DeclCharStr(q2, qs);
+ 2897                   QbeGen.StrCat(q, qs, qt)
+ 2898                 ELSE
+ 2899                   QbeGen.DeclCharStr(q, qs);
+ 2900                   QbeGen.StrCat(qs, q2, qt)
+ 2901                 END
+ 2902               END;
+ 2903               t := SymTab.NewStr();
+ 2904               QbeGen.CopyOp(qt, q)
+ 2905             ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
+ 2906   AND (SymTab.ClassOf(t) = SymTab.ClSet)
+ 2907   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 2908               lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
+ 2909               mw := lw;
+ 2910               IF rw > mw THEN mw := rw END;
+ 2911               IF op = SymTab.OpAdd THEN
+ 2912                 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
+ 2913               ELSE
+ 2914                 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
+ 2915               END;
+ 2916               t := SymTab.NewSet(
+ 2917                      SymTab.NewSubR(0,
+ 2918                        VAL(INTEGER, mw) * 32 - 1));
+ 2919               QbeGen.CopyOp(qt, q)
+ 2920             ELSE
+ 2921               IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
+ 2922                 lt := t; rt := t2; t := res2
+ 2923               ELSE SemError(211); t := SymTab.InvalidType END;
+ 2924               IF t # SymTab.InvalidType THEN
+ 2925                 isL := SymTab.IsLongFamily(t);
+ 2926                 isR := SymTab.ClassOf(t) = SymTab.ClReal;
+ 2927                 folded := FALSE;
+ 2928                 IF (NOT isL) AND (NOT isR)
+ 2929    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
+ 2930                   IF op = SymTab.OpAdd THEN
+ 2931                     folded := QbeGen.Fold2(0, q, q2, qf)
+ 2932                   ELSE
+ 2933                     folded := QbeGen.Fold2(1, q, q2, qf)
+ 2934                   END
+ 2935                 END;
+ 2936                 IF folded THEN QbeGen.CopyOp(qf, q)
+ 2937                 ELSE
+ 2938                 IF isL THEN
+ 2939                   IF SymTab.IsIntFamily(lt) THEN
+ 2940                     QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
+ 2941                   END;
+ 2942                   IF SymTab.IsIntFamily(rt) THEN
+ 2943                     QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
+ 2944                   END;
+ 2945                   QbeGen.NewTemp(qt);
+ 2946                   IF op = SymTab.OpAdd THEN
+ 2947                     QbeGen.Op3L("add", qt, q, q2)
+ 2948                   ELSE
+ 2949                     QbeGen.Op3L("sub", qt, q, q2)
+ 2950                   END
+ 2951                 ELSE
+ 2952                   QbeGen.NewTemp(qt);
+ 2953                   IF op = SymTab.OpAdd THEN
+ 2954                     QbeGen.Op3("add", qt, q, q2, isR)
+ 2955                   ELSE
+ 2956                     QbeGen.Op3("sub", qt, q, q2, isR)
+ 2957                   END
+ 2958                 END;
+ 2959                 QbeGen.CopyOp(qt, q)
+ 2960                 END
+ 2961               ELSE QbeGen.CopyOp("0", q)
+ 2962               END
+ 2963             END; .) } .
+ 2964    AddOp<VAR op: INTEGER>
+ 2965      = "+"                               (. op := SymTab.OpAdd; .)
+ 2966      | "-"                               (. op := SymTab.OpSub; .)
+ 2967      | "OR"                              (. op := SymTab.OpOr; .) .
+ 2968    Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 2969                                          (. VAR t2, res2, lt, rt:
+ 2970                                                 SymTab.TypeIndex;
+ 2971                                               op: INTEGER;
+ 2972                                               q2, qt, wq, qf:
+ 2973                                                 QbeGen.QVal;
+ 2974                                               isR, isL, folded: BOOLEAN;
+ 2975                                               lw, rw, mw: CARDINAL;
+ 2976                                               lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
+ 2977                                                astA, astB: AST.Node;
+ 2978                                                astOp: INTEGER; .)
+ 2979      = Fact<t, q> (. astA := astCur; .) { MulOp<op>            (. IF op = SymTab.OpAnd THEN
+ 2980                                               QbeGen.DelayBegin END; .)
+ 2981          Fact<t2, q2> (. astB := astCur; IF op = SymTab.OpAnd THEN
+ 2982                                                QbeGen.DelayEnd END; .)
+ 2983        (. astOp := AST.OpMul;
+ 2984           IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
+ 2985           ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
+ 2986           ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
+ 2987           ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
+ 2988           astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
+ 2989           astCur := astA;
+ 2990           IF op = SymTab.OpAnd THEN
+ 2991             (* short-circuit: if q is false the RHS is skipped *)
+ 2992             IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
+ 2993               t := SymTab.BoolType()
+ 2994             ELSE SemError(212); t := SymTab.InvalidType END;
+ 2995             IF t # SymTab.InvalidType THEN
+ 2996               QbeGen.Slot4(qs);
+ 2997               QbeGen.NewLabel(lNext);
+ 2998               QbeGen.NewLabel(lFalse);
+ 2999               QbeGen.NewLabel(lDone);
+ 3000               QbeGen.Jnz(q, lNext, lFalse);
+ 3001               QbeGen.EmitLabel(lNext);
+ 3002               QbeGen.DelayFlush;
+ 3003               QbeGen.StoreW(qs, q2);
+ 3004               QbeGen.Jmp(lDone);
+ 3005               QbeGen.EmitLabel(lFalse);
+ 3006               QbeGen.StoreW(qs, "0");
+ 3007               QbeGen.Jmp(lDone);
+ 3008               QbeGen.EmitLabel(lDone);
+ 3009               QbeGen.LoadW(qs, qr);
+ 3010               QbeGen.CopyOp(qr, q)
+ 3011             ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
+ 3012             END
+ 3013           ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
+ 3014   AND (SymTab.ClassOf(t) = SymTab.ClSet)
+ 3015   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 3016             lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
+ 3017             mw := lw;
+ 3018             IF rw > mw THEN mw := rw END;
+ 3019             IF op = SymTab.OpTimes THEN
+ 3020               QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
+ 3021             ELSE
+ 3022               QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
+ 3023             END;
+ 3024             t := SymTab.NewSet(
+ 3025                    SymTab.NewSubR(0,
+ 3026                      VAL(INTEGER, mw) * 32 - 1));
+ 3027             QbeGen.CopyOp(qt, q)
+ 3028           ELSE
+ 3029             IF SymTab.ArithCheck(t, t2,
+ 3030                  (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
+ 3031                  res2) THEN
+ 3032               lt := t; rt := t2; t := res2
+ 3033             ELSE SemError(211); t := SymTab.InvalidType END;
+ 3034             IF t # SymTab.InvalidType THEN
+ 3035               isL := SymTab.IsLongFamily(t);
+ 3036               isR := SymTab.ClassOf(t) = SymTab.ClReal;
+ 3037               folded := FALSE;
+ 3038               IF (NOT isL) AND (NOT isR)
+ 3039    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
+ 3040                 IF op = SymTab.OpTimes THEN
+ 3041                   folded := QbeGen.Fold2(2, q, q2, qf)
+ 3042                 ELSIF op = SymTab.OpDiv THEN
+ 3043                   folded := QbeGen.Fold2(3, q, q2, qf)
+ 3044                 ELSIF op = SymTab.OpMod THEN
+ 3045                   folded := QbeGen.Fold2(4, q, q2, qf)
+ 3046                 END
+ 3047               END;
+ 3048               IF folded THEN QbeGen.CopyOp(qf, q)
+ 3049               ELSE
+ 3050               IF isL THEN
+ 3051                 IF SymTab.IsIntFamily(lt) THEN
+ 3052                   QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
+ 3053                 END;
+ 3054                 IF SymTab.IsIntFamily(rt) THEN
+ 3055                   QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
+ 3056                 END;
+ 3057                 QbeGen.NewTemp(qt);
+ 3058                 IF op = SymTab.OpTimes THEN
+ 3059                   QbeGen.Op3L("mul", qt, q, q2)
+ 3060                 ELSIF (op = SymTab.OpDiv)
+ 3061                    OR (op = SymTab.OpSlash) THEN
+ 3062                   QbeGen.Op3L("div", qt, q, q2)
+ 3063                 ELSE
+ 3064                   QbeGen.Op3L("rem", qt, q, q2)
+ 3065                 END
+ 3066               ELSE
+ 3067                 QbeGen.NewTemp(qt);
+ 3068                 IF op = SymTab.OpTimes THEN
+ 3069                   QbeGen.Op3("mul", qt, q, q2, isR)
+ 3070                 ELSIF (op = SymTab.OpDiv)
+ 3071                    OR (op = SymTab.OpSlash) THEN
+ 3072                   QbeGen.Op3("div", qt, q, q2, isR)
+ 3073                 ELSE
+ 3074                   QbeGen.Op3("rem", qt, q, q2, isR)
+ 3075                 END
+ 3076               END;
+ 3077               QbeGen.CopyOp(qt, q)
+ 3078               END
+ 3079             ELSE QbeGen.CopyOp("0", q)
+ 3080             END
+ 3081           END; .) } .
+ 3082    MulOp<VAR op: INTEGER>
+ 3083      = "*"                               (. op := SymTab.OpTimes; .)
+ 3084      | "/"                               (. op := SymTab.OpSlash; .)
+ 3085      | "DIV"                             (. op := SymTab.OpDiv; .)
+ 3086      | "MOD"                             (. op := SymTab.OpMod; .)
+ 3087      | ( "AND" | "&" )                   (. op := SymTab.OpAnd; .) .
+ 3088    Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 3089                                          (. VAR s: ARRAY [0 .. 255] OF CHAR;
+ 3090                                               et, dt, t2, st, ct2, et2:
+ 3091                                                 SymTab.TypeIndex;
+ 3092                                               dk: INTEGER;
+ 3093                                               qd, q2, sq, qa, qm0, qr, qt:
+ 3094                                                 QbeGen.QVal;
+ 3095                                               qn, vn: SymTab.Name;
+ 3096                                               vt: SymTab.TypeIndex;
+ 3097                                               c1, c2: INTEGER;
+ 3098                                               lo, hi: INTEGER;
+ 3099                                               isMax: BOOLEAN;
+ 3100                                               called, isHigh, sfx, isCh,
+ 3101                                               isU, uok, isStr: BOOLEAN;
+ 3102                                               ucp: INTEGER; astIsLit: BOOLEAN;
+ 3103                                                astD: AST.Node;
+ 3104                                                astCall: BOOLEAN;
+ 3105                                                astNode, astNot: AST.Node;
+ 3106                                                j: CARDINAL;
+ 3107                                                astArg2: AST.Node;
+ 3108                                                astBrace: AST.Node;
+ 3109                                                astRes: AST.Node; .)
+ 3110      = (. astIsLit := FALSE; .)
+ 3111      ( integer                           (. LexString(s);
+ 3112                                             QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
+ 3113                                             t := SymTab.IntType(); .)
+ 3114      | charConst                         (. LexString(s);
+ 3115                                             QbeGen.NormLit(s, q, isCh);
+ 3116                                             IF twoPhase THEN
+ 3117                                               astIsLit := TRUE;
+ 3118                                               astCur := AST.MakeLeaf(
+ 3119                                                 AST.NkCharLit, s)
+ 3120                                             END;
+ 3121                                             t := SymTab.CharType(); .)
+ 3122      | real                              (. LexString(s);
+ 3123                                             QbeGen.NormReal(s, q);
+ 3124                                             IF twoPhase THEN
+ 3125                                               astIsLit := TRUE;
+ 3126                                               astCur := AST.MakeLeaf(
+ 3127                                                 AST.NkRealLit, s)
+ 3128                                             END;
+ 3129                                             t := SymTab.RealType(); .)
+ 3130      | string                            (. LexString(s);
+ 3131                                             IF twoPhase THEN
+ 3132                                               astIsLit := TRUE;
+ 3133                                               astCur := AST.MakeLeaf(
+ 3134                                                 AST.NkStrLit, s)
+ 3135                                             END;
+ 3136                                             IF SymTab.StrLen(s) = 3 THEN
+ 3137                                               t := SymTab.CharType();
+ 3138                                               QbeGen.IntStr(
+ 3139                                                 QbeGen.CharVal(s), q)
+ 3140                                             ELSE t := SymTab.NewStr();
+ 3141                                               QbeGen.DeclStr(s, q);
+ 3142                                               (* a literal's value IS its
+ 3143                                                  static descriptor address *)
+ 3144                                               QbeGen.NoteAddr(q, q)
+ 3145                                             END; .)
+ 3146      | ustring                           (. LexString(s);
+ 3147                                             IF twoPhase THEN
+ 3148                                               astIsLit := TRUE;
+ 3149                                               astCur := AST.MakeLeaf(
+ 3150                                                 AST.NkStrLit, s)
+ 3151                                             END;
+ 3152                                             QbeGen.DeclUStr(s, q, isU, ucp,
+ 3153                                               uok);
+ 3154                                             IF NOT uok THEN
+ 3155                                               SemError(234);
+ 3156                                               t := SymTab.InvalidType
+ 3157                                             ELSIF isU THEN
+ 3158                                               t := SymTab.UCharType();
+ 3159                                               QbeGen.IntStr(ucp, q)
+ 3160                                             ELSE
+ 3161                                               t := SymTab.NewUStr();
+ 3162                                               QbeGen.NoteAddr(q, q)
+ 3163                                             END; .)
+ 3164      | Design<dt, dk, qd, qn, sfx>       (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
+ 3165                                             astNArgs := 0; called := FALSE;
+ 3166                                             t := dt;
+ 3167                                             IF sfx THEN
+ 3168                                               IF dt =
+ 3169                                                  SymTab.InvalidType THEN
+ 3170                                                 QbeGen.CopyOp("0", q)
+ 3171                                               ELSIF (SymTab.ClassOf(dt) =
+ 3172                                                      SymTab.ClRecord)
  3173                                                  OR (SymTab.ClassOf(dt) =
- 3174                                                      SymTab.ClClass) THEN
- 3175                                                 QbeGen.CopyOp(qd, q)
- 3176                                               ELSE QbeGen.ElemLoad(qd, dt,
- 3177                                                 q)
- 3178                                               END
- 3179                                             ELSE QbeGen.CopyOp(qd, q)
- 3180                                             END;
- 3181                                             IF (dk = SymTab.KindVar)
- 3182                                                OR (dk = SymTab.KindParam)
- 3183                                                OR (dk =
- 3184                                                   SymTab.KindField) THEN
- 3185                                               IF sfx THEN
- 3186                                                 QbeGen.NoteAddr(q, qd)
- 3187                                               ELSE
- 3188                                                 QbeGen.AddrOf(qn, qa);
- 3189                                                 QbeGen.NoteAddr(q, qa)
- 3190                                               END
- 3191                                             ELSIF sfx
- 3192   AND (dt #
- 3193                                                   SymTab.InvalidType)
- 3194   AND ((SymTab.ClassOf(dt) =
- 3195                                                    SymTab.ClArray)
- 3196                                                   OR (SymTab.ClassOf(dt) =
- 3197                                                       SymTab.ClSet)
- 3198                                                   OR (SymTab.ClassOf(dt) =
- 3199                                                       SymTab.ClRecord)) THEN
- 3200                                               QbeGen.NoteAddr(qd, qd)
- 3201                                             END; .)
- 3202        [ TypedBraceLit<dt, q>            (. t := dt; astCall := TRUE;
- 3203                                               astBrace := astCur; .) ]
- 3204        [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
- 3205                                          (. astCall := TRUE;
- 3206                                             astNode := AstCallNode(astD);
- 3207                                             astRes := astNode;
- 3208                                             t := ct2;
- 3209                                             QbeGen.CopyOp(q2, q);
- 3210                                             sfx := FALSE; .)
- 3211          { ResultComp<t, q, sfx, astRes> }
- 3212                                          (. IF sfx THEN
- 3213                                               IF t = SymTab.InvalidType THEN
- 3214                                                 QbeGen.CopyOp("0", q)
- 3215                                               ELSIF (SymTab.ClassOf(t) #
- 3216                                                      SymTab.ClRecord)
- 3217    AND (SymTab.ClassOf(t) # SymTab.ClSet)
- 3218    AND (SymTab.ClassOf(t) # SymTab.ClArray)
- 3219    AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
- 3220                                                 QbeGen.ElemLoad(q, t, q2);
- 3221                                                 QbeGen.CopyOp(q2, q)
- 3222                                               END
- 3223                                             END; .) ]
- 3224                                          (. IF called THEN
- 3225                                               astCur := astRes
- 3226                                             ELSIF astCall THEN
- 3227                                               astCur := astBrace
- 3228                                             ELSE astCur := astD
- 3229                                             END;
- 3230                                              astIsLit := TRUE;
- 3231                                              IF NOT called
- 3232   AND (dk = SymTab.KindProc) THEN
- 3233                                               (* bare zero-arg function
- 3234                                                  call (parentheses may be
- 3235                                                  omitted); a proper or
- 3236                                                  parameterised proc here
- 3237                                                  is 230 *)
- 3238                                               IF (SymTab.ProcNPar(qn) = 0)
- 3239   AND (SymTab.ProcRes(qn) #
- 3240                                                     SymTab.InvalidType) THEN
- 3241                                                 QbeGen.Mangled(qn,
- 3242                                                   SymTab.ProcUid(qn), qm0);
- 3243                                                 QbeGen.CallBegin(qm0,
- 3244                                                   SymTab.ProcRes(qn),
- 3245                                                   SymTab.ProcDepthOf(qn),
- 3246                                                   SymTab.IsExternal(qn));
- 3247                                                 QbeGen.CallEnd(TRUE, q);
- 3248                                                 t := SymTab.ProcRes(qn)
- 3249                                               ELSE
- 3250                                                 (* procedure used as a
- 3251                                                    value (assign to a
- 3252                                                    procedure variable):
- 3253                                                    its code address *)
- 3254                                                 t := SymTab.ProcTypeOf(qn);
- 3255                                                 QbeGen.Mangled(qn,
- 3256                                                   SymTab.ProcUid(qn), qm0);
- 3257                                                 QbeGen.ProcAddr(qm0, q)
- 3258                                               END
- 3259                                             END; .)
- 3260      | ( "HIGH"                          (. isHigh := TRUE; .)
- 3261        | ( "LEN" | "LENGTH" )            (. isHigh := FALSE; .) )
- 3262        "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
- 3263                                              isU := FALSE; .)
- 3264            | string                       (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
- 3265                                              isStr := TRUE;
- 3266                                              isU := FALSE;
- 3267                                              IF SymTab.StrLen(s) = 3 THEN
- 3268                                                dt := SymTab.CharType();
- 3269                                                QbeGen.IntStr(QbeGen.CharVal(s),
- 3270                                                  qd)
- 3271                                              ELSE
- 3272                                                dt := SymTab.NewStr();
- 3273                                                QbeGen.DeclStr(s, qd);
- 3274                                                QbeGen.NoteAddr(qd, qd)
- 3275                                              END;
- 3276                                              dk := -1;
- 3277                                              qn[0] := CHR(0); .)
- 3278            | ustring                      (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
- 3279                                              QbeGen.DeclUStr(s, qd, isU, ucp,
- 3280                                                uok);
- 3281                                              isStr := FALSE;
- 3282                                              IF NOT uok THEN
- 3283                                                SemError(234);
- 3284                                                dt := SymTab.InvalidType
- 3285                                              ELSIF isU THEN
- 3286                                                (* one codepoint: a UCHAR;
- 3287                                                   LEN is 1, HIGH is 0 *)
- 3288                                                dt := SymTab.UCharType();
- 3289                                                QbeGen.IntStr(ucp, qd)
- 3290                                              ELSE
- 3291                                                dt := SymTab.NewUStr();
- 3292                                                QbeGen.NoteAddr(qd, qd)
- 3293                                              END;
- 3294                                              dk := -1;
- 3295                                              qn[0] := CHR(0); .) )
- 3296        ")"
- 3297                                          (. astNode := AST.MakeNode(AST.NkCall);
- 3298     IF isHigh THEN AST.SetChild(astNode, 0,
- 3299       AST.MakeLeaf(AST.NkIdent, "HIGH"))
- 3300     ELSE AST.SetChild(astNode, 0,
- 3301       AST.MakeLeaf(AST.NkIdent, "LEN")) END;
- 3302     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3303     astCur := astNode; astIsLit := TRUE;
- 3304                                             IF (dt # SymTab.InvalidType)
- 3305    AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
- 3306                                               (* UString: the count is
- 3307                                                  the descriptor header *)
- 3308                                               IF isHigh THEN
- 3309                                                 QbeGen.UStrLen(qd, qr);
- 3310                                                 QbeGen.DecQ(qr)
- 3311                                               ELSE
- 3312                                                 QbeGen.UStrLen(qd, qr)
- 3313                                               END;
- 3314                                               t := SymTab.IntType();
- 3315                                               QbeGen.CopyOp(qr, q)
- 3316                                             ELSIF (dt # SymTab.InvalidType)
- 3317    AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
- 3318                                               (* single UCHAR codepoint *)
- 3319                                               IF isHigh THEN
- 3320                                                 QbeGen.CopyOp("0", qr)
- 3321                                               ELSE
- 3322                                                 QbeGen.CopyOp("1", qr)
- 3323                                               END;
- 3324                                               t := SymTab.IntType();
- 3325                                               QbeGen.CopyOp(qr, q)
- 3326                                             ELSIF isStr THEN
- 3327                                               (* fold: content length at
- 3328                                                  compile time *)
- 3329                                               IF SymTab.StrLen(s) = 3 THEN
- 3330                                                 c1 := 1
- 3331                                               ELSE
- 3332                                                 c1 :=
- 3333                                                   SymTab.StrLen(s) - 2
- 3334                                               END;
- 3335                                               IF isHigh THEN
- 3336                                                 DEC(c1)
- 3337                                               END;
- 3338                                               QbeGen.IntStr(c1, qr);
- 3339                                               t := SymTab.IntType();
- 3340                                               QbeGen.CopyOp(qr, q)
- 3341                                             ELSIF dt = SymTab.InvalidType THEN
- 3342                                               t := SymTab.InvalidType;
- 3343                                               QbeGen.CopyOp("0", q)
- 3344                                             ELSIF SymTab.ClassOf(dt) #
- 3345                                                   SymTab.ClArray THEN
- 3346                                               SemError(217);
- 3347                                               t := SymTab.InvalidType;
- 3348                                               QbeGen.CopyOp("0", q)
- 3349                                             ELSE
- 3350                                               IF isHigh THEN
- 3351                                                 IF SymTab.IsOpenArray(dt) THEN
- 3352                                                   QbeGen.OpenHi(qd, qr)
- 3353                                                 ELSE
- 3354                                                   QbeGen.IntStr(
- 3355                                                     SymTab.ArrayHi(dt), qr)
- 3356                                                 END
- 3357                                               ELSE
- 3358                                                 IF SymTab.IsOpenArray(dt) THEN
- 3359                                                   QbeGen.LoadCount(qd, qr)
- 3360                                                 ELSE
- 3361                                                   QbeGen.IntStr(VAL(
- 3362                                                     INTEGER,
- 3363                                                     SymTab.ArrayLen(dt)),
- 3364                                                     qr)
- 3365                                                 END
- 3366                                               END;
- 3367                                                t := SymTab.IntType();
- 3368                                                QbeGen.CopyOp(qr, q)
- 3369                                              END; .)
- 3370      | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
- 3371      (. astNode := AST.MakeNode(AST.NkCall);
- 3372     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
- 3373     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3374     astCur := astNode; astIsLit := TRUE; .)
- 3375                                          (. IF dt = SymTab.InvalidType THEN
- 3376                                               t := SymTab.InvalidType;
- 3377                                               QbeGen.CopyOp("0", q)
- 3378                                             ELSE
- 3379                                               QbeGen.IntStr(VAL(INTEGER,
- 3380                                                 SymTab.ObjectSize(dt)), q);
- 3381                                               t := SymTab.IntType()
- 3382                                             END; .)
- 3383      | ( "SHIFT"                         (. isMax := FALSE; .)
- 3384        | "ROTATE"                        (. isMax := TRUE; .) )
- 3385        "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
- 3386                                          (. astNode := AST.MakeNode(AST.NkCall);
- 3387     IF isMax THEN AST.SetChild(astNode, 0,
- 3388       AST.MakeLeaf(AST.NkIdent, "ROTATE"))
- 3389     ELSE AST.SetChild(astNode, 0,
- 3390       AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
- 3391     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
- 3392     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
- 3393     astCur := astNode; astIsLit := TRUE;
- 3394                                             (* set shift/rotate: isMax
- 3395                                                doubles as "rotate" *)
- 3396                                             IF (et # SymTab.InvalidType)
- 3397                                                AND (SymTab.ClassOf(et) =
- 3398                                                   SymTab.ClSet) THEN
- 3399                                               QbeGen.SetShift(q, q2,
- 3400                                                 SymTab.SetWords(et),
- 3401                                                 SymTab.SetCount(et), isMax,
- 3402                                                 qt);
- 3403                                               t := et;
- 3404                                               QbeGen.CopyOp(qt, q)
- 3405                                             ELSE SemError(230);
- 3406                                               t := SymTab.InvalidType;
- 3407                                               QbeGen.CopyOp("0", q)
- 3408                                             END; .)
- 3409      | ( "MIN"                           (. isMax := FALSE; .)
- 3410        | "MAX"                           (. isMax := TRUE; .) )
- 3411        "(" Design<dt, dk, qd, qn, sfx> ")"
- 3412                                          (. astNode := AST.MakeNode(AST.NkCall);
- 3413     IF isMax THEN AST.SetChild(astNode, 0,
- 3414       AST.MakeLeaf(AST.NkIdent, "MAX"))
- 3415     ELSE AST.SetChild(astNode, 0,
- 3416       AST.MakeLeaf(AST.NkIdent, "MIN")) END;
- 3417     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3418     astCur := astNode; astIsLit := TRUE;
- 3419                                             IF (dt # SymTab.InvalidType)
- 3420   AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
- 3421                                               (* REAL/LONGREAL: the
- 3422                                                  implementation bounds *)
- 3423                                               IF isMax THEN
- 3424                                                 QbeGen.NormReal(
- 3425                                                   "3.402823e38", q)
- 3426                                               ELSE QbeGen.NormReal(
- 3427                                                   "-3.402823e38", q)
- 3428                                               END;
- 3429                                               t := SymTab.RealType()
- 3430                                             ELSIF (dt #
- 3431                                                SymTab.InvalidType)
- 3432   AND (SymTab.ClassOf(dt) =
- 3433                                                   SymTab.ClLong) THEN
- 3434                                               IF isMax THEN
- 3435                                                 QbeGen.CopyOp(
- 3436                                                   "9223372036854775807", q)
- 3437                                               ELSE QbeGen.CopyOp(
- 3438                                                   "-9223372036854775808", q)
- 3439                                               END;
- 3440                                               t := SymTab.LongType()
- 3441                                             ELSIF SymTab.TypeBounds(dt, lo,
- 3442                                                      hi) THEN
- 3443                                               IF isMax THEN
- 3444                                                 QbeGen.IntStr(hi, q)
- 3445                                               ELSE QbeGen.IntStr(lo, q)
- 3446                                               END;
- 3447                                               t := SymTab.IntType()
- 3448                                             ELSE SemError(230);
- 3449                                               t := SymTab.InvalidType;
- 3450                                               QbeGen.CopyOp("0", q)
- 3451                                             END; .)
- 3452      | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
- 3453      (. astNode := AST.MakeNode(AST.NkCall);
- 3454     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
- 3455     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3456     astCur := astNode; astIsLit := TRUE; .)
- 3457                                          (. IF dt = SymTab.InvalidType THEN
- 3458                                               t := SymTab.InvalidType;
- 3459                                               QbeGen.CopyOp("0", q)
- 3460                                             ELSE
- 3461                                               IF sfx THEN
- 3462                                                 QbeGen.CopyOp(qd, q)
- 3463                                               ELSIF (dk = SymTab.KindVar)
- 3464                                                  OR (dk = SymTab.KindParam) THEN
- 3465                                                 QbeGen.AddrOf(qn, q)
- 3466                                               ELSE SemError(230);
- 3467                                                 QbeGen.CopyOp("0", q)
- 3468                                               END;
- 3469                                               t := SymTab.AddrType()
- 3470                                             END; .)
- 3471      | "CHR" "(" Expr<et, q> ")"
- 3472      (. astNode := AST.MakeNode(AST.NkCall);
- 3473     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
- 3474     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3475     astCur := astNode; astIsLit := TRUE; .)
- 3476                                          (. IF (et # SymTab.InvalidType)
- 3477   AND NOT SymTab.IsIntFamily(et) THEN
- 3478                                               SemError(211) END;
- 3479                                             t := SymTab.CharType(); .)
- 3480      | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
- 3481      (. astNode := AST.MakeNode(AST.NkCall);
- 3482     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
- 3483     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3484     astCur := astNode; astIsLit := TRUE; .)
- 3485                                          (. IF et # SymTab.InvalidType THEN
- 3486                                               IF (SymTab.ClassOf(et) #
- 3487                                                   SymTab.ClChar)
- 3488   AND (SymTab.ClassOf(et) #
- 3489                                                     SymTab.ClBool)
- 3490   AND (SymTab.ClassOf(et) #
- 3491                                                     SymTab.ClEnum)
- 3492   AND NOT SymTab.IsIntFamily(et) THEN
- 3493                                                 SemError(211) END
- 3494                                             END;
- 3495                                             t := SymTab.IntType(); .)
- 3496      | "CAP" "(" Expr<et, q> ")"
- 3497      (. astNode := AST.MakeNode(AST.NkCall);
- 3498     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
- 3499     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3500     astCur := astNode; astIsLit := TRUE; .)
- 3501                                          (. QbeGen.CapQ(q, qa);
- 3502                                             QbeGen.CopyOp(qa, q);
- 3503                                             t := SymTab.CharType(); .)
- 3504      | "UCHR" "(" Expr<et, q> ")"
- 3505      (. astNode := AST.MakeNode(AST.NkCall);
- 3506     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
- 3507     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3508     astCur := astNode; astIsLit := TRUE; .)
- 3509                                          (. (* UCHR: the UCHAR constructor.
- 3510                                                CHAR -> UCHAR (identity);
- 3511                                                INTEGER familly -> UCHAR
- 3512                                                (codepoint value). *)
- 3513                                             IF (et # SymTab.InvalidType)
- 3514    AND (SymTab.ClassOf(et) # SymTab.ClChar)
- 3515    AND NOT SymTab.IsIntFamily(et) THEN
- 3516                                               SemError(211) END;
- 3517                                             t := SymTab.UCharType(); .)
- 3518      | "CHR8" "(" Expr<et, q> ")"
- 3519      (. astNode := AST.MakeNode(AST.NkCall);
- 3520     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
- 3521     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3522     astCur := astNode; astIsLit := TRUE; .)
- 3523                                          (. IF (et # SymTab.InvalidType)
- 3524    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
- 3525                                               SemError(211) END;
- 3526                                             QbeGen.WidenLong(q, qa);
- 3527                                             QbeGen.CheckRange(qa, "0", "255");
- 3528                                             t := SymTab.CharType(); .)
- 3529      | "UORD" "(" Expr<et, q> ")"
- 3530      (. astNode := AST.MakeNode(AST.NkCall);
- 3531     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
- 3532     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3533     astCur := astNode; astIsLit := TRUE; .)
- 3534                                          (. (* UORD(u): the codepoint as a
- 3535                                                32-bit ordinal (INTEGER),
- 3536                                                cf. ORD for CHAR. *)
- 3537                                             IF (et # SymTab.InvalidType)
- 3538    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
- 3539                                               SemError(211) END;
- 3540                                             t := SymTab.IntType(); .)
- 3541      | "ABS" "(" Expr<et, q> ")"
- 3542      (. astNode := AST.MakeNode(AST.NkCall);
- 3543     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
- 3544     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3545     astCur := astNode; astIsLit := TRUE; .)
- 3546                                          (. IF (et # SymTab.InvalidType)
- 3547   AND NOT SymTab.IsIntFamily(et)
- 3548   AND (SymTab.ClassOf(et) #
- 3549                                                  SymTab.ClReal) THEN
- 3550                                               SemError(211)
- 3551                                             ELSE QbeGen.AbsQ(q, qa,
- 3552                                                    SymTab.ClassOf(et) =
- 3553                                                      SymTab.ClReal);
- 3554                                               QbeGen.CopyOp(qa, q)
- 3555                                             END;
- 3556                                             t := et; .)
- 3557      | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
- 3558      (. astNode := AST.MakeNode(AST.NkCall);
- 3559     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
- 3560     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
- 3561     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
- 3562     astCur := astNode; astIsLit := TRUE; .)
- 3563                                          (. IF NOT SymTab.Lookup(vn) THEN
- 3564                                               SemError(201);
- 3565                                               t := SymTab.InvalidType
- 3566                                             ELSE vt := SymTab.SymType(vn);
- 3567                                               IF vt = SymTab.InvalidType THEN
- 3568                                                 t := SymTab.InvalidType
- 3569                                               ELSIF et =
- 3570                                                  SymTab.InvalidType THEN
- 3571                                                 t := vt
- 3572                                               ELSE
- 3573                                                 c1 := SymTab.ClassOf(et);
- 3574                                                 c2 := SymTab.ClassOf(vt);
- 3575                                                 IF (c1 = SymTab.ClInt)
- 3576    AND (c2 = SymTab.ClLong) THEN
- 3577                                                   QbeGen.WidenLong(q, qa);
- 3578                                                   QbeGen.CopyOp(qa, q);
- 3579                                                   t := vt
- 3580                                                 ELSIF (c1 = SymTab.ClLong)
- 3581    AND (c2 = SymTab.ClInt) THEN
- 3582                                                   QbeGen.NarrowLong(q, qa);
- 3583                                                   QbeGen.CopyOp(qa, q);
- 3584                                                   t := vt
- 3585                                                 ELSIF (c1 = SymTab.ClInt)
- 3586    AND (c2 = SymTab.ClReal) THEN
- 3587                                                   QbeGen.ConvIR(q, qa);
- 3588                                                   QbeGen.CopyOp(qa, q);
- 3589                                                   t := vt
- 3590                                                 ELSIF (c1 = SymTab.ClLong)
- 3591    AND (c2 = SymTab.ClReal) THEN
- 3592                                                   QbeGen.ConvLR(q, qa);
- 3593                                                   QbeGen.CopyOp(qa, q);
- 3594                                                   t := vt
- 3595                                                 ELSIF (c1 = SymTab.ClReal)
- 3596    AND (c2 = SymTab.ClInt) THEN
- 3597                                                   QbeGen.ConvRI(q, qa);
- 3598                                                   QbeGen.CopyOp(qa, q);
- 3599                                                   t := vt
- 3600                                                 ELSIF (c1 = SymTab.ClReal)
- 3601    AND (c2 = SymTab.ClLong) THEN
- 3602                                                   QbeGen.ConvRL(q, qa);
- 3603                                                   QbeGen.CopyOp(qa, q);
- 3604                                                   t := vt
- 3605                                                 ELSIF ((c1 = SymTab.ClInt)
- 3606                                                     OR (c1 =
- 3607                                                        SymTab.ClChar)
- 3608                                                     OR (c1 =
- 3609                                                        SymTab.ClBool)
+ 3174                                                      SymTab.ClSet)
+ 3175                                                  OR (SymTab.ClassOf(dt) =
+ 3176                                                      SymTab.ClArray)
+ 3177                                                  OR (SymTab.ClassOf(dt) =
+ 3178                                                      SymTab.ClClass) THEN
+ 3179                                                 QbeGen.CopyOp(qd, q)
+ 3180                                               ELSE QbeGen.ElemLoad(qd, dt,
+ 3181                                                 q)
+ 3182                                               END
+ 3183                                             ELSE QbeGen.CopyOp(qd, q)
+ 3184                                             END;
+ 3185                                             IF (dk = SymTab.KindVar)
+ 3186                                                OR (dk = SymTab.KindParam)
+ 3187                                                OR (dk =
+ 3188                                                   SymTab.KindField) THEN
+ 3189                                               IF sfx THEN
+ 3190                                                 QbeGen.NoteAddr(q, qd)
+ 3191                                               ELSE
+ 3192                                                 QbeGen.AddrOf(qn, qa);
+ 3193                                                 QbeGen.NoteAddr(q, qa)
+ 3194                                               END
+ 3195                                             ELSIF sfx
+ 3196   AND (dt #
+ 3197                                                   SymTab.InvalidType)
+ 3198   AND ((SymTab.ClassOf(dt) =
+ 3199                                                    SymTab.ClArray)
+ 3200                                                   OR (SymTab.ClassOf(dt) =
+ 3201                                                       SymTab.ClSet)
+ 3202                                                   OR (SymTab.ClassOf(dt) =
+ 3203                                                       SymTab.ClRecord)) THEN
+ 3204                                               QbeGen.NoteAddr(qd, qd)
+ 3205                                             END; .)
+ 3206        [ TypedBraceLit<dt, q>            (. t := dt; astCall := TRUE;
+ 3207                                               astBrace := astCur; .) ]
+ 3208        [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
+ 3209                                          (. astCall := TRUE;
+ 3210                                             astNode := AstCallNode(astD);
+ 3211                                             astRes := astNode;
+ 3212                                             t := ct2;
+ 3213                                             QbeGen.CopyOp(q2, q);
+ 3214                                             sfx := FALSE; .)
+ 3215          { ResultComp<t, q, sfx, astRes> }
+ 3216                                          (. IF sfx THEN
+ 3217                                               IF t = SymTab.InvalidType THEN
+ 3218                                                 QbeGen.CopyOp("0", q)
+ 3219                                               ELSIF (SymTab.ClassOf(t) #
+ 3220                                                      SymTab.ClRecord)
+ 3221    AND (SymTab.ClassOf(t) # SymTab.ClSet)
+ 3222    AND (SymTab.ClassOf(t) # SymTab.ClArray)
+ 3223    AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
+ 3224                                                 QbeGen.ElemLoad(q, t, q2);
+ 3225                                                 QbeGen.CopyOp(q2, q)
+ 3226                                               END
+ 3227                                             END; .) ]
+ 3228                                          (. IF called THEN
+ 3229                                               astCur := astRes
+ 3230                                             ELSIF astCall THEN
+ 3231                                               astCur := astBrace
+ 3232                                             ELSE astCur := astD
+ 3233                                             END;
+ 3234                                              astIsLit := TRUE;
+ 3235                                              IF NOT called
+ 3236   AND (dk = SymTab.KindProc) THEN
+ 3237                                               (* bare zero-arg function
+ 3238                                                  call (parentheses may be
+ 3239                                                  omitted); a proper or
+ 3240                                                  parameterised proc here
+ 3241                                                  is 230 *)
+ 3242                                               IF (SymTab.ProcNPar(qn) = 0)
+ 3243   AND (SymTab.ProcRes(qn) #
+ 3244                                                     SymTab.InvalidType) THEN
+ 3245                                                 QbeGen.Mangled(qn,
+ 3246                                                   SymTab.ProcUid(qn), qm0);
+ 3247                                                 QbeGen.CallBegin(qm0,
+ 3248                                                   SymTab.ProcRes(qn),
+ 3249                                                   SymTab.ProcDepthOf(qn),
+ 3250                                                   SymTab.IsExternal(qn));
+ 3251                                                 QbeGen.CallEnd(TRUE, q);
+ 3252                                                 t := SymTab.ProcRes(qn)
+ 3253                                               ELSE
+ 3254                                                 (* procedure used as a
+ 3255                                                    value (assign to a
+ 3256                                                    procedure variable):
+ 3257                                                    its code address *)
+ 3258                                                 t := SymTab.ProcTypeOf(qn);
+ 3259                                                 QbeGen.Mangled(qn,
+ 3260                                                   SymTab.ProcUid(qn), qm0);
+ 3261                                                 QbeGen.ProcAddr(qm0, q)
+ 3262                                               END
+ 3263                                             END; .)
+ 3264      | ( "HIGH"                          (. isHigh := TRUE; .)
+ 3265        | ( "LEN" | "LENGTH" )            (. isHigh := FALSE; .) )
+ 3266        "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
+ 3267                                              isU := FALSE; .)
+ 3268            | string                       (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
+ 3269                                              isStr := TRUE;
+ 3270                                              isU := FALSE;
+ 3271                                              IF SymTab.StrLen(s) = 3 THEN
+ 3272                                                dt := SymTab.CharType();
+ 3273                                                QbeGen.IntStr(QbeGen.CharVal(s),
+ 3274                                                  qd)
+ 3275                                              ELSE
+ 3276                                                dt := SymTab.NewStr();
+ 3277                                                QbeGen.DeclStr(s, qd);
+ 3278                                                QbeGen.NoteAddr(qd, qd)
+ 3279                                              END;
+ 3280                                              dk := -1;
+ 3281                                              qn[0] := CHR(0); .)
+ 3282            | ustring                      (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
+ 3283                                              QbeGen.DeclUStr(s, qd, isU, ucp,
+ 3284                                                uok);
+ 3285                                              isStr := FALSE;
+ 3286                                              IF NOT uok THEN
+ 3287                                                SemError(234);
+ 3288                                                dt := SymTab.InvalidType
+ 3289                                              ELSIF isU THEN
+ 3290                                                (* one codepoint: a UCHAR;
+ 3291                                                   LEN is 1, HIGH is 0 *)
+ 3292                                                dt := SymTab.UCharType();
+ 3293                                                QbeGen.IntStr(ucp, qd)
+ 3294                                              ELSE
+ 3295                                                dt := SymTab.NewUStr();
+ 3296                                                QbeGen.NoteAddr(qd, qd)
+ 3297                                              END;
+ 3298                                              dk := -1;
+ 3299                                              qn[0] := CHR(0); .) )
+ 3300        ")"
+ 3301                                          (. astNode := AST.MakeNode(AST.NkCall);
+ 3302     IF isHigh THEN AST.SetChild(astNode, 0,
+ 3303       AST.MakeLeaf(AST.NkIdent, "HIGH"))
+ 3304     ELSE AST.SetChild(astNode, 0,
+ 3305       AST.MakeLeaf(AST.NkIdent, "LEN")) END;
+ 3306     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3307     astCur := astNode; astIsLit := TRUE;
+ 3308                                             IF (dt # SymTab.InvalidType)
+ 3309    AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
+ 3310                                               (* UString: the count is
+ 3311                                                  the descriptor header *)
+ 3312                                               IF isHigh THEN
+ 3313                                                 QbeGen.UStrLen(qd, qr);
+ 3314                                                 QbeGen.DecQ(qr)
+ 3315                                               ELSE
+ 3316                                                 QbeGen.UStrLen(qd, qr)
+ 3317                                               END;
+ 3318                                               t := SymTab.IntType();
+ 3319                                               QbeGen.CopyOp(qr, q)
+ 3320                                             ELSIF (dt # SymTab.InvalidType)
+ 3321    AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
+ 3322                                               (* single UCHAR codepoint *)
+ 3323                                               IF isHigh THEN
+ 3324                                                 QbeGen.CopyOp("0", qr)
+ 3325                                               ELSE
+ 3326                                                 QbeGen.CopyOp("1", qr)
+ 3327                                               END;
+ 3328                                               t := SymTab.IntType();
+ 3329                                               QbeGen.CopyOp(qr, q)
+ 3330                                             ELSIF isStr THEN
+ 3331                                               (* fold: content length at
+ 3332                                                  compile time *)
+ 3333                                               IF SymTab.StrLen(s) = 3 THEN
+ 3334                                                 c1 := 1
+ 3335                                               ELSE
+ 3336                                                 c1 :=
+ 3337                                                   SymTab.StrLen(s) - 2
+ 3338                                               END;
+ 3339                                               IF isHigh THEN
+ 3340                                                 DEC(c1)
+ 3341                                               END;
+ 3342                                               QbeGen.IntStr(c1, qr);
+ 3343                                               t := SymTab.IntType();
+ 3344                                               QbeGen.CopyOp(qr, q)
+ 3345                                             ELSIF dt = SymTab.InvalidType THEN
+ 3346                                               t := SymTab.InvalidType;
+ 3347                                               QbeGen.CopyOp("0", q)
+ 3348                                             ELSIF SymTab.ClassOf(dt) #
+ 3349                                                   SymTab.ClArray THEN
+ 3350                                               SemError(217);
+ 3351                                               t := SymTab.InvalidType;
+ 3352                                               QbeGen.CopyOp("0", q)
+ 3353                                             ELSE
+ 3354                                               IF isHigh THEN
+ 3355                                                 IF SymTab.IsOpenArray(dt) THEN
+ 3356                                                   QbeGen.OpenHi(qd, qr)
+ 3357                                                 ELSE
+ 3358                                                   QbeGen.IntStr(
+ 3359                                                     SymTab.ArrayHi(dt), qr)
+ 3360                                                 END
+ 3361                                               ELSE
+ 3362                                                 IF SymTab.IsOpenArray(dt) THEN
+ 3363                                                   QbeGen.LoadCount(qd, qr)
+ 3364                                                 ELSE
+ 3365                                                   QbeGen.IntStr(VAL(
+ 3366                                                     INTEGER,
+ 3367                                                     SymTab.ArrayLen(dt)),
+ 3368                                                     qr)
+ 3369                                                 END
+ 3370                                               END;
+ 3371                                                t := SymTab.IntType();
+ 3372                                                QbeGen.CopyOp(qr, q)
+ 3373                                              END; .)
+ 3374      | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
+ 3375      (. astNode := AST.MakeNode(AST.NkCall);
+ 3376     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
+ 3377     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3378     astCur := astNode; astIsLit := TRUE; .)
+ 3379                                          (. IF dt = SymTab.InvalidType THEN
+ 3380                                               t := SymTab.InvalidType;
+ 3381                                               QbeGen.CopyOp("0", q)
+ 3382                                             ELSE
+ 3383                                               QbeGen.IntStr(VAL(INTEGER,
+ 3384                                                 SymTab.ObjectSize(dt)), q);
+ 3385                                               t := SymTab.IntType()
+ 3386                                             END; .)
+ 3387      | ( "SHIFT"                         (. isMax := FALSE; .)
+ 3388        | "ROTATE"                        (. isMax := TRUE; .) )
+ 3389        "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
+ 3390                                          (. astNode := AST.MakeNode(AST.NkCall);
+ 3391     IF isMax THEN AST.SetChild(astNode, 0,
+ 3392       AST.MakeLeaf(AST.NkIdent, "ROTATE"))
+ 3393     ELSE AST.SetChild(astNode, 0,
+ 3394       AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
+ 3395     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
+ 3396     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
+ 3397     astCur := astNode; astIsLit := TRUE;
+ 3398                                             (* set shift/rotate: isMax
+ 3399                                                doubles as "rotate" *)
+ 3400                                             IF (et # SymTab.InvalidType)
+ 3401                                                AND (SymTab.ClassOf(et) =
+ 3402                                                   SymTab.ClSet) THEN
+ 3403                                               QbeGen.SetShift(q, q2,
+ 3404                                                 SymTab.SetWords(et),
+ 3405                                                 SymTab.SetCount(et), isMax,
+ 3406                                                 qt);
+ 3407                                               t := et;
+ 3408                                               QbeGen.CopyOp(qt, q)
+ 3409                                             ELSE SemError(230);
+ 3410                                               t := SymTab.InvalidType;
+ 3411                                               QbeGen.CopyOp("0", q)
+ 3412                                             END; .)
+ 3413      | ( "MIN"                           (. isMax := FALSE; .)
+ 3414        | "MAX"                           (. isMax := TRUE; .) )
+ 3415        "(" Design<dt, dk, qd, qn, sfx> ")"
+ 3416                                          (. astNode := AST.MakeNode(AST.NkCall);
+ 3417     IF isMax THEN AST.SetChild(astNode, 0,
+ 3418       AST.MakeLeaf(AST.NkIdent, "MAX"))
+ 3419     ELSE AST.SetChild(astNode, 0,
+ 3420       AST.MakeLeaf(AST.NkIdent, "MIN")) END;
+ 3421     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3422     astCur := astNode; astIsLit := TRUE;
+ 3423                                             IF (dt # SymTab.InvalidType)
+ 3424   AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
+ 3425                                               (* REAL/LONGREAL: the
+ 3426                                                  implementation bounds *)
+ 3427                                               IF isMax THEN
+ 3428                                                 QbeGen.NormReal(
+ 3429                                                   "3.402823e38", q)
+ 3430                                               ELSE QbeGen.NormReal(
+ 3431                                                   "-3.402823e38", q)
+ 3432                                               END;
+ 3433                                               t := SymTab.RealType()
+ 3434                                             ELSIF (dt #
+ 3435                                                SymTab.InvalidType)
+ 3436   AND (SymTab.ClassOf(dt) =
+ 3437                                                   SymTab.ClLong) THEN
+ 3438                                               IF isMax THEN
+ 3439                                                 QbeGen.CopyOp(
+ 3440                                                   "9223372036854775807", q)
+ 3441                                               ELSE QbeGen.CopyOp(
+ 3442                                                   "-9223372036854775808", q)
+ 3443                                               END;
+ 3444                                               t := SymTab.LongType()
+ 3445                                             ELSIF SymTab.TypeBounds(dt, lo,
+ 3446                                                      hi) THEN
+ 3447                                               IF isMax THEN
+ 3448                                                 QbeGen.IntStr(hi, q)
+ 3449                                               ELSE QbeGen.IntStr(lo, q)
+ 3450                                               END;
+ 3451                                               t := SymTab.IntType()
+ 3452                                             ELSE SemError(230);
+ 3453                                               t := SymTab.InvalidType;
+ 3454                                               QbeGen.CopyOp("0", q)
+ 3455                                             END; .)
+ 3456      | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
+ 3457      (. astNode := AST.MakeNode(AST.NkCall);
+ 3458     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
+ 3459     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3460     astCur := astNode; astIsLit := TRUE; .)
+ 3461                                          (. IF dt = SymTab.InvalidType THEN
+ 3462                                               t := SymTab.InvalidType;
+ 3463                                               QbeGen.CopyOp("0", q)
+ 3464                                             ELSE
+ 3465                                               IF sfx THEN
+ 3466                                                 QbeGen.CopyOp(qd, q)
+ 3467                                               ELSIF (dk = SymTab.KindVar)
+ 3468                                                  OR (dk = SymTab.KindParam) THEN
+ 3469                                                 QbeGen.AddrOf(qn, q)
+ 3470                                               ELSE SemError(230);
+ 3471                                                 QbeGen.CopyOp("0", q)
+ 3472                                               END;
+ 3473                                               t := SymTab.AddrType()
+ 3474                                             END; .)
+ 3475      | "CHR" "(" Expr<et, q> ")"
+ 3476      (. astNode := AST.MakeNode(AST.NkCall);
+ 3477     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
+ 3478     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3479     astCur := astNode; astIsLit := TRUE; .)
+ 3480                                          (. IF (et # SymTab.InvalidType)
+ 3481   AND NOT SymTab.IsIntFamily(et) THEN
+ 3482                                               SemError(211) END;
+ 3483                                             t := SymTab.CharType(); .)
+ 3484      | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
+ 3485      (. astNode := AST.MakeNode(AST.NkCall);
+ 3486     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
+ 3487     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3488     astCur := astNode; astIsLit := TRUE; .)
+ 3489                                          (. IF et # SymTab.InvalidType THEN
+ 3490                                               IF (SymTab.ClassOf(et) #
+ 3491                                                   SymTab.ClChar)
+ 3492   AND (SymTab.ClassOf(et) #
+ 3493                                                     SymTab.ClBool)
+ 3494   AND (SymTab.ClassOf(et) #
+ 3495                                                     SymTab.ClEnum)
+ 3496   AND NOT SymTab.IsIntFamily(et) THEN
+ 3497                                                 SemError(211) END
+ 3498                                             END;
+ 3499                                             t := SymTab.IntType(); .)
+ 3500      | "CAP" "(" Expr<et, q> ")"
+ 3501      (. astNode := AST.MakeNode(AST.NkCall);
+ 3502     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
+ 3503     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3504     astCur := astNode; astIsLit := TRUE; .)
+ 3505                                          (. QbeGen.CapQ(q, qa);
+ 3506                                             QbeGen.CopyOp(qa, q);
+ 3507                                             t := SymTab.CharType(); .)
+ 3508      | "UCHR" "(" Expr<et, q> ")"
+ 3509      (. astNode := AST.MakeNode(AST.NkCall);
+ 3510     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
+ 3511     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3512     astCur := astNode; astIsLit := TRUE; .)
+ 3513                                          (. (* UCHR: the UCHAR constructor.
+ 3514                                                CHAR -> UCHAR (identity);
+ 3515                                                INTEGER familly -> UCHAR
+ 3516                                                (codepoint value). *)
+ 3517                                             IF (et # SymTab.InvalidType)
+ 3518    AND (SymTab.ClassOf(et) # SymTab.ClChar)
+ 3519    AND NOT SymTab.IsIntFamily(et) THEN
+ 3520                                               SemError(211) END;
+ 3521                                             t := SymTab.UCharType(); .)
+ 3522      | "CHR8" "(" Expr<et, q> ")"
+ 3523      (. astNode := AST.MakeNode(AST.NkCall);
+ 3524     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
+ 3525     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3526     astCur := astNode; astIsLit := TRUE; .)
+ 3527                                          (. IF (et # SymTab.InvalidType)
+ 3528    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
+ 3529                                               SemError(211) END;
+ 3530                                             QbeGen.WidenLong(q, qa);
+ 3531                                             QbeGen.CheckRange(qa, "0", "255");
+ 3532                                             t := SymTab.CharType(); .)
+ 3533      | "UORD" "(" Expr<et, q> ")"
+ 3534      (. astNode := AST.MakeNode(AST.NkCall);
+ 3535     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
+ 3536     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3537     astCur := astNode; astIsLit := TRUE; .)
+ 3538                                          (. (* UORD(u): the codepoint as a
+ 3539                                                32-bit ordinal (INTEGER),
+ 3540                                                cf. ORD for CHAR. *)
+ 3541                                             IF (et # SymTab.InvalidType)
+ 3542    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
+ 3543                                               SemError(211) END;
+ 3544                                             t := SymTab.IntType(); .)
+ 3545      | "ABS" "(" Expr<et, q> ")"
+ 3546      (. astNode := AST.MakeNode(AST.NkCall);
+ 3547     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
+ 3548     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3549     astCur := astNode; astIsLit := TRUE; .)
+ 3550                                          (. IF (et # SymTab.InvalidType)
+ 3551   AND NOT SymTab.IsIntFamily(et)
+ 3552   AND (SymTab.ClassOf(et) #
+ 3553                                                  SymTab.ClReal) THEN
+ 3554                                               SemError(211)
+ 3555                                             ELSE QbeGen.AbsQ(q, qa,
+ 3556                                                    SymTab.ClassOf(et) =
+ 3557                                                      SymTab.ClReal);
+ 3558                                               QbeGen.CopyOp(qa, q)
+ 3559                                             END;
+ 3560                                             t := et; .)
+ 3561      | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
+ 3562      (. astNode := AST.MakeNode(AST.NkCall);
+ 3563     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
+ 3564     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
+ 3565     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
+ 3566     astCur := astNode; astIsLit := TRUE; .)
+ 3567                                          (. IF NOT SymTab.Lookup(vn) THEN
+ 3568                                               SemError(201);
+ 3569                                               t := SymTab.InvalidType
+ 3570                                             ELSE vt := SymTab.SymType(vn);
+ 3571                                               IF vt = SymTab.InvalidType THEN
+ 3572                                                 t := SymTab.InvalidType
+ 3573                                               ELSIF et =
+ 3574                                                  SymTab.InvalidType THEN
+ 3575                                                 t := vt
+ 3576                                               ELSE
+ 3577                                                 c1 := SymTab.ClassOf(et);
+ 3578                                                 c2 := SymTab.ClassOf(vt);
+ 3579                                                 IF (c1 = SymTab.ClInt)
+ 3580    AND (c2 = SymTab.ClLong) THEN
+ 3581                                                   QbeGen.WidenLong(q, qa);
+ 3582                                                   QbeGen.CopyOp(qa, q);
+ 3583                                                   t := vt
+ 3584                                                 ELSIF (c1 = SymTab.ClLong)
+ 3585    AND (c2 = SymTab.ClInt) THEN
+ 3586                                                   QbeGen.NarrowLong(q, qa);
+ 3587                                                   QbeGen.CopyOp(qa, q);
+ 3588                                                   t := vt
+ 3589                                                 ELSIF (c1 = SymTab.ClInt)
+ 3590    AND (c2 = SymTab.ClReal) THEN
+ 3591                                                   QbeGen.ConvIR(q, qa);
+ 3592                                                   QbeGen.CopyOp(qa, q);
+ 3593                                                   t := vt
+ 3594                                                 ELSIF (c1 = SymTab.ClLong)
+ 3595    AND (c2 = SymTab.ClReal) THEN
+ 3596                                                   QbeGen.ConvLR(q, qa);
+ 3597                                                   QbeGen.CopyOp(qa, q);
+ 3598                                                   t := vt
+ 3599                                                 ELSIF (c1 = SymTab.ClReal)
+ 3600    AND (c2 = SymTab.ClInt) THEN
+ 3601                                                   QbeGen.ConvRI(q, qa);
+ 3602                                                   QbeGen.CopyOp(qa, q);
+ 3603                                                   t := vt
+ 3604                                                 ELSIF (c1 = SymTab.ClReal)
+ 3605    AND (c2 = SymTab.ClLong) THEN
+ 3606                                                   QbeGen.ConvRL(q, qa);
+ 3607                                                   QbeGen.CopyOp(qa, q);
+ 3608                                                   t := vt
+ 3609                                                 ELSIF ((c1 = SymTab.ClInt)
  3610                                                     OR (c1 =
- 3611                                                        SymTab.ClEnum))
- 3612   AND ((c2 = SymTab.ClInt)
- 3613                                                     OR (c2 =
- 3614                                                        SymTab.ClChar)
- 3615                                                     OR (c2 =
- 3616                                                        SymTab.ClBool)
+ 3611                                                        SymTab.ClChar)
+ 3612                                                     OR (c1 =
+ 3613                                                        SymTab.ClBool)
+ 3614                                                     OR (c1 =
+ 3615                                                        SymTab.ClEnum))
+ 3616   AND ((c2 = SymTab.ClInt)
  3617                                                     OR (c2 =
- 3618                                                        SymTab.ClEnum)) THEN
- 3619                                                   t := vt
- 3620                                                 ELSIF (c1 = SymTab.ClPtr)
- 3621   AND (c2 = SymTab.ClPtr) THEN
- 3622                                                   t := vt
- 3623                                                 ELSIF (c1 = SymTab.ClReal)
- 3624   AND (c2 = SymTab.ClReal) THEN
- 3625                                                   t := vt
- 3626                                                 ELSE SemError(230);
- 3627                                                   t := SymTab.InvalidType
- 3628                                                 END
- 3629                                               END
- 3630                                             END; .)
- 3631      | "(" Expr<et, q> ")"               (. t := et; astIsLit := TRUE; .)
- 3632      | SetLit<st, sq>                    (. astIsLit := TRUE; t := st;
- 3633                                             QbeGen.CopyOp(sq, q); .)
- 3634      | ( "NOT" | "~" ) Fact<t2, q2>      (. astNot := astCur;
- 3635                                             IF SymTab.BoolCheck(t2) THEN
- 3636                                               t := SymTab.BoolType()
- 3637                                             ELSE SemError(212);
- 3638                                               t := SymTab.InvalidType END;
- 3639                                             IF t # SymTab.InvalidType THEN
- 3640                                               QbeGen.NotQ(q2, q)
- 3641                                             ELSE QbeGen.CopyOp("0", q)
- 3642                                             END;
- 3643                                             astIsLit := TRUE;
- 3644                                             astCur := AST.MakeUn(
- 3645                                               AST.NkUnary, AST.OpNot, astNot); .)
- 3646      )
- 3647      (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
- 3648    (* Set literals are SET OF [0..255] (8 words); elements validated
- 3649       0..255 statically when foldable (222 otherwise), runtime trap
- 3650       for computed elements. Ranges always lower via SetRange. *)
- 3651    SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 3652                                          (. VAR astNode: AST.Node; .)
- 3653      = "{"                               (. t := SymTab.NewSet(
- 3654                                               SymTab.NewSubR(0, 255));
- 3655                                             astNode := AST.MakeNode(AST.NkSetLit);
- 3656                                             QbeGen.NewSetTemp(8, q);
- 3657                                             QbeGen.SetZero(q, 8); .)
- 3658        [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
- 3659        "}"                               (. astCur := astNode; .) .
- 3660    (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
- 3661       or ArrayName{...} (an array constructor, GNU Modula-2).  The
- 3662       declared type sets the width (set) or element type (array). *)
- 3663    TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 3664                                          (. VAR nw: CARDINAL;
- 3665                                               astNode: AST.Node;
- 3666                                               savedCls: INTEGER; .)
- 3667      = "{"                               (. savedCls := braceCls;
- 3668                                             astNode := AST.MakeNode(AST.NkBraceLit);
- 3669                                             IF vt = SymTab.InvalidType THEN
- 3670                                               braceCls := -1
- 3671                                             ELSE braceCls :=
- 3672                                                    SymTab.ClassOf(vt)
- 3673                                             END;
- 3674                                             IF braceCls = SymTab.ClSet THEN
- 3675                                               IF vt = SymTab.InvalidType THEN
- 3676                                                 nw := 8
- 3677                                               ELSE nw := SymTab.SetWords(vt);
- 3678                                                 IF nw = 0 THEN nw := 8 END
- 3679                                               END;
- 3680                                               QbeGen.NewSetTemp(nw, q);
- 3681                                               QbeGen.SetZero(q, nw)
- 3682                                             ELSIF (braceCls =
- 3683                                                    SymTab.ClArray)
- 3684                                                OR (braceCls =
- 3685                                                    SymTab.ClRecord)
- 3686                                                OR (braceCls =
- 3687                                                    SymTab.ClClass) THEN
- 3688                                               QbeGen.CtorBegin(vt)
- 3689                                             ELSE
- 3690                                               IF vt # SymTab.InvalidType THEN
- 3691                                                 SemError(230) END;
- 3692                                               braceCls := -1
- 3693                                             END; .)
- 3694        [ BraceElem<vt, q, astNode> { "," BraceElem<vt, q, astNode> } ]
- 3695        "}"                               (. IF (braceCls = SymTab.ClArray)
- 3696                                                OR (braceCls =
- 3697                                                   SymTab.ClRecord)
- 3698                                                OR (braceCls =
- 3699                                                   SymTab.ClClass) THEN
- 3700                                               QbeGen.CtorEnd(q)
- 3701                                             ELSIF braceCls # SymTab.ClSet THEN
- 3702                                               QbeGen.CopyOp("0", q)
- 3703                                             END;
- 3704                                             braceCls := savedCls; .)
- 3705                                          (. astCur := astNode; .) .
- 3706    BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal; node: AST.Node>
- 3707                                          (. VAR et, et2: SymTab.TypeIndex;
- 3708                                               qe, q2: QbeGen.QVal;
- 3709                                               v, v2, reps, k: INTEGER;
- 3710                                               elem: SymTab.TypeIndex;
- 3711                                               lo: INTEGER;
- 3712                                               span: CARDINAL;
- 3713                                               cl, cl2: INTEGER;
- 3714                                               hasR, hasB: BOOLEAN;
- 3715                                               astEl: AST.Node; .)
- 3716      =                                   (. hasR := FALSE; hasB := FALSE; .)
- 3717        Expr<et, qe> (. astEl := astCur; .)
- 3718        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
- 3719                                               AST.NkSubrange, 0, astEl, astCur);
- 3720                                             hasR := TRUE; .) ]
- 3721        [ "BY" Expr<et2, q2>              (. hasB := TRUE; .) ]
- 3722                                          (. IF braceCls = SymTab.ClSet THEN
- 3723                                               IF hasB THEN SemError(230) END;
- 3724                                               lo := SymTab.SetBaseLo(vt);
- 3725                                               span := SymTab.SetCount(vt);
- 3726                                               IF (et = SymTab.InvalidType)
- 3727                                                  OR (hasR AND (et2 =
- 3728                                                     SymTab.InvalidType)) THEN
- 3729                                               ELSE cl :=
- 3730                                                      SymTab.ClassOf(et);
- 3731                                                 IF hasR THEN
- 3732                                                   cl2 :=
- 3733                                                     SymTab.ClassOf(et2)
- 3734                                                 ELSE cl2 := SymTab.ClInt
- 3735                                                 END;
- 3736                                                 IF NOT SymTab.SetElemClassOk(cl)
- 3737                                                    OR (hasR AND NOT
- 3738                                                       SymTab.SetElemClassOk(cl2))
- 3739                                                 THEN
- 3740                                                   SemError(222)
- 3741                                                 ELSIF hasR
- 3742   AND SymTab.ConstInt(qe, v)
- 3743   AND SymTab.ConstInt(q2,
- 3744                                                       v2)
- 3745   AND ((v < lo)
- 3746                                                       OR (v2 < lo)
- 3747                                                       OR (v >= lo +
- 3748                                                          VAL(INTEGER, span))
- 3749                                                       OR (v2 >= lo +
- 3750                                                          VAL(INTEGER, span))
- 3751                                                       OR (v > v2)) THEN
- 3752                                                   SemError(222)
- 3753                                                  ELSIF hasR THEN
- 3754                                                    QbeGen.SetRange(sq, qe, q2,
- 3755                                                      lo, span)
- 3756                                                  ELSIF SymTab.ConstInt(qe,
- 3757                                                          v)
- 3758   AND ((v < lo)
- 3759                                                        OR (v >= lo +
- 3760                                                           VAL(INTEGER,
- 3761                                                             span))) THEN
- 3762                                                    SemError(222)
- 3763                                                  ELSE QbeGen.SetBit(sq, qe,
- 3764                                                    lo, span)
- 3765                                                 END
- 3766                                               END
- 3767                                             ELSIF (braceCls = SymTab.ClArray)
- 3768                                                OR (braceCls =
- 3769                                                   SymTab.ClRecord)
- 3770                                                OR (braceCls =
- 3771                                                   SymTab.ClClass) THEN
- 3772                                               IF hasR THEN SemError(230) END;
- 3773                                               reps := 1;
- 3774                                               IF hasB THEN
- 3775                                                 IF SymTab.ConstInt(q2, v2)
- 3776   AND (v2 >= 1) THEN
- 3777                                                   reps := v2
- 3778                                                 ELSE SemError(230)
- 3779                                                 END
- 3780                                               END;
- 3781                                               k := 0;
- 3782                                               WHILE k < reps DO
- 3783                                                 QbeGen.CtorElem(qe);
- 3784                                                 INC(k)
- 3785                                               END
- 3786                                             END; .)
- 3787                                          (. AST.SetChild(node,
- 3788                                               AST.NChild(node), astEl); .) .
- 3789    SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node>         (. VAR et, et2: SymTab.TypeIndex;
- 3790                                               qe, q2: QbeGen.QVal;
- 3791                                               v, v2: INTEGER;
- 3792                                               lo: INTEGER;
- 3793                                               span: CARDINAL;
- 3794                                               cl, cl2: INTEGER;
- 3795                                               hasR: BOOLEAN;
- 3796                                               astEl: AST.Node; .)
- 3797      =                                   (. hasR := FALSE; .)
- 3798        Expr<et, qe> (. astEl := astCur; .)
- 3799        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
- 3800                                               AST.NkSubrange, 0, astEl, astCur);
- 3801                                             hasR := TRUE; .) ]
- 3802                                          (. lo := SymTab.SetBaseLo(st);
- 3803                                             span := SymTab.SetCount(st);
- 3804                                             IF (et = SymTab.InvalidType)
- 3805                                                OR (hasR AND (et2 =
- 3806                                                   SymTab.InvalidType)) THEN
- 3807                                             ELSE cl :=
- 3808                                                    SymTab.ClassOf(et);
- 3809                                               IF hasR THEN
- 3810                                                 cl2 :=
- 3811                                                   SymTab.ClassOf(et2)
- 3812                                               ELSE cl2 := SymTab.ClInt
- 3813                                               END;
- 3814                                               IF NOT SymTab.SetElemClassOk(cl)
- 3815                                                  OR (hasR AND NOT
- 3816                                                     SymTab.SetElemClassOk(cl2))
- 3817                                               THEN
- 3818                                                 SemError(222)
- 3819                                               ELSIF hasR
- 3820   AND SymTab.ConstInt(qe, v)
- 3821   AND SymTab.ConstInt(q2,
- 3822                                                     v2)
- 3823   AND ((v < lo)
- 3824                                                     OR (v2 < lo)
- 3825                                                     OR (v >= lo +
- 3826                                                        VAL(INTEGER, span))
- 3827                                                     OR (v2 >= lo +
- 3828                                                        VAL(INTEGER, span))
- 3829                                                     OR (v > v2)) THEN
- 3830                                                 SemError(222)
- 3831                                                ELSIF hasR THEN
- 3832                                                  QbeGen.SetRange(sq, qe, q2,
- 3833                                                    lo, span)
- 3834                                                ELSIF SymTab.ConstInt(qe,
- 3835                                                        v)
- 3836   AND ((v < lo)
- 3837                                                      OR (v >= lo +
- 3838                                                         VAL(INTEGER,
- 3839                                                           span))) THEN
- 3840                                                  SemError(222)
- 3841                                                ELSE QbeGen.SetBit(sq, qe,
- 3842                                                  lo, span)
- 3843                                               END
- 3844                                             END; .)
- 3845                                          (. AST.SetChild(node,
- 3846                                               AST.NChild(node), astEl); .) .
- 3847    GetIdent<VAR n: SymTab.Name>
- 3848      = ident                             (. LexName(n); .) .
- 3849  
- 3850  END M2.
+ 3618                                                        SymTab.ClChar)
+ 3619                                                     OR (c2 =
+ 3620                                                        SymTab.ClBool)
+ 3621                                                     OR (c2 =
+ 3622                                                        SymTab.ClEnum)) THEN
+ 3623                                                   t := vt
+ 3624                                                 ELSIF (c1 = SymTab.ClPtr)
+ 3625   AND (c2 = SymTab.ClPtr) THEN
+ 3626                                                   t := vt
+ 3627                                                 ELSIF (c1 = SymTab.ClReal)
+ 3628   AND (c2 = SymTab.ClReal) THEN
+ 3629                                                   t := vt
+ 3630                                                 ELSE SemError(230);
+ 3631                                                   t := SymTab.InvalidType
+ 3632                                                 END
+ 3633                                               END
+ 3634                                             END; .)
+ 3635      | "(" Expr<et, q> ")"               (. t := et; astIsLit := TRUE; .)
+ 3636      | SetLit<st, sq>                    (. astIsLit := TRUE; t := st;
+ 3637                                             QbeGen.CopyOp(sq, q); .)
+ 3638      | ( "NOT" | "~" ) Fact<t2, q2>      (. astNot := astCur;
+ 3639                                             IF SymTab.BoolCheck(t2) THEN
+ 3640                                               t := SymTab.BoolType()
+ 3641                                             ELSE SemError(212);
+ 3642                                               t := SymTab.InvalidType END;
+ 3643                                             IF t # SymTab.InvalidType THEN
+ 3644                                               QbeGen.NotQ(q2, q)
+ 3645                                             ELSE QbeGen.CopyOp("0", q)
+ 3646                                             END;
+ 3647                                             astIsLit := TRUE;
+ 3648                                             astCur := AST.MakeUn(
+ 3649                                               AST.NkUnary, AST.OpNot, astNot); .)
+ 3650      )
+ 3651      (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
+ 3652    (* Set literals are SET OF [0..255] (8 words); elements validated
+ 3653       0..255 statically when foldable (222 otherwise), runtime trap
+ 3654       for computed elements. Ranges always lower via SetRange. *)
+ 3655    SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 3656                                          (. VAR astNode: AST.Node; .)
+ 3657      = "{"                               (. t := SymTab.NewSet(
+ 3658                                               SymTab.NewSubR(0, 255));
+ 3659                                             astNode := AST.MakeNode(AST.NkSetLit);
+ 3660                                             QbeGen.NewSetTemp(8, q);
+ 3661                                             QbeGen.SetZero(q, 8); .)
+ 3662        [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
+ 3663        "}"                               (. astCur := astNode; .) .
+ 3664    (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
+ 3665       or ArrayName{...} (an array constructor, GNU Modula-2).  The
+ 3666       declared type sets the width (set) or element type (array). *)
+ 3667    TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 3668                                          (. VAR nw: CARDINAL;
+ 3669                                               astNode: AST.Node;
+ 3670                                               savedCls: INTEGER; .)
+ 3671      = "{"                               (. savedCls := braceCls;
+ 3672                                             astNode := AST.MakeNode(AST.NkBraceLit);
+ 3673                                             IF vt = SymTab.InvalidType THEN
+ 3674                                               braceCls := -1
+ 3675                                             ELSE braceCls :=
+ 3676                                                    SymTab.ClassOf(vt)
+ 3677                                             END;
+ 3678                                             IF braceCls = SymTab.ClSet THEN
+ 3679                                               IF vt = SymTab.InvalidType THEN
+ 3680                                                 nw := 8
+ 3681                                               ELSE nw := SymTab.SetWords(vt);
+ 3682                                                 IF nw = 0 THEN nw := 8 END
+ 3683                                               END;
+ 3684                                               QbeGen.NewSetTemp(nw, q);
+ 3685                                               QbeGen.SetZero(q, nw)
+ 3686                                             ELSIF (braceCls =
+ 3687                                                    SymTab.ClArray)
+ 3688                                                OR (braceCls =
+ 3689                                                    SymTab.ClRecord)
+ 3690                                                OR (braceCls =
+ 3691                                                    SymTab.ClClass) THEN
+ 3692                                               QbeGen.CtorBegin(vt)
+ 3693                                             ELSE
+ 3694                                               IF vt # SymTab.InvalidType THEN
+ 3695                                                 SemError(230) END;
+ 3696                                               braceCls := -1
+ 3697                                             END; .)
+ 3698        [ BraceElem<vt, q, astNode> { "," BraceElem<vt, q, astNode> } ]
+ 3699        "}"                               (. IF (braceCls = SymTab.ClArray)
+ 3700                                                OR (braceCls =
+ 3701                                                   SymTab.ClRecord)
+ 3702                                                OR (braceCls =
+ 3703                                                   SymTab.ClClass) THEN
+ 3704                                               QbeGen.CtorEnd(q)
+ 3705                                             ELSIF braceCls # SymTab.ClSet THEN
+ 3706                                               QbeGen.CopyOp("0", q)
+ 3707                                             END;
+ 3708                                             braceCls := savedCls; .)
+ 3709                                          (. astCur := astNode; .) .
+ 3710    BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal; node: AST.Node>
+ 3711                                          (. VAR et, et2: SymTab.TypeIndex;
+ 3712                                               qe, q2: QbeGen.QVal;
+ 3713                                               v, v2, reps, k: INTEGER;
+ 3714                                               elem: SymTab.TypeIndex;
+ 3715                                               lo: INTEGER;
+ 3716                                               span: CARDINAL;
+ 3717                                               cl, cl2: INTEGER;
+ 3718                                               hasR, hasB: BOOLEAN;
+ 3719                                               astEl: AST.Node; .)
+ 3720      =                                   (. hasR := FALSE; hasB := FALSE; .)
+ 3721        Expr<et, qe> (. astEl := astCur; .)
+ 3722        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
+ 3723                                               AST.NkSubrange, 0, astEl, astCur);
+ 3724                                             hasR := TRUE; .) ]
+ 3725        [ "BY" Expr<et2, q2>              (. hasB := TRUE; .) ]
+ 3726                                          (. IF braceCls = SymTab.ClSet THEN
+ 3727                                               IF hasB THEN SemError(230) END;
+ 3728                                               lo := SymTab.SetBaseLo(vt);
+ 3729                                               span := SymTab.SetCount(vt);
+ 3730                                               IF (et = SymTab.InvalidType)
+ 3731                                                  OR (hasR AND (et2 =
+ 3732                                                     SymTab.InvalidType)) THEN
+ 3733                                               ELSE cl :=
+ 3734                                                      SymTab.ClassOf(et);
+ 3735                                                 IF hasR THEN
+ 3736                                                   cl2 :=
+ 3737                                                     SymTab.ClassOf(et2)
+ 3738                                                 ELSE cl2 := SymTab.ClInt
+ 3739                                                 END;
+ 3740                                                 IF NOT SymTab.SetElemClassOk(cl)
+ 3741                                                    OR (hasR AND NOT
+ 3742                                                       SymTab.SetElemClassOk(cl2))
+ 3743                                                 THEN
+ 3744                                                   SemError(222)
+ 3745                                                 ELSIF hasR
+ 3746   AND SymTab.ConstInt(qe, v)
+ 3747   AND SymTab.ConstInt(q2,
+ 3748                                                       v2)
+ 3749   AND ((v < lo)
+ 3750                                                       OR (v2 < lo)
+ 3751                                                       OR (v >= lo +
+ 3752                                                          VAL(INTEGER, span))
+ 3753                                                       OR (v2 >= lo +
+ 3754                                                          VAL(INTEGER, span))
+ 3755                                                       OR (v > v2)) THEN
+ 3756                                                   SemError(222)
+ 3757                                                  ELSIF hasR THEN
+ 3758                                                    QbeGen.SetRange(sq, qe, q2,
+ 3759                                                      lo, span)
+ 3760                                                  ELSIF SymTab.ConstInt(qe,
+ 3761                                                          v)
+ 3762   AND ((v < lo)
+ 3763                                                        OR (v >= lo +
+ 3764                                                           VAL(INTEGER,
+ 3765                                                             span))) THEN
+ 3766                                                    SemError(222)
+ 3767                                                  ELSE QbeGen.SetBit(sq, qe,
+ 3768                                                    lo, span)
+ 3769                                                 END
+ 3770                                               END
+ 3771                                             ELSIF (braceCls = SymTab.ClArray)
+ 3772                                                OR (braceCls =
+ 3773                                                   SymTab.ClRecord)
+ 3774                                                OR (braceCls =
+ 3775                                                   SymTab.ClClass) THEN
+ 3776                                               IF hasR THEN SemError(230) END;
+ 3777                                               reps := 1;
+ 3778                                               IF hasB THEN
+ 3779                                                 IF SymTab.ConstInt(q2, v2)
+ 3780   AND (v2 >= 1) THEN
+ 3781                                                   reps := v2
+ 3782                                                 ELSE SemError(230)
+ 3783                                                 END
+ 3784                                               END;
+ 3785                                               k := 0;
+ 3786                                               WHILE k < reps DO
+ 3787                                                 QbeGen.CtorElem(qe);
+ 3788                                                 INC(k)
+ 3789                                               END
+ 3790                                             END; .)
+ 3791                                          (. AST.SetChild(node,
+ 3792                                               AST.NChild(node), astEl); .) .
+ 3793    SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node>         (. VAR et, et2: SymTab.TypeIndex;
+ 3794                                               qe, q2: QbeGen.QVal;
+ 3795                                               v, v2: INTEGER;
+ 3796                                               lo: INTEGER;
+ 3797                                               span: CARDINAL;
+ 3798                                               cl, cl2: INTEGER;
+ 3799                                               hasR: BOOLEAN;
+ 3800                                               astEl: AST.Node; .)
+ 3801      =                                   (. hasR := FALSE; .)
+ 3802        Expr<et, qe> (. astEl := astCur; .)
+ 3803        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
+ 3804                                               AST.NkSubrange, 0, astEl, astCur);
+ 3805                                             hasR := TRUE; .) ]
+ 3806                                          (. lo := SymTab.SetBaseLo(st);
+ 3807                                             span := SymTab.SetCount(st);
+ 3808                                             IF (et = SymTab.InvalidType)
+ 3809                                                OR (hasR AND (et2 =
+ 3810                                                   SymTab.InvalidType)) THEN
+ 3811                                             ELSE cl :=
+ 3812                                                    SymTab.ClassOf(et);
+ 3813                                               IF hasR THEN
+ 3814                                                 cl2 :=
+ 3815                                                   SymTab.ClassOf(et2)
+ 3816                                               ELSE cl2 := SymTab.ClInt
+ 3817                                               END;
+ 3818                                               IF NOT SymTab.SetElemClassOk(cl)
+ 3819                                                  OR (hasR AND NOT
+ 3820                                                     SymTab.SetElemClassOk(cl2))
+ 3821                                               THEN
+ 3822                                                 SemError(222)
+ 3823                                               ELSIF hasR
+ 3824   AND SymTab.ConstInt(qe, v)
+ 3825   AND SymTab.ConstInt(q2,
+ 3826                                                     v2)
+ 3827   AND ((v < lo)
+ 3828                                                     OR (v2 < lo)
+ 3829                                                     OR (v >= lo +
+ 3830                                                        VAL(INTEGER, span))
+ 3831                                                     OR (v2 >= lo +
+ 3832                                                        VAL(INTEGER, span))
+ 3833                                                     OR (v > v2)) THEN
+ 3834                                                 SemError(222)
+ 3835                                                ELSIF hasR THEN
+ 3836                                                  QbeGen.SetRange(sq, qe, q2,
+ 3837                                                    lo, span)
+ 3838                                                ELSIF SymTab.ConstInt(qe,
+ 3839                                                        v)
+ 3840   AND ((v < lo)
+ 3841                                                      OR (v >= lo +
+ 3842                                                         VAL(INTEGER,
+ 3843                                                           span))) THEN
+ 3844                                                  SemError(222)
+ 3845                                                ELSE QbeGen.SetBit(sq, qe,
+ 3846                                                  lo, span)
+ 3847                                               END
+ 3848                                             END; .)
+ 3849                                          (. AST.SetChild(node,
+ 3850                                               AST.NChild(node), astEl); .) .
+ 3851    GetIdent<VAR n: SymTab.Name>
+ 3852      = ident                             (. LexName(n); .) .
+ 3853  
+ 3854  END M2.
 
     0 errors