MiniJava Compiler Exercise 2d : C++ Translation Visitor 0. You must first complete the "visitor pattern warmup assignment" posted on the web page, which asks you to use the visitor pattern for your truth table assignment. This part should be completed by Thursday 3/23. Visitors from planet 124 want your MiniJava translated into C++. You need to write a Visitor class that translates MiniJava programs to C++. The visitor Can return type Object, which means that there should be a "return null;" at the end of every visit method. /////////////////// Problems with C++ /////////////////////// Although Java and C++ are similar, there are enough differences to make a perfect translation difficult. The most daunting task is that of garbage collection. This is a topic that will require us to do flow-control analysis on our program, and is outside the scope of a first compiler course. However, there are also several other issues, though none of them quite as difficult as garbage collection. a. C++ arrays are not objects, they do not have a .length field. This problem, however, is easy to solve. Find on web page "cpputils.cpp", which contains the following class: class intarray { public: int *A; int length; intarray(int s) { length=s; A = new int[length]; } }; Your translated C++ program will just have to #include "cpputils.cpp". Java integer arrays (the only kind in MiniJava) can then be mapped to corresponding expressions using this class: int[] M = new int[4]; translates to intarray *M = new intarray(4); M[2] = 3; translates to M->A[2] and of course, M.length now simply translates to M->length. *********** Feature a. is a required component of the assignment. b. C++ does not allow for forward reference. This is solved by first producing prototypes. That is, a Minijava class: class A { public int f() { return this.g(); } public int g() { return 1; } } need to be translated into: class A { public: int f(); int g(); }; int A::f() { return this->g(); } int A::g() { return 1; } This is also doable. Your visit method for class "methoddec" must be more clever - it can't just make the usual recursive visitations. You must first write a loop to print the headers, and another to print the method declarations. The "baseinfo" class might also be useful, since it lets you remember which class each method should belong to. To do this really well, however, you will need generate a separate .h file. *********** Feature b. is currently optional, but may become required. c. C++ does not allow for initialization of instance varibles. This means that: class A { int x = 2; int y = 3; ... } need to be translated into class A { public: int x; int y; A() { x = 2; y = 3; } }; Fortunately, MiniJava has no constructor, so we can use the default constructor in C++ for this purpose (thanks to Mr. Barry LaVergne for this observation). An alternative would be to add a new line to initialize it manually each time an instance of A is created. *********** Feature c. is optional for this assignment. d. If you look at my sample programs, the generated C++ file is well indented. This is not so hard. Simply keep a global counter int tablength=0; When writing an indented segment, do: tablength++; // visit segment tablength--; You can also write a method similar to "out" that tabs a certain number of spaces based on the tablength value. *********** Feature d is required for the assignment, though not in a do-or-die kind of way. :) If you think these problems are difficult, consider what it would mean to translate C++ to Java. There are many constructs that simply have no equivalent in Java, and need to be handled by rewriting the program using a different approach. Translating BETWEEN very high-level languages is acutally a very difficult task. It is actually easier to translate a high level language to a lower level one, such as Java to C or Java to assembly. ///////////////////////////////////////////////////////// Mechanics and some help: Find on the webpage "transcpp.java", which is the front end interface. Study it first. It takes two command-line args indicating the source and destination files. If you want to leave it unchanged, then your visitor class' constructor must take a PrintWriter object. This object is used to write output to the target file. Given PrintWriter pw, you can use pw.print or pw.println, just like with System.out. Here's something to get you started. Note that the "out" method is simply a convenience - it catches exceptions during output, so there's no need for you to catch them elsewhere. import java.io.*; class cppvisitor implements visitor { PrintWriter pw; public cppvisitor(PrintWriter p) { pw = p; out("using namespace std;\n"); out("#include \n"); out("#include \n"); out("#include \"cpputils.cpp\"\n\n"); } // constructor // utility for printing (encapsulates try-catch) private void out(String s) { try { pw.print(s); } catch (Exception ie) {System.out.println(ie); System.exit(1); } }// out // sample visit method (don't be fooled, some of them are quite tricky!) public Object visit(andexp x) { x.e1.accept(this); out(" && "); x.e2.accept(this); return null; } //// etc ... } // cppvisitor Make sure your generated C++ actually work! (use g++ and ./a.out or ./a.exe).