ソースを参照

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 2 日 前
親
コミット
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;
 (* 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);
    FlushForward resolves it once the unit's declarations are complete. *)
 

+ 1 - 1
compiler/src/Check.mod

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

+ 4 - 6
compiler/src/M2.atg

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

+ 920 - 922
compiler/src/M2.lst

@@ -2146,14 +2146,14 @@ Listing:
  2127                                               fo: INTEGER;
  2128                                               isOpen: BOOLEAN;
  2129                                               qb, cv: QbeGen.QVal;
- 2130                                               fid, fref, slot: INTEGER;
+ 2130                                               fid, fref: INTEGER;
  2131                                               r: BOOLEAN;
  2132                                                astDes, astSel: AST.Node;
  2133                                               fwd: BOOLEAN; .)
  2134      =                                   (. methCls := SymTab.InvalidType;
  2135                                             QbeGen.CopyOp(n, qn);
  2136                                             sfx := FALSE; fwd := FALSE;
- 2137                                             fid := 0; fref := 0; slot := 0;
+ 2137                                             fid := 0; fref := 0;
  2138                                             IF NOT SymTab.Lookup(n) THEN
  2139                                               (* a bare method name inside
  2140                                                  a CLASS IMPLEMENTATION
@@ -2176,7 +2176,7 @@ Listing:
  2157                                                 k := SymTab.KindVar;
  2158                                                 r := SymTab.FwdVarRef(n, k,
  2159                                                   fref, t);
- 2160                                                  Check.NoteForward(fref, 0);
+ 2160                                                  Check.NoteForward(fref);
  2161                                                  QbeGen.CopyOp("@", q);
  2162                                                 sfx := TRUE; fwd := TRUE
  2163                                               ELSE
@@ -2537,935 +2537,933 @@ Listing:
  2518                 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
  2519               ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
  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) #
- 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 =
- 3194                                                        SymTab.ClChar)
+ 3194                                                        SymTab.ClBool)
  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 =
- 3201                                                        SymTab.ClChar)
+ 3201                                                        SymTab.ClBool)
  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 =
- 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 =
- 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))
- 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 =
- 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))
- 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
 

+ 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;
 (* Registers a reference to a module-level name used inside a procedure
    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);
 (* The identifier behind forward reference id (1-based). *)

+ 6 - 26
compiler/src/SymTab.mod

@@ -95,7 +95,6 @@ VAR
   nFwdVar : CARDINAL;
   fwdVarName : ARRAY [0 .. 255] OF Name;
   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 *)
   tparent : ARRAY [0 .. MaxTypes - 1] OF TypeIndex;
   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 ----
    Inside a procedure body a not-yet-declared identifier may be a
    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
-   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);
 (* 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
       IF Equal(fwdVarName[k], name) THEN
         id := VAL(INTEGER, k) + 1;
-        t := fwdVarT[k];
+        t := InvalidType;
         RETURN TRUE
       END;
       INC(k)
@@ -2617,8 +2604,7 @@ PROCEDURE FwdVarRef (name: ARRAY OF CHAR; kind: INTEGER;
     Assign(fwdVarName[nFwdVar], name);
     fwdVarKind[nFwdVar] := kind;
     fwdVarScope[nFwdVar] := curScope;
-    t := NewAlias();
-    fwdVarT[nFwdVar] := t;
+    t := InvalidType;
     id := VAL(INTEGER, nFwdVar) + 1;
     INC(nFwdVar);
     RETURN TRUE
@@ -2628,8 +2614,7 @@ PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
 (* Resolves forward reference id against the unit's declarations.  The
    scope recorded at reference time is used, so this may run after the
    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;
   BEGIN
     IF (id < 1) OR (id > VAL(INTEGER, nFwdVar)) THEN RETURN TRUE END;
@@ -2642,7 +2627,6 @@ PROCEDURE FwdVarResolve (id: INTEGER): BOOLEAN;
         RETURN FALSE
       END
     END;
-    fwdVarT[id - 1] := node^.typ;
     RETURN TRUE
   END FwdVarResolve;
 
@@ -2720,7 +2704,6 @@ PROCEDURE Assignable (src, dst: TypeIndex): BOOLEAN;
   VAR rs, rd: TypeIndex;
   BEGIN
     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);
     IF rs = rd 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
     res := InvalidType;
     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))
        OR (IsLongFamily(l) AND IsIntFamily(r))
        OR (IsIntFamily(l) AND IsLongFamily(r)) THEN
@@ -2843,7 +2825,6 @@ PROCEDURE StrCompat (l, r: TypeIndex): BOOLEAN;
 PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
   VAR rl, rr: TypeIndex;
   BEGIN
-    IF IsFwdVar(l) OR IsFwdVar(r) THEN RETURN TRUE END;
     IF (l = InvalidType) OR (r = InvalidType) THEN RETURN TRUE END;
     IF ClassOf(l) = ClNil THEN
       RETURN (ClassOf(r) = ClNil) OR (ClassOf(r) = ClPtr)
@@ -2890,7 +2871,6 @@ PROCEDURE EqCheck (l, r: TypeIndex): BOOLEAN;
 
 PROCEDURE OrdCheck (l, r: TypeIndex): BOOLEAN;
   BEGIN
-    IF IsFwdVar(l) OR IsFwdVar(r) 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 (ClassOf(l) = ClLong) AND (ClassOf(r) = ClLong) THEN