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