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]; 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; 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. FlowExpression.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Sweet, May 20, 1986 9:31:12 am PDT Satterthwaite, November 2, 1982 3:56 pm Russ Atkinson (RRA) March 6, 1985 11:19:51 pm PST imported definitions lengthen => l _ Lengthen[node]; shorten => l _ Shorten[node]; 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; Κ_˜codešœ™Kšœ Οmœ1™