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]; }; }.