DIRECTORY PrintingDefs USING [OutCode], PrintDclsDefs USING [GetAttributes], PrintExprDefs USING [], SymbolTableDefs USING [SymbolType, LookUpSymbol], TreesDefs USING [MakeNode, TreeNode], Storage USING [AppendString, CopyString, FreeString, Free]; PrintExprImpl: PROGRAM IMPORTS PrintDclsDefs, PrintingDefs, Storage, TreesDefs, SymbolTableDefs EXPORTS PrintExprDefs = { -- Look at the expression node and see if an integer value -- is used as a logical value (as is common in C). -- If so then change to a logical value by comparing -- the integer value (not equal) with 0. -- We need pointer to pointer to node since we might change -- the node itself. IntExpToRelation: PUBLIC PROCEDURE [e: LONG POINTER TO LONG POINTER TO TreesDefs.TreeNode] = { IF e = NIL OR e↑ = NIL THEN RETURN; IF e.nodeType # operation THEN PrintingDefs.OutCode["*** no operation in IntExpToRelation ***", 0]; FixPass1[e↑]; -- to get the type analysis information into the tree IF e.dataType # boolean THEN { temp: LONG POINTER TO TreesDefs.TreeNode; s: LONG STRING ← Storage.CopyString["0"L]; temp ← TreesDefs.MakeNode[left: NIL, right: NIL, string: s, nodeType: operation]; temp.operationType ← iconValue; temp ← TreesDefs.MakeNode[left: e↑, right: temp, string: NIL, nodeType: operation]; temp.operationType ← notEquals; e↑ ← temp; e.dataType ← boolean; e.baseDataType ← boolean; e.typeString ← "BOOLEAN"L; e.pointerCount ← 0; }; }; -- This looks through an expression tree and makes some changes -- so that code generation will work out better. -- It does the following things: -- (Pass 1) Does a type analysis of the expression. -- (Pass 2) (a) finds logical operations and makes sure their operands -- are logical rather than integer values -- (b) changes preIncrement to plusAssign 1 -- (c) changes preDecement to minusAssign 1 -- (d) adds a simpleValue "1" to postIncrement and postDecrement -- (e) changes arrayReferences with pointers to -- pointer arithmetic and dereferencing -- (f) LOOPHOLEs pointers in relational expressions to INT -- -- (Pass 3) Scales pointer arithmetic FixExpression: PROCEDURE [e: LONG POINTER TO LONG POINTER TO TreesDefs.TreeNode] = { FixPass1[e↑]; -- do type analysis FixPass2[e]; FixPass3[e]; }; FixPass1: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode] = { -- Do a bottom up tree walk and propogate the type information -- throughout the tree IF node = NIL THEN RETURN; IF node.nodeType # operation AND node.nodeType # eList THEN { PrintingDefs.OutCode["FixPass1←Error;", 0]; RETURN; }; -- Do a bottom up (postorder) tree traversal. IF node.operationType # sizeOf THEN FixPass1[node.left]; IF node.operationType # castOp THEN FixPass1[node.right]; IF node.nodeType = eList THEN RETURN; SELECT node.operationType FROM multiplyOp, assignOp, multiplyAssign, divideAssign, modulusAssign, shiftLeftAssign, shiftRightAssign, plusAssign, postIncrement, postDecrement, preIncrement, preDecrement, minusAssign, bitAndAssign, bitOrAssign, bitXorAssign => { node.dataType ← node.left.dataType; node.baseDataType ← node.left.baseDataType; node.typeString ← node.left.typeString; node.pointerCount ← node.left.pointerCount; }; divideOp, modulusOp, shiftLeft, shiftRight, plusOp, minusOp, bitAnd, bitOr, bitXor => { l, r: LONG POINTER TO TreesDefs.TreeNode; l ← node.left; r ← node.right; -- The basic algorithm here is -- (1) If either is pointer then result is pointer -- (2) Else if either is long the result is long -- (3) Else the result is that of the left hand -- argument unless that is boolean, then -- it is the right hand argument. SELECT l.dataType FROM pointer => NULL; long => IF r.dataType = pointer THEN l ← r; short => IF r.dataType = long OR r.dataType = pointer THEN l ← r; boolean => IF r.dataType # boolean THEN l ← r; ENDCASE => NULL; node.dataType ← l.dataType; node.baseDataType ← l.baseDataType; node.typeString ← l.typeString; node.pointerCount ← l.pointerCount; }; bitNot, unaryMinus => { node.dataType ← node.left.dataType; node.baseDataType ← node.left.baseDataType; node.typeString ← node.left.typeString; node.pointerCount ← node.left.pointerCount; }; sizeOf => { node.dataType ← short; node.baseDataType ← short; node.typeString ← "INTEGER"L; node.pointerCount ← 0; }; ifExpression => { -- take the type of from the 'then' expression node.dataType ← node.right.left.dataType; node.baseDataType ← node.right.left.baseDataType; node.typeString ← node.right.left.typeString; node.pointerCount ← node.right.left.pointerCount; }; logicalOr, logicalAnd, logicalNot, equals, notEquals, lessThan, greaterThan, lessThanOrEqual, greaterThanOrEqual => { node.dataType ← boolean; node.baseDataType ← boolean; node.typeString ← "BOOLEAN"L; node.pointerCount ← 0; }; dereference => { node.pointerCount ← IF node.left. pointerCount > 0 THEN node.left.pointerCount - 1 ELSE 0; node.baseDataType ← node.left.baseDataType; node.typeString ← node.left.typeString; node.dataType ← IF node.pointerCount > 0 THEN pointer ELSE node.baseDataType; }; addressOf => { node.dataType ← pointer; node.baseDataType ← node.left.baseDataType; node.typeString ← node.left.typeString; node.pointerCount ← node.left.pointerCount + 1; }; castOp => { [node.typeString, node.dataType, node.baseDataType, node.pointerCount] ← GetCastType[node.right.left, node.right.right]; }; arrayReference => { node.typeString ← node.left.typeString; node.baseDataType ← node.left.baseDataType; node.pointerCount ← IF node.left.pointerCount > 0 THEN node.left.pointerCount - 1 ELSE 0; node.dataType ← IF node.left.dataType = arrayArray THEN array ELSE IF node.pointerCount > 0 THEN pointer ELSE node.baseDataType; }; procedureCall, nameValue => { [node.dataType, node.baseDataType, node.typeString, node.pointerCount] ← SymbolTableDefs.LookUpSymbol[node.string]; }; iconValue => { node.dataType ← long; node.baseDataType ← long; node.typeString ← "INT"; node.pointerCount ← 0; }; fconValue => { node.dataType ← double; node.baseDataType ← double; node.typeString ← "LONG REAL"; node.pointerCount ← 0; }; stringValue => { node.dataType ← pointer; node.baseDataType ← short; node.typeString ← "INTEGER"; node.pointerCount ← 1; }; structReference => { [node.dataType, node.baseDataType, node.typeString, node.pointerCount] ← SymbolTableDefs.LookUpSymbol[node.right.string]; }; eList, thenElseExpression => NULL; ENDCASE => ERROR; }; FixPass2: PROCEDURE [e: LONG POINTER TO LONG POINTER TO TreesDefs.TreeNode] = { temp2: LONG POINTER TO TreesDefs.TreeNode; IF e = NIL OR e↑ = NIL THEN RETURN; IF e.nodeType # eList THEN SELECT e.operationType FROM -- For logical operations, first do the rest of the tree -- and then check the operands for logical type. logicalAnd, logicalOr => { IntExpToRelation[@e.left]; IntExpToRelation[@e.right]; }; logicalNot => { IntExpToRelation[@e.left]; }; lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual => { IF e.left.dataType = pointer OR e.left.dataType = array OR e.left.dataType = arrayArray THEN e.left ← LoopholeToINT[e.left]; IF e.right.dataType = pointer OR e.right.dataType = array OR e.right.dataType = arrayArray THEN e.right ← LoopholeToINT[e.right]; }; ifExpression => { IntExpToRelation[@e.left]; }; postIncrement, postDecrement => { temp: LONG STRING ← Storage.CopyString[s: "1"L, longer: 64]; e.right ← TreesDefs.MakeNode[left: NIL, right: NIL, string: temp, nodeType: operation]; e.right.operationType ← iconValue; e.right.pointerCount ← 0; e.right.typeString ← e.left.typeString; e.right.dataType ← e.left.baseDataType; e.right.baseDataType ← e.left.baseDataType; }; preIncrement => { -- make a "1" node and change to plusAssign temp: LONG STRING ← Storage.CopyString[s: "1"L, longer: 64]; e.operationType ← plusAssign; temp2 ← TreesDefs.MakeNode[left: NIL, right: NIL, string: temp, nodeType: operation]; temp2.operationType ← iconValue; e.right ← temp2; e.right.pointerCount ← 0; e.right.typeString ← e.left.typeString; e.right.dataType ← e.left.baseDataType; e.right.baseDataType ← e.left.baseDataType; }; preDecrement => { -- make a "1" node and change to minusAssign temp: LONG STRING ← Storage.CopyString[s: "1"L, longer: 64]; e.operationType ← minusAssign; temp2 ← TreesDefs.MakeNode[left: NIL, right: NIL, string: temp, nodeType: operation]; temp2.operationType ← iconValue; e.right ← temp2; e.right.pointerCount ← 0; e.right.typeString ← e.left.typeString; e.right.dataType ← e.left.baseDataType; e.right.baseDataType ← e.left.baseDataType; }; arrayReference => { IF e.left.dataType = pointer THEN { -- change to pointer arithmetic and dereferencing e.operationType ← plusOp; e.pointerCount ← e.left.pointerCount; e.dataType ← e.left.dataType; -- baseDataType and typeString values have already -- been correctly set by FixPass1. e↑ ← TreesDefs.MakeNode[left: e↑, right: NIL, string: NIL, nodeType: operation]; e.operationType ← dereference; e.baseDataType ← e.left.baseDataType; e.typeString ← e.left.typeString; e.pointerCount ← IF e.left.pointerCount > 0 THEN e.left.pointerCount - 1 ELSE 0; e.dataType ← IF e.pointerCount > 0 THEN pointer ELSE e.baseDataType; }; }; ENDCASE => NULL; IF e.operationType # sizeOf THEN FixPass2[@e.left]; IF e.operationType # castOp THEN FixPass2[@e.right]; }; FixPass3: PROCEDURE [e: LONG POINTER TO LONG POINTER TO TreesDefs.TreeNode] = { IF e = NIL OR e↑ = NIL THEN RETURN; -- Do a bottom up (postorder) tree traversal. IF e.operationType # sizeOf THEN FixPass3[@e.left]; IF e.operationType # castOp THEN FixPass3[@e.right]; IF e.nodeType = eList THEN RETURN; SELECT e.operationType FROM plusOp, plusAssign, minusOp, minusAssign, postIncrement, postDecrement => { temp: LONG POINTER TO TreesDefs.TreeNode; -- if pointer is on the right, exchange left and right IF e.left.dataType # pointer AND e.right.dataType = pointer THEN { temp ← e.left; e.left ← e.right; e.right ← temp; }; IF e.left.dataType = pointer AND e.right.dataType # pointer THEN { IF e.right.operationType = iconValue AND e.right.string.length = 1 AND e.right.string.text[0] = '0 THEN { NULL; } -- leave the '0 as is ELSE IF e.right.operationType = iconValue AND e.right.string.length = 1 AND e.right.string.text[0] = '1 THEN { Storage.Free[e.right]; e.right ← GetPointerTypeNode[e.left.pointerCount, e.left.typeString, FALSE]; } ELSE { temp ← GetPointerTypeNode[e.left.pointerCount, e.left.typeString, TRUE]; temp.left ← e.right; temp.dataType ← e.right.dataType; temp.baseDataType ← e.right.baseDataType; temp.typeString ← e.right.typeString; temp.pointerCount ← e.right.pointerCount; e.right ← temp; }; }; IF e.operationType = minusOp AND e.left.dataType = pointer AND e.right.dataType = pointer THEN { -- Fix up the minusOp node. e.dataType ← long; e.baseDataType ← long; e.typeString ← "INT"L; e.pointerCount ← 0; temp ← GetPointerTypeNode[e.left.pointerCount, e.left.typeString, TRUE]; temp.left ← e↑; e↑ ← temp; e.dataType ← long; e.baseDataType ← long; e.typeString ← "INT"L; e.pointerCount ← 0; }; }; ENDCASE => NULL; }; LoopholeToINT: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode] RETURNS [resultNode: LONG POINTER TO TreesDefs.TreeNode] = { -- first make a node to be the second argument to LOOPHOLE resultNode ← TreesDefs.MakeNode[left: NIL, right: NIL, string: Storage.CopyString["INT"L], nodeType: operation]; resultNode.operationType ← nameValue; resultNode.dataType ← long; resultNode.baseDataType ← long; resultNode.typeString ← "INT"; resultNode.pointerCount ← 0; -- then make it into an expression list (second arg to proc) resultNode ← TreesDefs.MakeNode[left: resultNode, right: NIL, string: NIL, nodeType: eList]; -- then make it into an expression list (first arg to proc) resultNode ← TreesDefs.MakeNode[left: node, right: resultNode, string: NIL, nodeType: eList]; -- then make the procedure call node using this argument list resultNode ← TreesDefs.MakeNode[left: NIL, right: resultNode, string: Storage.CopyString["LOOPHOLE"L], nodeType: operation]; resultNode.operationType ← procedureCall; resultNode.dataType ← long; resultNode.baseDataType ← long; resultNode.typeString ← "INT"; resultNode.pointerCount ← 0; }; GetPointerTypeNode: PROCEDURE [pointerCount: CARDINAL, typeString: LONG STRING, multiplyNode: BOOLEAN] RETURNS [resultNode: LONG POINTER TO TreesDefs.TreeNode] = { tempTypeString: LONG STRING; -- first make the argument expression tempTypeString ← Storage.CopyString[s: ""L, longer: 64]; THROUGH [1..pointerCount) DO Storage.AppendString[@tempTypeString, "LONG POINTER TO "L]; ENDLOOP; Storage.AppendString[@tempTypeString, typeString]; resultNode ← TreesDefs.MakeNode[left: NIL, right: NIL, string: tempTypeString, nodeType: operation]; resultNode.operationType ← nameValue; -- then make it into an expression list resultNode ← TreesDefs.MakeNode[left: resultNode, right: NIL, string: NIL, nodeType: eList]; -- then make the procedure call node using this argument list resultNode ← TreesDefs.MakeNode[left: NIL, right: resultNode, string: Storage.CopyString["SIZE"L], nodeType: operation]; resultNode.operationType ← procedureCall; resultNode.dataType ← short; resultNode.baseDataType ← short; resultNode.typeString ← "INTEGER"; resultNode.pointerCount ← 0; IF NOT multiplyNode THEN RETURN; -- then make the multiply node resultNode ← TreesDefs.MakeNode[left: NIL, right: resultNode, string: NIL, nodeType: operation]; resultNode.operationType ← multiplyOp; }; MakeExpression: PUBLIC PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode, withParens: BOOLEAN] RETURNS [result: LONG STRING] = { temp: LONG STRING; MakeExpressionRec: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode, withParens: BOOLEAN] RETURNS [result: LONG STRING] = { InfixOperation: PROCEDURE [ left: LONG POINTER TO TreesDefs.TreeNode, operationName: LONG STRING, right: LONG POINTER TO TreesDefs.TreeNode] = { IF withParens THEN Storage.AppendString[@result, "("L]; IF left # NIL THEN { temp ← MakeExpressionRec[left, TRUE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; }; Storage.AppendString[@result, operationName]; IF right # NIL THEN { temp ← MakeExpressionRec[right, TRUE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; }; IF withParens THEN Storage.AppendString[@result, ")"L]; }; FunctionOperation: PROCEDURE [functionName: LONG STRING, indirection: BOOLEAN, left: LONG POINTER TO TreesDefs.TreeNode, right: LONG POINTER TO TreesDefs.TreeNode] = { Storage.AppendString[@result, functionName]; Storage.AppendString[@result, "["L]; IF indirection THEN Storage.AppendString[@result, "@"L]; temp ← MakeExpressionRec[left, FALSE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; IF right # NIL THEN { Storage.AppendString[@result, ","L]; temp ← MakeExpressionRec[right, FALSE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; }; Storage.AppendString[@result, "]"L]; }; result ← Storage.CopyString[s: ""L, longer: 64]; IF node = NIL THEN RETURN; IF node.nodeType # operation THEN { Storage.AppendString[@result, "*** no operation in MakeExpressionRec ***"L]; RETURN; }; SELECT node.operationType FROM assignOp => { coerce: BOOLEAN ← FALSE; IF withParens THEN Storage.AppendString[@result, "("L]; temp ← MakeExpressionRec[node.left, FALSE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; Storage.AppendString[@result, " ← "L]; IF node.left.dataType = long AND node.right.dataType = short THEN { coerce ← TRUE; Storage.AppendString[@result, "LONG["L]; } ELSE IF node.left.dataType = short AND node.right.dataType = long THEN { coerce ← TRUE; Storage.AppendString[@result, "INTEGER["L]; }; temp ← MakeExpressionRec[node.right, FALSE]; Storage.AppendString[@result, temp]; IF coerce THEN Storage.AppendString[@result, "]"L]; IF withParens THEN Storage.AppendString[@result, ")"L]; Storage.FreeString[temp]; }; multiplyAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["MultipyAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; divideAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["DivideAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; modulusAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["ModulusAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; plusAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; IF node.left.dataType = pointer OR node.left.dataType = array THEN FunctionOperation["PlusAssignPtr"L, TRUE, node.left, node.right] ELSE FunctionOperation["PlusAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; minusAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; IF node.left.dataType = pointer OR node.left.dataType = array THEN FunctionOperation["MinusAssignPtr"L, TRUE, node.left, node.right] ELSE FunctionOperation["MinusAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; shiftLeftAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["ShiftLeftAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; shiftRightAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["ShiftRightAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; bitAndAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["BitAndAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; bitOrAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["BitOrAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; bitXorAssign => { IF withParens THEN Storage.AppendString[@result, "("L]; FunctionOperation["BitXorAssign", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; ifExpression => { Storage.AppendString[@result, "IF "L]; temp ← MakeExpressionRec[node.left, TRUE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; Storage.AppendString[@result, " THEN "L]; temp ← MakeExpressionRec[node.right.left, TRUE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; Storage.AppendString[@result, " ELSE "L]; temp ← MakeExpressionRec[node.right.right, TRUE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; }; logicalOr => { InfixOperation[node.left, " OR "L, node.right]; }; logicalAnd => { InfixOperation[node.left, " AND "L, node.right]; }; bitOr => { FunctionOperation["BitOr"L, FALSE, node.left, node.right]; }; bitAnd => { FunctionOperation["BitAnd"L, FALSE, node.left, node.right]; }; bitXor => { FunctionOperation["BitXor"L, FALSE, node.left, node.right]; }; equals => { InfixOperation[node.left, " = "L, node.right]; }; notEquals => { InfixOperation[node.left, " # "L, node.right]; }; lessThan => { InfixOperation[node.left, " < "L, node.right]; }; greaterThan => { InfixOperation[node.left, " > "L, node.right]; }; lessThanOrEqual => { InfixOperation[node.left, " <= "L, node.right]; }; greaterThanOrEqual => { InfixOperation[node.left, " >= "L, node.right]; }; shiftLeft => { FunctionOperation["ShiftLeft"L, FALSE, node.left, node.right]; }; shiftRight => { FunctionOperation["ShiftRight"L, FALSE, node.left, node.right]; }; plusOp => { InfixOperation[node.left, " + "L, node.right]; }; minusOp => { InfixOperation[node.left, " - "L, node.right]; }; multiplyOp => { InfixOperation[node.left, " * "L, node.right]; }; divideOp => { InfixOperation[node.left, " / "L, node.right]; }; modulusOp => { InfixOperation[node.left, " MOD "L, node.right]; }; postIncrement => { IF withParens THEN Storage.AppendString[@result, "("L]; IF node.left.dataType = pointer OR node.left.dataType = array THEN FunctionOperation["PostIncPtr"L, TRUE, node.left, node.right] ELSE FunctionOperation["PostInc", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; postDecrement => { IF withParens THEN Storage.AppendString[@result, "("L]; IF node.left.dataType = pointer OR node.left.dataType = array THEN FunctionOperation["PostDecPtr"L, TRUE, node.left, node.right] ELSE FunctionOperation["PostDec", TRUE, node.left, node.right]; IF withParens THEN Storage.AppendString[@result, ")"L]; }; dereference => { IF node.left.pointerCount = 0 THEN Storage.AppendString[@result, "***dereference of non pointer***"L]; InfixOperation[node.left, "↑"L, NIL]; }; addressOf => { InfixOperation[NIL, "@"L, node.left]; }; unaryMinus => { InfixOperation[NIL, "-"L, node.left]; }; logicalNot => { InfixOperation[NIL, "NOT "L, node.left]; }; bitNot => { FunctionOperation["BitNot"L, FALSE, node.left, NIL]; }; sizeOf => { temp: LONG STRING ← GetSizeOfType[node.left]; Storage.AppendString[@result, "SIZE["L]; Storage.AppendString[@result, temp]; Storage.AppendString[@result, "]"L]; Storage.FreeString[temp]; }; castOp => { temp: LONG STRING; Storage.AppendString[@result, "LOOPHOLE["L]; temp ← MakeExpressionRec[node.left, FALSE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; Storage.AppendString[@result, ", "L]; temp ← GetCastString[node.right.left, node.right.right]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; Storage.AppendString[@result, "]"L]; }; arrayReference => { temp: LONG STRING ← MakeExpressionRec[node.left, TRUE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; IF node.left.dataType = array AND node.left.operationType = nameValue THEN Storage.AppendString[@result, "Array"L] ELSE IF node.left.dataType = arrayArray THEN Storage.AppendString[@result, "ArrayArray"L]; Storage.AppendString[@result, "["L]; IF node.right.dataType # short THEN Storage.AppendString[@result, "INTEGER["L]; temp ← MakeExpressionRec[node.right, FALSE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; IF node.right.dataType # short THEN Storage.AppendString[@result, "]"L]; Storage.AppendString[@result, "]"L]; }; procedureCall => { n: LONG POINTER TO TreesDefs.TreeNode; Storage.AppendString[@result, node.string]; Storage.AppendString[@result, "["L]; FOR n ← node.right, n ← n.right WHILE n # NIL DO temp ← MakeExpressionRec[n.left, FALSE]; Storage.AppendString[@result, temp]; Storage.FreeString[temp]; IF n.right # NIL THEN Storage.AppendString[@result, ", "L]; ENDLOOP; Storage.AppendString[@result, "]"L]; }; structReference => { InfixOperation[node.left, "."L, node.right]; }; nameValue => { IF node.string.length = 4 AND node.string.text[0] = 'N AND node.string.text[1] = 'U AND node.string.text[2] = 'L AND node.string.text[3] = 'L THEN Storage.AppendString[@result, "c"L]; Storage.AppendString[@result, node.string]; }; iconValue, fconValue, stringValue => { Storage.AppendString[@result, node.string]; }; ENDCASE => { Storage.AppendString[@result, "*** expression error in MakeExpression ***"L]; }; }; -- main MakeExpression code -- FixExpression[@node]; result ← IF node = NIL THEN Storage.CopyString[""L] ELSE MakeExpressionRec[node, FALSE]; }; GetCastType: PROCEDURE [type: LONG POINTER TO TreesDefs.TreeNode, declarator: LONG POINTER TO TreesDefs.TreeNode] RETURNS [baseType: LONG STRING, symType, baseSymType: SymbolTableDefs.SymbolType, pointerCount: CARDINAL] = { n: LONG POINTER TO TreesDefs.TreeNode; IF type = NIL OR declarator = NIL THEN RETURN [Storage.CopyString["*** NIL argument to GetCastType ***"L], none, none, 0]; IF type.nodeType # attributes THEN RETURN [Storage.CopyString["*** cast error in GetCastType ***"L], none, none, 0]; pointerCount ← 0; [symType: baseSymType, typeString: baseType] ← PrintDclsDefs.GetAttributes[type, 0]; FOR n ← declarator, n.right WHILE n # NIL DO SELECT n.declaratorType FROM arrayOf, pointerTo => pointerCount ← pointerCount + 1; ENDCASE => NULL; ENDLOOP; symType ← IF pointerCount > 0 THEN pointer ELSE baseSymType; }; GetCastString: PROCEDURE [type: LONG POINTER TO TreesDefs.TreeNode, declarator: LONG POINTER TO TreesDefs.TreeNode] RETURNS [castType: LONG STRING] = { temp, baseType: LONG STRING; n: LONG POINTER TO TreesDefs.TreeNode; IF type = NIL OR declarator = NIL THEN RETURN [Storage.CopyString["*** NIL argument to GetCastType ***"L]]; IF type.nodeType # attributes THEN RETURN [Storage.CopyString["*** cast error in GetCastType ***"L]]; [typeString: baseType] ← PrintDclsDefs.GetAttributes[type, 0]; castType ← Storage.CopyString[s: ""L, longer: 64]; FOR n ← declarator, n.right WHILE n # NIL DO SELECT n.declaratorType FROM pointerTo => Storage.AppendString[@castType, "LONG POINTER TO "L]; arrayOf => { Storage.AppendString[@castType, "ARRAY [0.."L]; temp ← IF n.left # NIL THEN MakeExpression[n.left, FALSE] ELSE Storage.CopyString["0"L]; Storage.AppendString[@castType, temp]; Storage.FreeString[temp]; Storage.AppendString[@castType, ") OF "L]; }; functionOf => Storage.AppendString[@castType, "PROCEDURE [] "L]; simpleName => NULL; ENDCASE => ERROR; ENDLOOP; Storage.AppendString[@castType, baseType]; }; GetSizeOfType: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode] RETURNS [result: LONG STRING] = { IF node = NIL THEN RETURN["*** NIL argument to GetSizeOfType ***"L]; IF node.nodeType # operation THEN { result ← GetCastString[node.left, node.right]; RETURN; }; result ← Storage.CopyString[s: ""L, longer: 64]; THROUGH [0..node.pointerCount) DO Storage.AppendString[@result, "LONG POINTER TO "L]; ENDLOOP; Storage.AppendString[@result, node.typeString]; }; }.