소스 검색

two-phase slice 4b: builtins as named NkCall nodes

CHR/ORD/CAP/UCHR/CHR8/UORD/ABS/ADR/SIZE/HIGH/LEN/MIN/MAX/SHIFT/ROTATE
and VAL now build NkCall with an NkIdent naming the builtin and the
argument(s) from astCur/astArg2.  Node-building actions are inserted
before the existing emit actions, which are unchanged.  Nodes are inert.

Still NoNode: brace/set literals and ResultComp call suffixes.  Lower
and .ssa byte-compare not started.

Gates: suite 178/178; fixpoint OK (stage2 == stage3, 2987484 bytes).

See docs/summary_two-phase-slice4.md.
Eric Streit 1 주 전
부모
커밋
5811fe4bcd
4개의 변경된 파일과 863개의 추가작업 그리고 684개의 파일을 삭제
  1. 72 8
      compiler/src/M2.atg
  2. 736 672
      compiler/src/M2.lst
  3. 6 4
      docs/plan-two-phase.md
  4. 49 0
      docs/summary_two-phase-slice4.md

+ 72 - 8
compiler/src/M2.atg

@@ -2622,7 +2622,8 @@ PRODUCTIONS
                                               astD: AST.Node;
                                               astCall: BOOLEAN;
                                               astNode, astNot: AST.Node;
-                                              j: CARDINAL; .)
+                                              j: CARDINAL;
+                                              astArg2: AST.Node; .)
     = (. astIsLit := FALSE; .)
     ( integer                           (. LexString(s);
                                            QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
@@ -2786,7 +2787,7 @@ PRODUCTIONS
       | ( "LEN" | "LENGTH" )            (. isHigh := FALSE; .) )
       "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
                                             isU := FALSE; .)
