Kaynağa Gözat

lower L7 (start): session re-emit mechanism

Adds the enabling mechanism for the flip: the driver collects every
unit's AST (GetUnit after each Parse) and, under -lower, calls
Lower.LowerSession, which re-emits all units in order into one image.

- Lower.LowerSession/LowerOneUnit/MaterializeGlobals; SymTab.Materialize
  makes each unit's own VAR/CONST visible in globScope so GlobalRef
  resolves "<unit>_<name>" at session end.
- Remove Lower.Reset from the M2 root so the owned tables persist across
  a session (needed to resolve earlier units).

Scaffolding only (still under -lower; the inline emit is untouched), so
self-hosting is unaffected.  Known L7 gaps found: DefUnit builds no AST
(its proc headings are not recorded), Lower's table sizes (MaxProc=64)
are far too small for a full-session re-emit, and nested-module globals
are unresolved.  Suite 200/200; FIXPOINT OK (3,401,129 bytes).
Eric Streit 6 gün önce
ebeveyn
işleme
d30abfd182

+ 2 - 0
compiler/src/Lower.def

@@ -15,6 +15,8 @@ IMPORT AST, SymTab;
 
 PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
 PROCEDURE LowerUnit (unit: AST.Node);
+PROCEDURE LowerSession (units: ARRAY OF AST.Node; n: CARDINAL;
+                        progName: ARRAY OF CHAR);
 
 PROCEDURE Reset;
 PROCEDURE NoteVar (name: ARRAY OF CHAR; kind: INTEGER; t: SymTab.TypeIndex);

+ 64 - 0
compiler/src/Lower.mod

@@ -1782,6 +1782,70 @@ PROCEDURE LowerDecls (seq: AST.Node);
     END
   END LowerDecls;
 
