FlowExpression:
PROGRAM
IMPORTS CPtr: Code, CodeDefs, P5U, P5L, P5, Stack, TreeOps
EXPORTS CodeDefs, P5 = BEGIN OPEN FOpCodes, CodeDefs, IntCodeDefs;
imported definitions
ISEIndex: TYPE = Symbols.ISEIndex;
ISENull: ISEIndex = Symbols.ISENull;
BitCount: TYPE = Symbols.BitCount;
tb: Tree.Base; -- tree base (local copy)
cb: CodeDefs.Base; -- code base (local copy)
FlowExpressionNotify:
PUBLIC Alloc.Notifier =
BEGIN -- called by allocator whenever table area is repacked
tb ← base[Tree.treeType];
cb ← base[codeType];
END;
CompForNodeName:
PACKED
ARRAY Tree.NodeName[relE..notin]
OF Comparator ← [
relE:eq, relN:ne, relL:lt, relGE:ge, relG:gt, relLE:le, in: in, notin: out];
JumpNN:
ARRAY Tree.NodeName[relE..relLE]
OF JumpType = [
relE:JumpE, relN:JumpN, relL:JumpL, relGE:JumpGE, relG:JumpG, relLE:JumpLE];
UJumpNN:
ARRAY Tree.NodeName[relE..relLE]
OF JumpType = [
relE:JumpE, relN:JumpN, relL:UJumpL, relGE:UJumpGE, relG:UJumpG, relLE:UJumpLE];
CNN:
ARRAY Tree.NodeName[relE..relLE]
OF Tree.NodeName = [
relE:relN, relN:relE, relL:relGE, relGE:relL, relG:relLE, relLE:relG];
RNN:
ARRAY Tree.NodeName[relE..relLE]
OF Tree.NodeName = [
relE:relE, relN:relN, relL:relG, relGE:relLE, relG:relL, relLE:relGE];
PushOnly:
PROC [t: Tree.Link] =
BEGIN
P5.PushRhs[t];
END;
FlowExp:
PUBLIC
PROC [node: Tree.Index]
RETURNS [l: Node] =
BEGIN -- generates code for a flow expression
SELECT tb[node].name
FROM
ifx => l ← IfExp[node];
or => l ← Or[node];
and => l ← And[node];
not => l ← Not[node];
relE, relN, relL, relGE, relG, relLE, in, notin => l ← Rel[node];
abs => l ← Abs[node];
lengthen => l ← Lengthen[node];
shorten => l ← Shorten[node];
min => l ← Min[node];
max => l ← Max[node];
istype => l ← Rel[node];
ENDCASE => {SIGNAL CPtr.CodeNotImplemented};
RETURN
END;
Abs:
PROC [node: Tree.Index]
RETURNS [Node] =
BEGIN -- generate code for ABS
op: Node ← P5U.ArithOpForTree[node, abs];
bits: BitCount ← P5U.BitsForType[tb[node].info];
val: Node ← P5.Exp[tb[node].son[1]];
RETURN [P5U.ApplyOp[op, P5U.MakeNodeList[val], bits]];
END;
Lengthen: PROC [node: Tree.Index] RETURNS [Lexeme] =
BEGIN
r: VarIndex = P5L.VarForLex[P5.Exp[tb[node].son[1]]];
nw: CARDINAL;
IF P5L.VarAlignment[r, load].wSize = 2 THEN -- array descriptor
BEGIN
IF P5L.AllLoaded[r] THEN
BEGIN
len: VarComponent = Stack.TempStore[1];
P5U.Out0[qLP];
P5L.LoadComponent[len];
END
ELSE
BEGIN
tr1, tr2: VarIndex;
[first: tr1, next: tr2] ← P5L.ReusableCopies[r, load, TRUE];
P5L.FieldOfVar[r: tr1, wSize: 1];
P5L.FieldOfVar[r: tr2, wd: 1, wSize: 1];
IF P5L.AllLoaded[tr2] THEN -- clearly on top of stack
tr2 ← P5L.OVarItem[P5L.CopyToTemp[tr2].var];
P5L.LoadVar[tr1];
P5U.Out0[qLP];
P5L.LoadVar[tr2];
END;
nw ← 3;
END
ELSE
BEGIN
P5L.LoadVar[r];
IF tb[node].attr1 THEN P5U.Out0[qLP]
ELSE IF tb[node].attr3 THEN P5U.Out0[qLINT]
ELSE P5U.Out1[qLI, 0];
nw ← 2;
END;
RETURN [P5L.TOSLex[nw]]
END;
Shorten: PROC [node: Tree.Index] RETURNS [Lexeme] =
BEGIN
P5.PushRhs[tb[node].son[1]];
IF ~tb[node].attr1 THEN P5U.Out0[qPOP] -- no checking
ELSE IF tb[node].attr3 THEN
BEGIN
P5U.Out1[qLI, 100000b]; P5U.Out1[qLI, 0]; P5U.Out0[qDADD];
P5U.Out1[qLI, 1]; P5U.Out0[qBNDCK]; P5U.Out0[qPOP];
P5U.Out1[qLI, 100000b]; P5U.Out0[qXOR];
END
ELSE
BEGIN
P5U.Out1[qLI, 1]; P5U.Out0[qBNDCK]; P5U.Out0[qPOP];
END;
RETURN [P5L.TOSLex[1]]
END;
And:
PROC [node: Tree.Index]
RETURNS [l: Node] =
INLINE
BEGIN -- generate code for "AND"
e1: Node = P5.Exp[tb[node].son[1]];
e2: Node = P5.Exp[tb[node].son[2]];
else: CaseList = P5U.MakeCaseList[NIL, CPtr.falseNode];
then: CaseList = P5U.MakeCaseList[P5U.MakeNodeList[e1], e2, else];
l ← z.NEW[NodeRep.cond ← [bits: e1.bits, details: cond[then]]];
END;
Or:
PROC [node: Tree.Index]
RETURNS [l: Node] =
INLINE
BEGIN -- generate code for "OR"
e1: Node = P5.Exp[tb[node].son[1]];
e2: Node = P5.Exp[tb[node].son[2]];
else: CaseList = P5U.MakeCaseList[NIL, e2];
then: CaseList = P5U.MakeCaseList[P5U.MakeNodeList[e1], CPtr.trueNode, else];
l ← z.NEW[NodeRep.cond ← [bits: e1.bits, details: cond[then]]];
END;
Not:
PROC [node: Tree.Index]
RETURNS [l: Node] =
BEGIN -- generate code for "NOT"
e1: Node = P5.Exp[tb[node].son[1]];
else: CaseList = P5U.MakeCaseList[NIL, CPtr.trueNode];
then: CaseList = P5U.MakeCaseList[P5U.MakeNodeList[e1], CPtr.falseNode, else];
l ← z.NEW[NodeRep.cond ← [bits: e1.bits, details: cond[then]]];
END;
Rel:
PROC [node: Tree.Index]
RETURNS [l: Node] =
BEGIN -- produces code for relationals
e1: Node = P5.Exp[tb[node].son[1]];
e2: Node = P5.Exp[tb[node].son[2]];
ops: NodeList ← P5U.MakeNodeList[e1, P5U.MakeNodeList[e2]];
name: Tree.NodeName ← tb[node].name;
SELECT name
FROM
relE, relN, relL, relGE, relG, relLE, in, notin =>
l ← P5U.ApplyOp[oper: P5U.CompareOpForTree[node, CompForNodeName[name]], args: ops, bits: 1];
istype => NULL; -- obviously needs work
ENDCASE;
END;
IfExp:
PROC [node: Tree.Index]
RETURNS [l: Node] =
BEGIN -- generates code for an IF expression
test: Node = P5.Exp[tb[node].son[1]];
e1: Node = P5.Exp[tb[node].son[2]];
e2: Node = P5.Exp[tb[node].son[3]];
else: CaseList = P5U.MakeCaseList[NIL, e2];
then: CaseList = P5U.MakeCaseList[P5U.MakeNodeList[test], e1, else];
l ← z.NEW[NodeRep.cond ← [bits: e1.bits, details: cond[then]]];
END;
Min:
PROC [node: Tree.Index]
RETURNS [l: Node] =
BEGIN -- generates code for "MAX[...]"
op: Node ← P5U.ArithOpForTree[node, min];
bits: BitCount ← P5U.BitsForType[tb[node].info];
l ← CMinMax[op, tb[node].son[1], bits];
END;
Max:
PROC [node: Tree.Index]
RETURNS [l: Node] =
BEGIN -- generates code for "MAX[...]"
op: Node ← P5U.ArithOpForTree[node, max];
bits: BitCount ← P5U.BitsForType[tb[node].info];
l ← CMinMax[op, tb[node].son[1], bits];
END;
CMinMax:
PROC [mOp: Node, t: Tree.Link, bits: BitCount]
RETURNS [l: Node] =
BEGIN -- common subroutine for Cmin and Cmax
args: NodeList ← P5.ExpList[t];
RETURN [P5U.ApplyOp[mOp, args, bits]];
END;
END.