-          | string                       (. LexString(s);
+          | string                       (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
                                             isStr := TRUE;
                                             isU := FALSE;
                                             IF SymTab.StrLen(s) = 3 THEN
@@ -2800,7 +2801,7 @@ PRODUCTIONS
                                             END;
                                             dk := -1;
                                             qn[0] := CHR(0); .)
-          | ustring                      (. LexString(s);
+          | ustring                      (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
                                             QbeGen.DeclUStr(s, qd, isU, ucp,
                                               uok);
                                             isStr := FALSE;
@@ -2819,7 +2820,14 @@ PRODUCTIONS
                                             dk := -1;
                                             qn[0] := CHR(0); .) )
       ")"
-                                        (. IF (dt # SymTab.InvalidType)
+                                        (. astNode := AST.MakeNode(AST.NkCall);
+   IF isHigh THEN AST.SetChild(astNode, 0,
+     AST.MakeLeaf(AST.NkIdent, "HIGH"))
+   ELSE AST.SetChild(astNode, 0,
+     AST.MakeLeaf(AST.NkIdent, "LEN")) END;
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE;
+                                           IF (dt # SymTab.InvalidType)
   AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
                                              (* UString: the count is
                                                 the descriptor header *)
@@ -2886,6 +2894,10 @@ PRODUCTIONS
                                               QbeGen.CopyOp(qr, q)
                                             END; .)
     | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF dt = SymTab.InvalidType THEN
                                              t := SymTab.InvalidType;
                                              QbeGen.CopyOp("0", q)
@@ -2896,8 +2908,16 @@ PRODUCTIONS
                                            END; .)
     | ( "SHIFT"                         (. isMax := FALSE; .)
       | "ROTATE"                        (. isMax := TRUE; .) )
-      "(" Expr<et, q> "," Expr<et2, q2> ")"
-                                        (. (* set shift/rotate: isMax
+      "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
+                                        (. astNode := AST.MakeNode(AST.NkCall);
+   IF isMax THEN AST.SetChild(astNode, 0,
+     AST.MakeLeaf(AST.NkIdent, "ROTATE"))
+   ELSE AST.SetChild(astNode, 0,
+     AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
+   IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
+   astCur := astNode; astIsLit := TRUE;
+                                           (* set shift/rotate: isMax
                                               doubles as "rotate" *)
                                            IF (et # SymTab.InvalidType)
                                               AND (SymTab.ClassOf(et) =
@@ -2915,7 +2935,14 @@ PRODUCTIONS
     | ( "MIN"                           (. isMax := FALSE; .)
       | "MAX"                           (. isMax := TRUE; .) )
       "(" Design<dt, dk, qd, qn, sfx> ")"
-                                        (. IF (dt # SymTab.InvalidType)
+                                        (. astNode := AST.MakeNode(AST.NkCall);
+   IF isMax THEN AST.SetChild(astNode, 0,
+     AST.MakeLeaf(AST.NkIdent, "MAX"))
+   ELSE AST.SetChild(astNode, 0,
+     AST.MakeLeaf(AST.NkIdent, "MIN")) END;
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE;
+                                           IF (dt # SymTab.InvalidType)
  AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
                                              (* REAL/LONGREAL: the
                                                 implementation bounds *)
@@ -2949,6 +2976,10 @@ PRODUCTIONS
                                              QbeGen.CopyOp("0", q)
                                            END; .)
     | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF dt = SymTab.InvalidType THEN
                                              t := SymTab.InvalidType;
                                              QbeGen.CopyOp("0", q)
@@ -2964,11 +2995,19 @@ PRODUCTIONS
                                              t := SymTab.AddrType()
                                            END; .)
     | "CHR" "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF (et # SymTab.InvalidType)
  AND NOT SymTab.IsIntFamily(et) THEN
                                              SemError(211) END;
                                            t := SymTab.CharType(); .)
     | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF et # SymTab.InvalidType THEN
                                              IF (SymTab.ClassOf(et) #
                                                  SymTab.ClChar)
@@ -2981,10 +3020,18 @@ PRODUCTIONS
                                            END;
                                            t := SymTab.IntType(); .)
     | "CAP" "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. QbeGen.CapQ(q, qa);
                                            QbeGen.CopyOp(qa, q);
                                            t := SymTab.CharType(); .)
     | "UCHR" "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. (* UCHR: the UCHAR constructor.
                                               CHAR -> UCHAR (identity);
                                               INTEGER familly -> UCHAR
@@ -2995,6 +3042,10 @@ PRODUCTIONS
                                              SemError(211) END;
                                            t := SymTab.UCharType(); .)
     | "CHR8" "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF (et # SymTab.InvalidType)
   AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
                                              SemError(211) END;
@@ -3002,6 +3053,10 @@ PRODUCTIONS
                                            QbeGen.CheckRange(qa, "0", "255");
                                            t := SymTab.CharType(); .)
     | "UORD" "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. (* UORD(u): the codepoint as a
                                               32-bit ordinal (INTEGER),
                                               cf. ORD for CHAR. *)
@@ -3010,6 +3065,10 @@ PRODUCTIONS
                                              SemError(211) END;
                                            t := SymTab.IntType(); .)
     | "ABS" "(" Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF (et # SymTab.InvalidType)
  AND NOT SymTab.IsIntFamily(et)
  AND (SymTab.ClassOf(et) #
@@ -3021,7 +3080,12 @@ PRODUCTIONS
                                              QbeGen.CopyOp(qa, q)
                                            END;
                                            t := et; .)
-    | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
+    | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
+    (. astNode := AST.MakeNode(AST.NkCall);
+   AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
+   IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
+   IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
+   astCur := astNode; astIsLit := TRUE; .)
                                         (. IF NOT SymTab.Lookup(vn) THEN
                                              SemError(201);
                                              t := SymTab.InvalidType

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 736 - 672
compiler/src/M2.lst


+ 6 - 4
docs/plan-two-phase.md

@@ -71,11 +71,13 @@ Suggested slices, each ending in `build.sh` + `run_tests.sh` +
    Nothing consumes it.  Green (178/178, fixpoint OK).
 2. **Expressions → AST** — PARTIAL (branch `ast-stage-c`):
    `docs/summary_two-phase-slice2.md` (spine, literals, parens, unary
-   minus via `astCur` + per-invocation `astIsLit`) and
+   minus via `astCur` + per-invocation `astIsLit`),
    `docs/summary_two-phase-slice3.md` (`Design`: identifiers,
-   `[i]`/`.f`/`^` selectors, qualified names).  Still `NoNode`: calls,
-   brace/set literals, `ResultComp`, builtins, `NOT`; `Lower` + `.ssa`
-   compare not started.  Green (178/178, fixpoint OK).
+   `[i]`/`.f`/`^` selectors, qualified names), and
+   `docs/summary_two-phase-slice4.md` (calls/`NkCall` with actuals,
+   `NOT`, builtins as named `NkCall`s).  Still `NoNode`: brace/set
+   literals, `ResultComp` suffixes; `Lower` + `.ssa` compare not
+   started.  Green (178/178, fixpoint OK).
 3. **Statements → AST**: `Block`/`Stat` build `NkAssign`/`NkIf`/`NkWhile`/
    …; `Lower` them.
 4. **Declarations → AST**: `ConstBlock`/`TypeBlock`/`VarBlock`/

+ 49 - 0
docs/summary_two-phase-slice4.md

@@ -0,0 +1,49 @@
+# Two-phase refactor — slice 4 (calls, NOT, builtins → AST)
+
+Branch `ast-stage-c`.  Suite **178/178**; self-hosting fixpoint **OK**
+(**2,987,484 bytes**; slice 3 was 2,970,007).
+
+## What landed
+
+`Fact` now covers calls, logical `NOT`, and the builtin pseudo-calls
+(they build an `NkCall` whose callee is an `NkIdent` naming the builtin).
+
+| Construct | AST |
+| --- | --- |
+| `P(a, b, …)` | `NkCall` — child 0 = designator `P`, children 1.. = actuals |
+| bare `F` / designator | unchanged (`NkDesignator`) |
+| `NOT x` / `~ x` | `NkUnary(OpNot, x)` (`OpNot = 14` added to `AST.def`) |
+| `CHR` `ORD`/`ORDL` `CAP` `UCHR` `CHR8` `UORD` `ABS` | `NkCall(NkIdent "…", arg)` |
+| `ADR` `SIZE`/`TSIZE` `HIGH`/`LEN` `MIN`/`MAX` | `NkCall(NkIdent "…", designator)` |
+| `SHIFT`/`ROTATE` | `NkCall(NkIdent "…", target, amount)` |
+| `VAL(T, x)` | `NkCall(NkIdent "VAL", NkIdent "T", x)` |
+
+Actual arguments are collected by `ActParam` (each `Expr`'s node into
+`astArgs`), and `Fact` folds them into the `NkCall` after `ArgList`.
+Node-building actions are inserted *before* each builtin's existing emit
+action, so they read the argument node still sitting in `astCur` and then
+let the emit code run unchanged.
+
+## Verified (temporary `AST.Dump`, then removed)
+
+- `P(2,3)` → `NkCall(Ident P, 2, 3)`
+- `ABS(-3)` → `NkCall(Ident ABS, Unary(Sub,3))`
+- `CHR(65)+1` → `Add(NkCall(Ident CHR,65), 1)`
+- `HIGH(a)` → `NkCall(Ident HIGH, NkDesignator a)`
+- `VAL(INTEGER, x)` → `NkCall(Ident VAL, Ident INTEGER, NkDesignator x)`
+- `SHIFT(s,1)` → `NkCall(Ident SHIFT, NkDesignator s, 1)`
+- `x + MIN(x)` → `Add(NkDesignator x, NkCall(Ident MIN, NkDesignator x))`
+
+## Deliberately deferred
+
+- **Brace literals** (`T{…}`) and **set literals** (`{…}`) still leave
+  `astCur := NoNode`.
+- **`ResultComp` suffixes** after a call (`F()[i]`, `F().f`, `F()^`) are
+  not yet nodes (the call itself is).
+- `Lower` + `.ssa` byte-compare still not started.
+
+## Next
+
+Statements (`Block`/`Stat`: `NkAssign`/`NkIf`/`NkWhile`/`NkRepeat`/
+`NkFor`/`NkCase`/`NkCall`/…), then brace/set literals and `ResultComp`,
+then declarations and the `Lower` walk.

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.