|
|
@@ -1292,22 +1292,31 @@ PRODUCTIONS
|
|
|
END; .) .
|
|
|
(* WITH pushes each record's fields (inner wins) plus its base
|
|
|
address; field designators resolve through both stacks. *)
|
|
|
- WithStat (. VAR nW: CARDINAL; .)
|
|
|
- = "WITH" (. nW := 0; .)
|
|
|
- WithItem<nW> { "," WithItem<nW> }
|
|
|
- "DO" [ StatSeq ] "END" (. astStmt := AST.NoNode;
|
|
|
+ WithStat (. VAR nW: CARDINAL;
|
|
|
+ astNode: AST.Node; .)
|
|
|
+ = "WITH" (. nW := 0;
|
|
|
+ astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
+ WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
+ "DO" (. astStmt := AST.NoNode; .)
|
|
|
+ [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
+ AST.NChild(astNode), astStmt);
|
|
|
+ astStmt := astNode;
|
|
|
WHILE nW > 0 DO
|
|
|
SymTab.PopScope;
|
|
|
QbeGen.PopWith;
|
|
|
DEC(nW)
|
|
|
END; .) .
|
|
|
- WithItem<VAR nW: CARDINAL> (. VAR dt: SymTab.TypeIndex;
|
|
|
+ WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
+ (. VAR dt: SymTab.TypeIndex;
|
|
|
dk: INTEGER;
|
|
|
qd, qe: QbeGen.QVal;
|
|
|
qn: SymTab.Name;
|
|
|
sfx: BOOLEAN; .)
|
|
|
= Design<dt, dk, qd, qn, sfx>
|
|
|
- (. IF dt = SymTab.InvalidType THEN
|
|
|
+ (. IF astCur # AST.NoNode THEN
|
|
|
+ AST.SetChild(wnode,
|
|
|
+ AST.NChild(wnode), astCur) END;
|
|
|
+ IF dt = SymTab.InvalidType THEN
|
|
|
ELSIF (SymTab.ClassOf(dt) #
|
|
|
SymTab.ClRecord)
|
|
|
AND (SymTab.ClassOf(dt) #
|
|
|
@@ -1849,33 +1858,52 @@ PRODUCTIONS
|
|
|
QbeGen.Jmp(lTop);
|
|
|
QbeGen.EmitLabel(lEnd); .) .
|
|
|
CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- qsel, lEnd: QbeGen.QVal; .)
|
|
|
- = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
- "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
- { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
- [ "ELSE" [ StatSeq ] ]
|
|
|
- "END" (. astStmt := AST.NoNode;
|
|
|
+ qsel, lEnd: QbeGen.QVal;
|
|
|
+ arm, astNode: AST.Node; .)
|
|
|
+ = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ AST.SetChild(astNode, 0, astCur);
|
|
|
+ QbeGen.NewLabel(lEnd); .)
|
|
|
+ "OF" CaseAlt<tsel, qsel, lEnd, astNode>
|
|
|
+ { "|" CaseAlt<tsel, qsel, lEnd, astNode> }
|
|
|
+ [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ AST.SetOp(arm, 1);
|
|
|
+ AST.SetChild(arm, 0, astStmt);
|
|
|
+ AST.SetChild(astNode,
|
|
|
+ AST.NChild(astNode), arm); .) ]
|
|
|
+ "END" (. astStmt := astNode;
|
|
|
QbeGen.EmitLabel(lEnd); .) .
|
|
|
(* Compare-chain lowering: each alternative ends its match-tests
|
|
|
with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
"cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
- = (. QbeGen.NewLabel(lBody);
|
|
|
+ lEnd: QbeGen.QVal; cnode: AST.Node>
|
|
|
+ (. VAR lBody, lAfter: QbeGen.QVal;
|
|
|
+ arm: AST.Node; .)
|
|
|
+ = (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ QbeGen.NewLabel(lBody);
|
|
|
QbeGen.NewLabel(lAfter); .)
|
|
|
- CaseLabel<tsel, qsel, lBody>
|
|
|
- { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
- ":" (. QbeGen.Jmp(lAfter);
|
|
|
+ CaseLabel<tsel, qsel, lBody, arm>
|
|
|
+ { "," CaseLabel<tsel, qsel, lBody, arm> }
|
|
|
+ ":" (. astStmt := AST.NoNode;
|
|
|
+ QbeGen.Jmp(lAfter);
|
|
|
QbeGen.EmitLabel(lBody); .)
|
|
|
- [ StatSeq ] (. QbeGen.Jmp(lEnd);
|
|
|
+ [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ astStmt);
|
|
|
+ AST.SetChild(cnode,
|
|
|
+ AST.NChild(cnode), arm);
|
|
|
+ QbeGen.Jmp(lEnd);
|
|
|
QbeGen.EmitLabel(lAfter); .) .
|
|
|
CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ lBody: QbeGen.QVal; arm: AST.Node>
|
|
|
+ (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
q2, q3, qc, qd, qe:
|
|
|
QbeGen.QVal;
|
|
|
+ astLab: AST.Node;
|
|
|
lNext: QbeGen.QVal; .)
|
|
|
- = Expr<t2, q2> (. IF (t2 #
|
|
|
+ = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ IF (t2 #
|
|
|
SymTab.InvalidType)
|
|
|
AND (tsel #
|
|
|
SymTab.InvalidType)
|
|
|
@@ -1900,7 +1928,9 @@ PRODUCTIONS
|
|
|
qsel, q2, qc, FALSE);
|
|
|
QbeGen.Jnz(qc, lBody, lNext);
|
|
|
QbeGen.EmitLabel(lNext); .)
|
|
|
- [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
+ [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ IF (t3 #
|
|
|
SymTab.InvalidType)
|
|
|
AND (tsel #
|
|
|
SymTab.InvalidType)
|
|
|
@@ -1920,7 +1950,9 @@ PRODUCTIONS
|
|
|
FALSE);
|
|
|
QbeGen.NewLabel(lNext);
|
|
|
QbeGen.Jnz(qe, lBody, lNext);
|
|
|
- QbeGen.EmitLabel(lNext); .) ] .
|
|
|
+ QbeGen.EmitLabel(lNext); .) ]
|
|
|
+ (. AST.SetChild(arm,
|
|
|
+ AST.NChild(arm), astLab); .) .
|
|
|
ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
q, qt: QbeGen.QVal;
|
|
|
res: SymTab.TypeIndex;
|