+PROCEDURE MaterializeGlobals (unitName: ARRAY OF CHAR; decls: AST.Node);
+(* Make a unit's module-level VAR/CONST visible in the (global) scope
+   Lower runs in at session end, so GlobalRef resolves "<unit>_<name>". *)
+  VAR i, j: CARDINAL; c: AST.Node; nm: SymTab.Name;
+  BEGIN
+    IF decls = AST.NoNode THEN RETURN END;
+    i := 0;
+    WHILE i < AST.NChild(decls) DO
+      c := AST.Child(decls, i);
+      IF i = AST.MaxChild - 1 THEN MaterializeGlobals(unitName, c)
+      ELSIF AST.Kind(c) = AST.NkDeclSeq THEN MaterializeGlobals(unitName, c)
+      ELSIF (AST.Kind(c) = AST.NkVarDecl) OR (AST.Kind(c) = AST.NkConstDecl) THEN
+        j := 0;
+        WHILE j < AST.NChild(c) DO
+          IF AST.Kind(AST.Child(c, j)) = AST.NkIdent THEN
+            Name(AST.Child(c, j), nm);
+            IF NOT SymTab.Materialize(unitName, nm) THEN END
+          END;
+          INC(j)
+        END
+      END;
+      INC(i)
+    END
+  END MaterializeGlobals;
+
+PROCEDURE LowerOneUnit (u: AST.Node; isProg: BOOLEAN);
+  VAR nm: SymTab.Name;
+  BEGIN
+    Name(AST.Child(u, 0), nm);
+    QbeGen.SetModule(nm);
+    MaterializeGlobals(nm, AST.Child(u, 1));
+    LowerDecls(AST.Child(u, 1));
+    IF isProg THEN
+      QbeGen.BeginBody;
+      LowerStmt(AST.Child(u, 2))
+    ELSIF AST.Child(u, 2) # AST.NoNode THEN
+      QbeGen.BeginInit(nm);
+      LowerStmt(AST.Child(u, 2));
+      QbeGen.EndInit
+    END
+  END LowerOneUnit;
+
+PROCEDURE LowerSession (units: ARRAY OF AST.Node; n: CARDINAL;
+                        progName: ARRAY OF CHAR);
+(* Re-emit a whole session (all units, in order) into one image. *)
+  VAR i, j: CARDINAL; out: ARRAY [0 .. 255] OF CHAR;
+  BEGIN
+    j := 0;
+    WHILE (j <= 254) AND (j <= HIGH(progName)) AND (progName[j] # CHR(0)) DO
+      out[j] := progName[j]; INC(j)
+    END;
+    out[j] := "L"; INC(j); out[j] := CHR(0);
+    withTop := 0;
+    curImplCls := SymTab.InvalidType;
+    QbeGen.OpenModule(progName);
+    QbeGen.SetOutName(out);
+    i := 0;
+    WHILE i < n DO
+      LowerOneUnit(units[i], i = n - 1);
+      INC(i)
+    END;
+    QbeGen.EndModule(progName)
+  END LowerSession;
+
 PROCEDURE LowerUnit (unit: AST.Node);
   VAR nm: SymTab.Name; out: ARRAY [0 .. 255] OF CHAR; i: CARDINAL;
   BEGIN

+ 1 - 1
compiler/src/M2.atg

@@ -243,7 +243,7 @@ TOKENS
 
 PRODUCTIONS
   M2
-    = (. AST.Init; twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode; Lower.Reset;
+    = (. AST.Init; twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
                                            astImp := AST.NoNode;
                                            astImpTail := AST.NoNode; .)
       Unit "." (. FileIO.WriteString(FileIO.StdOut, "ASTDUMP:"); FileIO.WriteLn(FileIO.StdOut); AST.Dump(astUnit, 0); .) .

+ 1 - 1
compiler/src/M2.lst

@@ -261,7 +261,7 @@ Listing:
   243  
   244  PRODUCTIONS
   245    M2
-  246      = (. AST.Init; twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode; Lower.Reset;
+  246      = (. AST.Init; twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
   247                                             astImp := AST.NoNode;
   248                                             astImpTail := AST.NoNode; .)
   249        Unit "." (. FileIO.WriteString(FileIO.StdOut, "ASTDUMP:"); FileIO.WriteLn(FileIO.StdOut); AST.Dump(astUnit, 0); .) .

+ 12 - 3
compiler/src/compiler.frm

@@ -6,9 +6,9 @@ MODULE -->Grammar;
    are assumed to have been constructed with COCO/R compiler generator. *)
 
   FROM -->Scanner IMPORT lst, src, errors, Error, CharAt;
-  FROM -->Parser IMPORT Parse, Successful, SetLower;
+  FROM -->Parser IMPORT Parse, Successful, SetLower, GetUnit;
   IMPORT
-    Strings, Storage, SYSTEM, FileIO, SymTab, QbeGen;
+    Strings, Storage, SYSTEM, FileIO, SymTab, QbeGen, AST, Lower;
     (* and any others needed *)
 
   TYPE
@@ -288,6 +288,8 @@ MODULE -->Grammar;
     f: CARDINAL;
     bad: BOOLEAN;
     lowerAst: BOOLEAN;
+    units: ARRAY [0 .. 31] OF AST.Node;
+    nUnits: CARDINAL;
 
   BEGIN
     (* collect the session's source files (program module last) *)
@@ -315,7 +317,7 @@ MODULE -->Grammar;
     Error := StoreError;
 
     (* parse each unit into the shared session *)
-    bad := FALSE; f := 0;
+    bad := FALSE; f := 0; nUnits := 0;
     WHILE f < nFiles DO
       Strings.Assign(files[f], sourceName);
       FileIO.Open(src, sourceName, FALSE);
@@ -332,6 +334,9 @@ MODULE -->Grammar;
       FileIO.WriteString(FileIO.StdOut, "Parsing");
       FileIO.WriteLn(FileIO.StdOut);
       Parse;
+      IF lowerAst AND (nUnits <= HIGH(units)) THEN
+        units[nUnits] := GetUnit(); INC(nUnits)
+      END;
       PrintListing;
       IF lst # FileIO.StdOut THEN FileIO.Close(lst) END;
       IF NOT Successful() THEN
@@ -347,6 +352,10 @@ MODULE -->Grammar;
       INC(f)
     END;
 
+    IF lowerAst AND (nUnits > 0) THEN
+      Lower.LowerSession(units, nUnits, progName)
+    END;
+
     IF bad OR NOT SymTab.HaveProgram()
       THEN FileIO.WriteString(FileIO.StdOut, "Incorrect source")
       ELSE FileIO.WriteString(FileIO.StdOut, "Parsed correctly")