DIRECTORY
PrintingDefs USING [PrintComments, OutCode],
PrintDclsDefs USING [PrintDeclarations],
PrintExprDefs USING [IntExpToRelation, MakeExpression],
PrintStmtsDefs USING [],
SymbolTableDefs USING [EnterBlock, ExitBlock, PrintSymbolTable],
TreesDefs USING [FreeTree, TreeNode],
Storage USING [FreeString];
PrintStmtsImpl: PROGRAM IMPORTS PrintDclsDefs, PrintingDefs, Storage,
TreesDefs, SymbolTableDefs, PrintExprDefs
EXPORTS PrintStmtsDefs = {
PrintStatement: PUBLIC PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode] = {
temp: LONG STRING;
PrintStatementRec: PUBLIC PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode,
indent: CARDINAL, semiAtEnd, inSwitch, inContinue: BOOLEAN]
RETURNS [wasGoto: BOOLEAN] = {
wasGoto ← FALSE;
DO
IF node = NIL THEN RETURN;
SELECT node.nodeType FROM
ifStmt => {
PrintingDefs.OutCode["IF "L, indent];
PrintExprDefs.IntExpToRelation[@node.left];
temp ← PrintExprDefs.MakeExpression[node.left, FALSE];
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
PrintingDefs.OutCode[" THEN\n"L, 0];
wasGoto ← PrintStatementRec[node: node.right.left,
indent: indent + 1, semiAtEnd: FALSE, inSwitch: inSwitch,
inContinue: FALSE];
IF node.right.right # NIL THEN {
PrintingDefs.OutCode["\n"L, 0];
PrintingDefs.OutCode["ELSE\n"L, indent];
wasGoto ← wasGoto OR PrintStatementRec[node: node.right.right,
indent: indent + 1, semiAtEnd: FALSE, inSwitch: inSwitch,
inContinue: FALSE]; };
GOTO Done; };
whileStmt => {
PrintingDefs.OutCode["WHILE "L, indent];
PrintExprDefs.IntExpToRelation[@node.left];
temp ← PrintExprDefs.MakeExpression[node.left, FALSE];
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
PrintingDefs.OutCode[" DO\n"L, 0];
-- skip compound statement by first printing
-- its declarations then printing the stmtList
IF node.right.nodeType = compoundStmt THEN {
SymbolTableDefs.EnterBlock[];
PrintDclsDefs.PrintDeclarations[node.right.left,
indent + 1, ";\n"L, TRUE];
[] ← PrintStatementRec[node: node.right.right,
indent: indent + 1, semiAtEnd: TRUE, inSwitch: FALSE,
inContinue: FALSE];
SymbolTableDefs.ExitBlock[]; }
ELSE [] ← PrintStatementRec[node: node.right,
indent: indent + 1, semiAtEnd: TRUE, inSwitch: FALSE,
inContinue: FALSE];
PrintingDefs.OutCode["ENDLOOP"L, indent + 1];
GOTO Done; };
doWhileStmt => {
loopInBlock: BOOLEAN ← LoopInBlock[node.right];
PrintingDefs.OutCode["DO"L, indent];
IF loopInBlock THEN PrintingDefs.OutCode[" BEGIN"L, 0];
PrintingDefs.OutCode["\n"L, 0];
-- skip compound statement by first printing
-- its declarations then printing the stmtList
IF node.right.nodeType = compoundStmt THEN {
SymbolTableDefs.EnterBlock[];
PrintDclsDefs.PrintDeclarations[node.right.left, indent + 1, ";\n"L, TRUE];
[] ← PrintStatementRec[node: node.right.right,
indent: indent + 1, semiAtEnd: TRUE, inSwitch: FALSE,
inContinue: loopInBlock];
SymbolTableDefs.ExitBlock[]; }
ELSE [] ← PrintStatementRec[node: node.right,
indent: indent + 1, semiAtEnd: TRUE, inSwitch: FALSE,
inContinue: loopInBlock];
IF loopInBlock THEN
PrintingDefs.OutCode["EXITS Continue => NULL; END;\n"L, indent + 1];
PrintingDefs.OutCode["IF NOT "L, indent + 1];
PrintExprDefs.IntExpToRelation[@node.left];
temp ← PrintExprDefs.MakeExpression[node.left, TRUE];
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
PrintingDefs.OutCode[" THEN EXIT;\n"L, 0];
PrintingDefs.OutCode["ENDLOOP"L, indent + 1];
GOTO Done; };
forStmt1 => {
loopInBlock: BOOLEAN ← LoopInBlock[node.left];
IF node.right.right.left # NIL THEN {
PrintExpressionAsStatement[node.right.right.left, indent];
PrintingDefs.OutCode[";\n"L, 0]; };
IF node.right.right.right # NIL THEN {
PrintingDefs.OutCode["WHILE "L, indent];
PrintExprDefs.IntExpToRelation[@node.right.right.right];
temp ← PrintExprDefs.MakeExpression[node.right.right.right, FALSE];
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
PrintingDefs.OutCode[" "L, 0]; }
ELSE
PrintingDefs.OutCode[""L, indent];
PrintingDefs.OutCode["DO"L, 0];
IF loopInBlock THEN PrintingDefs.OutCode[" BEGIN"L, 0];
PrintingDefs.OutCode["\n"L, 0];
IF node.left.nodeType = compoundStmt THEN {
SymbolTableDefs.EnterBlock[];
PrintDclsDefs.PrintDeclarations[node.left.left, indent + 1, ";\n"L, TRUE];
wasGoto ← PrintStatementRec[node: node.left.right,
indent: indent + 1, semiAtEnd: TRUE, inSwitch: FALSE,
inContinue: loopInBlock];
SymbolTableDefs.ExitBlock[]; }
ELSE wasGoto ← PrintStatementRec[node: node.left,
indent: indent + 1, semiAtEnd: TRUE, inSwitch: FALSE,
inContinue: loopInBlock];
IF loopInBlock THEN
PrintingDefs.OutCode["EXITS Continue => NULL; END;\n"L, indent + 1];
IF node.right.left # NIL THEN {
PrintExpressionAsStatement[node.right.left, indent + 1];
PrintingDefs.OutCode[";\n"L, 0]; };
PrintingDefs.OutCode["ENDLOOP"L, indent + 1];
GOTO Done; };
switchStmt => {
n: LONG POINTER TO TreesDefs.TreeNode;
backUpTo: LONG POINTER TO TreesDefs.TreeNode;
default: LONG POINTER TO TreesDefs.TreeNode;
statement: LONG POINTER TO TreesDefs.TreeNode;
wasBreak: BOOLEAN;
PrintingDefs.OutCode["SELECT "L, indent];
temp ← PrintExprDefs.MakeExpression[node.left, FALSE];
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
PrintingDefs.OutCode[" FROM\n"L, 0];
default ← NIL;
backUpTo ← NIL;
wasBreak ← TRUE;
wasGoto ← FALSE;
n ← node.right; -- get to compoundStmt
IF n.nodeType # compoundStmt THEN
PrintingDefs.OutCode[
"*** select error - no compound statement. ***"L, 0];
n ← n.right; -- get to stmtList
DO
statement ← n.left;
IF n.string # NIL AND n.string.length > 0 THEN
PrintingDefs.PrintComments[n.string, indent];
IF statement # NIL THEN -- skip the select if statment = NIL
SELECT statement.nodeType FROM
caseLabel => {
IF wasBreak THEN {
IF backUpTo # NIL THEN {
n ← backUpTo;
backUpTo ← NIL;
LOOP; };
wasBreak ← FALSE;
temp ← PrintExprDefs.MakeExpression[statement.left, FALSE];
PrintingDefs.OutCode[temp, indent + 1];
Storage.FreeString[temp];
WHILE n.right # NIL
AND n.right.left # NIL
AND n.right.left.nodeType = caseLabel
DO
n ← n.right;
PrintingDefs.OutCode[", "L, 0];
temp ← PrintExprDefs.MakeExpression[n.left.left, FALSE];
PrintingDefs.OutCode[temp, indent + 1];
Storage.FreeString[temp];
ENDLOOP;
PrintingDefs.OutCode[" => {\n"L, 0]; }
ELSE {
IF backUpTo = NIL THEN backUpTo ← n; }; };
breakStmt => {
wasBreak ← TRUE;
IF wasGoto THEN {
wasGoto ← FALSE;
PrintingDefs.OutCode["EXITS outSwitch=>NULL};"L, indent + 2]; }
ELSE PrintingDefs.OutCode["};"L, indent + 2];
PrintingDefs.OutCode["\n"L, 0];};
loopStmt, gotoStmt, returnStmt => {
[] ← PrintStatementRec[node: statement, indent: indent + 2,
semiAtEnd: TRUE, inSwitch: TRUE, inContinue: FALSE];
wasBreak ← TRUE;
IF wasGoto THEN {
wasGoto ← FALSE;
PrintingDefs.OutCode["EXITS outSwitch=>NULL};"L, indent + 2]; }
ELSE PrintingDefs.OutCode["};"L, indent + 2];
PrintingDefs.OutCode["\n"L, 0];};
defaultLabel => {
default ← n; -- remember where it is
-- skip to next case if there was a break
IF wasBreak THEN {
WHILE n.right # NIL AND n.right.left.nodeType # caseLabel DO
n ← n.right; ENDLOOP; };
IF n.right = NIL THEN wasBreak ← TRUE; };
ENDCASE => {wasGoto ← wasGoto OR PrintStatementRec[node: statement,
indent: indent + 2, semiAtEnd: TRUE, inSwitch: TRUE,
inContinue: FALSE]; };
n ← n.right;
IF n = NIL THEN {
IF NOT wasBreak THEN {
IF wasGoto THEN {
wasGoto ← FALSE;
PrintingDefs.OutCode["EXITS outSwitch=>NULL}"L, indent + 2]; }
ELSE PrintingDefs.OutCode["};"L, indent + 2];
PrintingDefs.OutCode["\n"L, 0];
wasBreak ← TRUE; };
IF backUpTo # NIL THEN {
n ← backUpTo;
backUpTo ← NIL }
ELSE EXIT; };
ENDLOOP;
PrintingDefs.OutCode["ENDCASE"L, indent + 1];
IF default # NIL THEN {
PrintingDefs.OutCode[" => {\n"L, 0];
wasGoto ← FALSE;
DO
default ← default.right; -- next statment
IF default = NIL THEN EXIT;
SELECT default.left.nodeType FROM
breakStmt => EXIT;
caseLabel => NULL;
ENDCASE => wasGoto ← wasGoto OR
PrintStatementRec[node: default.left,
indent: indent + 2, semiAtEnd: TRUE, inSwitch: TRUE,
inContinue: FALSE];
ENDLOOP;
IF wasGoto THEN {
wasGoto ← FALSE;
PrintingDefs.OutCode["EXITS outSwitch=>NULL}"L, indent + 2]; }
ELSE PrintingDefs.OutCode["}"L, indent + 2];
};
GOTO Done; };
breakStmt => {
IF inSwitch THEN {
PrintingDefs.OutCode["GOTO outSwitch"L, indent];
wasGoto ← TRUE; }
ELSE PrintingDefs.OutCode["EXIT"L, indent];
GOTO Done; };
loopStmt => {
IF inContinue THEN PrintingDefs.OutCode["GOTO Continue"L, indent]
ELSE PrintingDefs.OutCode["LOOP"L, indent];
GOTO Done; };
returnStmt => {
PrintingDefs.OutCode["RETURN"L, indent];
IF node.left # NIL THEN {
PrintingDefs.OutCode[" ["L, 0];
temp ← PrintExprDefs.MakeExpression[node.left, FALSE];
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
PrintingDefs.OutCode["]"L, 0]; };
GOTO Done; };
gotoStmt => {
PrintingDefs.OutCode["GOTO "L, indent];
PrintingDefs.OutCode[node.string, 0];
GOTO Done; };
emptyStmt => {
PrintingDefs.OutCode["NULL"L, indent];
GOTO Done; };
compoundStmt => {
PrintingDefs.OutCode["{\n"L, indent];
SymbolTableDefs.EnterBlock[];
PrintDclsDefs.PrintDeclarations[node.left, indent, ";\n"L, TRUE];
wasGoto ← PrintStatementRec[node: node.right, indent: indent,
semiAtEnd: TRUE, inSwitch: inSwitch, inContinue: FALSE];
SymbolTableDefs.PrintSymbolTable[];
SymbolTableDefs.ExitBlock[];
PrintingDefs.OutCode["}"L, indent];
GOTO Done; };
expressionStmt => {
PrintExpressionAsStatement[node.left, indent];
GOTO Done; };
labelLabel => {
PrintingDefs.OutCode["label ← "L, indent];
PrintingDefs.OutCode[node.string, 0];
GOTO Done; };
stmtList => {
IF node.string # NIL AND node.string.length > 0 THEN
PrintingDefs.PrintComments[node.string, indent];
wasGoto ← PrintStatementRec[node: node.left,indent: indent,
semiAtEnd: TRUE, inSwitch: inSwitch,inContinue: FALSE];
node ← node.right; };
ENDCASE => {
PrintingDefs.OutCode["*** unknown node type ***"L, 0];
IF node.string # NIL THEN {
PrintingDefs.OutCode[" string: "L, 0];
PrintingDefs.OutCode[node.string, 0]; };
PrintingDefs.OutCode[";\n"L, 0];
GOTO Done; };
REPEAT
Done => {IF semiAtEnd THEN PrintingDefs.OutCode[";\n"L, 0]; };
ENDLOOP;
};
-- begin of main PrintStatement code --
[] ← PrintStatementRec[node: node, indent: 0,
semiAtEnd: TRUE, inSwitch: FALSE, inContinue: FALSE];
TreesDefs.FreeTree[node];
};
LoopInBlock: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode]
RETURNS [BOOLEAN] = {
LoopInBlockRec: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode]
RETURNS [BOOLEAN] = {
IF node = NIL THEN RETURN [FALSE];
SELECT node.nodeType FROM
loopStmt => RETURN [TRUE];
whileStmt => RETURN [FALSE];
doWhileStmt => RETURN [FALSE];
forStmt1 => RETURN [FALSE];
ENDCASE => RETURN [LoopInBlockRec[node.left]
OR LoopInBlockRec[node.right]];
};
RETURN [LoopInBlockRec[node]];
};
PrintExpressionAsStatement: PROCEDURE [node: LONG POINTER TO TreesDefs.TreeNode, indent: CARDINAL] = {
temp:LONG STRING ← PrintExprDefs.MakeExpression[node, FALSE];
PrintingDefs.OutCode[""L, indent]; -- print indent only
-- If this is an assignment expression used solely for the assignment
-- side effect then use the non-value-producing form of the
-- assignment procedure.
SELECT node.operationType FROM
multiplyAssign,
divideAssign,
modulusAssign,
plusAssign,
minusAssign,
shiftLeftAssign,
shiftRightAssign,
bitAndAssign,
bitOrAssign,
bitXorAssign,
postIncrement,
postDecrement => PrintingDefs.OutCode["[]←"L, 0];
ENDCASE => NULL;
PrintingDefs.OutCode[temp, 0];
Storage.FreeString[temp];
};
}.