|
|
@@ -88,6 +88,12 @@ VAR
|
|
|
nodes here; each unit stores them as NkUnit child[3]. *)
|
|
|
astImp, astImpTail: AST.Node;
|
|
|
|
|
|
+ (* Class-AST accumulators (slice 13): the class node currently being
|
|
|
+ parsed and its parent/field/method lists. Classes are not nested
|
|
|
+ inside one another, so module-level state is safe. *)
|
|
|
+ astCls, astClsP, astClsPTail, astClsF, astClsFTail,
|
|
|
+ astClsM, astClsMTail, astMethod: 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. *)
|
|
|
@@ -465,10 +471,16 @@ PRODUCTIONS
|
|
|
(* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
- TypeBlock<isDef: BOOLEAN>
|
|
|
- = "TYPE" (. SymTab.BeginTypeBlock; .)
|
|
|
- { TypeItem<isDef> ";" | ClassItem ";" }
|
|
|
- (. SymTab.EndTypeBlock; .) .
|
|
|
+ TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
+ astSeq := AST.NoNode;
|
|
|
+ astTail := AST.NoNode; .)
|
|
|
+ { (. astDecl := AST.NoNode; .)
|
|
|
+ ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
+ (. AstAppend(AST.NkDeclSeq,
|
|
|
+ astSeq, astTail, astDecl); .) }
|
|
|
+ (. SymTab.EndTypeBlock;
|
|
|
+ astDecl := astSeq; .) .
|
|
|
TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
t, op: SymTab.TypeIndex;
|
|
|
astNode: AST.Node; .)
|
|
|
@@ -805,7 +817,16 @@ PRODUCTIONS
|
|
|
SemError(200) END;
|
|
|
ct := SymTab.NewClass();
|
|
|
SymTab.SetSymType(cn, ct);
|
|
|
- SymTab.PushClassScope(ct); .)
|
|
|
+ SymTab.PushClassScope(ct);
|
|
|
+ astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ AST.SetChild(astCls, 0,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ astClsP := AST.NoNode;
|
|
|
+ astClsPTail := AST.NoNode;
|
|
|
+ astClsF := AST.NoNode;
|
|
|
+ astClsFTail := AST.NoNode;
|
|
|
+ astClsM := AST.NoNode;
|
|
|
+ astClsMTail := AST.NoNode; .)
|
|
|
[ Parents<ct> ]
|
|
|
";"
|
|
|
{ ClassField<ct> ";" }
|
|
|
@@ -816,7 +837,11 @@ PRODUCTIONS
|
|
|
GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
SemError(202) END;
|
|
|
SymTab.LayoutClass(ct);
|
|
|
- SymTab.PopScope; .) .
|
|
|
+ SymTab.PopScope;
|
|
|
+ AST.SetChild(astCls, 1, astClsP);
|
|
|
+ AST.SetChild(astCls, 2, astClsF);
|
|
|
+ AST.SetChild(astCls, 3, astClsM);
|
|
|
+ astDecl := astCls; .) .
|
|
|
Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
= "(" Parent1<ct>
|
|
|
{ "," GetIdent<p> (. SemError(230); .) }
|
|
|
@@ -831,30 +856,59 @@ PRODUCTIONS
|
|
|
SemError(230)
|
|
|
ELSE SymTab.SetParent(ct, pt)
|
|
|
END
|
|
|
- END; .) .
|
|
|
+ END;
|
|
|
+ AstAppend(AST.NkFieldDecl,
|
|
|
+ astClsP, astClsPTail,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
- t: SymTab.TypeIndex; .)
|
|
|
+ t: SymTab.TypeIndex;
|
|
|
+ astNode: AST.Node; .)
|
|
|
= GetIdent<n>
|
|
|
( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
SymTab.KindConst) THEN
|
|
|
SemError(200) END;
|
|
|
+ astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ AST.SetChild(astNode, 0,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ AST.SetChild(astNode, 1,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
+ AstAppend(AST.NkFieldDecl,
|
|
|
+ astClsF, astClsFTail, astNode);
|
|
|
IF SymTab.Lookup(rhs) THEN
|
|
|
SymTab.SetSymType(n,
|
|
|
SymTab.SymType(rhs))
|
|
|
END; .)
|
|
|
| (. IF NOT SymTab.FieldPending(ct,
|
|
|
n) THEN
|
|
|
- SemError(200) END; .)
|
|
|
+ SemError(200) END;
|
|
|
+ astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ AST.SetChild(astNode, 0,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
{ "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
n) THEN
|
|
|
- SemError(200) END; .) }
|
|
|
- ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
+ SemError(200) END;
|
|
|
+ AST.SetChild(astNode,
|
|
|
+ AST.NChild(astNode),
|
|
|
+ AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
+ ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
+ AST.SetTy(astNode, t);
|
|
|
+ AstAppend(AST.NkFieldDecl,
|
|
|
+ astClsF, astClsFTail, astNode); .) ) .
|
|
|
MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
(. VAR wantVirt: BOOLEAN; .)
|
|
|
= (. wantVirt := FALSE; .)
|
|
|
[ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
- SymTab.MarkVirtual END; .) .
|
|
|
+ SymTab.MarkVirtual END;
|
|
|
+ astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ AST.SetChild(astMethod, 0,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ IF wantVirt THEN
|
|
|
+ AST.SetOp(astMethod, 3)
|
|
|
+ ELSE AST.SetOp(astMethod, 0)
|
|
|
+ END;
|
|
|
+ AstAppend(AST.NkFieldDecl,
|
|
|
+ astClsM, astClsMTail, astMethod); .) .
|
|
|
ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
ct: SymTab.TypeIndex; .)
|
|
|
= GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
@@ -867,6 +921,13 @@ PRODUCTIONS
|
|
|
ct := SymTab.InvalidType
|
|
|
END
|
|
|
END;
|
|
|
+ astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ AST.SetOp(astCls, 1);
|
|
|
+ AST.SetChild(astCls, 0,
|
|
|
+ AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ astClsM := AST.NoNode;
|
|
|
+ astClsMTail := AST.NoNode;
|
|
|
+ astStmt := AST.NoNode;
|
|
|
IF ct #
|
|
|
SymTab.InvalidType THEN
|
|
|
IF NOT SymTab.PushClassMembers(
|
|
|
@@ -875,13 +936,19 @@ PRODUCTIONS
|
|
|
SymTab.PushImplClass(ct)
|
|
|
END; .)
|
|
|
";" { MethodImpl<ct> ";" }
|
|
|
- [ "BEGIN" (. QbeGen.BeginInit(cn); .)
|
|
|
+ (. astStmt := AST.NoNode; .)
|
|
|
+ [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
+ QbeGen.BeginInit(cn); .)
|
|
|
[ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
"END"
|
|
|
GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
SemError(202) END;
|
|
|
SymTab.PopImplClass;
|
|
|
- SymTab.PopScope; .) .
|
|
|
+ SymTab.PopScope;
|
|
|
+ AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
+ AST.SetChild(astCls, 2, astStmt);
|
|
|
+ AST.SetChild(astCls, 3, astClsM);
|
|
|
+ astDecl := astCls; .) .
|
|
|
MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
thisQ: QbeGen.QVal;
|
|
|
methRes: SymTab.TypeIndex; .)
|
|
|
@@ -891,7 +958,8 @@ PRODUCTIONS
|
|
|
AND NOT SymTab.MethodExists(ct,
|
|
|
pn) THEN
|
|
|
SemError(201) END; .)
|
|
|
- ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
+ ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
+ SymTab.MarkFwd;
|
|
|
QbeGen.AbortFunc;
|
|
|
SymTab.CloseProc; .)
|
|
|
| (. QbeGen.EndFuncHeader;
|
|
|
@@ -900,7 +968,8 @@ PRODUCTIONS
|
|
|
against THIS *)
|
|
|
QbeGen.ThisBase(thisQ);
|
|
|
QbeGen.PushWith(thisQ); .)
|
|
|
- Block<pn> (. QbeGen.PopWith;
|
|
|
+ Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
+ QbeGen.PopWith;
|
|
|
methRes := SymTab.CurRes();
|
|
|
SymTab.CloseProc;
|
|
|
QbeGen.EndFunc(methRes); .) ) .
|