浏览代码

feat: statement-context result suffixes (call result as assignment target)

`Get()^.x := e` (and `F()[i] := e`, `F().f := e`) now parse and lower:
AssOrCall calls ArgList with want=TRUE and a new "soft" result rule, then
applies ResultComp suffixes and, on `:=`, builds the NkAssign with the
suffixed call as its LHS (LowerDesign already handles a call-base
designator).  A suffix is required for the target to be an lvalue
(233 otherwise); a value-returning call with no suffix is still 233 as a
statement.

Chained post-call calls (`F().M()`) remain unsupported: they need a
function to return a record/class, which ProcHeading rejects (230).

Regression: compiler/tests/t_stmtsfx.mod (exit 42).
Suite 184/184; FIXPOINT OK (3,392,601 bytes).
Eric Streit 4 天之前
父节点
当前提交
8c8ed06965
共有 4 个文件被更改,包括 1766 次插入 和 1718 次删除
  1. 1 0
      compiler/run_tests.sh
  2. 18 4
      compiler/src/M2.atg
  3. 1728 1714
      compiler/src/M2.lst
  4. 19 0
      compiler/tests/t_stmtsfx.mod

+ 1 - 0
compiler/run_tests.sh

@@ -95,6 +95,7 @@ expect_run t_recarr.mod 42
 expect_run t_nestarr.mod 42
 expect_run t_arrrecfld.mod 42
 expect_run t_arrrecbig.mod 42
+expect_run t_stmtsfx.mod 42
 expect_run t_under.mod 42
 expect_run t_with.mod 114
 expect_run t_set.mod 131

+ 18 - 4
compiler/src/M2.atg

@@ -1463,7 +1463,7 @@ PRODUCTIONS
                                              q2, mg0: QbeGen.QVal;
                                              isR, conv, wconv: BOOLEAN;
                                              called, sfx: BOOLEAN;
-                                             astLhs: AST.Node; .)
+                                             astLhs, astRes: AST.Node; .)
     = Design<dt, dk, qd, qn, sfx>
       (. astLhs := astCur; astNArgs := 0; .)
       ( ":="
@@ -1499,8 +1499,22 @@ PRODUCTIONS
  AND (SymTab.ClassOf(dt) #
                                                SymTab.ClClass) THEN
                                          END; .)
-      | ArgList<qn, dt, qd, FALSE, FALSE, methCls, ct2, q2, called>
-                                        (. astStmt := AstCallNode(astLhs); .)
+      | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
+                                        (. astRes := AstCallNode(astLhs);
+                                           sfx := FALSE; .)
+        ( { ResultComp<ct2, q2, sfx, astRes> }
+          ":=" Expr<et, qe>             (. astStmt := AST.MakeBin(
+                                             AST.NkAssign, 0, astRes, astCur);
+                                           IF NOT sfx THEN
+                                             SemError(233)
+                                           ELSIF (ct2 # SymTab.InvalidType)
+  AND NOT SymTab.Assignable(et, ct2) THEN
+                                             SemError(210)
+                                           END; .)
+        |                               (. IF ct2 #
+                                             SymTab.InvalidType THEN
+                                             SemError(233) END;
+                                           astStmt := astRes; .) )
       |                                 (* bare `P;`: proper parameterless
                                             procedure call; anything else
                                             here is 233 (was a bare syntax
@@ -1572,7 +1586,7 @@ PRODUCTIONS
                                            ELSIF want THEN
                                              IF res =
                                                 SymTab.InvalidType THEN
-                                               SemError(233);
+                                               IF NOT soft THEN SemError(233) END;
                                                t := SymTab.InvalidType;
                                                QbeGen.CopyOp("0", q)
                                              ELSE t := res;

文件差异内容过多而无法显示
+ 1728 - 1714
compiler/src/M2.lst


+ 19 - 0
compiler/tests/t_stmtsfx.mod

@@ -0,0 +1,19 @@
+MODULE TStmtSfx;
+(* Statement-context result suffix: a call result used as an assignment
+   target, `Get()^.x := e` (pointer result).  Exit 42. *)
+VAR ExitCode : INTEGER;
+
+TYPE
+  Rec = RECORD x : INTEGER END;
+  PR = POINTER TO Rec;
+VAR g : PR;
+
+PROCEDURE Get () : PR;
+BEGIN RETURN g END Get;
+
+BEGIN
+  NEW(g);
+  g^.x := 0;
+  Get()^.x := 42;
+  IF g^.x = 42 THEN ExitCode := 42 ELSE ExitCode := 1 END
+END TStmtSfx.

部分文件因为文件数量过多而无法显示