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

resolve-check step 3: forward operand is InvalidType; drop IsFwdVar

The forward-reference placeholder (a fresh alias) existed only so the
type checks could recognise it (IsFwdVar) and be lenient.  Make the
forward operand InvalidType instead: the existing 'skip checks on an
unknown type' rule (Assignable/ArithCheck/EqCheck/OrdCheck all return
early on InvalidType) does the same job, so the placeholder and the
whole IsFwdVar mechanism go:

- FwdVarRef no longer allocates a placeholder alias (t := InvalidType);
  the fwdVarT table and FwdVarType/IsFwdVar are removed, and
  FwdVarResolve only reports whether the name now exists.
- the four IsFwdVar guards and the one in the grammar's relation check
  are removed.

Behaviour: a forward reference still compiles (now typed as unknown
rather than assumed INTEGER/pointer); a never-declared name is still
201.  Suite 190/190; fixpoint OK (3,466,859 bytes); default vs
-noresolve byte-identical on forward-free code.
Eric Streit 3 дней назад
Родитель
Сommit
7ca434b449
6 измененных файлов с 933 добавлено и 959 удалено
  1. 1 1
      compiler/src/Check.def
  2. 1 1
      compiler/src/Check.mod
  3. 4 6
      compiler/src/M2.atg
  4. 920 922
      compiler/src/M2.lst
  5. 1 3
      compiler/src/SymTab.def
  6. 6 26
      compiler/src/SymTab.mod

+ 1 - 1
compiler/src/Check.def

@@ -13,7 +13,7 @@ PROCEDURE BeginSession (progName: ARRAY OF CHAR);
 PROCEDURE BeginUnit;
 PROCEDURE BeginUnit;
 (* Per-unit setup (called before Parse). *)
 (* Per-unit setup (called before Parse). *)
 
 
