فهرست منبع

lower L5 (sets/strings): set arithmetic and string concatenation

Extend the arithmetic binop to mirror SimExpr/Term:
- set + - (union/difference) and * / (intersection/symmetric difference)
  via SetBinOp, result type NewSet(NewSubR(0, maxwords*32-1));
- string concatenation (StrFold, else StrCat with a 1-char char operand);
- proper long/real result types (Op3L with WidenLong, Op3 with isR),
  replacing the previous unconditional IntType.

t_lower5set byte-matches.  Suite 190/190; FIXPOINT OK (stage2 ==
stage3, 3,304,346 bytes).
Eric Streit 6 روز پیش
والد
کامیت
081869f333
3فایلهای تغییر یافته به همراه94 افزوده شده و 20 حذف شده
  1. 1 0
      compiler/run_tests.sh
  2. 76 20
      compiler/src/Lower.mod
  3. 17 0
      compiler/tests/t_lower5set.mod

+ 1 - 0
compiler/run_tests.sh

@@ -474,6 +474,7 @@ lower_ok t_lower4case.mod
 lower_ok t_lower4with.mod
 lower_ok t_lower5.mod
 lower_ok t_lower5lit.mod
+lower_ok t_lower5set.mod
 
 # --- step 7 gate: compiler sources free of gm2-only imports.
 #     FileIO is the last module to port (see docs/summary_step7.md);

+ 76 - 20
compiler/src/Lower.mod

