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

lower L6 (start): nested modules

CanDecl accepts a nested NkUnit (no imports); LowerDecls emits its
declarations and, when it has a BEGIN body, BeginInit/body/EndInit
(registering <nested>_init so the enclosing BeginBody calls it).

ReenterGlobals re-registers a nested module's non-exported globals in
the still-open enclosing module scope, so QbeGen.GlobalRef resolves
their "<outer>_<name>" symbols after the nested scope has been popped.

lower_ok t_nestedmod.mod byte-matches.  Suite 194/194; FIXPOINT OK
(stage2 == stage3, 3,328,857 bytes).
Eric Streit 6 дней назад
Родитель
Сommit
f82f72b5bb
2 измененных файлов с 40 добавлено и 0 удалено
  1. 1 0
      compiler/run_tests.sh
  2. 39 0
      compiler/src/Lower.mod

+ 1 - 0
compiler/run_tests.sh

@@ -471,6 +471,7 @@ lower_ok t_arith.mod
 lower_ok t_lower1.mod
 lower_ok t_lower2.mod
 lower_ok t_lower3.mod
+lower_ok t_nestedmod.mod
 lower_ok t_lower4.mod
 lower_ok t_lower4case.mod
 lower_ok t_lower4with.mod

+ 39 - 0
compiler/src/Lower.mod

@@ -541,6 +541,10 @@ PROCEDURE CanStmt (n: AST.Node): BOOLEAN;
 PROCEDURE CanDecl (c: AST.Node): BOOLEAN;
   VAR i: CARDINAL;
   BEGIN
+    IF AST.Kind(c) = AST.NkUnit THEN
+      IF AST.Child(c, 3) # AST.NoNode THEN RETURN FALSE END;
+      RETURN CanDecls(AST.Child(c, 1)) AND CanStmt(AST.Child(c, 2))
+    END;
     IF AST.Kind(c) = AST.NkTypeDecl THEN RETURN TRUE END;
     IF AST.Kind(c) = AST.NkVarDecl THEN
       IF NOT CanType(AST.Ty(c)) THEN RETURN FALSE END;
@@ -1336,6 +1340,32 @@ PROCEDURE LowerStmt (seq: AST.Node);
     END
   END LowerStmt;
 
+PROCEDURE ReenterGlobals (seq: AST.Node);
+(* Re-registers a nested module's non-exported globals in the enclosing
+   (still-open) module scope, so QbeGen.GlobalRef can resolve their
+   "<outer>_<name>" symbols after the nested scope has been popped. *)
+  VAR i, j: CARDINAL; c: AST.Node; nm: SymTab.Name;
+  BEGIN
+    IF seq = AST.NoNode THEN RETURN END;
+    i := 0;
+    WHILE i < AST.NChild(seq) DO
+      c := AST.Child(seq, i);
+      IF i = AST.MaxChild - 1 THEN ReenterGlobals(c)
+      ELSIF AST.Kind(c) = AST.NkDeclSeq THEN ReenterGlobals(c)
+      ELSIF AST.Kind(c) = AST.NkVarDecl THEN
+        j := 0;
+        WHILE j < AST.NChild(c) DO
+          Name(AST.Child(c, j), nm);
+          IF SymTab.Enter(nm, SymTab.KindVar) THEN
+            SymTab.SetSymType(nm, AST.Ty(c))
+          END;
+          INC(j)
+        END
+      END;
+      INC(i)
+    END
+  END ReenterGlobals;
+
 PROCEDURE LowerDecls (seq: AST.Node);
   VAR i, j: CARDINAL; c: AST.Node; nm, txt: SymTab.Name; qv: QbeGen.QVal;
       mg: QbeGen.QVal; uid, depth, np: CARDINAL; res, pt: SymTab.TypeIndex;
@@ -1347,6 +1377,15 @@ PROCEDURE LowerDecls (seq: AST.Node);
       c := AST.Child(seq, i);
       IF i = AST.MaxChild - 1 THEN LowerDecls(c)
       ELSIF AST.Kind(c) = AST.NkDeclSeq THEN LowerDecls(c)
+      ELSIF AST.Kind(c) = AST.NkUnit THEN
+        Name(AST.Child(c, 0), nm);
+        ReenterGlobals(AST.Child(c, 1));
+        LowerDecls(AST.Child(c, 1));
+        IF AST.Child(c, 2) # AST.NoNode THEN
+          QbeGen.BeginInit(nm);
+          LowerStmt(AST.Child(c, 2));
+          QbeGen.EndInit
+        END
       ELSIF AST.Kind(c) = AST.NkVarDecl THEN
         j := 0;
         WHILE j < AST.NChild(c) DO