package xtc.translator.translation; import java.io.FileWriter; import java.io.IOException; import java.util.List; import java.util.Map; import xtc.translator.representation.ClassVisitor; import xtc.translator.representation.ConstructorVisitor; import xtc.translator.representation.CppPrintable; import xtc.translator.representation.FieldVisitor; import xtc.translator.representation.ImplementationVisitor; import xtc.translator.representation.MethodVisitor; public class PrintHandler { private List<ClassVisitor> classVisitors; private String classPath; public PrintHandler(List<ClassVisitor> classVisitors, String classPath) { this.classVisitors = classVisitors; this.classPath = classPath; } public void printAllHeaders() throws IOException { // Make new printer printing to outfile CppPrinter cp = new CppPrinter(new FileWriter("out/" + classPath + ".h")); //Pragma once cp.pln("#pragma once"); // Imports this.printStandardImports(cp); cp.pln().pln("using namespace java::lang;"); // Forward declarations for (ClassVisitor classVisitor : classVisitors) { //TODO : put namespace stuff in method String[] namespaces = splitPackageName(classVisitor.getPackageName()); // Open namespaces for (String name : namespaces) { cp.p("namespace ").p(name).pln("{"); cp.incr(); cp.pln(); } // Declare data model. cp.p("struct ").p(prepend(classVisitor.getIdentifier())).pln(";"); // Declare Vtable cp.p("struct ").p(vtDec(classVisitor.getIdentifier())).pln(";"); // Typedef definition cp.p("typedef ").p(smartPtrTo(classVisitor.getIdentifier())).p(" ").p(classVisitor.getIdentifier()).pln(";"); // Close namespaces for (String name : namespaces) { cp.decr(); cp.pln("}"); } } for (ClassVisitor classVisitor : classVisitors) { String[] namespaces = splitPackageName(classVisitor.getPackageName()); // Open namespaces for (String name : namespaces) { cp.p("namespace ").p(name).pln("{"); cp.incr(); cp.pln(); } // Print data structure cp.pln(); this.printDataStructure(cp, classVisitor); // Print vTable cp.pln(); this.printVTable(cp, classVisitor); // Close namespaces for (String name : namespaces) { cp.decr(); cp.pln("}"); } // Flush buffers cp.flush(); } } public void printAllImplementations() throws IOException { CppPrinter cp = new CppPrinter(new FileWriter("out/" + classPath + ".cc")); // Print standard imports printStandardImports(cp); cp.pln("#include \"System.h\""); // Include header cp.pln("#include \"" + classPath + ".h\"").pln(); // Print using declarations for (ClassVisitor classVisitor : classVisitors) { cp.p("using ").p(classVisitor.getFullIdentifier()).pln(";"); cp.p("using ").p(classVisitor.getFullIdentifierPointer()).pln(";"); } cp.pln(); for (ClassVisitor classVisitor : classVisitors) { String[] namespaces = splitPackageName(classVisitor.getPackageName()); // Open namespaces for (String name : namespaces) { cp.p("namespace ").p(name).pln("{"); cp.incr(); cp.pln(); } for (ConstructorVisitor con : classVisitor.getConstructorList()) { // Print constructor // TODO: FIX CONSTRUCOR PRINTING cp.p(prepend(classVisitor.getIdentifier())).p("::") .p(prepend(classVisitor.getIdentifier())); cp.p("() : __vptr(&__vtable)").pln(); ImplementationVisitor iv = con.getImplementationVisitor(); if (iv == null) { // Do nothing } else { for (CppPrintable p : iv.getCppPrintList()) { p.printCpp(cp); } } } // the fields for ( FieldVisitor f : classVisitor.getFieldList()) { if (f.isStatic) cp.p(f.forImplementation()).pln(); } // Print destructor cp.p("void ").p(prepend(classVisitor.getIdentifier())).p("::").p("__delete"); cp.p("(").p(prepend(classVisitor.getIdentifier())).p("*").p(" __this)").pln("{"); cp.pln("delete __this;"); cp.pln("}"); cp.pln(); // Print all methods for (MethodVisitor m : classVisitor.getMethodList()) { // Print method signature // print return type cp.p(m.getReturnType()).p(" "); // print de-scoped method identifier cp.p(prepend(classVisitor.getIdentifier())).p("::").p(m.getIdentifier()); if (m.getIdentifier().equals("main")) { // Special case main to have no arguments cp.p("()").pln(); } else { if (!m.isStatic()){ // print parameters with implicit this cp.p(" (").p(classVisitor.getIdentifier() + " __this") .p(m.parametersToString()).p(")").pln(); } else { cp.p(" (").p(m.parametersToStringNoComma()).p(")").pln(); } } for (CppPrintable p : m.getImplementationVisitor().getCppPrintList()) { p.printCpp(cp); } cp.pln(); } // Print internal class accessor cp.p("Class ").p(prepend(classVisitor.getIdentifier())); cp.p("::__class() {").pln(); cp.p("static Class k = new __Class(__rt::literal("); //TODO: print full name here String fullName = "\"" + classVisitor.getPackageName() + "." + classVisitor.getIdentifier() + "\""; cp.p(fullName); //print superclass cp.p("), ").p(prepend(classVisitor.getSuperClass().getIdentifier())); cp.p("::__class());").pln(); cp.p("return k;").pln(); cp.p("}").pln(); // Invoke vtable constructor cp.p(vtDec(classVisitor.getIdentifier())); cp.p(" ").p(prepend(classVisitor.getIdentifier())); cp.p("::__vtable;").pln(); // Close namespaces for (String name : namespaces) { cp.decr(); cp.pln("}"); } cp.flush(); } } public void printMainFile(String mainClass) throws IOException { CppPrinter cp = new CppPrinter(new FileWriter("out/main.cc")); ClassVisitor main = null; //TODO: this is inefficient, but i don't know how else to do it. for (ClassVisitor cv : classVisitors) { if ((cv.getIdentifier() + ".java").equals(mainClass)) { main = cv; } } // Print standard imports printStandardImports(cp); //TODO: Include all headers cp.p("#include \"").p(classPath + ".h").p("\"").pln(); cp.p("int main(){").pln(); //Declare new object //TODO: need to instantiate single object String[] namespaces = splitPackageName(main.getPackageName()); for (String namespace : namespaces ) { cp.p(namespace).p("::"); } //TODO: this needs to change as well cp.p(prepend(main.getIdentifier())).p("::main()").p(";").pln(); cp.p("}").pln(); cp.flush(); } private void printDataStructure(CppPrinter cp, ClassVisitor classVisitor) { cp.p("struct ").p(prepend(classVisitor.getIdentifier())).pln("{"); cp.incr(); // vptr cp.p(vtDec(classVisitor.getIdentifier())).p("*").p(" ").p("__vptr").pln(";"); // the constructor for (ConstructorVisitor con : classVisitor.getConstructorList()) { cp.p(con.getSignature()).pln(";"); } // the fields for ( FieldVisitor f : classVisitor.getFieldList()) { cp.p(f.forHeader()).pln(); } // the destructor cp.p("static void __delete(").p(prepend(classVisitor.getIdentifier()) + "*").p(")").pln(";"); for ( MethodVisitor m : classVisitor.getMethodList() ) { cp.p(m.getSignature(classVisitor)).pln(";"); } // __class function cp.p("static Class __class()").pln(";"); // the vtable for the object cp.p("static ").p(vtDec(classVisitor.getIdentifier())).p(" ").p("__vtable").pln(";"); cp.decr(); cp.pln("};"); } private void printStandardImports(CppPrinter cp) { cp.pln("#include <stdint.h>"); cp.pln("#include <string>"); cp.pln("#include <iostream>"); cp.pln("#include <cstring>"); cp.pln("#include \"ptr.h\""); cp.pln("#include \"java_lang.h\""); } private void printVTable(CppPrinter cp, ClassVisitor classVisitor) { cp.p("struct ").p(vtDec(classVisitor.getIdentifier())).pln(" {"); cp.incr(); cp.pln(); // Print isa method cp.p("Class __isa;").pln(); // Print delete method cp.p("void ").p("(*__delete)(").p(prepend(classVisitor.getIdentifier())); cp.p("*);").pln(); // Recurse over all methods (even inherited) printVTable(cp, classVisitor, classVisitor); // Generate constructor cp.pln(); cp.pln(vtDec(classVisitor.getIdentifier()) + "()"); cp.pln(": __isa(" + prepend(classVisitor.getIdentifier()) + "::__class()),"); cp.p("__delete(&" + prepend(classVisitor.getIdentifier()) + "::__delete)"); printVTableConstructor(cp, classVisitor, classVisitor); cp.pln("{ }"); cp.decr(); cp.pln("};"); } private void printVTable(CppPrinter cp, ClassVisitor classVisitor, ClassVisitor original) { if (classVisitor == null) { // do nothing } else { printVTable(cp, classVisitor.getSuperClass(), original); for (MethodVisitor m : classVisitor.getMethodList()) { if (!m.isOverride() && !m.isStatic()) cp.p(m.getMethodPointer(original)).pln(";"); } } } private static void printVTableConstructor(CppPrinter cp, ClassVisitor cv, ClassVisitor original) { if (cv == null) { // do nothing } else { printVTableConstructor(cp, cv.getSuperClass(), original); for (int i = 0; i < cv.getMethodList().size(); i++) { MethodVisitor m = cv.getMethodList().get(i); // exclude main if (!m.isOverride() && !m.isStatic()) { // comma from previous line cp.pln(","); String classPointer = original.getImplementationMap().get(m.getIdentifier()); if (!classPointer.equals(original.getIdentifier())) { // If class pointer is not class, we must cast it cp.p(cast(m, original, classPointer)); } else { // otherwise, reference original classes implementation cp.p(m.getIdentifier() + openParen() + reference(scope(classPointer, m.getIdentifier())) + closeParen()); } } } } } private String[] splitPackageName(String packageName) { String[] pieces = packageName.split("[.]"); return pieces; } protected static String __isa() { return "Class __isa"; } protected static String __class() { return "static Class __class()"; } protected static String scope(String left, String right){ return left + "::" + right; } protected static String reference(String object){ return "&" + object; } protected static String prepend(String out) { return "__" + out; } protected static String vtDec(String identifier) { return prepend(identifier) + "_VT"; } protected static String ptrTo(String object) { return object + star(); } protected static String newLine() { return "\n"; } protected static String space() { return " "; } protected static String end() { return ";"; } protected static String openBlock() { return "{"; } protected static String closeBlock() { return "}"; } protected static String openParen() { return "("; } protected static String closeParen() { return ")"; } protected static String star() { return "*"; } protected static String smartPtrTo(String object) { return "__rt::Ptr<" + prepend(object) + ">"; } private static String cast(MethodVisitor m, ClassVisitor original, String classPointer) { String out = ""; out += m.getIdentifier() + openParen() + openParen() + m.getReturnType() + "(*)" + openParen() + original.getIdentifier() + ","; // Include original parameters for (Map<String, String> p : m.getParameters()) { out += p.get("type") + ","; } out = removeLastComma(out); out += closeParen() + closeParen() + reference(scope(classPointer, m.getIdentifier())) + closeParen(); return out; } protected static String removeLastComma(String string){ // remove last comma return string.substring(0, string.length() - 1); } }