-PROCEDURE NoteForward (id, slot: INTEGER);
+PROCEDURE NoteForward (id: INTEGER);
 (* Records a forward module-level reference noted by the parser (Design);
 (* Records a forward module-level reference noted by the parser (Design);
    FlushForward resolves it once the unit's declarations are complete. *)
    FlushForward resolves it once the unit's declarations are complete. *)
 
 

+ 1 - 1
compiler/src/Check.mod

@@ -24,7 +24,7 @@ PROCEDURE BeginUnit;
 BEGIN
 BEGIN
 END BeginUnit;
 END BeginUnit;
 
 
-PROCEDURE NoteForward (id, slot: INTEGER);
+PROCEDURE NoteForward (id: INTEGER);
 (* Records a forward reference id noted during parse. *)
 (* Records a forward reference id noted during parse. *)
 BEGIN
 BEGIN
   IF nFwd <= HIGH(fwdId) THEN
   IF nFwd <= HIGH(fwdId) THEN

+ 4 - 6
compiler/src/M2.atg

@@ -2127,14 +2127,14 @@ PRODUCTIONS
                                              fo: INTEGER;
                                              fo: INTEGER;
                                              isOpen: BOOLEAN;
                                              isOpen: BOOLEAN;
                                              qb, cv: QbeGen.QVal;
                                              qb, cv: QbeGen.QVal;
-                                             fid, fref, slot: INTEGER;
+                                             fid, fref: INTEGER;
                                              r: BOOLEAN;
                                              r: BOOLEAN;
                                               astDes, astSel: AST.Node;
                                               astDes, astSel: AST.Node;
                                              fwd: BOOLEAN; .)
                                              fwd: BOOLEAN; .)
     =                                   (. methCls := SymTab.InvalidType;
     =                                   (. methCls := SymTab.InvalidType;
                                            QbeGen.CopyOp(n, qn);
                                            QbeGen.CopyOp(n, qn);
                                            sfx := FALSE; fwd := FALSE;
                                            sfx := FALSE; fwd := FALSE;
-                                           fid := 0; fref := 0; slot := 0;
+                                           fid := 0; fref := 0;
                                            IF NOT SymTab.Lookup(n) THEN
                                            IF NOT SymTab.Lookup(n) THEN
                                              (* a bare method name inside
                                              (* a bare method name inside
                                                 a CLASS IMPLEMENTATION
                                                 a CLASS IMPLEMENTATION
@@ -2157,7 +2157,7 @@ PRODUCTIONS
                                                k := SymTab.KindVar;
                                                k := SymTab.KindVar;
                                                r := SymTab.FwdVarRef(n, k,
                                                r := SymTab.FwdVarRef(n, k,
                                                  fref, t);
                                                  fref, t);
-                                                Check.NoteForward(fref, 0);
+                                                Check.NoteForward(fref);
                                                 QbeGen.CopyOp("@", q);
                                                 QbeGen.CopyOp("@", q);
                                                sfx := TRUE; fwd := TRUE
                                                sfx := TRUE; fwd := TRUE
                                              ELSE
                                              ELSE
@@ -2518,9 +2518,7 @@ PRODUCTIONS
                t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
                t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
              ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
              ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
                 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
                 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
-                IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
-                  t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
-               ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
+               IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
  AND (op # SymTab.OpNeq2) THEN
  AND (op # SymTab.OpNeq2) THEN
                  SemError(213); t := SymTab.InvalidType;
                  SemError(213); t := SymTab.InvalidType;
                  QbeGen.CopyOp("0", q)
                  QbeGen.CopyOp("0", q)

+ 920 - 922
compiler/src/M2.lst

@@ -2146,14 +2146,14 @@ Listing:
  2127                                               fo: INTEGER;
  2127                                               fo: INTEGER;
  2128                                               isOpen: BOOLEAN;
  2128                                               isOpen: BOOLEAN;
  2129                                               qb, cv: QbeGen.QVal;
  2129                                               qb, cv: QbeGen.QVal;
- 2130                                               fid, fref, slot: INTEGER;
+ 2130                                               fid, fref: INTEGER;
  2131                                               r: BOOLEAN;
  2131                                               r: BOOLEAN;
  2132                                                astDes, astSel: AST.Node;
  2132                                                astDes, astSel: AST.Node;
  2133                                               fwd: BOOLEAN; .)
  2133                                               fwd: BOOLEAN; .)
  2134      =                                   (. methCls := SymTab.InvalidType;
  2134      =                                   (. methCls := SymTab.InvalidType;
  2135                                             QbeGen.CopyOp(n, qn);
  2135                                             QbeGen.CopyOp(n, qn);
  2136                                             sfx := FALSE; fwd := FALSE;
  2136                                             sfx := FALSE; fwd := FALSE;
- 2137                                             fid := 0; fref := 0; slot := 0;
+ 2137                                             fid := 0; fref := 0;
  2138                                             IF NOT SymTab.Lookup(n) THEN
  2138                                             IF NOT SymTab.Lookup(n) THEN
  2139                                               (* a bare method name inside
  2139                                               (* a bare method name inside
  2140                                                  a CLASS IMPLEMENTATION
  2140                                                  a CLASS IMPLEMENTATION
@@ -2176,7 +2176,7 @@ Listing:
  2157                                                 k := SymTab.KindVar;
  2157                                                 k := SymTab.KindVar;
  2158                                                 r := SymTab.FwdVarRef(n, k,
  2158                                                 r := SymTab.FwdVarRef(n, k,
  2159                                                   fref, t);
  2159                                                   fref, t);
- 2160                                                  Check.NoteForward(fref, 0);
+ 2160                                                  Check.NoteForward(fref);
  2161                                                  QbeGen.CopyOp("@", q);
  2161                                                  QbeGen.CopyOp("@", q);
  2162                                                 sfx := TRUE; fwd := TRUE
  2162                                                 sfx := TRUE; fwd := TRUE
  2163                                               ELSE
  2163                                               ELSE
@@ -2537,935 +2537,933 @@ Listing:
  2518                 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  2518                 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  2519               ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
  2519               ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
  2520                  OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
  2520                  OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
- 2521                  IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
- 2522                    t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
- 2523                 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
- 2524   AND (op # SymTab.OpNeq2) THEN
- 2525                   SemError(213); t := SymTab.InvalidType;
- 2526                   QbeGen.CopyOp("0", q)
- 2527                  ELSE
- 2528                    t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
- 2529                  END
- 2530                ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
- 2531                   OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 2532                  t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
- 2533               ELSIF SymTab.StrCompat(t, t2) THEN
- 2534                 QbeGen.StrEq(op, q, q2, qt);
- 2535                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
- 2536               ELSIF SymTab.IsLongFamily(t)
- 2537                  OR SymTab.IsLongFamily(t2) THEN
- 2538                  t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
- 2539                ELSE
- 2540                  t := SymTab.BoolType();
- 2541                  QbeGen.CopyOp("@", q)
- 2542                END
- 2543             ELSE SemError(213); t := SymTab.InvalidType;
- 2544                QbeGen.CopyOp("0", q)
- 2545              END;
- 2546              astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
- 2547         (. IF NOT astMade THEN astCur := astA END; .) .
- 2548    Rel<VAR op: INTEGER>
- 2549      = "="                               (. op := SymTab.OpEq; .)
- 2550      | "#"                               (. op := SymTab.OpNeq1; .)
- 2551      | "<"                               (. op := SymTab.OpLt; .)
- 2552      | "<="                              (. op := SymTab.OpLe; .)
- 2553      | ">"                               (. op := SymTab.OpGt; .)
- 2554      | ">="                              (. op := SymTab.OpGe; .)
- 2555      | "IN"                              (. op := SymTab.OpIn; .) .
- 2556    SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 2557                                          (. VAR t2, res2, lt, rt:
- 2558                                                 SymTab.TypeIndex;
- 2559                                               op: INTEGER;
- 2560                                               q2, qt, wq, qf, q2a, q2b:
- 2561                                                 QbeGen.QVal;
- 2562                                               neg, isR, isL, folded:
- 2563                                                 BOOLEAN;
- 2564                                               fok: BOOLEAN;
- 2565                                               lw, rw, mw: CARDINAL;
- 2566                                               lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
- 2567                                                astA, astB: AST.Node;
- 2568                                                astSign, astOp: INTEGER; .)
- 2569      =                                   (. neg := FALSE; astSign := 0; .)
- 2570        [ "+"                         (. neg := TRUE; astSign := 1; .)
- 2571        | "-"                         (. neg := TRUE; astSign := -1; .) ]
- 2572        Term<t, q> (. astA := astCur;
- 2573                                            IF neg AND QbeGen.IsImm(q) THEN
- 2574                                              QbeGen.NegFold(q, q)
- 2575                                            END;
- 2576                                           IF astSign < 0 THEN
- 2577                                             astCur := AST.MakeUn(
- 2578                                               AST.NkUnary, AST.OpSub, astA);
- 2579                                             astA := astCur
- 2580                                           END; .)
- 2581         { AddOp<op>
- 2582           Term<t2, q2> (. astB := astCur; .)
- 2583          (. astOp := AST.OpAdd;
- 2584             IF op = SymTab.OpSub THEN astOp := AST.OpSub
- 2585             ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
- 2586             astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
- 2587             astCur := astA;
- 2588             IF op = SymTab.OpOr THEN
- 2589               (* short-circuit: if q is true the RHS is skipped *)
- 2590               IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
- 2591                 t := SymTab.BoolType()
- 2592               ELSE SemError(212); t := SymTab.InvalidType END;
- 2593                IF t # SymTab.InvalidType THEN
- 2594                  QbeGen.CopyOp("@", q)
- 2595                ELSE QbeGen.CopyOp("0", q)
- 2596                END
- 2597             ELSIF (op = SymTab.OpAdd)
- 2598               AND (SymTab.UStrCompat(t, t2)
- 2599                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
- 2600                   AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
- 2601                 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
- 2602                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
- 2603                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
- 2604                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
- 2605               (* UString concatenation: a UCHAR operand becomes a
- 2606                  1-codepoint UString; the result is a descriptor in the
- 2607                  shim's concat buffer.  Work on copies so neither
- 2608                  operand is clobbered. *)
- 2609                t := SymTab.NewUStr();
- 2610                QbeGen.CopyOp("@", q)
- 2611             ELSIF (op = SymTab.OpAdd)
- 2612               AND (SymTab.StrCompat(t, t2)
- 2613                 OR (SymTab.IsStrType(t)
- 2614                   AND (SymTab.ClassOf(t2) = SymTab.ClChar))
- 2615                 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
- 2616                   AND SymTab.IsStrType(t2))) THEN
- 2617               (* string concatenation; a CHAR operand becomes a
- 2618                  1-character string literal.  When both operands are
- 2619                  constants, fold to a single string literal so a
- 2620                  constructor element stays compile-time. *)
- 2621                QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
- 2622                  qt, fok);
- 2623                IF fok THEN QbeGen.CopyOp(qt, q)
- 2624                ELSE QbeGen.CopyOp("@", q)
- 2625                END;
- 2626                t := SymTab.NewStr()
- 2627             ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
- 2628   AND (SymTab.ClassOf(t) = SymTab.ClSet)
- 2629   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 2630                lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
- 2631                mw := lw;
- 2632                IF rw > mw THEN mw := rw END;
- 2633                t := SymTab.NewSet(
- 2634                       SymTab.NewSubR(0,
- 2635                         VAL(INTEGER, mw) * 32 - 1));
- 2636                QbeGen.CopyOp("@", q)
- 2637             ELSE
- 2638               IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
- 2639                 lt := t; rt := t2; t := res2
- 2640               ELSE SemError(211); t := SymTab.InvalidType END;
- 2641               IF t # SymTab.InvalidType THEN
- 2642                 isL := SymTab.IsLongFamily(t);
- 2643                 isR := SymTab.ClassOf(t) = SymTab.ClReal;
- 2644                 folded := FALSE;
- 2645                 IF (NOT isL) AND (NOT isR)
- 2646    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
- 2647                   IF op = SymTab.OpAdd THEN
- 2648                     folded := QbeGen.Fold2(0, q, q2, qf)
- 2649                   ELSE
- 2650                     folded := QbeGen.Fold2(1, q, q2, qf)
- 2651                   END
- 2652                 END;
- 2653                 IF folded THEN QbeGen.CopyOp(qf, q)
- 2654                  ELSE
- 2655                  QbeGen.CopyOp("@", q)
- 2656                  END
- 2657               ELSE QbeGen.CopyOp("0", q)
- 2658               END
- 2659             END; .) } .
- 2660    AddOp<VAR op: INTEGER>
- 2661      = "+"                               (. op := SymTab.OpAdd; .)
- 2662      | "-"                               (. op := SymTab.OpSub; .)
- 2663      | "OR"                              (. op := SymTab.OpOr; .) .
- 2664    Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 2665                                          (. VAR t2, res2, lt, rt:
- 2666                                                 SymTab.TypeIndex;
- 2667                                               op: INTEGER;
- 2668                                               q2, qt, wq, qf:
- 2669                                                 QbeGen.QVal;
- 2670                                               isR, isL, folded: BOOLEAN;
- 2671                                               lw, rw, mw: CARDINAL;
- 2672                                               lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
- 2673                                                astA, astB: AST.Node;
- 2674                                                astOp: INTEGER; .)
- 2675      = Fact<t, q> (. astA := astCur; .) { MulOp<op>
- 2676          Fact<t2, q2> (. astB := astCur; .)
- 2677        (. astOp := AST.OpMul;
- 2678           IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
- 2679           ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
- 2680           ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
- 2681           ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
- 2682           astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
- 2683           astCur := astA;
- 2684           IF op = SymTab.OpAnd THEN
- 2685             (* short-circuit: if q is false the RHS is skipped *)
- 2686             IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
- 2687               t := SymTab.BoolType()
- 2688             ELSE SemError(212); t := SymTab.InvalidType END;
- 2689              IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
- 2690              ELSE QbeGen.CopyOp("0", q)
- 2691              END
- 2692           ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
- 2693   AND (SymTab.ClassOf(t) = SymTab.ClSet)
- 2694   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
- 2695              lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
- 2696              mw := lw;
- 2697              IF rw > mw THEN mw := rw END;
- 2698              t := SymTab.NewSet(
- 2699                     SymTab.NewSubR(0,
- 2700                       VAL(INTEGER, mw) * 32 - 1));
- 2701              QbeGen.CopyOp("@", q)
- 2702           ELSE
- 2703             IF SymTab.ArithCheck(t, t2,
- 2704                  (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
- 2705                  res2) THEN
- 2706               lt := t; rt := t2; t := res2
- 2707             ELSE SemError(211); t := SymTab.InvalidType END;
- 2708             IF t # SymTab.InvalidType THEN
- 2709               isL := SymTab.IsLongFamily(t);
- 2710               isR := SymTab.ClassOf(t) = SymTab.ClReal;
- 2711               folded := FALSE;
- 2712               IF (NOT isL) AND (NOT isR)
- 2713    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
- 2714                 IF op = SymTab.OpTimes THEN
- 2715                   folded := QbeGen.Fold2(2, q, q2, qf)
- 2716                 ELSIF op = SymTab.OpDiv THEN
- 2717                   folded := QbeGen.Fold2(3, q, q2, qf)
- 2718                 ELSIF op = SymTab.OpMod THEN
- 2719                   folded := QbeGen.Fold2(4, q, q2, qf)
- 2720                 END
- 2721               END;
- 2722               IF folded THEN QbeGen.CopyOp(qf, q)
- 2723                ELSE
- 2724                QbeGen.CopyOp("@", q)
- 2725                END
- 2726             ELSE QbeGen.CopyOp("0", q)
- 2727             END
- 2728           END; .) } .
- 2729    MulOp<VAR op: INTEGER>
- 2730      = "*"                               (. op := SymTab.OpTimes; .)
- 2731      | "/"                               (. op := SymTab.OpSlash; .)
- 2732      | "DIV"                             (. op := SymTab.OpDiv; .)
- 2733      | "MOD"                             (. op := SymTab.OpMod; .)
- 2734      | ( "AND" | "&" )                   (. op := SymTab.OpAnd; .) .
- 2735    Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 2736                                          (. VAR s: ARRAY [0 .. 255] OF CHAR;
- 2737                                               et, dt, t2, st, ct2, et2:
- 2738                                                 SymTab.TypeIndex;
- 2739                                               dk: INTEGER;
- 2740                                               qd, q2, sq, qa, qm0, qr, qt:
- 2741                                                 QbeGen.QVal;
- 2742                                               qn, vn: SymTab.Name;
- 2743                                               vt: SymTab.TypeIndex;
- 2744                                               c1, c2: INTEGER;
- 2745                                               lo, hi: INTEGER;
- 2746                                               isMax: BOOLEAN;
- 2747                                               called, isHigh, sfx, isCh,
- 2748                                               isU, uok, isStr: BOOLEAN;
- 2749                                               ucp: INTEGER; astIsLit: BOOLEAN;
- 2750                                                astD: AST.Node;
- 2751                                                astCall: BOOLEAN;
- 2752                                                astNode, astNot: AST.Node;
- 2753                                                j: CARDINAL;
- 2754                                                astArg2: AST.Node;
- 2755                                                astBrace: AST.Node;
- 2756                                                astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
- 2757      = (. astIsLit := FALSE; .)
- 2758      ( integer                           (. LexString(s);
- 2759                                             QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
- 2760                                             t := SymTab.IntType(); .)
- 2761      | charConst                         (. LexString(s);
- 2762                                             QbeGen.NormLit(s, q, isCh);
- 2763                                             IF twoPhase THEN
- 2764                                               astIsLit := TRUE;
- 2765                                               astCur := AST.MakeLeaf(
- 2766                                                 AST.NkCharLit, s)
- 2767                                             END;
- 2768                                             t := SymTab.CharType(); .)
- 2769      | real                              (. LexString(s);
- 2770                                             QbeGen.NormReal(s, q);
- 2771                                             IF twoPhase THEN
- 2772                                               astIsLit := TRUE;
- 2773                                               astCur := AST.MakeLeaf(
- 2774                                                 AST.NkRealLit, s)
- 2775                                             END;
- 2776                                             t := SymTab.RealType(); .)
- 2777      | string                            (. LexString(s);
- 2778                                             IF twoPhase THEN
- 2779                                               astIsLit := TRUE;
- 2780                                               astCur := AST.MakeLeaf(
- 2781                                                 AST.NkStrLit, s)
- 2782                                             END;
- 2783                                             IF SymTab.StrLen(s) = 3 THEN
- 2784                                               t := SymTab.CharType();
- 2785                                               QbeGen.IntStr(
- 2786                                                 QbeGen.CharVal(s), q)
- 2787                                             ELSE t := SymTab.NewStr();
- 2788                                               QbeGen.DeclStr(s, q);
- 2789                                               (* a literal's value IS its
- 2790                                                  static descriptor address *)
- 2791                                             END; .)
- 2792      | ustring                           (. LexString(s);
- 2793                                             IF twoPhase THEN
- 2794                                               astIsLit := TRUE;
- 2795                                               astCur := AST.MakeLeaf(
- 2796                                                 AST.NkStrLit, s)
- 2797                                             END;
- 2798                                             QbeGen.DeclUStr(s, q, isU, ucp,
- 2799                                               uok);
- 2800                                             IF NOT uok THEN
- 2801                                               SemError(234);
- 2802                                               t := SymTab.InvalidType
- 2803                                             ELSIF isU THEN
- 2804                                               t := SymTab.UCharType();
- 2805                                               QbeGen.IntStr(ucp, q)
- 2806                                             ELSE
- 2807                                               t := SymTab.NewUStr();
- 2808                                             END; .)
- 2809      | Design<dt, dk, qd, qn, sfx>       (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
- 2810                                             astNArgs := 0; called := FALSE;
- 2811                                             t := dt;
- 2812                                             IF dk = SymTab.KindConst THEN
- 2813                                               QbeGen.CopyOp(qd, q)
- 2814                                             ELSE QbeGen.CopyOp("@", q)
- 2815                                             END; .)
- 2816        [ TypedBraceLit<dt, q>            (. t := dt; astCall := TRUE;
- 2817                                               astBrace := astCur; .) ]
- 2818        [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
- 2819                                          (. astCall := TRUE;
- 2820                                             astNode := AstCallNode(astD);
- 2821                                             astRes := astNode;
- 2822                                             t := ct2;
- 2823                                             QbeGen.CopyOp(q2, q);
- 2824                                             sfx := FALSE; .)
- 2825          { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
- 2826            [ (. astNArgs := 0; .)
- 2827              ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
- 2828                                          (. astNode := AstCallNode(astRes);
- 2829                                             astRes := astNode;
- 2830                                             t := ct2;
- 2831                                             QbeGen.CopyOp(q2, q);
- 2832                                             sfx := FALSE; .) ] }
- 2833                                          (. IF sfx THEN
- 2834                                               IF t = SymTab.InvalidType THEN
- 2835                                                 QbeGen.CopyOp("0", q)
- 2836                                               ELSIF (SymTab.ClassOf(t) #
- 2837                                                      SymTab.ClRecord)
- 2838    AND (SymTab.ClassOf(t) # SymTab.ClSet)
- 2839    AND (SymTab.ClassOf(t) # SymTab.ClArray)
- 2840    AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
- 2841                                                  QbeGen.CopyOp("@", q)
- 2842                                               END
- 2843                                             END; .) ]
- 2844                                          (. IF called THEN
- 2845                                               astCur := astRes
- 2846                                             ELSIF astCall THEN
- 2847                                               astCur := astBrace
- 2848                                             ELSE astCur := astD
- 2849                                             END;
- 2850                                              astIsLit := TRUE;
- 2851                                              IF NOT called
- 2852   AND (dk = SymTab.KindProc) THEN
- 2853                                               (* bare zero-arg function
- 2854                                                  call (parentheses may be
- 2855                                                  omitted); a proper or
- 2856                                                  parameterised proc here
- 2857                                                  is 230 *)
- 2858                                                IF (SymTab.ProcNPar(qn) = 0)
- 2859   AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
- 2860                                                  t := SymTab.ProcRes(qn);
- 2861                                                  QbeGen.CopyOp("@", q);
- 2862                                                  astCur := AST.MakeNode(AST.NkCall);
- 2863                                                  AST.SetChild(astCur, 0, astD)
- 2864                                                ELSE
- 2865                                                  t := SymTab.ProcTypeOf(qn);
- 2866                                                  QbeGen.CopyOp("@", q)
- 2867                                                END
- 2868                                             END; .)
- 2869      | ( "HIGH"                          (. isHigh := TRUE; .)
- 2870        | ( "LEN" | "LENGTH" )            (. isHigh := FALSE; .) )
- 2871        "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
- 2872                                              isU := FALSE; .)
- 2873            | string                       (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
- 2874                                              isStr := TRUE;
- 2875                                              isU := FALSE;
- 2876                                              IF SymTab.StrLen(s) = 3 THEN
- 2877                                                dt := SymTab.CharType();
- 2878                                                QbeGen.IntStr(QbeGen.CharVal(s),
- 2879                                                  qd)
- 2880                                              ELSE
- 2881                                                dt := SymTab.NewStr();
- 2882                                                QbeGen.DeclStr(s, qd);
- 2883                                              END;
- 2884                                              dk := -1;
- 2885                                              qn[0] := CHR(0); .)
- 2886            | ustring                      (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
- 2887                                              QbeGen.DeclUStr(s, qd, isU, ucp,
- 2888                                                uok);
- 2889                                              isStr := FALSE;
- 2890                                              IF NOT uok THEN
- 2891                                                SemError(234);
- 2892                                                dt := SymTab.InvalidType
- 2893                                              ELSIF isU THEN
- 2894                                                (* one codepoint: a UCHAR;
- 2895                                                   LEN is 1, HIGH is 0 *)
- 2896                                                dt := SymTab.UCharType();
- 2897                                                QbeGen.IntStr(ucp, qd)
- 2898                                              ELSE
- 2899                                                dt := SymTab.NewUStr();
- 2900                                              END;
- 2901                                              dk := -1;
- 2902                                              qn[0] := CHR(0); .) )
- 2903        ")"
- 2904                                          (. astNode := AST.MakeNode(AST.NkCall);
- 2905     IF isHigh THEN AST.SetChild(astNode, 0,
- 2906       AST.MakeLeaf(AST.NkIdent, "HIGH"))
- 2907     ELSE AST.SetChild(astNode, 0,
- 2908       AST.MakeLeaf(AST.NkIdent, "LEN")) END;
- 2909     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 2910     astCur := astNode; astIsLit := TRUE;
- 2911                                             IF (dt # SymTab.InvalidType)
- 2912    AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
- 2913                                               (* UString: the count is
- 2914                                                  the descriptor header *)
- 2915                                                t := SymTab.IntType();
- 2916                                                QbeGen.CopyOp("@", q)
- 2917                                             ELSIF (dt # SymTab.InvalidType)
- 2918    AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
- 2919                                               (* single UCHAR codepoint *)
- 2920                                               IF isHigh THEN
- 2921                                                 QbeGen.CopyOp("0", qr)
- 2922                                               ELSE
- 2923                                                 QbeGen.CopyOp("1", qr)
- 2924                                               END;
- 2925                                               t := SymTab.IntType();
- 2926                                               QbeGen.CopyOp(qr, q)
- 2927                                             ELSIF isStr THEN
- 2928                                               (* fold: content length at
- 2929                                                  compile time *)
- 2930                                               IF SymTab.StrLen(s) = 3 THEN
- 2931                                                 c1 := 1
- 2932                                               ELSE
- 2933                                                 c1 :=
- 2934                                                   SymTab.StrLen(s) - 2
- 2935                                               END;
- 2936                                               IF isHigh THEN
- 2937                                                 DEC(c1)
- 2938                                               END;
- 2939                                               QbeGen.IntStr(c1, qr);
- 2940                                               t := SymTab.IntType();
- 2941                                               QbeGen.CopyOp(qr, q)
- 2942                                             ELSIF dt = SymTab.InvalidType THEN
- 2943                                               t := SymTab.InvalidType;
- 2944                                               QbeGen.CopyOp("0", q)
- 2945                                             ELSIF SymTab.ClassOf(dt) #
- 2946                                                   SymTab.ClArray THEN
- 2947                                               SemError(217);
- 2948                                               t := SymTab.InvalidType;
- 2949                                               QbeGen.CopyOp("0", q)
- 2950                                             ELSE
- 2951                                                IF SymTab.IsOpenArray(dt) THEN
- 2952                                                  t := SymTab.IntType();
- 2953                                                  QbeGen.CopyOp("@", q)
- 2954                                                ELSE
- 2955                                                  IF isHigh THEN
- 2956                                                    QbeGen.IntStr(
- 2957                                                      SymTab.ArrayHi(dt), qr)
- 2958                                                  ELSE
- 2959                                                    QbeGen.IntStr(VAL(
- 2960                                                      INTEGER,
- 2961                                                      SymTab.ArrayLen(dt)),
- 2962                                                      qr)
- 2963                                                  END;
- 2964                                                  t := SymTab.IntType();
- 2965                                                  QbeGen.CopyOp(qr, q)
- 2966                                                END
- 2967                                              END; .)
- 2968      | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
- 2969      (. astNode := AST.MakeNode(AST.NkCall);
- 2970     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
- 2971     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 2972     astCur := astNode; astIsLit := TRUE; .)
- 2973                                          (. IF dt = SymTab.InvalidType THEN
- 2974                                               t := SymTab.InvalidType;
- 2975                                               QbeGen.CopyOp("0", q)
- 2976                                             ELSE
- 2977                                               QbeGen.IntStr(VAL(INTEGER,
- 2978                                                 SymTab.ObjectSize(dt)), q);
- 2979                                               t := SymTab.IntType()
- 2980                                             END; .)
- 2981      | ( "SHIFT"                         (. isMax := FALSE; .)
- 2982        | "ROTATE"                        (. isMax := TRUE; .) )
- 2983        "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
- 2984                                          (. astNode := AST.MakeNode(AST.NkCall);
- 2985     IF isMax THEN AST.SetChild(astNode, 0,
- 2986       AST.MakeLeaf(AST.NkIdent, "ROTATE"))
- 2987     ELSE AST.SetChild(astNode, 0,
- 2988       AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
- 2989     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
- 2990     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
- 2991     astCur := astNode; astIsLit := TRUE;
- 2992                                             (* set shift/rotate: isMax
- 2993                                                doubles as "rotate" *)
- 2994                                             IF (et # SymTab.InvalidType)
- 2995                                                AND (SymTab.ClassOf(et) =
- 2996                                                   SymTab.ClSet) THEN
- 2997                                                t := et;
- 2998                                                QbeGen.CopyOp("@", q)
- 2999                                             ELSE SemError(230);
- 3000                                               t := SymTab.InvalidType;
- 3001                                               QbeGen.CopyOp("0", q)
- 3002                                             END; .)
- 3003      | ( "MIN"                           (. isMax := FALSE; .)
- 3004        | "MAX"                           (. isMax := TRUE; .) )
- 3005        "(" Design<dt, dk, qd, qn, sfx> ")"
- 3006                                          (. astNode := AST.MakeNode(AST.NkCall);
- 3007     IF isMax THEN AST.SetChild(astNode, 0,
- 3008       AST.MakeLeaf(AST.NkIdent, "MAX"))
- 3009     ELSE AST.SetChild(astNode, 0,
- 3010       AST.MakeLeaf(AST.NkIdent, "MIN")) END;
- 3011     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3012     astCur := astNode; astIsLit := TRUE;
- 3013                                             IF (dt # SymTab.InvalidType)
- 3014   AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
- 3015                                               (* REAL/LONGREAL: the
- 3016                                                  implementation bounds *)
- 3017                                               IF isMax THEN
- 3018                                                 QbeGen.NormReal(
- 3019                                                   "3.402823e38", q)
- 3020                                               ELSE QbeGen.NormReal(
- 3021                                                   "-3.402823e38", q)
- 3022                                               END;
- 3023                                               t := SymTab.RealType()
- 3024                                             ELSIF (dt #
- 3025                                                SymTab.InvalidType)
- 3026   AND (SymTab.ClassOf(dt) =
- 3027                                                   SymTab.ClLong) THEN
- 3028                                               IF isMax THEN
- 3029                                                 QbeGen.CopyOp(
- 3030                                                   "9223372036854775807", q)
- 3031                                               ELSE QbeGen.CopyOp(
- 3032                                                   "-9223372036854775808", q)
- 3033                                               END;
- 3034                                               t := SymTab.LongType()
- 3035                                             ELSIF SymTab.TypeBounds(dt, lo,
- 3036                                                      hi) THEN
- 3037                                               IF isMax THEN
- 3038                                                 QbeGen.IntStr(hi, q)
- 3039                                               ELSE QbeGen.IntStr(lo, q)
- 3040                                               END;
- 3041                                               t := SymTab.IntType()
- 3042                                             ELSE SemError(230);
- 3043                                               t := SymTab.InvalidType;
- 3044                                               QbeGen.CopyOp("0", q)
- 3045                                             END; .)
- 3046      | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
- 3047      (. astNode := AST.MakeNode(AST.NkCall);
- 3048     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
- 3049     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3050     astCur := astNode; astIsLit := TRUE; .)
- 3051                                          (. IF dt = SymTab.InvalidType THEN
- 3052                                               t := SymTab.InvalidType;
- 3053                                               QbeGen.CopyOp("0", q)
- 3054                                             ELSE
- 3055                                                IF sfx
- 3056                                                   OR (dk = SymTab.KindVar)
- 3057                                                   OR (dk = SymTab.KindParam) THEN
- 3058                                                  QbeGen.CopyOp("@", q)
- 3059                                                ELSE SemError(230);
- 3060                                                  QbeGen.CopyOp("0", q)
- 3061                                                END;
- 3062                                               t := SymTab.AddrType()
- 3063                                             END; .)
- 3064      | "CHR" "(" Expr<et, q> ")"
- 3065      (. astNode := AST.MakeNode(AST.NkCall);
- 3066     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
- 3067     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3068     astCur := astNode; astIsLit := TRUE; .)
- 3069                                          (. IF (et # SymTab.InvalidType)
- 3070   AND NOT SymTab.IsIntFamily(et) THEN
- 3071                                               SemError(211) END;
- 3072                                             t := SymTab.CharType(); .)
- 3073      | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
- 3074      (. astNode := AST.MakeNode(AST.NkCall);
- 3075     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
- 3076     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3077     astCur := astNode; astIsLit := TRUE; .)
- 3078                                          (. IF et # SymTab.InvalidType THEN
- 3079                                               IF (SymTab.ClassOf(et) #
- 3080                                                   SymTab.ClChar)
+ 2521                 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
+ 2522   AND (op # SymTab.OpNeq2) THEN
+ 2523                   SemError(213); t := SymTab.InvalidType;
+ 2524                   QbeGen.CopyOp("0", q)
+ 2525                  ELSE
+ 2526                    t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
+ 2527                  END
+ 2528                ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
+ 2529                   OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 2530                  t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
+ 2531               ELSIF SymTab.StrCompat(t, t2) THEN
+ 2532                 QbeGen.StrEq(op, q, q2, qt);
+ 2533                 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
+ 2534               ELSIF SymTab.IsLongFamily(t)
+ 2535                  OR SymTab.IsLongFamily(t2) THEN
+ 2536                  t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
+ 2537                ELSE
+ 2538                  t := SymTab.BoolType();
+ 2539                  QbeGen.CopyOp("@", q)
+ 2540                END
+ 2541             ELSE SemError(213); t := SymTab.InvalidType;
+ 2542                QbeGen.CopyOp("0", q)
+ 2543              END;
+ 2544              astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
+ 2545         (. IF NOT astMade THEN astCur := astA END; .) .
+ 2546    Rel<VAR op: INTEGER>
+ 2547      = "="                               (. op := SymTab.OpEq; .)
+ 2548      | "#"                               (. op := SymTab.OpNeq1; .)
+ 2549      | "<"                               (. op := SymTab.OpLt; .)
+ 2550      | "<="                              (. op := SymTab.OpLe; .)
+ 2551      | ">"                               (. op := SymTab.OpGt; .)
+ 2552      | ">="                              (. op := SymTab.OpGe; .)
+ 2553      | "IN"                              (. op := SymTab.OpIn; .) .
+ 2554    SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 2555                                          (. VAR t2, res2, lt, rt:
+ 2556                                                 SymTab.TypeIndex;
+ 2557                                               op: INTEGER;
+ 2558                                               q2, qt, wq, qf, q2a, q2b:
+ 2559                                                 QbeGen.QVal;
+ 2560                                               neg, isR, isL, folded:
+ 2561                                                 BOOLEAN;
+ 2562                                               fok: BOOLEAN;
+ 2563                                               lw, rw, mw: CARDINAL;
+ 2564                                               lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
+ 2565                                                astA, astB: AST.Node;
+ 2566                                                astSign, astOp: INTEGER; .)
+ 2567      =                                   (. neg := FALSE; astSign := 0; .)
+ 2568        [ "+"                         (. neg := TRUE; astSign := 1; .)
+ 2569        | "-"                         (. neg := TRUE; astSign := -1; .) ]
+ 2570        Term<t, q> (. astA := astCur;
+ 2571                                            IF neg AND QbeGen.IsImm(q) THEN
+ 2572                                              QbeGen.NegFold(q, q)
+ 2573                                            END;
+ 2574                                           IF astSign < 0 THEN
+ 2575                                             astCur := AST.MakeUn(
+ 2576                                               AST.NkUnary, AST.OpSub, astA);
+ 2577                                             astA := astCur
+ 2578                                           END; .)
+ 2579         { AddOp<op>
+ 2580           Term<t2, q2> (. astB := astCur; .)
+ 2581          (. astOp := AST.OpAdd;
+ 2582             IF op = SymTab.OpSub THEN astOp := AST.OpSub
+ 2583             ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
+ 2584             astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
+ 2585             astCur := astA;
+ 2586             IF op = SymTab.OpOr THEN
+ 2587               (* short-circuit: if q is true the RHS is skipped *)
+ 2588               IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
+ 2589                 t := SymTab.BoolType()
+ 2590               ELSE SemError(212); t := SymTab.InvalidType END;
+ 2591                IF t # SymTab.InvalidType THEN
+ 2592                  QbeGen.CopyOp("@", q)
+ 2593                ELSE QbeGen.CopyOp("0", q)
+ 2594                END
+ 2595             ELSIF (op = SymTab.OpAdd)
+ 2596               AND (SymTab.UStrCompat(t, t2)
+ 2597                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
+ 2598                   AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
+ 2599                 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
+ 2600                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
+ 2601                 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
+ 2602                   AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
+ 2603               (* UString concatenation: a UCHAR operand becomes a
+ 2604                  1-codepoint UString; the result is a descriptor in the
+ 2605                  shim's concat buffer.  Work on copies so neither
+ 2606                  operand is clobbered. *)
+ 2607                t := SymTab.NewUStr();
+ 2608                QbeGen.CopyOp("@", q)
+ 2609             ELSIF (op = SymTab.OpAdd)
+ 2610               AND (SymTab.StrCompat(t, t2)
+ 2611                 OR (SymTab.IsStrType(t)
+ 2612                   AND (SymTab.ClassOf(t2) = SymTab.ClChar))
+ 2613                 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
+ 2614                   AND SymTab.IsStrType(t2))) THEN
+ 2615               (* string concatenation; a CHAR operand becomes a
+ 2616                  1-character string literal.  When both operands are
+ 2617                  constants, fold to a single string literal so a
+ 2618                  constructor element stays compile-time. *)
+ 2619                QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
+ 2620                  qt, fok);
+ 2621                IF fok THEN QbeGen.CopyOp(qt, q)
+ 2622                ELSE QbeGen.CopyOp("@", q)
+ 2623                END;
+ 2624                t := SymTab.NewStr()
+ 2625             ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
+ 2626   AND (SymTab.ClassOf(t) = SymTab.ClSet)
+ 2627   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 2628                lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
+ 2629                mw := lw;
+ 2630                IF rw > mw THEN mw := rw END;
+ 2631                t := SymTab.NewSet(
+ 2632                       SymTab.NewSubR(0,
+ 2633                         VAL(INTEGER, mw) * 32 - 1));
+ 2634                QbeGen.CopyOp("@", q)
+ 2635             ELSE
+ 2636               IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
+ 2637                 lt := t; rt := t2; t := res2
+ 2638               ELSE SemError(211); t := SymTab.InvalidType END;
+ 2639               IF t # SymTab.InvalidType THEN
+ 2640                 isL := SymTab.IsLongFamily(t);
+ 2641                 isR := SymTab.ClassOf(t) = SymTab.ClReal;
+ 2642                 folded := FALSE;
+ 2643                 IF (NOT isL) AND (NOT isR)
+ 2644    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
+ 2645                   IF op = SymTab.OpAdd THEN
+ 2646                     folded := QbeGen.Fold2(0, q, q2, qf)
+ 2647                   ELSE
+ 2648                     folded := QbeGen.Fold2(1, q, q2, qf)
+ 2649                   END
+ 2650                 END;
+ 2651                 IF folded THEN QbeGen.CopyOp(qf, q)
+ 2652                  ELSE
+ 2653                  QbeGen.CopyOp("@", q)
+ 2654                  END
+ 2655               ELSE QbeGen.CopyOp("0", q)
+ 2656               END
+ 2657             END; .) } .
+ 2658    AddOp<VAR op: INTEGER>
+ 2659      = "+"                               (. op := SymTab.OpAdd; .)
+ 2660      | "-"                               (. op := SymTab.OpSub; .)
+ 2661      | "OR"                              (. op := SymTab.OpOr; .) .
+ 2662    Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 2663                                          (. VAR t2, res2, lt, rt:
+ 2664                                                 SymTab.TypeIndex;
+ 2665                                               op: INTEGER;
+ 2666                                               q2, qt, wq, qf:
+ 2667                                                 QbeGen.QVal;
+ 2668                                               isR, isL, folded: BOOLEAN;
+ 2669                                               lw, rw, mw: CARDINAL;
+ 2670                                               lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
+ 2671                                                astA, astB: AST.Node;
+ 2672                                                astOp: INTEGER; .)
+ 2673      = Fact<t, q> (. astA := astCur; .) { MulOp<op>
+ 2674          Fact<t2, q2> (. astB := astCur; .)
+ 2675        (. astOp := AST.OpMul;
+ 2676           IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
+ 2677           ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
+ 2678           ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
+ 2679           ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
+ 2680           astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
+ 2681           astCur := astA;
+ 2682           IF op = SymTab.OpAnd THEN
+ 2683             (* short-circuit: if q is false the RHS is skipped *)
+ 2684             IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
+ 2685               t := SymTab.BoolType()
+ 2686             ELSE SemError(212); t := SymTab.InvalidType END;
+ 2687              IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
+ 2688              ELSE QbeGen.CopyOp("0", q)
+ 2689              END
+ 2690           ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
+ 2691   AND (SymTab.ClassOf(t) = SymTab.ClSet)
+ 2692   AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+ 2693              lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
+ 2694              mw := lw;
+ 2695              IF rw > mw THEN mw := rw END;
+ 2696              t := SymTab.NewSet(
+ 2697                     SymTab.NewSubR(0,
+ 2698                       VAL(INTEGER, mw) * 32 - 1));
+ 2699              QbeGen.CopyOp("@", q)
+ 2700           ELSE
+ 2701             IF SymTab.ArithCheck(t, t2,
+ 2702                  (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
+ 2703                  res2) THEN
+ 2704               lt := t; rt := t2; t := res2
+ 2705             ELSE SemError(211); t := SymTab.InvalidType END;
+ 2706             IF t # SymTab.InvalidType THEN
+ 2707               isL := SymTab.IsLongFamily(t);
+ 2708               isR := SymTab.ClassOf(t) = SymTab.ClReal;
+ 2709               folded := FALSE;
+ 2710               IF (NOT isL) AND (NOT isR)
+ 2711    AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
+ 2712                 IF op = SymTab.OpTimes THEN
+ 2713                   folded := QbeGen.Fold2(2, q, q2, qf)
+ 2714                 ELSIF op = SymTab.OpDiv THEN
+ 2715                   folded := QbeGen.Fold2(3, q, q2, qf)
+ 2716                 ELSIF op = SymTab.OpMod THEN
+ 2717                   folded := QbeGen.Fold2(4, q, q2, qf)
+ 2718                 END
+ 2719               END;
+ 2720               IF folded THEN QbeGen.CopyOp(qf, q)
+ 2721                ELSE
+ 2722                QbeGen.CopyOp("@", q)
+ 2723                END
+ 2724             ELSE QbeGen.CopyOp("0", q)
+ 2725             END
+ 2726           END; .) } .
+ 2727    MulOp<VAR op: INTEGER>
+ 2728      = "*"                               (. op := SymTab.OpTimes; .)
+ 2729      | "/"                               (. op := SymTab.OpSlash; .)
+ 2730      | "DIV"                             (. op := SymTab.OpDiv; .)
+ 2731      | "MOD"                             (. op := SymTab.OpMod; .)
+ 2732      | ( "AND" | "&" )                   (. op := SymTab.OpAnd; .) .
+ 2733    Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 2734                                          (. VAR s: ARRAY [0 .. 255] OF CHAR;
+ 2735                                               et, dt, t2, st, ct2, et2:
+ 2736                                                 SymTab.TypeIndex;
+ 2737                                               dk: INTEGER;
+ 2738                                               qd, q2, sq, qa, qm0, qr, qt:
+ 2739                                                 QbeGen.QVal;
+ 2740                                               qn, vn: SymTab.Name;
+ 2741                                               vt: SymTab.TypeIndex;
+ 2742                                               c1, c2: INTEGER;
+ 2743                                               lo, hi: INTEGER;
+ 2744                                               isMax: BOOLEAN;
+ 2745                                               called, isHigh, sfx, isCh,
+ 2746                                               isU, uok, isStr: BOOLEAN;
+ 2747                                               ucp: INTEGER; astIsLit: BOOLEAN;
+ 2748                                                astD: AST.Node;
+ 2749                                                astCall: BOOLEAN;
+ 2750                                                astNode, astNot: AST.Node;
+ 2751                                                j: CARDINAL;
+ 2752                                                astArg2: AST.Node;
+ 2753                                                astBrace: AST.Node;
+ 2754                                                astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
+ 2755      = (. astIsLit := FALSE; .)
+ 2756      ( integer                           (. LexString(s);
+ 2757                                             QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
+ 2758                                             t := SymTab.IntType(); .)
+ 2759      | charConst                         (. LexString(s);
+ 2760                                             QbeGen.NormLit(s, q, isCh);
+ 2761                                             IF twoPhase THEN
+ 2762                                               astIsLit := TRUE;
+ 2763                                               astCur := AST.MakeLeaf(
+ 2764                                                 AST.NkCharLit, s)
+ 2765                                             END;
+ 2766                                             t := SymTab.CharType(); .)
+ 2767      | real                              (. LexString(s);
+ 2768                                             QbeGen.NormReal(s, q);
+ 2769                                             IF twoPhase THEN
+ 2770                                               astIsLit := TRUE;
+ 2771                                               astCur := AST.MakeLeaf(
+ 2772                                                 AST.NkRealLit, s)
+ 2773                                             END;
+ 2774                                             t := SymTab.RealType(); .)
+ 2775      | string                            (. LexString(s);
+ 2776                                             IF twoPhase THEN
+ 2777                                               astIsLit := TRUE;
+ 2778                                               astCur := AST.MakeLeaf(
+ 2779                                                 AST.NkStrLit, s)
+ 2780                                             END;
+ 2781                                             IF SymTab.StrLen(s) = 3 THEN
+ 2782                                               t := SymTab.CharType();
+ 2783                                               QbeGen.IntStr(
+ 2784                                                 QbeGen.CharVal(s), q)
+ 2785                                             ELSE t := SymTab.NewStr();
+ 2786                                               QbeGen.DeclStr(s, q);
+ 2787                                               (* a literal's value IS its
+ 2788                                                  static descriptor address *)
+ 2789                                             END; .)
+ 2790      | ustring                           (. LexString(s);
+ 2791                                             IF twoPhase THEN
+ 2792                                               astIsLit := TRUE;
+ 2793                                               astCur := AST.MakeLeaf(
+ 2794                                                 AST.NkStrLit, s)
+ 2795                                             END;
+ 2796                                             QbeGen.DeclUStr(s, q, isU, ucp,
+ 2797                                               uok);
+ 2798                                             IF NOT uok THEN
+ 2799                                               SemError(234);
+ 2800                                               t := SymTab.InvalidType
+ 2801                                             ELSIF isU THEN
+ 2802                                               t := SymTab.UCharType();
+ 2803                                               QbeGen.IntStr(ucp, q)
+ 2804                                             ELSE
+ 2805                                               t := SymTab.NewUStr();
+ 2806                                             END; .)
+ 2807      | Design<dt, dk, qd, qn, sfx>       (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
+ 2808                                             astNArgs := 0; called := FALSE;
+ 2809                                             t := dt;
+ 2810                                             IF dk = SymTab.KindConst THEN
+ 2811                                               QbeGen.CopyOp(qd, q)
+ 2812                                             ELSE QbeGen.CopyOp("@", q)
+ 2813                                             END; .)
+ 2814        [ TypedBraceLit<dt, q>            (. t := dt; astCall := TRUE;
+ 2815                                               astBrace := astCur; .) ]
+ 2816        [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
+ 2817                                          (. astCall := TRUE;
+ 2818                                             astNode := AstCallNode(astD);
+ 2819                                             astRes := astNode;
+ 2820                                             t := ct2;
+ 2821                                             QbeGen.CopyOp(q2, q);
+ 2822                                             sfx := FALSE; .)
+ 2823          { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
+ 2824            [ (. astNArgs := 0; .)
+ 2825              ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
+ 2826                                          (. astNode := AstCallNode(astRes);
+ 2827                                             astRes := astNode;
+ 2828                                             t := ct2;
+ 2829                                             QbeGen.CopyOp(q2, q);
+ 2830                                             sfx := FALSE; .) ] }
+ 2831                                          (. IF sfx THEN
+ 2832                                               IF t = SymTab.InvalidType THEN
+ 2833                                                 QbeGen.CopyOp("0", q)
+ 2834                                               ELSIF (SymTab.ClassOf(t) #
+ 2835                                                      SymTab.ClRecord)
+ 2836    AND (SymTab.ClassOf(t) # SymTab.ClSet)
+ 2837    AND (SymTab.ClassOf(t) # SymTab.ClArray)
+ 2838    AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
+ 2839                                                  QbeGen.CopyOp("@", q)
+ 2840                                               END
+ 2841                                             END; .) ]
+ 2842                                          (. IF called THEN
+ 2843                                               astCur := astRes
+ 2844                                             ELSIF astCall THEN
+ 2845                                               astCur := astBrace
+ 2846                                             ELSE astCur := astD
+ 2847                                             END;
+ 2848                                              astIsLit := TRUE;
+ 2849                                              IF NOT called
+ 2850   AND (dk = SymTab.KindProc) THEN
+ 2851                                               (* bare zero-arg function
+ 2852                                                  call (parentheses may be
+ 2853                                                  omitted); a proper or
+ 2854                                                  parameterised proc here
+ 2855                                                  is 230 *)
+ 2856                                                IF (SymTab.ProcNPar(qn) = 0)
+ 2857   AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
+ 2858                                                  t := SymTab.ProcRes(qn);
+ 2859                                                  QbeGen.CopyOp("@", q);
+ 2860                                                  astCur := AST.MakeNode(AST.NkCall);
+ 2861                                                  AST.SetChild(astCur, 0, astD)
+ 2862                                                ELSE
+ 2863                                                  t := SymTab.ProcTypeOf(qn);
+ 2864                                                  QbeGen.CopyOp("@", q)
+ 2865                                                END
+ 2866                                             END; .)
+ 2867      | ( "HIGH"                          (. isHigh := TRUE; .)
+ 2868        | ( "LEN" | "LENGTH" )            (. isHigh := FALSE; .) )
+ 2869        "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
+ 2870                                              isU := FALSE; .)
+ 2871            | string                       (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
+ 2872                                              isStr := TRUE;
+ 2873                                              isU := FALSE;
+ 2874                                              IF SymTab.StrLen(s) = 3 THEN
+ 2875                                                dt := SymTab.CharType();
+ 2876                                                QbeGen.IntStr(QbeGen.CharVal(s),
+ 2877                                                  qd)
+ 2878                                              ELSE
+ 2879                                                dt := SymTab.NewStr();
+ 2880                                                QbeGen.DeclStr(s, qd);
+ 2881                                              END;
+ 2882                                              dk := -1;
+ 2883                                              qn[0] := CHR(0); .)
+ 2884            | ustring                      (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
+ 2885                                              QbeGen.DeclUStr(s, qd, isU, ucp,
+ 2886                                                uok);
+ 2887                                              isStr := FALSE;
+ 2888                                              IF NOT uok THEN
+ 2889                                                SemError(234);
+ 2890                                                dt := SymTab.InvalidType
+ 2891                                              ELSIF isU THEN
+ 2892                                                (* one codepoint: a UCHAR;
+ 2893                                                   LEN is 1, HIGH is 0 *)
+ 2894                                                dt := SymTab.UCharType();
+ 2895                                                QbeGen.IntStr(ucp, qd)
+ 2896                                              ELSE
+ 2897                                                dt := SymTab.NewUStr();
+ 2898                                              END;
+ 2899                                              dk := -1;
+ 2900                                              qn[0] := CHR(0); .) )
+ 2901        ")"
+ 2902                                          (. astNode := AST.MakeNode(AST.NkCall);
+ 2903     IF isHigh THEN AST.SetChild(astNode, 0,
+ 2904       AST.MakeLeaf(AST.NkIdent, "HIGH"))
+ 2905     ELSE AST.SetChild(astNode, 0,
+ 2906       AST.MakeLeaf(AST.NkIdent, "LEN")) END;
+ 2907     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 2908     astCur := astNode; astIsLit := TRUE;
+ 2909                                             IF (dt # SymTab.InvalidType)
+ 2910    AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
+ 2911                                               (* UString: the count is
+ 2912                                                  the descriptor header *)
+ 2913                                                t := SymTab.IntType();
+ 2914                                                QbeGen.CopyOp("@", q)
+ 2915                                             ELSIF (dt # SymTab.InvalidType)
+ 2916    AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
+ 2917                                               (* single UCHAR codepoint *)
+ 2918                                               IF isHigh THEN
+ 2919                                                 QbeGen.CopyOp("0", qr)
+ 2920                                               ELSE
+ 2921                                                 QbeGen.CopyOp("1", qr)
+ 2922                                               END;
+ 2923                                               t := SymTab.IntType();
+ 2924                                               QbeGen.CopyOp(qr, q)
+ 2925                                             ELSIF isStr THEN
+ 2926                                               (* fold: content length at
+ 2927                                                  compile time *)
+ 2928                                               IF SymTab.StrLen(s) = 3 THEN
+ 2929                                                 c1 := 1
+ 2930                                               ELSE
+ 2931                                                 c1 :=
+ 2932                                                   SymTab.StrLen(s) - 2
+ 2933                                               END;
+ 2934                                               IF isHigh THEN
+ 2935                                                 DEC(c1)
+ 2936                                               END;
+ 2937                                               QbeGen.IntStr(c1, qr);
+ 2938                                               t := SymTab.IntType();
+ 2939                                               QbeGen.CopyOp(qr, q)
+ 2940                                             ELSIF dt = SymTab.InvalidType THEN
+ 2941                                               t := SymTab.InvalidType;
+ 2942                                               QbeGen.CopyOp("0", q)
+ 2943                                             ELSIF SymTab.ClassOf(dt) #
+ 2944                                                   SymTab.ClArray THEN
+ 2945                                               SemError(217);
+ 2946                                               t := SymTab.InvalidType;
+ 2947                                               QbeGen.CopyOp("0", q)
+ 2948                                             ELSE
+ 2949                                                IF SymTab.IsOpenArray(dt) THEN
+ 2950                                                  t := SymTab.IntType();
+ 2951                                                  QbeGen.CopyOp("@", q)
+ 2952                                                ELSE
+ 2953                                                  IF isHigh THEN
+ 2954                                                    QbeGen.IntStr(
+ 2955                                                      SymTab.ArrayHi(dt), qr)
+ 2956                                                  ELSE
+ 2957                                                    QbeGen.IntStr(VAL(
+ 2958                                                      INTEGER,
+ 2959                                                      SymTab.ArrayLen(dt)),
+ 2960                                                      qr)
+ 2961                                                  END;
+ 2962                                                  t := SymTab.IntType();
+ 2963                                                  QbeGen.CopyOp(qr, q)
+ 2964                                                END
+ 2965                                              END; .)
+ 2966      | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
+ 2967      (. astNode := AST.MakeNode(AST.NkCall);
+ 2968     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
+ 2969     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 2970     astCur := astNode; astIsLit := TRUE; .)
+ 2971                                          (. IF dt = SymTab.InvalidType THEN
+ 2972                                               t := SymTab.InvalidType;
+ 2973                                               QbeGen.CopyOp("0", q)
+ 2974                                             ELSE
+ 2975                                               QbeGen.IntStr(VAL(INTEGER,
+ 2976                                                 SymTab.ObjectSize(dt)), q);
+ 2977                                               t := SymTab.IntType()
+ 2978                                             END; .)
+ 2979      | ( "SHIFT"                         (. isMax := FALSE; .)
+ 2980        | "ROTATE"                        (. isMax := TRUE; .) )
+ 2981        "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
+ 2982                                          (. astNode := AST.MakeNode(AST.NkCall);
+ 2983     IF isMax THEN AST.SetChild(astNode, 0,
+ 2984       AST.MakeLeaf(AST.NkIdent, "ROTATE"))
+ 2985     ELSE AST.SetChild(astNode, 0,
+ 2986       AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
+ 2987     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
+ 2988     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
+ 2989     astCur := astNode; astIsLit := TRUE;
+ 2990                                             (* set shift/rotate: isMax
+ 2991                                                doubles as "rotate" *)
+ 2992                                             IF (et # SymTab.InvalidType)
+ 2993                                                AND (SymTab.ClassOf(et) =
+ 2994                                                   SymTab.ClSet) THEN
+ 2995                                                t := et;
+ 2996                                                QbeGen.CopyOp("@", q)
+ 2997                                             ELSE SemError(230);
+ 2998                                               t := SymTab.InvalidType;
+ 2999                                               QbeGen.CopyOp("0", q)
+ 3000                                             END; .)
+ 3001      | ( "MIN"                           (. isMax := FALSE; .)
+ 3002        | "MAX"                           (. isMax := TRUE; .) )
+ 3003        "(" Design<dt, dk, qd, qn, sfx> ")"
+ 3004                                          (. astNode := AST.MakeNode(AST.NkCall);
+ 3005     IF isMax THEN AST.SetChild(astNode, 0,
+ 3006       AST.MakeLeaf(AST.NkIdent, "MAX"))
+ 3007     ELSE AST.SetChild(astNode, 0,
+ 3008       AST.MakeLeaf(AST.NkIdent, "MIN")) END;
+ 3009     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3010     astCur := astNode; astIsLit := TRUE;
+ 3011                                             IF (dt # SymTab.InvalidType)
+ 3012   AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
+ 3013                                               (* REAL/LONGREAL: the
+ 3014                                                  implementation bounds *)
+ 3015                                               IF isMax THEN
+ 3016                                                 QbeGen.NormReal(
+ 3017                                                   "3.402823e38", q)
+ 3018                                               ELSE QbeGen.NormReal(
+ 3019                                                   "-3.402823e38", q)
+ 3020                                               END;
+ 3021                                               t := SymTab.RealType()
+ 3022                                             ELSIF (dt #
+ 3023                                                SymTab.InvalidType)
+ 3024   AND (SymTab.ClassOf(dt) =
+ 3025                                                   SymTab.ClLong) THEN
+ 3026                                               IF isMax THEN
+ 3027                                                 QbeGen.CopyOp(
+ 3028                                                   "9223372036854775807", q)
+ 3029                                               ELSE QbeGen.CopyOp(
+ 3030                                                   "-9223372036854775808", q)
+ 3031                                               END;
+ 3032                                               t := SymTab.LongType()
+ 3033                                             ELSIF SymTab.TypeBounds(dt, lo,
+ 3034                                                      hi) THEN
+ 3035                                               IF isMax THEN
+ 3036                                                 QbeGen.IntStr(hi, q)
+ 3037                                               ELSE QbeGen.IntStr(lo, q)
+ 3038                                               END;
+ 3039                                               t := SymTab.IntType()
+ 3040                                             ELSE SemError(230);
+ 3041                                               t := SymTab.InvalidType;
+ 3042                                               QbeGen.CopyOp("0", q)
+ 3043                                             END; .)
+ 3044      | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
+ 3045      (. astNode := AST.MakeNode(AST.NkCall);
+ 3046     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
+ 3047     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3048     astCur := astNode; astIsLit := TRUE; .)
+ 3049                                          (. IF dt = SymTab.InvalidType THEN
+ 3050                                               t := SymTab.InvalidType;
+ 3051                                               QbeGen.CopyOp("0", q)
+ 3052                                             ELSE
+ 3053                                                IF sfx
+ 3054                                                   OR (dk = SymTab.KindVar)
+ 3055                                                   OR (dk = SymTab.KindParam) THEN
+ 3056                                                  QbeGen.CopyOp("@", q)
+ 3057                                                ELSE SemError(230);
+ 3058                                                  QbeGen.CopyOp("0", q)
+ 3059                                                END;
+ 3060                                               t := SymTab.AddrType()
+ 3061                                             END; .)
+ 3062      | "CHR" "(" Expr<et, q> ")"
+ 3063      (. astNode := AST.MakeNode(AST.NkCall);
+ 3064     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
+ 3065     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3066     astCur := astNode; astIsLit := TRUE; .)
+ 3067                                          (. IF (et # SymTab.InvalidType)
+ 3068   AND NOT SymTab.IsIntFamily(et) THEN
+ 3069                                               SemError(211) END;
+ 3070                                             t := SymTab.CharType(); .)
+ 3071      | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
+ 3072      (. astNode := AST.MakeNode(AST.NkCall);
+ 3073     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
+ 3074     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3075     astCur := astNode; astIsLit := TRUE; .)
+ 3076                                          (. IF et # SymTab.InvalidType THEN
+ 3077                                               IF (SymTab.ClassOf(et) #
+ 3078                                                   SymTab.ClChar)
+ 3079   AND (SymTab.ClassOf(et) #
+ 3080                                                     SymTab.ClBool)
  3081   AND (SymTab.ClassOf(et) #
  3081   AND (SymTab.ClassOf(et) #
- 3082                                                     SymTab.ClBool)
- 3083   AND (SymTab.ClassOf(et) #
- 3084                                                     SymTab.ClEnum)
- 3085   AND NOT SymTab.IsIntFamily(et) THEN
- 3086                                                 SemError(211) END
- 3087                                             END;
- 3088                                             t := SymTab.IntType(); .)
- 3089      | "CAP" "(" Expr<et, q> ")"
- 3090      (. astNode := AST.MakeNode(AST.NkCall);
- 3091     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
- 3092     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3093     astCur := astNode; astIsLit := TRUE; .)
- 3094                                           (. QbeGen.CopyOp("@", q);
- 3095                                             t := SymTab.CharType(); .)
- 3096      | "UCHR" "(" Expr<et, q> ")"
- 3097      (. astNode := AST.MakeNode(AST.NkCall);
- 3098     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
- 3099     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3100     astCur := astNode; astIsLit := TRUE; .)
- 3101                                          (. (* UCHR: the UCHAR constructor.
- 3102                                                CHAR -> UCHAR (identity);
- 3103                                                INTEGER familly -> UCHAR
- 3104                                                (codepoint value). *)
- 3105                                             IF (et # SymTab.InvalidType)
- 3106    AND (SymTab.ClassOf(et) # SymTab.ClChar)
- 3107    AND NOT SymTab.IsIntFamily(et) THEN
- 3108                                               SemError(211) END;
- 3109                                             t := SymTab.UCharType(); .)
- 3110      | "CHR8" "(" Expr<et, q> ")"
- 3111      (. astNode := AST.MakeNode(AST.NkCall);
- 3112     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
- 3113     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3114     astCur := astNode; astIsLit := TRUE; .)
- 3115                                          (. IF (et # SymTab.InvalidType)
- 3116    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
- 3117                                               SemError(211) END;
- 3118                                             t := SymTab.CharType(); .)
- 3119      | "UORD" "(" Expr<et, q> ")"
- 3120      (. astNode := AST.MakeNode(AST.NkCall);
- 3121     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
- 3122     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3123     astCur := astNode; astIsLit := TRUE; .)
- 3124                                          (. (* UORD(u): the codepoint as a
- 3125                                                32-bit ordinal (INTEGER),
- 3126                                                cf. ORD for CHAR. *)
- 3127                                             IF (et # SymTab.InvalidType)
- 3128    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
- 3129                                               SemError(211) END;
- 3130                                             t := SymTab.IntType(); .)
- 3131      | "ABS" "(" Expr<et, q> ")"
- 3132      (. astNode := AST.MakeNode(AST.NkCall);
- 3133     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
- 3134     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
- 3135     astCur := astNode; astIsLit := TRUE; .)
- 3136                                          (. IF (et # SymTab.InvalidType)
- 3137   AND NOT SymTab.IsIntFamily(et)
- 3138   AND (SymTab.ClassOf(et) #
- 3139                                                  SymTab.ClReal) THEN
- 3140                                               SemError(211)
- 3141                                              ELSE QbeGen.CopyOp("@", q)
- 3142                                             END;
- 3143                                             t := et; .)
- 3144      | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
- 3145      (. astNode := AST.MakeNode(AST.NkCall);
- 3146     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
- 3147     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
- 3148     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
- 3149     astCur := astNode; astIsLit := TRUE; .)
- 3150                                          (. IF NOT SymTab.Lookup(vn) THEN
- 3151                                               SemError(201);
- 3152                                               t := SymTab.InvalidType
- 3153                                             ELSE vt := SymTab.SymType(vn);
- 3154                                               IF vt = SymTab.InvalidType THEN
- 3155                                                 t := SymTab.InvalidType
- 3156                                               ELSIF et =
- 3157                                                  SymTab.InvalidType THEN
- 3158                                                 t := vt
- 3159                                               ELSE
- 3160                                                 c1 := SymTab.ClassOf(et);
- 3161                                                 c2 := SymTab.ClassOf(vt);
- 3162                                                 IF (c1 = SymTab.ClInt)
- 3163    AND (c2 = SymTab.ClLong) THEN
- 3164                                                   QbeGen.WidenLong(q, qa);
- 3165                                                   QbeGen.CopyOp(qa, q);
- 3166                                                   t := vt
- 3167                                                 ELSIF (c1 = SymTab.ClLong)
- 3168    AND (c2 = SymTab.ClInt) THEN
- 3169                                                   QbeGen.NarrowLong(q, qa);
- 3170                                                   QbeGen.CopyOp(qa, q);
- 3171                                                   t := vt
- 3172                                                 ELSIF (c1 = SymTab.ClInt)
- 3173    AND (c2 = SymTab.ClReal) THEN
- 3174                                                   QbeGen.ConvIR(q, qa);
- 3175                                                   QbeGen.CopyOp(qa, q);
- 3176                                                   t := vt
- 3177                                                 ELSIF (c1 = SymTab.ClLong)
- 3178    AND (c2 = SymTab.ClReal) THEN
- 3179                                                   QbeGen.ConvLR(q, qa);
- 3180                                                   QbeGen.CopyOp(qa, q);
- 3181                                                   t := vt
- 3182                                                 ELSIF (c1 = SymTab.ClReal)
- 3183    AND (c2 = SymTab.ClInt) THEN
- 3184                                                   QbeGen.ConvRI(q, qa);
- 3185                                                   QbeGen.CopyOp(qa, q);
- 3186                                                   t := vt
- 3187                                                 ELSIF (c1 = SymTab.ClReal)
- 3188    AND (c2 = SymTab.ClLong) THEN
- 3189                                                   QbeGen.ConvRL(q, qa);
- 3190                                                   QbeGen.CopyOp(qa, q);
- 3191                                                   t := vt
- 3192                                                 ELSIF ((c1 = SymTab.ClInt)
+ 3082                                                     SymTab.ClEnum)
+ 3083   AND NOT SymTab.IsIntFamily(et) THEN
+ 3084                                                 SemError(211) END
+ 3085                                             END;
+ 3086                                             t := SymTab.IntType(); .)
+ 3087      | "CAP" "(" Expr<et, q> ")"
+ 3088      (. astNode := AST.MakeNode(AST.NkCall);
+ 3089     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
+ 3090     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3091     astCur := astNode; astIsLit := TRUE; .)
+ 3092                                           (. QbeGen.CopyOp("@", q);
+ 3093                                             t := SymTab.CharType(); .)
+ 3094      | "UCHR" "(" Expr<et, q> ")"
+ 3095      (. astNode := AST.MakeNode(AST.NkCall);
+ 3096     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
+ 3097     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3098     astCur := astNode; astIsLit := TRUE; .)
+ 3099                                          (. (* UCHR: the UCHAR constructor.
+ 3100                                                CHAR -> UCHAR (identity);
+ 3101                                                INTEGER familly -> UCHAR
+ 3102                                                (codepoint value). *)
+ 3103                                             IF (et # SymTab.InvalidType)
+ 3104    AND (SymTab.ClassOf(et) # SymTab.ClChar)
+ 3105    AND NOT SymTab.IsIntFamily(et) THEN
+ 3106                                               SemError(211) END;
+ 3107                                             t := SymTab.UCharType(); .)
+ 3108      | "CHR8" "(" Expr<et, q> ")"
+ 3109      (. astNode := AST.MakeNode(AST.NkCall);
+ 3110     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
+ 3111     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3112     astCur := astNode; astIsLit := TRUE; .)
+ 3113                                          (. IF (et # SymTab.InvalidType)
+ 3114    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
+ 3115                                               SemError(211) END;
+ 3116                                             t := SymTab.CharType(); .)
+ 3117      | "UORD" "(" Expr<et, q> ")"
+ 3118      (. astNode := AST.MakeNode(AST.NkCall);
+ 3119     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
+ 3120     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3121     astCur := astNode; astIsLit := TRUE; .)
+ 3122                                          (. (* UORD(u): the codepoint as a
+ 3123                                                32-bit ordinal (INTEGER),
+ 3124                                                cf. ORD for CHAR. *)
+ 3125                                             IF (et # SymTab.InvalidType)
+ 3126    AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
+ 3127                                               SemError(211) END;
+ 3128                                             t := SymTab.IntType(); .)
+ 3129      | "ABS" "(" Expr<et, q> ")"
+ 3130      (. astNode := AST.MakeNode(AST.NkCall);
+ 3131     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
+ 3132     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+ 3133     astCur := astNode; astIsLit := TRUE; .)
+ 3134                                          (. IF (et # SymTab.InvalidType)
+ 3135   AND NOT SymTab.IsIntFamily(et)
+ 3136   AND (SymTab.ClassOf(et) #
+ 3137                                                  SymTab.ClReal) THEN
+ 3138                                               SemError(211)
+ 3139                                              ELSE QbeGen.CopyOp("@", q)
+ 3140                                             END;
+ 3141                                             t := et; .)
+ 3142      | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
+ 3143      (. astNode := AST.MakeNode(AST.NkCall);
+ 3144     AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
+ 3145     IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
+ 3146     IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
+ 3147     astCur := astNode; astIsLit := TRUE; .)
+ 3148                                          (. IF NOT SymTab.Lookup(vn) THEN
+ 3149                                               SemError(201);
+ 3150                                               t := SymTab.InvalidType
+ 3151                                             ELSE vt := SymTab.SymType(vn);
+ 3152                                               IF vt = SymTab.InvalidType THEN
+ 3153                                                 t := SymTab.InvalidType
+ 3154                                               ELSIF et =
+ 3155                                                  SymTab.InvalidType THEN
+ 3156                                                 t := vt
+ 3157                                               ELSE
+ 3158                                                 c1 := SymTab.ClassOf(et);
+ 3159                                                 c2 := SymTab.ClassOf(vt);
+ 3160                                                 IF (c1 = SymTab.ClInt)
+ 3161    AND (c2 = SymTab.ClLong) THEN
+ 3162                                                   QbeGen.WidenLong(q, qa);
+ 3163                                                   QbeGen.CopyOp(qa, q);
+ 3164                                                   t := vt
+ 3165                                                 ELSIF (c1 = SymTab.ClLong)
+ 3166    AND (c2 = SymTab.ClInt) THEN
+ 3167                                                   QbeGen.NarrowLong(q, qa);
+ 3168                                                   QbeGen.CopyOp(qa, q);
+ 3169                                                   t := vt
+ 3170                                                 ELSIF (c1 = SymTab.ClInt)
+ 3171    AND (c2 = SymTab.ClReal) THEN
+ 3172                                                   QbeGen.ConvIR(q, qa);
+ 3173                                                   QbeGen.CopyOp(qa, q);
+ 3174                                                   t := vt
+ 3175                                                 ELSIF (c1 = SymTab.ClLong)
+ 3176    AND (c2 = SymTab.ClReal) THEN
+ 3177                                                   QbeGen.ConvLR(q, qa);
+ 3178                                                   QbeGen.CopyOp(qa, q);
+ 3179                                                   t := vt
+ 3180                                                 ELSIF (c1 = SymTab.ClReal)
+ 3181    AND (c2 = SymTab.ClInt) THEN
+ 3182                                                   QbeGen.ConvRI(q, qa);
+ 3183                                                   QbeGen.CopyOp(qa, q);
+ 3184                                                   t := vt
+ 3185                                                 ELSIF (c1 = SymTab.ClReal)
+ 3186    AND (c2 = SymTab.ClLong) THEN
+ 3187                                                   QbeGen.ConvRL(q, qa);
+ 3188                                                   QbeGen.CopyOp(qa, q);
+ 3189                                                   t := vt
+ 3190                                                 ELSIF ((c1 = SymTab.ClInt)
+ 3191                                                     OR (c1 =
+ 3192                                                        SymTab.ClChar)
  3193                                                     OR (c1 =
  3193                                                     OR (c1 =
- 3194                                                        SymTab.ClChar)
+ 3194                                                        SymTab.ClBool)
  3195                                                     OR (c1 =
  3195                                                     OR (c1 =
- 3196                                                        SymTab.ClBool)
- 3197                                                     OR (c1 =
- 3198                                                        SymTab.ClEnum))
- 3199   AND ((c2 = SymTab.ClInt)
+ 3196                                                        SymTab.ClEnum))
+ 3197   AND ((c2 = SymTab.ClInt)
+ 3198                                                     OR (c2 =
+ 3199                                                        SymTab.ClChar)
  3200                                                     OR (c2 =
  3200                                                     OR (c2 =
- 3201                                                        SymTab.ClChar)
+ 3201                                                        SymTab.ClBool)
  3202                                                     OR (c2 =
  3202                                                     OR (c2 =
- 3203                                                        SymTab.ClBool)
- 3204                                                     OR (c2 =
- 3205                                                        SymTab.ClEnum)) THEN
- 3206                                                   t := vt
- 3207                                                 ELSIF (c1 = SymTab.ClPtr)
- 3208   AND (c2 = SymTab.ClPtr) THEN
- 3209                                                   t := vt
- 3210                                                 ELSIF (c1 = SymTab.ClReal)
- 3211   AND (c2 = SymTab.ClReal) THEN
- 3212                                                   t := vt
- 3213                                                 ELSE SemError(230);
- 3214                                                   t := SymTab.InvalidType
- 3215                                                 END
- 3216                                               END
- 3217                                             END; .)
- 3218      | "(" Expr<et, q> ")"               (. t := et; astIsLit := TRUE; .)
- 3219      | SetLit<st, sq>                    (. astIsLit := TRUE; t := st;
- 3220                                             QbeGen.CopyOp(sq, q); .)
- 3221      | ( "NOT" | "~" ) Fact<t2, q2>      (. astNot := astCur;
- 3222                                             IF SymTab.BoolCheck(t2) THEN
- 3223                                               t := SymTab.BoolType()
- 3224                                             ELSE SemError(212);
- 3225                                               t := SymTab.InvalidType END;
- 3226                                             IF t # SymTab.InvalidType THEN
- 3227                                                QbeGen.CopyOp("@", q)
- 3228                                             ELSE QbeGen.CopyOp("0", q)
- 3229                                             END;
- 3230                                             astIsLit := TRUE;
- 3231                                             astCur := AST.MakeUn(
- 3232                                               AST.NkUnary, AST.OpNot, astNot); .)
- 3233      )
- 3234      (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
- 3235    (* Set literals are SET OF [0..255] (8 words); elements validated
- 3236       0..255 statically when foldable (222 otherwise), runtime trap
- 3237       for computed elements. Ranges always lower via SetRange. *)
- 3238    SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 3239                                          (. VAR astNode: AST.Node; .)
- 3240      = "{"                               (. t := SymTab.NewSet(
- 3241                                               SymTab.NewSubR(0, 255));
- 3242                                             astNode := AST.MakeNode(AST.NkSetLit);
- 3243                                             QbeGen.NewSetTemp(8, q);
- 3244                                             QbeGen.SetZero(q, 8); .)
- 3245        [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
- 3246        "}"                               (. astCur := astNode; .) .
- 3247    (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
- 3248       or ArrayName{...} (an array constructor, GNU Modula-2).  The
- 3249       declared type sets the width (set) or element type (array). *)
- 3250    TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
- 3251                                          (. VAR nw: CARDINAL;
- 3252                                               astNode, astTail: AST.Node;
- 3253                                               savedCls: INTEGER; .)
- 3254      = "{"                               (. savedCls := braceCls;
- 3255                                             astNode := AST.MakeNode(AST.NkBraceLit);
- 3256                                             AST.SetTy(astNode, vt);
- 3257                                             astTail := astNode;
- 3258                                             IF vt = SymTab.InvalidType THEN
- 3259                                               braceCls := -1
- 3260                                             ELSE braceCls :=
- 3261                                                    SymTab.ClassOf(vt)
- 3262                                             END;
- 3263                                             IF braceCls = SymTab.ClSet THEN
- 3264                                               IF vt = SymTab.InvalidType THEN
- 3265                                                 nw := 8
- 3266                                               ELSE nw := SymTab.SetWords(vt);
- 3267                                                 IF nw = 0 THEN nw := 8 END
- 3268                                               END;
- 3269                                               QbeGen.NewSetTemp(nw, q);
- 3270                                               QbeGen.SetZero(q, nw)
- 3271                                             ELSIF (braceCls =
- 3272                                                    SymTab.ClArray)
+ 3203                                                        SymTab.ClEnum)) THEN
+ 3204                                                   t := vt
+ 3205                                                 ELSIF (c1 = SymTab.ClPtr)
+ 3206   AND (c2 = SymTab.ClPtr) THEN
+ 3207                                                   t := vt
+ 3208                                                 ELSIF (c1 = SymTab.ClReal)
+ 3209   AND (c2 = SymTab.ClReal) THEN
+ 3210                                                   t := vt
+ 3211                                                 ELSE SemError(230);
+ 3212                                                   t := SymTab.InvalidType
+ 3213                                                 END
+ 3214                                               END
+ 3215                                             END; .)
+ 3216      | "(" Expr<et, q> ")"               (. t := et; astIsLit := TRUE; .)
+ 3217      | SetLit<st, sq>                    (. astIsLit := TRUE; t := st;
+ 3218                                             QbeGen.CopyOp(sq, q); .)
+ 3219      | ( "NOT" | "~" ) Fact<t2, q2>      (. astNot := astCur;
+ 3220                                             IF SymTab.BoolCheck(t2) THEN
+ 3221                                               t := SymTab.BoolType()
+ 3222                                             ELSE SemError(212);
+ 3223                                               t := SymTab.InvalidType END;
+ 3224                                             IF t # SymTab.InvalidType THEN
+ 3225                                                QbeGen.CopyOp("@", q)
+ 3226                                             ELSE QbeGen.CopyOp("0", q)
+ 3227                                             END;
+ 3228                                             astIsLit := TRUE;
+ 3229                                             astCur := AST.MakeUn(
+ 3230                                               AST.NkUnary, AST.OpNot, astNot); .)
+ 3231      )
+ 3232      (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
+ 3233    (* Set literals are SET OF [0..255] (8 words); elements validated
+ 3234       0..255 statically when foldable (222 otherwise), runtime trap
+ 3235       for computed elements. Ranges always lower via SetRange. *)
+ 3236    SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 3237                                          (. VAR astNode: AST.Node; .)
+ 3238      = "{"                               (. t := SymTab.NewSet(
+ 3239                                               SymTab.NewSubR(0, 255));
+ 3240                                             astNode := AST.MakeNode(AST.NkSetLit);
+ 3241                                             QbeGen.NewSetTemp(8, q);
+ 3242                                             QbeGen.SetZero(q, 8); .)
+ 3243        [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
+ 3244        "}"                               (. astCur := astNode; .) .
+ 3245    (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
+ 3246       or ArrayName{...} (an array constructor, GNU Modula-2).  The
+ 3247       declared type sets the width (set) or element type (array). *)
+ 3248    TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
+ 3249                                          (. VAR nw: CARDINAL;
+ 3250                                               astNode, astTail: AST.Node;
+ 3251                                               savedCls: INTEGER; .)
+ 3252      = "{"                               (. savedCls := braceCls;
+ 3253                                             astNode := AST.MakeNode(AST.NkBraceLit);
+ 3254                                             AST.SetTy(astNode, vt);
+ 3255                                             astTail := astNode;
+ 3256                                             IF vt = SymTab.InvalidType THEN
+ 3257                                               braceCls := -1
+ 3258                                             ELSE braceCls :=
+ 3259                                                    SymTab.ClassOf(vt)
+ 3260                                             END;
+ 3261                                             IF braceCls = SymTab.ClSet THEN
+ 3262                                               IF vt = SymTab.InvalidType THEN
+ 3263                                                 nw := 8
+ 3264                                               ELSE nw := SymTab.SetWords(vt);
+ 3265                                                 IF nw = 0 THEN nw := 8 END
+ 3266                                               END;
+ 3267                                               QbeGen.NewSetTemp(nw, q);
+ 3268                                               QbeGen.SetZero(q, nw)
+ 3269                                             ELSIF (braceCls =
+ 3270                                                    SymTab.ClArray)
+ 3271                                                OR (braceCls =
+ 3272                                                    SymTab.ClRecord)
  3273                                                OR (braceCls =
  3273                                                OR (braceCls =
- 3274                                                    SymTab.ClRecord)
- 3275                                                OR (braceCls =
- 3276                                                    SymTab.ClClass) THEN
- 3277                                               QbeGen.CtorBegin(vt)
- 3278                                             ELSE
- 3279                                               IF vt # SymTab.InvalidType THEN
- 3280                                                 SemError(230) END;
- 3281                                               braceCls := -1
- 3282                                             END; .)
- 3283        [ BraceElem<vt, q, astNode, astTail>
- 3284          { "," BraceElem<vt, q, astNode, astTail> } ]
- 3285        "}"                               (. IF (braceCls = SymTab.ClArray)
+ 3274                                                    SymTab.ClClass) THEN
+ 3275                                               QbeGen.CtorBegin(vt)
+ 3276                                             ELSE
+ 3277                                               IF vt # SymTab.InvalidType THEN
+ 3278                                                 SemError(230) END;
+ 3279                                               braceCls := -1
+ 3280                                             END; .)
+ 3281        [ BraceElem<vt, q, astNode, astTail>
+ 3282          { "," BraceElem<vt, q, astNode, astTail> } ]
+ 3283        "}"                               (. IF (braceCls = SymTab.ClArray)
+ 3284                                                OR (braceCls =
+ 3285                                                   SymTab.ClRecord)
  3286                                                OR (braceCls =
  3286                                                OR (braceCls =
- 3287                                                   SymTab.ClRecord)
- 3288                                                OR (braceCls =
- 3289                                                   SymTab.ClClass) THEN
- 3290                                               QbeGen.CtorEnd(q)
- 3291                                             ELSIF braceCls # SymTab.ClSet THEN
- 3292                                               QbeGen.CopyOp("0", q)
- 3293                                             END;
- 3294                                             braceCls := savedCls; .)
- 3295                                          (. astCur := astNode; .) .
- 3296    BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
- 3297              VAR node, tail: AST.Node>
- 3298                                          (. VAR et, et2: SymTab.TypeIndex;
- 3299                                               qe, q2: QbeGen.QVal;
- 3300                                               v, v2, reps, k: INTEGER;
- 3301                                               elem: SymTab.TypeIndex;
- 3302                                               lo: INTEGER;
- 3303                                               span: CARDINAL;
- 3304                                               cl, cl2: INTEGER;
- 3305                                               hasR, hasB: BOOLEAN;
- 3306                                               astEl: AST.Node; .)
- 3307      =                                   (. hasR := FALSE; hasB := FALSE;
- 3308                                             reps := 1; .)
- 3309        Expr<et, qe> (. astEl := astCur; .)
- 3310        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
- 3311                                               AST.NkSubrange, 0, astEl, astCur);
- 3312                                             hasR := TRUE; .) ]
- 3313        [ "BY" Expr<et2, q2>              (. hasB := TRUE; .) ]
- 3314                                          (. IF braceCls = SymTab.ClSet THEN
- 3315                                               IF hasB THEN SemError(230) END;
- 3316                                               lo := SymTab.SetBaseLo(vt);
- 3317                                               span := SymTab.SetCount(vt);
- 3318                                               IF (et = SymTab.InvalidType)
- 3319                                                  OR (hasR AND (et2 =
- 3320                                                     SymTab.InvalidType)) THEN
- 3321                                               ELSE cl :=
- 3322                                                      SymTab.ClassOf(et);
- 3323                                                 IF hasR THEN
- 3324                                                   cl2 :=
- 3325                                                     SymTab.ClassOf(et2)
- 3326                                                 ELSE cl2 := SymTab.ClInt
- 3327                                                 END;
- 3328                                                 IF NOT SymTab.SetElemClassOk(cl)
- 3329                                                    OR (hasR AND NOT
- 3330                                                       SymTab.SetElemClassOk(cl2))
- 3331                                                 THEN
- 3332                                                   SemError(222)
- 3333                                                 ELSIF hasR
- 3334   AND SymTab.ConstInt(qe, v)
- 3335   AND SymTab.ConstInt(q2,
- 3336                                                       v2)
- 3337   AND ((v < lo)
- 3338                                                       OR (v2 < lo)
- 3339                                                       OR (v >= lo +
+ 3287                                                   SymTab.ClClass) THEN
+ 3288                                               QbeGen.CtorEnd(q)
+ 3289                                             ELSIF braceCls # SymTab.ClSet THEN
+ 3290                                               QbeGen.CopyOp("0", q)
+ 3291                                             END;
+ 3292                                             braceCls := savedCls; .)
+ 3293                                          (. astCur := astNode; .) .
+ 3294    BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
+ 3295              VAR node, tail: AST.Node>
+ 3296                                          (. VAR et, et2: SymTab.TypeIndex;
+ 3297                                               qe, q2: QbeGen.QVal;
+ 3298                                               v, v2, reps, k: INTEGER;
+ 3299                                               elem: SymTab.TypeIndex;
+ 3300                                               lo: INTEGER;
+ 3301                                               span: CARDINAL;
+ 3302                                               cl, cl2: INTEGER;
+ 3303                                               hasR, hasB: BOOLEAN;
+ 3304                                               astEl: AST.Node; .)
+ 3305      =                                   (. hasR := FALSE; hasB := FALSE;
+ 3306                                             reps := 1; .)
+ 3307        Expr<et, qe> (. astEl := astCur; .)
+ 3308        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
+ 3309                                               AST.NkSubrange, 0, astEl, astCur);
+ 3310                                             hasR := TRUE; .) ]
+ 3311        [ "BY" Expr<et2, q2>              (. hasB := TRUE; .) ]
+ 3312                                          (. IF braceCls = SymTab.ClSet THEN
+ 3313                                               IF hasB THEN SemError(230) END;
+ 3314                                               lo := SymTab.SetBaseLo(vt);
+ 3315                                               span := SymTab.SetCount(vt);
+ 3316                                               IF (et = SymTab.InvalidType)
+ 3317                                                  OR (hasR AND (et2 =
+ 3318                                                     SymTab.InvalidType)) THEN
+ 3319                                               ELSE cl :=
+ 3320                                                      SymTab.ClassOf(et);
+ 3321                                                 IF hasR THEN
+ 3322                                                   cl2 :=
+ 3323                                                     SymTab.ClassOf(et2)
+ 3324                                                 ELSE cl2 := SymTab.ClInt
+ 3325                                                 END;
+ 3326                                                 IF NOT SymTab.SetElemClassOk(cl)
+ 3327                                                    OR (hasR AND NOT
+ 3328                                                       SymTab.SetElemClassOk(cl2))
+ 3329                                                 THEN
+ 3330                                                   SemError(222)
+ 3331                                                 ELSIF hasR
+ 3332   AND SymTab.ConstInt(qe, v)
+ 3333   AND SymTab.ConstInt(q2,
+ 3334                                                       v2)
+ 3335   AND ((v < lo)
+ 3336                                                       OR (v2 < lo)
+ 3337                                                       OR (v >= lo +
+ 3338                                                          VAL(INTEGER, span))
+ 3339                                                       OR (v2 >= lo +
  3340                                                          VAL(INTEGER, span))
  3340                                                          VAL(INTEGER, span))
- 3341                                                       OR (v2 >= lo +
- 3342                                                          VAL(INTEGER, span))
- 3343                                                       OR (v > v2)) THEN
- 3344                                                   SemError(222)
- 3345                                                  ELSIF hasR THEN
- 3346                                                    QbeGen.SetRange(sq, qe, q2,
- 3347                                                      lo, span)
- 3348                                                  ELSIF SymTab.ConstInt(qe,
- 3349                                                          v)
- 3350   AND ((v < lo)
- 3351                                                        OR (v >= lo +
- 3352                                                           VAL(INTEGER,
- 3353                                                             span))) THEN
- 3354                                                    SemError(222)
- 3355                                                  ELSE QbeGen.SetBit(sq, qe,
- 3356                                                    lo, span)
- 3357                                                 END
- 3358                                               END
- 3359                                             ELSIF (braceCls = SymTab.ClArray)
+ 3341                                                       OR (v > v2)) THEN
+ 3342                                                   SemError(222)
+ 3343                                                  ELSIF hasR THEN
+ 3344                                                    QbeGen.SetRange(sq, qe, q2,
+ 3345                                                      lo, span)
+ 3346                                                  ELSIF SymTab.ConstInt(qe,
+ 3347                                                          v)
+ 3348   AND ((v < lo)
+ 3349                                                        OR (v >= lo +
+ 3350                                                           VAL(INTEGER,
+ 3351                                                             span))) THEN
+ 3352                                                    SemError(222)
+ 3353                                                  ELSE QbeGen.SetBit(sq, qe,
+ 3354                                                    lo, span)
+ 3355                                                 END
+ 3356                                               END
+ 3357                                             ELSIF (braceCls = SymTab.ClArray)
+ 3358                                                OR (braceCls =
+ 3359                                                   SymTab.ClRecord)
  3360                                                OR (braceCls =
  3360                                                OR (braceCls =
- 3361                                                   SymTab.ClRecord)
- 3362                                                OR (braceCls =
- 3363                                                   SymTab.ClClass) THEN
- 3364                                               IF hasR THEN SemError(230) END;
- 3365                                               reps := 1;
- 3366                                               IF hasB THEN
- 3367                                                 IF SymTab.ConstInt(q2, v2)
- 3368   AND (v2 >= 1) THEN
- 3369                                                   reps := v2
- 3370                                                 ELSE SemError(230)
- 3371                                                 END
- 3372                                               END;
- 3373                                               k := 0;
- 3374                                               WHILE k < reps DO
- 3375                                                 QbeGen.CtorElem(qe);
- 3376                                                 INC(k)
- 3377                                               END
- 3378                                             END; .)
- 3379                                          (. (* the BY form repeats the
- 3380                                               element; keep the AST in
- 3381                                               step with CtorElem *)
- 3382                                             k := 0;
- 3383                                             WHILE k < reps DO
- 3384                                               AstAppend(AST.NkBlock,
- 3385                                                 node, tail, astEl);
- 3386                                               INC(k)
- 3387                                             END; .) .
- 3388    SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node>         (. VAR et, et2: SymTab.TypeIndex;
- 3389                                               qe, q2: QbeGen.QVal;
- 3390                                               v, v2: INTEGER;
- 3391                                               lo: INTEGER;
- 3392                                               span: CARDINAL;
- 3393                                               cl, cl2: INTEGER;
- 3394                                               hasR: BOOLEAN;
- 3395                                               astEl: AST.Node; .)
- 3396      =                                   (. hasR := FALSE; .)
- 3397        Expr<et, qe> (. astEl := astCur; .)
- 3398        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
- 3399                                               AST.NkSubrange, 0, astEl, astCur);
- 3400                                             hasR := TRUE; .) ]
- 3401                                          (. lo := SymTab.SetBaseLo(st);
- 3402                                             span := SymTab.SetCount(st);
- 3403                                             IF (et = SymTab.InvalidType)
- 3404                                                OR (hasR AND (et2 =
- 3405                                                   SymTab.InvalidType)) THEN
- 3406                                             ELSE cl :=
- 3407                                                    SymTab.ClassOf(et);
- 3408                                               IF hasR THEN
- 3409                                                 cl2 :=
- 3410                                                   SymTab.ClassOf(et2)
- 3411                                               ELSE cl2 := SymTab.ClInt
- 3412                                               END;
- 3413                                               IF NOT SymTab.SetElemClassOk(cl)
- 3414                                                  OR (hasR AND NOT
- 3415                                                     SymTab.SetElemClassOk(cl2))
- 3416                                               THEN
- 3417                                                 SemError(222)
- 3418                                               ELSIF hasR
- 3419   AND SymTab.ConstInt(qe, v)
- 3420   AND SymTab.ConstInt(q2,
- 3421                                                     v2)
- 3422   AND ((v < lo)
- 3423                                                     OR (v2 < lo)
- 3424                                                     OR (v >= lo +
+ 3361                                                   SymTab.ClClass) THEN
+ 3362                                               IF hasR THEN SemError(230) END;
+ 3363                                               reps := 1;
+ 3364                                               IF hasB THEN
+ 3365                                                 IF SymTab.ConstInt(q2, v2)
+ 3366   AND (v2 >= 1) THEN
+ 3367                                                   reps := v2
+ 3368                                                 ELSE SemError(230)
+ 3369                                                 END
+ 3370                                               END;
+ 3371                                               k := 0;
+ 3372                                               WHILE k < reps DO
+ 3373                                                 QbeGen.CtorElem(qe);
+ 3374                                                 INC(k)
+ 3375                                               END
+ 3376                                             END; .)
+ 3377                                          (. (* the BY form repeats the
+ 3378                                               element; keep the AST in
+ 3379                                               step with CtorElem *)
+ 3380                                             k := 0;
+ 3381                                             WHILE k < reps DO
+ 3382                                               AstAppend(AST.NkBlock,
+ 3383                                                 node, tail, astEl);
+ 3384                                               INC(k)
+ 3385                                             END; .) .
+ 3386    SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node>         (. VAR et, et2: SymTab.TypeIndex;
+ 3387                                               qe, q2: QbeGen.QVal;
+ 3388                                               v, v2: INTEGER;
+ 3389                                               lo: INTEGER;
+ 3390                                               span: CARDINAL;
+ 3391                                               cl, cl2: INTEGER;
+ 3392                                               hasR: BOOLEAN;
+ 3393                                               astEl: AST.Node; .)
+ 3394      =                                   (. hasR := FALSE; .)
+ 3395        Expr<et, qe> (. astEl := astCur; .)
+ 3396        [ ".." Expr<et2, q2>              (. astEl := AST.MakeBin(
+ 3397                                               AST.NkSubrange, 0, astEl, astCur);
+ 3398                                             hasR := TRUE; .) ]
+ 3399                                          (. lo := SymTab.SetBaseLo(st);
+ 3400                                             span := SymTab.SetCount(st);
+ 3401                                             IF (et = SymTab.InvalidType)
+ 3402                                                OR (hasR AND (et2 =
+ 3403                                                   SymTab.InvalidType)) THEN
+ 3404                                             ELSE cl :=
+ 3405                                                    SymTab.ClassOf(et);
+ 3406                                               IF hasR THEN
+ 3407                                                 cl2 :=
+ 3408                                                   SymTab.ClassOf(et2)
+ 3409                                               ELSE cl2 := SymTab.ClInt
+ 3410                                               END;
+ 3411                                               IF NOT SymTab.SetElemClassOk(cl)
+ 3412                                                  OR (hasR AND NOT
+ 3413                                                     SymTab.SetElemClassOk(cl2))
+ 3414                                               THEN
+ 3415                                                 SemError(222)
+ 3416                                               ELSIF hasR
+ 3417   AND SymTab.ConstInt(qe, v)
+ 3418   AND SymTab.ConstInt(q2,
+ 3419                                                     v2)
+ 3420   AND ((v < lo)
+ 3421                                                     OR (v2 < lo)
+ 3422                                                     OR (v >= lo +
+ 3423                                                        VAL(INTEGER, span))
+ 3424                                                     OR (v2 >= lo +
  3425                                                        VAL(INTEGER, span))
  3425                                                        VAL(INTEGER, span))
- 3426                                                     OR (v2 >= lo +
- 3427                                                        VAL(INTEGER, span))
- 3428                                                     OR (v > v2)) THEN
- 3429                                                 SemError(222)
- 3430                                                ELSIF hasR THEN
- 3431                                                  QbeGen.SetRange(sq, qe, q2,
- 3432                                                    lo, span)
- 3433                                                ELSIF SymTab.ConstInt(qe,
- 3434                                                        v)
- 3435   AND ((v < lo)
- 3436                                                      OR (v >= lo +
- 3437                                                         VAL(INTEGER,
- 3438                                                           span))) THEN
- 3439                                                  SemError(222)
- 3440                                                ELSE QbeGen.SetBit(sq, qe,
- 3441                                                  lo, span)
- 3442                                               END
- 3443                                             END; .)
- 3444                                          (. AST.SetChild(node,
- 3445                                               AST.NChild(node), astEl); .) .
- 3446    GetIdent<VAR n: SymTab.Name>
- 3447      = ident                             (. LexName(n); .) .
- 3448  
- 3449  END M2.
+ 3426                                                     OR (v > v2)) THEN
+ 3427                                                 SemError(222)
+ 3428                                                ELSIF hasR THEN
+ 3429                                                  QbeGen.SetRange(sq, qe, q2,
+ 3430                                                    lo, span)
+ 3431                                                ELSIF SymTab.ConstInt(qe,
+ 3432                                                        v)
+ 3433   AND ((v < lo)
+ 3434                                                      OR (v >= lo +
+ 3435                                                         VAL(INTEGER,
+ 3436                                                           span))) THEN
+ 3437                                                  SemError(222)
+ 3438                                                ELSE QbeGen.SetBit(sq, qe,
+ 3439                                                  lo, span)
+ 3440                                               END
+ 3441                                             END; .)
+ 3442                                          (. AST.SetChild(node,
+ 3443                                               AST.NChild(node), astEl); .) .
+ 3444    GetIdent<VAR n: SymTab.Name>
+ 3445      = ident                             (. LexName(n); .) .
+ 3446  
+ 3447  END M2.
 
 
     0 errors
     0 errors
 
 

+ 1 - 3
compiler/src/SymTab.def

@@ -447,9 +447,7 @@ PROCEDURE FwdVarRef (name: ARRAY OF CHAR; kind: INTEGER;
                      VAR id: INTEGER; VAR t: TypeIndex): BOOLEAN;
                      VAR id: INTEGER; VAR t: TypeIndex): BOOLEAN;
 (* Registers a reference to a module-level name used inside a procedure
 (* Registers a reference to a module-level name used inside a procedure
    body before its declaration (forward variable).  kind is KindVar
    body before its declaration (forward variable).  kind is KindVar
-   (variable) or KindProc (procedure); id/t identify the placeholder. *)
-PROCEDURE IsFwdVar (t: TypeIndex): BOOLEAN;
-(* TRUE for a forward-variable placeholder: type checks are lenient. *)
+   (variable) or KindProc (procedure); id identifies the reference. *)
 
 
 PROCEDURE FwdVarName (id: INTEGER; VAR name: Name);
 PROCEDURE FwdVarName (id: INTEGER; VAR name: Name);
 (* The identifier behind forward reference id (1-based). *)
 (* The identifier behind forward reference id (1-based). *)

+ 6 - 26
compiler/src/SymTab.mod

@@ -95,7 +95,6 @@ VAR
   nFwdVar : CARDINAL;
   nFwdVar : CARDINAL;
   fwdVarName : ARRAY [0 .. 255] OF Name;
   fwdVarName : ARRAY [0 .. 255] OF Name;
   fwdVarKind : ARRAY [0 .. 255] OF INTEGER;   (* KindVar / KindProc *)
   fwdVarKind : ARRAY [0 .. 255] OF INTEGER;   (* KindVar / KindProc *)
-  fwdVarT : ARRAY [0 .. 255] OF TypeIndex;    (* placeholder type index *)
   fwdVarScope : ARRAY [0 .. 255] OF ScopePtr; (* scope at reference time *)
   fwdVarScope : ARRAY [0 .. 255] OF ScopePtr; (* scope at reference time *)
   tparent : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
   tparent : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
   tscope : ARRAY [0 .. MaxTypes - 1] OF ScopePtr;
   tscope : ARRAY [0 .. MaxTypes - 1] OF ScopePtr;
@@ -2569,22 +2568,10 @@ PROCEDURE GlobalRef (name: ARRAY OF CHAR; VAR g: Name): BOOLEAN;
 (* ---- forward module-level variables ----
 (* ---- forward module-level variables ----
    Inside a procedure body a not-yet-declared identifier may be a
    Inside a procedure body a not-yet-declared identifier may be a
    module-level variable declared further down (gm2 tolerates this).
    module-level variable declared further down (gm2 tolerates this).
-   SymTab records the reference and reports it (FwdVarFix) once the
+   SymTab records the reference and reports it (FwdVarResolve) once the
    module's declarations are complete; an identifier never declared
    module's declarations are complete; an identifier never declared
-   still yields a 201. *)
-
-PROCEDURE IsFwdVar (t: TypeIndex): BOOLEAN;
-(* TRUE when t is a forward-variable placeholder (its real type is not
-   yet known, so type checks must be lenient). *)
-  VAR k: CARDINAL;
-  BEGIN
-    k := 0;
-    WHILE k < nFwdVar DO
-      IF fwdVarT[k] = t THEN RETURN TRUE END;
-      INC(k)
-    END;
-    RETURN FALSE
-  END IsFwdVar;
+   still yields a 201.  The reference's type is InvalidType, so the
+   same "skip checks on an unknown type" rule as elsewhere applies. *)
 
 
 PROCEDURE FwdVarName (id: INTEGER; VAR name: Name);
 PROCEDURE FwdVarName (id: INTEGER; VAR name: Name);
 (* The identifier behind a forward reference id (1-based). *)
 (* The identifier behind a forward reference id (1-based). *)
@@ -2606,7 +2593,7 @@ PROCEDURE FwdVarRef (name: ARRAY OF CHAR; kind: INTEGER;
     WHILE k < nFwdVar DO
     WHILE k < nFwdVar DO
       IF Equal(fwdVarName[k], name) THEN
       IF Equal(fwdVarName[k], name) THEN
         id := VAL(INTEGER, k) + 1;
         id := VAL(INTEGER, k) + 1;
-        t := fwdVarT[k];
+        t := InvalidType;
         RETURN TRUE
         RETURN TRUE
       END;
       END;
       INC(k)
       INC(k)
@@ -2617,8 +2604,7 @@ PROCEDURE FwdVarRef (name: ARRAY OF CHAR; kind: INTEGER;
     Assign(fwdVarName[nFwdVar], name);
     Assign(fwdVarName[nFwdVar], name);
     fwdVarKind[nFwdVar] := kind;
     fwdVarKind[nFwdVar] := kind;
     fwdVarScope[nFwdVar] := curScope;
     fwdVarScope[nFwdVar] := curScope;
-    t := NewAlias();
-    fwdVarT[nFwdVar] := t;
+    t := InvalidType;
     id := VAL(INTEGER, nFwdVar) + 1;
     id := VAL(INTEGER, nFwdVar) + 1;
     INC(nFwdVar);
     INC(nFwdVar);
     RETURN TRUE
     RETURN TRUE
@@ -2628,8 +2614,7 @@ PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
 (* Resolves forward reference id against the unit's declarations.  The
 (* Resolves forward reference id against the unit's declarations.  The
    scope recorded at reference time is used, so this may run after the
    scope recorded at reference time is used, so this may run after the
    module scope has been popped (the resolve/check pass).
    module scope has been popped (the resolve/check pass).
-   TRUE when the name now exists; sets the recorded placeholder's
-   target so ClassOf/Assignable see the real type. *)
+   TRUE when the name now exists with the expected kind. *)
   VAR node: SymPtr;
   VAR node: SymPtr;
   BEGIN
   BEGIN
     IF (id < 1) OR (id > VAL(INTEGER, nFwdVar)) THEN RETURN TRUE END;
     IF (id < 1) OR (id > VAL(INTEGER, nFwdVar)) THEN RETURN TRUE END;
@@ -2642,7 +2627,6 @@ PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
         RETURN FALSE
         RETURN FALSE
       END
       END
     END;
     END;
-    fwdVarT[id - 1] := node^.typ;
     RETURN TRUE
     RETURN TRUE
   END FwdVarResolve;
   END FwdVarResolve;
 
 
@@ -2720,7 +2704,6 @@ PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
   VAR rs, rd: TypeIndex;
   VAR rs, rd: TypeIndex;
   BEGIN
   BEGIN
     IF (src = InvalidType) OR (dst = InvalidType) THEN RETURN TRUE END;
     IF (src = InvalidType) OR (dst = InvalidType) THEN RETURN TRUE END;
-    IF IsFwdVar(src) OR IsFwdVar(dst) THEN RETURN TRUE END;
     rs := Resolve(src); rd := Resolve(dst);
     rs := Resolve(src); rd := Resolve(dst);
     IF rs = rd THEN RETURN TRUE END;
     IF rs = rd THEN RETURN TRUE END;
     IF (rs = InvalidType) OR (rd = InvalidType) THEN RETURN TRUE END;
     IF (rs = InvalidType) OR (rd = InvalidType) THEN RETURN TRUE END;
@@ -2780,7 +2763,6 @@ PROCEDURE ArithCheck (l, r: TypeIndex; divmod: BOOLEAN;
   BEGIN
   BEGIN
     res := InvalidType;
     res := InvalidType;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
-    IF IsFwdVar(l) OR IsFwdVar(r) THEN res := dInt; RETURN TRUE END;
     IF (IsLongFamily(l) AND IsLongFamily(r))
     IF (IsLongFamily(l) AND IsLongFamily(r))
        OR (IsLongFamily(l) AND IsIntFamily(r))
        OR (IsLongFamily(l) AND IsIntFamily(r))
        OR (IsIntFamily(l) AND IsLongFamily(r)) THEN
        OR (IsIntFamily(l) AND IsLongFamily(r)) THEN
@@ -2843,7 +2825,6 @@ PROCEDURE StrCompat (l, r: TypeIndex): BOOLEAN;
 PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
 PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
   VAR rl, rr: TypeIndex;
   VAR rl, rr: TypeIndex;
   BEGIN
   BEGIN
-    IF IsFwdVar(l) OR IsFwdVar(r) THEN RETURN TRUE END;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
     IF ClassOf(l) = ClNil THEN
     IF ClassOf(l) = ClNil THEN
       RETURN (ClassOf(r) = ClNil) OR (ClassOf(r) = ClPtr)
       RETURN (ClassOf(r) = ClNil) OR (ClassOf(r) = ClPtr)
@@ -2890,7 +2871,6 @@ PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
 
 
 PROCEDURE OrdCheck (l, r: TypeIndex): BOOLEAN;
 PROCEDURE OrdCheck (l, r: TypeIndex): BOOLEAN;
   BEGIN
   BEGIN
-    IF IsFwdVar(l) OR IsFwdVar(r) THEN RETURN TRUE END;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
     IF IsIntFamily(l) AND IsIntFamily(r) THEN RETURN TRUE END;
     IF IsIntFamily(l) AND IsIntFamily(r) THEN RETURN TRUE END;
     IF (ClassOf(l) = ClLong) AND (ClassOf(r) = ClLong) THEN
     IF (ClassOf(l) = ClLong) AND (ClassOf(r) = ClLong) THEN