|
|
@@ -84,6 +84,10 @@ VAR
|
|
|
(* Unit-AST root (slice 7): NkUnit(name, decls, body). *)
|
|
|
astUnit: AST.Node;
|
|
|
|
|
|
+ (* Import accumulator (slice 11): `{ Import }` appends NkImport
|
|
|
+ nodes here; each unit stores them as NkUnit child[3]. *)
|
|
|
+ astImp, astImpTail: AST.Node;
|
|
|
+
|
|
|
(* Class of the method named by the last `obj.Method` designator
|
|
|
(InvalidType when the callee is an ordinary procedure). Set by
|
|
|
Design, consumed by the following ArgList. *)
|
|
|
@@ -212,7 +216,9 @@ TOKENS
|
|
|
|
|
|
PRODUCTIONS
|
|
|
M2
|
|
|
- = (. AST.Init; twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; .)
|
|
|
+ = (. 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 "." .
|
|
|
(* Units: program modules compile fully; DEFINITION and
|
|
|
IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
@@ -230,7 +236,8 @@ PRODUCTIONS
|
|
|
SemError(200) END;
|
|
|
QbeGen.SetModule(m1); .)
|
|
|
";"
|
|
|
- { Import }
|
|
|
+ { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ astImp, astImpTail, astDecl); .) }
|
|
|
[ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
list: parsed, and the
|
|
|
names are already exported
|
|
|
@@ -243,6 +250,8 @@ PRODUCTIONS
|
|
|
(. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
AST.SetChild(astUnit, 0,
|
|
|
AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ AST.SetChild(astUnit, 1, astDecl);
|
|
|
+ AST.SetChild(astUnit, 3, astImp);
|
|
|
astDecl := AST.NoNode;
|
|
|
astStmt := AST.NoNode; .)
|
|
|
"END"
|
|
|
@@ -259,10 +268,13 @@ PRODUCTIONS
|
|
|
SemError(201) END;
|
|
|
astStmt := AST.NoNode;
|
|
|
astDecl := AST.NoNode;
|
|
|
+ astImp := AST.NoNode;
|
|
|
+ astImpTail := AST.NoNode;
|
|
|
nPendVar := 0;
|
|
|
QbeGen.SetModule(m1); .)
|
|
|
";"
|
|
|
- { Import }
|
|
|
+ { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ astImp, astImpTail, astDecl); .) }
|
|
|
DeclSeq
|
|
|
[ "BEGIN" (. FlushPend;
|
|
|
k := 0;
|
|
|
@@ -290,6 +302,7 @@ PRODUCTIONS
|
|
|
AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
AST.SetChild(astNode, 1, astDecl);
|
|
|
AST.SetChild(astNode, 2, astStmt);
|
|
|
+ AST.SetChild(astNode, 3, astImp);
|
|
|
astUnit := astNode;
|
|
|
IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
SemError(202) END;
|
|
|
@@ -304,11 +317,14 @@ PRODUCTIONS
|
|
|
SemError(200) END;
|
|
|
astStmt := AST.NoNode;
|
|
|
astDecl := AST.NoNode;
|
|
|
+ astImp := AST.NoNode;
|
|
|
+ astImpTail := AST.NoNode;
|
|
|
nPendVar := 0;
|
|
|
QbeGen.SetModule(m1); .)
|
|
|
[ Priority ]
|
|
|
";"
|
|
|
- { Import }
|
|
|
+ { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ astImp, astImpTail, astDecl); .) }
|
|
|
DeclSeq
|
|
|
[ "BEGIN" (. FlushPend;
|
|
|
k := 0;
|
|
|
@@ -338,6 +354,7 @@ PRODUCTIONS
|
|
|
AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
AST.SetChild(astNode, 1, astDecl);
|
|
|
AST.SetChild(astNode, 2, astStmt);
|
|
|
+ AST.SetChild(astNode, 3, astImp);
|
|
|
astUnit := astNode;
|
|
|
QbeGen.EndModule(m1);
|
|
|
SymTab.EndUnit; .) .
|
|
|
@@ -391,20 +408,27 @@ PRODUCTIONS
|
|
|
(* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
import lines don't fail); a known module's missing export is
|
|
|
201. *)
|
|
|
- Import (. VAR n: SymTab.Name; .)
|
|
|
+ Import (. VAR n: SymTab.Name;
|
|
|
+ astImport: AST.Node; .)
|
|
|
= "FROM"
|
|
|
- GetIdent<n>
|
|
|
+ GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
+ AST.SetChild(astImport, 0,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
"IMPORT"
|
|
|
- ImpList<n> ";"
|
|
|
- | "IMPORT"
|
|
|
- ImpModList ";" .
|
|
|
- ImpList<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
- = ImpName<mod>
|
|
|
- { "," ImpName<mod> } .
|
|
|
+ ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
+ | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
+ ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
+ ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
+ (. VAR n: SymTab.Name; .)
|
|
|
+ = ImpName<mod, node>
|
|
|
+ { "," ImpName<mod, node> } .
|
|
|
(* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
accepted and ignored: the built-in applies regardless. *)
|
|
|
- ImpName<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
- = GetIdent<n> (. IF SymTab.Equal(mod, "libc") THEN
|
|
|
+ ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
+ (. VAR n: SymTab.Name; .)
|
|
|
+ = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ IF SymTab.Equal(mod, "libc") THEN
|
|
|
(* intrinsic C library:
|
|
|
permissive external *)
|
|
|
IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
@@ -416,9 +440,11 @@ PRODUCTIONS
|
|
|
| "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
| "UCHR" | "CHR8" | "UORD"
|
|
|
| "INC" | "DEC" ) .
|
|
|
- ImpModList (. VAR n: SymTab.Name; .)
|
|
|
- = GetIdent<n>
|
|
|
- { "," GetIdent<n> } .
|
|
|
+ ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
+ = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
(* Opaque TYPE declarations (definition modules). The targetless
|
|
|
alias resolves to InvalidType until step 4 completes it. *)
|
|
|
(* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|