<> <> <> <> <> DIRECTORY Alloc, Code, CodeDefs, FOpCodes, IntCodeDefs, P5, P5L, P5U, Stack, Symbols, Tree, TreeOps; FlowExpression: PROGRAM IMPORTS CPtr: Code, CodeDefs, P5U, P5L, P5, Stack, TreeOps EXPORTS CodeDefs, P5 = BEGIN OPEN FOpCodes, CodeDefs, IntCodeDefs; <> 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]; < l _ Lengthen[node];>> < 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; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<[first: tr1, next: tr2] _ P5L.ReusableCopies[r, load, TRUE];>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>> <<>> 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.