@@ -973,6 +973,8 @@ PROCEDURE LowerExprFull (n: AST.Node; VAR t: SymTab.TypeIndex;
       kind, op, rop: INTEGER;
       folded, isR, isCh: BOOLEAN;
       i: CARDINAL; el: AST.Node;
+      lw, rw, mw: CARDINAL; idx: INTEGER; fok, isL: BOOLEAN;
+      lt, rt: SymTab.TypeIndex; qw: QbeGen.QVal;
   BEGIN
     IF AST.Kind(n) = AST.NkDesignator THEN
       LowerDesign(n, t, k, q, qn, sfx);
@@ -1097,28 +1099,82 @@ PROCEDURE LowerExprFull (n: AST.Node; VAR t: SymTab.TypeIndex;
       ELSE
         LowerExpr(AST.Child(n, 0), t, q);
         LowerExpr(AST.Child(n, 1), t2, q2);
-        kind := 0;
-        IF op = AST.OpSub THEN kind := 1
-        ELSIF op = AST.OpMul THEN kind := 2
-        ELSIF op = AST.OpDiv THEN kind := 3
-        ELSIF op = AST.OpMod THEN kind := 4
-        END;
-        folded := FALSE;
-        IF QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
-          folded := QbeGen.Fold2(kind, q, q2, qf)
-        END;
-        IF folded THEN QbeGen.CopyOp(qf, q)
-        ELSE
-          QbeGen.NewTemp(qt);
-          IF op = AST.OpAdd THEN QbeGen.Op3("add", qt, q, q2, FALSE)
-          ELSIF op = AST.OpSub THEN QbeGen.Op3("sub", qt, q, q2, FALSE)
-          ELSIF op = AST.OpMul THEN QbeGen.Op3("mul", qt, q, q2, FALSE)
-          ELSIF op = AST.OpDiv THEN QbeGen.Op3("div", qt, q, q2, FALSE)
-          ELSE QbeGen.Op3("rem", qt, q, q2, FALSE)
+        IF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
+           AND (SymTab.ClassOf(t) = SymTab.ClSet)
+           AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
+          (* set union/diff (Add/Sub) or intersection/symdiff (Mul/Div) *)
+          lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
+          mw := lw; IF rw > mw THEN mw := rw END;
+          IF op = AST.OpAdd THEN idx := 0
+          ELSIF op = AST.OpSub THEN idx := 2
+          ELSIF op = AST.OpMul THEN idx := 1
+          ELSE idx := 3
           END;
+          QbeGen.SetBinOp(idx, q, q2, lw, rw, qt);
+          t := SymTab.NewSet(SymTab.NewSubR(0, VAL(INTEGER, mw) * 32 - 1));
           QbeGen.CopyOp(qt, q)
-        END;
-        t := SymTab.IntType()
+        ELSIF (op = AST.OpAdd)
+           AND (SymTab.StrCompat(t, t2)
+                OR (SymTab.IsStrType(t) AND (SymTab.ClassOf(t2) = SymTab.ClChar))
+                OR ((SymTab.ClassOf(t) = SymTab.ClChar) AND SymTab.IsStrType(t2))) THEN
+          QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2), qt, fok);
+          IF NOT fok THEN
+            IF SymTab.StrCompat(t, t2) THEN QbeGen.StrCat(q, q2, qt)
+            ELSIF SymTab.IsStrType(t) THEN
+              QbeGen.DeclCharStr(q2, qs); QbeGen.StrCat(q, qs, qt)
+            ELSE
+              QbeGen.DeclCharStr(q, qs); QbeGen.StrCat(qs, q2, qt)
+            END
+          END;
+          t := SymTab.NewStr(); QbeGen.CopyOp(qt, q)
+        ELSE
+          lt := t; rt := t2;
+          IF (SymTab.ClassOf(lt) = SymTab.ClReal)
+             OR (SymTab.ClassOf(rt) = SymTab.ClReal) THEN
+            t := SymTab.RealType()
+          ELSIF SymTab.IsLongFamily(lt) OR SymTab.IsLongFamily(rt) THEN
+            t := SymTab.LongType()
+          ELSE t := SymTab.IntType()
+          END;
+          isL := SymTab.IsLongFamily(t);
+          isR := SymTab.ClassOf(t) = SymTab.ClReal;
+          kind := 0;
+          IF op = AST.OpSub THEN kind := 1
+          ELSIF op = AST.OpMul THEN kind := 2
+          ELSIF op = AST.OpDiv THEN kind := 3
+          ELSIF op = AST.OpMod THEN kind := 4
+          END;
+          folded := FALSE;
+          IF (NOT isL) AND (NOT isR) AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
+            folded := QbeGen.Fold2(kind, q, q2, qf)
+          END;
+          IF folded THEN QbeGen.CopyOp(qf, q)
+          ELSE
+            IF isL THEN
+              IF SymTab.IsIntFamily(lt) THEN
+                QbeGen.WidenLong(q, qw); QbeGen.CopyOp(qw, q)
+              END;
+              IF SymTab.IsIntFamily(rt) THEN
+                QbeGen.WidenLong(q2, qw); QbeGen.CopyOp(qw, q2)
+              END;
+              QbeGen.NewTemp(qt);
+              IF op = AST.OpAdd THEN QbeGen.Op3L("add", qt, q, q2)
+              ELSIF op = AST.OpSub THEN QbeGen.Op3L("sub", qt, q, q2)
+              ELSIF op = AST.OpMul THEN QbeGen.Op3L("mul", qt, q, q2)
+              ELSE QbeGen.Op3L("div", qt, q, q2)
+              END
+            ELSE
+              QbeGen.NewTemp(qt);
+              IF op = AST.OpAdd THEN QbeGen.Op3("add", qt, q, q2, isR)
+              ELSIF op = AST.OpSub THEN QbeGen.Op3("sub", qt, q, q2, isR)
+              ELSIF op = AST.OpMul THEN QbeGen.Op3("mul", qt, q, q2, isR)
+              ELSIF op = AST.OpDiv THEN QbeGen.Op3("div", qt, q, q2, isR)
+              ELSE QbeGen.Op3("rem", qt, q, q2, isR)
+              END
+            END;
+            QbeGen.CopyOp(qt, q)
+          END
+        END
       END
     END
   END LowerExprFull;

+ 17 - 0
compiler/tests/t_lower5set.mod

@@ -0,0 +1,17 @@
+MODULE TLower5Set;
+(* Lower slice L5: set arithmetic (+, -) and string concatenation.  Exit 42. *)
+TYPE
+  Vec = ARRAY [0..7] OF CHAR;
+VAR
+  a, b, c : SET OF [0..7];
+  t : Vec;
+  i, ExitCode : INTEGER;
+BEGIN
+  a := {1, 2, 3};
+  b := {3, 4};
+  c := a + b;
+  c := c - b;
+  t := "ab" + "cd";
+  i := ORD(t[2]);
+  IF (1 IN c) AND (2 IN c) THEN ExitCode := i - 57 ELSE ExitCode := 0 END
+END TLower5Set.