|
@@ -60,6 +60,13 @@ VAR
|
|
|
the emitted output is unchanged. *)
|
|
the emitted output is unchanged. *)
|
|
|
twoPhase: BOOLEAN;
|
|
twoPhase: BOOLEAN;
|
|
|
|
|
|
|
|
|
|
+ (* Result slot for the expression-AST builder (slice 2). Every
|
|
|
|
|
+ Expr/SimExpr/Term/Fact leaves its node here; the combination
|
|
|
|
|
+ productions save it into locals before parsing the next operand.
|
|
|
|
|
+ `astIsLit` in Fact is per-invocation, so a nested Fact cannot make
|
|
|
|
|
+ an outer non-literal Fact look literal. *)
|
|
|
|
|
+ astCur: AST.Node;
|
|
|
|
|
+
|
|
|
(* Class of the method named by the last `obj.Method` designator
|
|
(* Class of the method named by the last `obj.Method` designator
|
|
|
(InvalidType when the callee is an ordinary procedure). Set by
|
|
(InvalidType when the callee is an ordinary procedure). Set by
|
|
|
Design, consumed by the following ArgList. *)
|
|
Design, consumed by the following ArgList. *)
|
|
@@ -156,7 +163,7 @@ TOKENS
|
|
|
|
|
|
|
|
PRODUCTIONS
|
|
PRODUCTIONS
|
|
|
M2
|
|
M2
|
|
|
- = (. AST.Init; twoPhase := TRUE; .)
|
|
|
|
|
|
|
+ = (. AST.Init; twoPhase := TRUE; astCur := AST.NoNode; .)
|
|
|
Unit "." .
|
|
Unit "." .
|
|
|
(* Units: program modules compile fully; DEFINITION and
|
|
(* Units: program modules compile fully; DEFINITION and
|
|
|
IMPLEMENTATION modules parse + check now but lower in step 4
|
|
IMPLEMENTATION modules parse + check now but lower in step 4
|
|
@@ -2198,10 +2205,23 @@ PRODUCTIONS
|
|
|
(. VAR t2: SymTab.TypeIndex;
|
|
(. VAR t2: SymTab.TypeIndex;
|
|
|
op: INTEGER;
|
|
op: INTEGER;
|
|
|
q2, qt, wl: QbeGen.QVal;
|
|
q2, qt, wl: QbeGen.QVal;
|
|
|
|
|
+ astA, astB: AST.Node;
|
|
|
|
|
+ astOp: INTEGER;
|
|
|
|
|
+ astMade: BOOLEAN;
|
|
|
isR: BOOLEAN; .)
|
|
isR: BOOLEAN; .)
|
|
|
- = SimExpr<t, q>
|
|
|
|
|
|
|
+ = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
[ Rel<op> SimExpr<t2, q2>
|
|
[ Rel<op> SimExpr<t2, q2>
|
|
|
- (. IF op = SymTab.OpIn THEN
|
|
|
|
|
|
|
+ (. astB := astCur; astMade := TRUE;
|
|
|
|
|
+ astOp := AST.OpEq;
|
|
|
|
|
+ IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
|
|
+ ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
|
|
+ ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
|
|
+ ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
|
|
+ ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
|
|
+ ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
|
|
+ ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF op = SymTab.OpIn THEN
|
|
|
IF SymTab.InCheck(t, t2) THEN
|
|
IF SymTab.InCheck(t, t2) THEN
|
|
|
IF (t = SymTab.InvalidType)
|
|
IF (t = SymTab.InvalidType)
|
|
|
OR (t2 = SymTab.InvalidType) THEN
|
|
OR (t2 = SymTab.InvalidType) THEN
|
|
@@ -2256,8 +2276,10 @@ PRODUCTIONS
|
|
|
QbeGen.CopyOp(qt, q)
|
|
QbeGen.CopyOp(qt, q)
|
|
|
END
|
|
END
|
|
|
ELSE SemError(213); t := SymTab.InvalidType;
|
|
ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- QbeGen.CopyOp("0", q)
|
|
|
|
|
- END; .) ] .
|
|
|
|
|
|
|
+ QbeGen.CopyOp("0", q)
|
|
|
|
|
+ END;
|
|
|
|
|
+ astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
|
|
+ (. IF NOT astMade THEN astCur := astA END; .) .
|
|
|
Rel<VAR op: INTEGER>
|
|
Rel<VAR op: INTEGER>
|
|
|
= "=" (. op := SymTab.OpEq; .)
|
|
= "=" (. op := SymTab.OpEq; .)
|
|
|
| "#" (. op := SymTab.OpNeq1; .)
|
|
| "#" (. op := SymTab.OpNeq1; .)
|
|
@@ -2276,11 +2298,13 @@ PRODUCTIONS
|
|
|
BOOLEAN;
|
|
BOOLEAN;
|
|
|
fok: BOOLEAN;
|
|
fok: BOOLEAN;
|
|
|
lw, rw, mw: CARDINAL;
|
|
lw, rw, mw: CARDINAL;
|
|
|
- lTrue, lNext, lDone, qr, qs:
|
|
|
|
|
- QbeGen.QVal; .)
|
|
|
|
|
- = (. neg := FALSE; .)
|
|
|
|
|
- [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
|
|
- Term<t, q> (. IF neg THEN
|
|
|
|
|
|
|
+ lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
|
|
+ astA, astB: AST.Node;
|
|
|
|
|
+ astSign, astOp: INTEGER; .)
|
|
|
|
|
+ = (. neg := FALSE; astSign := 0; .)
|
|
|
|
|
+ [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
|
|
+ | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
|
|
+ Term<t, q> (. astA := astCur; IF neg THEN
|
|
|
IF QbeGen.IsImm(q) THEN
|
|
IF QbeGen.IsImm(q) THEN
|
|
|
QbeGen.NegFold(q, q)
|
|
QbeGen.NegFold(q, q)
|
|
|
ELSE QbeGen.NewTemp(qt);
|
|
ELSE QbeGen.NewTemp(qt);
|
|
@@ -2289,12 +2313,22 @@ PRODUCTIONS
|
|
|
= SymTab.ClReal);
|
|
= SymTab.ClReal);
|
|
|
QbeGen.CopyOp(qt, q)
|
|
QbeGen.CopyOp(qt, q)
|
|
|
END
|
|
END
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF astSign < 0 THEN
|
|
|
|
|
+ astCur := AST.MakeUn(
|
|
|
|
|
+ AST.NkUnary, AST.OpSub, astA);
|
|
|
|
|
+ astA := astCur
|
|
|
END; .)
|
|
END; .)
|
|
|
{ AddOp<op> (. IF op = SymTab.OpOr THEN
|
|
{ AddOp<op> (. IF op = SymTab.OpOr THEN
|
|
|
QbeGen.DelayBegin END; .)
|
|
QbeGen.DelayBegin END; .)
|
|
|
- Term<t2, q2> (. IF op = SymTab.OpOr THEN
|
|
|
|
|
|
|
+ Term<t2, q2> (. astB := astCur; IF op = SymTab.OpOr THEN
|
|
|
QbeGen.DelayEnd END; .)
|
|
QbeGen.DelayEnd END; .)
|
|
|
- (. IF op = SymTab.OpOr THEN
|
|
|
|
|
|
|
+ (. astOp := AST.OpAdd;
|
|
|
|
|
+ IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
|
|
+ ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
|
|
+ astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
|
|
+ astCur := astA;
|
|
|
|
|
+ IF op = SymTab.OpOr THEN
|
|
|
(* short-circuit: if q is true the RHS is skipped *)
|
|
(* short-circuit: if q is true the RHS is skipped *)
|
|
|
IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
t := SymTab.BoolType()
|
|
t := SymTab.BoolType()
|
|
@@ -2438,13 +2472,21 @@ PRODUCTIONS
|
|
|
QbeGen.QVal;
|
|
QbeGen.QVal;
|
|
|
isR, isL, folded: BOOLEAN;
|
|
isR, isL, folded: BOOLEAN;
|
|
|
lw, rw, mw: CARDINAL;
|
|
lw, rw, mw: CARDINAL;
|
|
|
- lNext, lFalse, lDone, qr, qs:
|
|
|
|
|
- QbeGen.QVal; .)
|
|
|
|
|
- = Fact<t, q> { MulOp<op> (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
|
|
+ lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
|
|
+ astA, astB: AST.Node;
|
|
|
|
|
+ astOp: INTEGER; .)
|
|
|
|
|
+ = Fact<t, q> (. astA := astCur; .) { MulOp<op> (. IF op = SymTab.OpAnd THEN
|
|
|
QbeGen.DelayBegin END; .)
|
|
QbeGen.DelayBegin END; .)
|
|
|
- Fact<t2, q2> (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
- QbeGen.DelayEnd END; .)
|
|
|
|
|
- (. IF op = SymTab.OpAnd THEN
|
|
|
|
|
|
|
+ Fact<t2, q2> (. astB := astCur; IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ QbeGen.DelayEnd END; .)
|
|
|
|
|
+ (. astOp := AST.OpMul;
|
|
|
|
|
+ IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
|
|
+ ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
|
|
+ ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
|
|
+ ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
|
|
+ astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
|
|
+ astCur := astA;
|
|
|
|
|
+ IF op = SymTab.OpAnd THEN
|
|
|
(* short-circuit: if q is false the RHS is skipped *)
|
|
(* short-circuit: if q is false the RHS is skipped *)
|
|
|
IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
t := SymTab.BoolType()
|
|
t := SymTab.BoolType()
|
|
@@ -2556,17 +2598,33 @@ PRODUCTIONS
|
|
|
isMax: BOOLEAN;
|
|
isMax: BOOLEAN;
|
|
|
called, isHigh, sfx, isCh,
|
|
called, isHigh, sfx, isCh,
|
|
|
isU, uok, isStr: BOOLEAN;
|
|
isU, uok, isStr: BOOLEAN;
|
|
|
- ucp: INTEGER; astScratch: AST.Node; .)
|
|
|
|
|
- = integer (. LexString(s);
|
|
|
|
|
- QbeGen.NormInt(s, q); IF twoPhase THEN astScratch := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
|
|
|
|
+ ucp: INTEGER; astIsLit: BOOLEAN; .)
|
|
|
|
|
+ = (. astIsLit := FALSE; .)
|
|
|
|
|
+ ( integer (. LexString(s);
|
|
|
|
|
+ QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
t := SymTab.IntType(); .)
|
|
t := SymTab.IntType(); .)
|
|
|
| charConst (. LexString(s);
|
|
| charConst (. LexString(s);
|
|
|
QbeGen.NormLit(s, q, isCh);
|
|
QbeGen.NormLit(s, q, isCh);
|
|
|
|
|
+ IF twoPhase THEN
|
|
|
|
|
+ astIsLit := TRUE;
|
|
|
|
|
+ astCur := AST.MakeLeaf(
|
|
|
|
|
+ AST.NkCharLit, s)
|
|
|
|
|
+ END;
|
|
|
t := SymTab.CharType(); .)
|
|
t := SymTab.CharType(); .)
|
|
|
| real (. LexString(s);
|
|
| real (. LexString(s);
|
|
|
QbeGen.NormReal(s, q);
|
|
QbeGen.NormReal(s, q);
|
|
|
|
|
+ IF twoPhase THEN
|
|
|
|
|
+ astIsLit := TRUE;
|
|
|
|
|
+ astCur := AST.MakeLeaf(
|
|
|
|
|
+ AST.NkRealLit, s)
|
|
|
|
|
+ END;
|
|
|
t := SymTab.RealType(); .)
|
|
t := SymTab.RealType(); .)
|
|
|
| string (. LexString(s);
|
|
| string (. LexString(s);
|
|
|
|
|
+ IF twoPhase THEN
|
|
|
|
|
+ astIsLit := TRUE;
|
|
|
|
|
+ astCur := AST.MakeLeaf(
|
|
|
|
|
+ AST.NkStrLit, s)
|
|
|
|
|
+ END;
|
|
|
IF SymTab.StrLen(s) = 3 THEN
|
|
IF SymTab.StrLen(s) = 3 THEN
|
|
|
t := SymTab.CharType();
|
|
t := SymTab.CharType();
|
|
|
QbeGen.IntStr(
|
|
QbeGen.IntStr(
|
|
@@ -2578,6 +2636,11 @@ PRODUCTIONS
|
|
|
QbeGen.NoteAddr(q, q)
|
|
QbeGen.NoteAddr(q, q)
|
|
|
END; .)
|
|
END; .)
|
|
|
| ustring (. LexString(s);
|
|
| ustring (. LexString(s);
|
|
|
|
|
+ IF twoPhase THEN
|
|
|
|
|
+ astIsLit := TRUE;
|
|
|
|
|
+ astCur := AST.MakeLeaf(
|
|
|
|
|
+ AST.NkStrLit, s)
|
|
|
|
|
+ END;
|
|
|
QbeGen.DeclUStr(s, q, isU, ucp,
|
|
QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
uok);
|
|
uok);
|
|
|
IF NOT uok THEN
|
|
IF NOT uok THEN
|
|
@@ -2986,7 +3049,7 @@ PRODUCTIONS
|
|
|
END
|
|
END
|
|
|
END
|
|
END
|
|
|
END; .)
|
|
END; .)
|
|
|
- | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
|
|
|
|
+ | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
| SetLit<st, sq> (. t := st;
|
|
| SetLit<st, sq> (. t := st;
|
|
|
QbeGen.CopyOp(sq, q); .)
|
|
QbeGen.CopyOp(sq, q); .)
|
|
|
| ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
| ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
@@ -2996,7 +3059,9 @@ PRODUCTIONS
|
|
|
IF t # SymTab.InvalidType THEN
|
|
IF t # SymTab.InvalidType THEN
|
|
|
QbeGen.NotQ(q2, q)
|
|
QbeGen.NotQ(q2, q)
|
|
|
ELSE QbeGen.CopyOp("0", q)
|
|
ELSE QbeGen.CopyOp("0", q)
|
|
|
- END; .) .
|
|
|
|
|
|
|
+ END; .)
|
|
|
|
|
+ )
|
|
|
|
|
+ (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
|
|
|
(* Set literals are SET OF [0..255] (8 words); elements validated
|
|
(* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
0..255 statically when foldable (222 otherwise), runtime trap
|
|
0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
for computed elements. Ranges always lower via SetRange. *)
|
|
for computed elements. Ranges always lower via SetRange. *)
|