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