Plan for Today PA3 Note Quiz 3 Visitor Design Pattern – main idea and example CS453 – example reprise using visitor that does traversal Visitor patterns – FAQ about visitors Type checking and Code Generation – Dot visitor – Other examples including integer and byte expression evaluation Debugging Ideas Big picture: using visitor design pattern for PA3 – Type checking for PA3 – Code generation for PA3 CS453 Lecture Building ASTs and Visitor Design Pattern 2 PA3 Note: Syntax-directed Construction of AST Quiz 3 Need the following in MJDriver.java Go to RamCT results. ast.node.Node ast_root = (ast.node.Node)parser.parse().value; ! Need the following in mj.cup (or mj_ast.cup if that is what you call it) Program ::= … {: RESULT = new Program( . . . ); :} ; CS453 Lecture Building ASTs and Visitor Design Pattern 3 CS453 Lecture Building ASTs and Visitor Design Pattern 4
Building AST Bottom Up Visitor Design Pattern Program class Byte { ! Situation public static void main(String[] whatever){ ! MainClass Meggy.setPixel( ! – Want to perform some processing on all items in a data structure, e.g type // Byte multiplication: Byte x Byte -> Int ! check or code generate BlockStatement (byte)( (byte)1*(byte)2 ), ! // Mixed type expression: Byte x Int -> Int ! – Will be adding many different ways to process items depending on the type (byte)( (byte)3 + 4 ), Meggy.Color.WHITE ); ! (class) MeggySetPixel } ! } ! – Will not be changing the classes of the data structure itself (much, or at all) Possibilities ColorLiteral ByteCast ByteCast Meggy.Color.WHITE – OO: For each functionality and each class, add a method – con: each new functionality is spread over multiple files MulExp PlusExp – con: sometimes can’t add methods to existing class hierarchy – Procedural: Use switch statement in one method traversing the data structure IntLiteral ByteCast ByteCast ByteCast – pro: keeps all the code for the feature in one place 4 – con: can be costly and involve lots of casting – Visitor design pattern (best of all) IntLiteral IntLiteral IntLiteral 1 2 3 CS453 Lecture Building ASTs and Visitor Design Pattern 5 CS453 Lecture Building ASTs and Visitor Design Pattern 6 AST and visitors Visit, In , Out We will generate an AST instead of directly generating code. When visiting the AST, we encounter a node for the first time (In encounter) and we encounter the node for the last time (Out encounter). These - Why is that a good idea? What can we now do better? encounters are often associated with certain actions: We can walk over this AST multiple times and perform different Visitor::visitXYZ(node) { ! functions, e.g. Create symbol table, Check types, Generate code inXYZ(node); ! for each child c of node in left to right order ! We will then traverse the AST for each particular need using visitors c.accept(this); ! each node of the AST has an accept method, that calls an appropriate outXYZ(node); ! } ! visitor method, e.g. plusExp.accept() calls visitPlusExp() inXYZ is called when the node is first encountered in the DFLR walk, and outXYZ is called when the node is left behind in the DFLR walk. Class hierarchy is USEFUL, because we only override a few methods the ones that differ from standard behavior This is often sufficient for code generation purposes (+,-,*,setPixel), but not always: (if, while, &&). WHY NOT? CS453 Lecture Building ASTs and Visitor Design Pattern 7 CS453 Lecture Building ASTs and Visitor Design Pattern 8
Depth First Visitor and in and out methods Example Use of the visitor design pattern Program // in driver: class Byte { ! public static void main(String[] whatever){ ! MainClass ast_root.accept(new AVRgenVisitor(outfilehandle)); Meggy.setPixel( ! // Byte multiplication: Byte x Byte -> Int ! // in AST class MulExp BlockStatement (byte)( (byte)1*(byte)2 ), ! public void accept(Visitor v) { v.visitMulExp(this); } // Mixed type expression: Byte x Int -> Int ! (byte)( (byte)3 + 4 ), Meggy.Color.WHITE ); ! MeggySetPixel } ! // in class DepthFirstVisitor } ! public void inMulExp(MulExp node) { defaultIn(node); } public void outMulExp(MulExp node) { defaultOut(node); } ColorLiteral ByteCast ByteCast Meggy.Color.WHITE public void visitMulExp(MulExp node){ inMulExp(node); if if(node.getLExp() != null null) node.getLExp().accept(this this); MulExp PlusExp if if(node.getRExp() != null null) node.getRExp().accept(this this); outMulExp(node); IntLiteral } ByteCast ByteCast ByteCast 4 // in type checker and code generator This is YOUR job public void outMulExp(MulExp node) { // overrides default IntLiteral IntLiteral IntLiteral 1 2 3 // gen code to pop operands, do the *, push the result } CS453 Lecture Building ASTs and Visitor Design Pattern 9 CS453 Lecture Building ASTs and Visitor Design Pattern 10 FAQ, Debugging Ideas Big Picture PA2 Check out your recit from last week. It tells you a lot!! – Syntax-directed expression “evaluation” – Syntax-directed code generation How do I associate data with a node in the AST if I can’t add fields to the PA3 node classes? – Syntax-directed AST creation – Visitors for creating the dot file for visualization (provided) What if I want to do the same thing on each node? – Visitor for checking types What if I only need to do something on certain nodes? – Visitor for generating code Later assignments Debugging – Visitor for building a symbol table System.out.println in parser actions – Visitor for allocating memory for variables Break points in visitor methods – Visitor for doing register allocation Use the DotVisitorWithMap CS453 Lecture Building ASTs and Visitor Design Pattern 11 CS453 Lecture Building ASTs and Visitor Design Pattern 12
Code Structure Code Structure cont’ In driver, first call the parser to get an AST: - CheckTypes and AVRgenVisitor inherit from DepthFirstVisitor. mj_ast_parser parser = new mj_ast_parser(lexer); - The first thing to do is move all of the code generation for the main ast.node.Node ast_root = (ast.node.Node)parser.parse().value; prologue and epilogue into the AVRgenVisitor. - The Meggy.setPixel() code generation should occur in outMeggySetPixel(). Next create a dot file for the AST for debugging purposes: - Code generation for expressions: use the AVR run-time stack. java.io.PrintStream astout = new java.io.PrintStream(…); Code that evaluates an expression should expects its operands and ast_root.accept(new DotVisitor(new PrintWriter(astout))); leaves its result on the top of the run-time stack (RTS), e.g. outFalseExp outTrueExp Finally, create Type-Checker and an AVRgenVisitor instances: ldi r24, 0 ldi r24,1 java.io.PrintStream avrsout = new java.io.PrintStream(…); push r24 push r24 symtable.SymTable globalST = new symtable.SymTable(); - The DFLR visitor can use the outOP method to generate code for an ast_root.accept(new CheckTypes(globalST)); operator, because code for the children has just been generated and has left ast_root.accept(new AVRgenVisitor(new PrintWriter(avrsout))); the result(s) on the RTS CS453 Lecture Building ASTs and Visitor Design Pattern 13 CS453 Lecture Building ASTs and Visitor Design Pattern 14 Code Generation with a Visitor Type Checking Program class Byte { ! Java allows mixing numeric types. For Meggy-Java this means that many public static void main(String[] whatever){ ! MainClass operators allow mixing byte and int Meggy.setPixel( ! // Byte multiplication: Byte x Byte -> Int ! BlockStatement (byte)( (byte)1*(byte)2 ), ! byte a = 0, b = 1; ! // Mixed type expression: Byte x Int -> Int ! (byte)( (byte)3 + 4 ), Meggy.Color.WHITE ); ! byte b2 = (byte)-b; ! MeggySetPixel } ! } ! byte wrong1 = -b; ! byte sum = (byte)(a + 5); ! ColorLiteral ByteCast ByteCast Meggy.Color.WHITE byte wrong2 = a+5; ! int ok = - - -b; ! MulExp PlusExp // but check out ! int wrong3 = ---b; ! IntLiteral ByteCast ByteCast ByteCast 4 int j, i = 2; ! if (i==b) j = i+b; else j=(byte)((byte)i+b); ! IntLiteral IntLiteral IntLiteral 1 2 3 CS453 Lecture Building ASTs and Visitor Design Pattern 15 CS453 Lecture Building ASTs and Visitor Design Pattern 16
Recommend
More recommend