package xtc.translator.translation; import java.util.List; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.io.File; import java.io.IOException; import xtc.translator.representation.Argument; import xtc.translator.representation.CallExpressionPiece; import xtc.translator.representation.ClassVisitor; import xtc.translator.representation.CompilationUnit; import xtc.translator.representation.ConstructorVisitor; import xtc.translator.representation.CppPrintable; import xtc.translator.representation.FieldMap; import xtc.translator.representation.FieldVisitor; import xtc.translator.representation.IPiece; import xtc.translator.representation.ImplementationVisitor; import xtc.translator.representation.Method; import xtc.translator.representation.MethodMaps; import xtc.translator.representation.MethodVisitor; import xtc.translator.representation.PostfixPiece; import xtc.translator.representation.SourceObject; import xtc.translator.representation.VariableVisitor; import xtc.parser.ParseException; import xtc.tree.Node; import xtc.tree.Visitor; /** * Top level class encapsulating all underlying data extracted from relavent * java source. Should act as a starting point for subsequent c++ translation. */ public class Collector extends Visitor { public ArrayList<File> packDirs; public ArrayList<String> imports; public ArrayList<String> packages; public List<ClassVisitor> classes; public ClassVisitor mainClass; public ArrayList<String> typeList; /** * a list of classes that are used this should come from * visitQualifiedIdentifiers in ImplementationVisitor */ public ArrayList<String> usedClasses; public HashMap<String, String> usedClassesDict; public Collector(List<CompilationUnit> compilationUnits) { this.imports = new ArrayList<String>(); this.classes = new ArrayList<ClassVisitor>(); for (CompilationUnit compilationUnit : compilationUnits) { for (ClassVisitor classVisitor : compilationUnit.getClassVisitors()) this.classes.add(classVisitor); } this.packages = new ArrayList<String>(); this.mainClass = null; this.packDirs = new ArrayList<File>(); this.typeList = new ArrayList<String>(); } /** * Main method to begin collection * */ public void collect() throws IOException, ParseException { // sort classes this.sortClasses(); // Make simple type list for consulting makeTypeList(); // assign super classes to classVisitors this.assignSuperClass(); // get overloaded methods this.generateMethodOverload(); // Use assigned super classes to create implementation // map of all methods in class hierarchy (vtable precursor) this.createImplementationMap(); // Create variable map for each method this.createVariableMaps(); // Process method calls for proper overloading this.processCallExpression(); // Process postfix pieces, which require special rules this.processPostfixPieces(); // Process general pieces, which require certain post processing this.processPieces(); // Inherit relevant fields in subclasses this.inheritFields(); // HACKY // Initialize inherited values in subclasses constructors this.initilizeInheritedValues(); } private void inheritFields() { for (ClassVisitor cv : classes) { inheritFields(cv.getSuperClass(), cv); } } // Inherits all fields of superclasses private void inheritFields(ClassVisitor current, ClassVisitor original) { if (current == null) { return; } else { inheritFields(current.getSuperClass(), original); for (FieldVisitor f : current.getFieldList()) { if (!f.isStatic) { original.getFieldList().add(f); original.getInheritedFields().add(f); } } } } private void sortClasses() { //TODO implement real sort, this one is a hack. ClassVisitor prev = null; ClassVisitor current = null; ArrayList<ClassVisitor> ordered = new ArrayList<ClassVisitor>(); for (ClassVisitor c : classes) { current = c; if (prev != null && current.getIdentifier().equals(prev.getExtension())) { int i1 = classes.indexOf(prev); int i2 = classes.indexOf(current); ordered.add(i1, current); ordered.add(i2, prev); } prev = current; } classes = ordered; } /** * Entry point to recursive method to assign superclasses. */ private void assignSuperClass() { for (ClassVisitor cv : classes) { assignSuperClass(cv); } } /** * Recursively assigns superclasses to classes based on extension string. * @param current */ private void assignSuperClass(ClassVisitor current) { if (current == null) { return; } else { if (current.getExtension().equals("Object")) { current.setSuperClass(new SourceObject()); } else { for (ClassVisitor cv : classes) { if (current.getExtension().equals(cv.getIdentifier())) { current.setSuperClass(cv.copy()); } } } assignSuperClass(current.getSuperClass()); } } private void createImplementationMap() { for (ClassVisitor classVisitor : classes) { createImplementationMap(classVisitor, classVisitor); } } /** * Recursive Helper method, recurses through class hierarchy, from Object * downward, and updates the implementation table of the original * classVisitor with the latest overridden implementation of a method with a * particular identifier. * * @param currentClass * @param original */ private void createImplementationMap(ClassVisitor currentClass, ClassVisitor original) { if (currentClass == null) { return; } else { createImplementationMap(currentClass.getSuperClass(), original); for (MethodVisitor m : currentClass.getMethodList()) { // If key is already in map, it means newer method is overriding // older one if (original.getImplementationMap().containsKey( m.getIdentifier())) { m.setOverride(true); } original.getImplementationMap().put(m.getIdentifier(), currentClass.getFullIdentifier()); } } } private void generateMethodOverload() { for (ClassVisitor classVisitor : classes) { ClassVisitor currentClass = classVisitor; while (currentClass != null) { for (MethodVisitor m : currentClass.getMethodList()) { Method method = new Method(m.getIdentifier(), m.getReturnType()); // set if method is static method.isStatic = m.isStatic(); List<Argument> paramTypes = new ArrayList<Argument>(); for (Map<String, String> param : m.getParameters()) { paramTypes.add(new Argument(param.get("type"), null)); } method.getArguments().setArguments(paramTypes); method.generateOverloadedIdentifier(); // if method is already there, add it to the list if (classVisitor.getOverloadMap().containsKey(method.getIdentifier())) { // Check to see if method is already there boolean add = true; for (Method checkMethod : classVisitor.getOverloadMap().get(method.getIdentifier())) { // If specific method is already there, then a subclass must implement it, // so don't add it to the list. if (checkMethod.getOverloadedIdentifier().equals(method.getOverloadedIdentifier())) { add = false; } } if (add){ classVisitor.getOverloadMap().get(method.getIdentifier()).add(method); } } else { List<Method> methodList = new ArrayList<Method>(); methodList.add(method); classVisitor.getOverloadMap().put(method.getIdentifier(), methodList); } if (!m.getIdentifier().equals("main")) if (!currentClass.getIdentifier().equals("Object")) m.setIdentifier(method.getOverloadedIdentifier()); } currentClass = currentClass.getSuperClass(); } MethodMaps.addMethodMapForClass(classVisitor.getIdentifier(), classVisitor.getOverloadMap()); } // do source object SourceObject source = new SourceObject(); for (MethodVisitor m : source.getMethodList()) { Method method = new Method(m.getIdentifier(), m.getReturnType()); // set if method is static method.isStatic = m.isStatic(); List<Argument> paramTypes = new ArrayList<Argument>(); for (Map<String, String> param : m.getParameters()) { paramTypes.add(new Argument(param.get("type"), null)); } method.getArguments().setArguments(paramTypes); // if method is already there, add it to the list if (source.getOverloadMap().containsKey(method.getIdentifier())) { source.getOverloadMap().get(method.getIdentifier()).add(method); } else { List<Method> methodList = new ArrayList<Method>(); methodList.add(method); source.getOverloadMap().put(method.getIdentifier(), methodList); } if (!m.getIdentifier().equals("main")) m.setIdentifier(method.getIdentifier()); } MethodMaps.addMethodMapForClass(source.getIdentifier(), source.getOverloadMap()); } private void createVariableMaps() { for (ClassVisitor classVisitor : classes) { for (MethodVisitor m : classVisitor.getMethodList()) { VariableVisitor vv = new VariableVisitor(); // Put field variables into it for (FieldVisitor fv : classVisitor.getFieldList()) { vv.getVariableMap().put(fv.getVariableName(), fv.getVariableType()); FieldMap.fieldmap.put(fv.getVariableName(), fv); } // get the rest of the variables in method scope vv.dispatch(m.getBaseNode()); // set methods variable map m.setVariableMap(vv.getVariableMap()); } } } private void processCallExpression() { for (ClassVisitor classVisitor : classes) { for (MethodVisitor m : classVisitor.getMethodList()) { ImplementationVisitor i = m.getImplementationVisitor(); if (i == null) { System.out.println("No implementationVisitor for " + m.getIdentifier()); } else { for (CallExpressionPiece c : m.getImplementationVisitor().getCallExpressions()) { c.setMethodMap(classVisitor.getOverloadMap()); c.setVariableMap(m.getVariableMap()); c.processNode(); } } } } } private void processPostfixPieces() { for (ClassVisitor classVisitor : classes) { for (MethodVisitor m : classVisitor.getMethodList()) { ImplementationVisitor i = m.getImplementationVisitor(); if (i == null) { System.out.println("No implementationVisitor for " + m.getIdentifier()); } else { for (PostfixPiece c : m.getImplementationVisitor().getPostfixPieces()) { c.setVariableMap(m.getImplementationVisitor().getVarTypeDict()); c.processNode(); } } } } } private void initilizeInheritedValues() { for (ClassVisitor classVisitor : classes) { for (ConstructorVisitor con : classVisitor.getConstructorList()) { List<CppPrintable> pieces = con.getImplementationVisitor().getCppPrintList(); pieces.remove(pieces.size() - 1); //remove last brace; for (FieldVisitor fv : classVisitor.getInheritedFields()) { pieces.add(new IPiece(null, fv.variableName + " = 0;")); } pieces.add(new IPiece(null, "}\n")); con.getImplementationVisitor().setCppPrintList(pieces); } } } private void processPieces() { for (ClassVisitor classVisitor: classes) { for (MethodVisitor m : classVisitor.getMethodList()) { ImplementationVisitor i = m.getImplementationVisitor(); if (i == null) { System.out.println("No implementationVisitor for " + m.getIdentifier()); } else { for (IPiece p : i.getIpieces()) { Node n = p.getBaseNode(); if (n.getName().equals("PrimaryIdentifier")) { FieldVisitor fv = FieldMap.fieldmap.get(p.getRepresentation()); if (fv != null) p.setRepresentation("__" + fv.parent.getIdentifier() + "::" + p.getRepresentation()); } if (n.getName().equals("SelectionExpression")) { String primaryId = n.getNode(0).getString(0); String field = n.getString(1); if (typeList.contains(primaryId)) p.setRepresentation("(__" + primaryId + "::" + field + ")"); else p.setRepresentation("(" + primaryId + "->" + field + ")"); } if (n.getName().equals("InstanceOfExpression")) { String primary = n.getNode(0).getString(0); String other = n.getNode(1).getNode(0).getString(0); String representation = ""; if (other.equals("String")) representation += primary + " -> __vptr -> getClass( " + primary + ") -> __vptr -> isInstance( " + primary + " -> __vptr -> getClass(" + primary + "), (" + other + ")(new __" + other+"(\"Hi\")))"; else if (other.equals("Object")) representation += primary + " -> __vptr -> getClass( " + primary + ") -> __vptr -> isInstance( " + primary + " -> __vptr -> getClass(" + primary + "), (new __" + other + "))"; else representation += primary + " -> __vptr -> getClass( " + primary + ") -> __vptr -> isInstance( " + primary + " -> __vptr -> getClass(" + primary + "), (" + other + ")(new __" + other + "))"; p.setRepresentation(representation); } if (n.getName().equals("AdditiveExpression")) { String real = concat("", n, null);; real = real.replaceAll("\"", ""); real = "\"" + real + "\""; real = "__rt::literal(" + real + ")"; p.setRepresentation(real); } if (p.representation.contains("short")) { p.setRepresentation(p.getRepresentation().replace("short", "int")); } } } } } } public static String concat(String result, Node n, Map<String, String> variableMap) { if (n.getNode(0).getName().equals("CharacterLiteral")) { String second = n.getNode(2).getString(0); String first = null; // special concatenation of characters if (n.getNode(0).getName().equals("CharacterLiteral")){ first = n.getNode(0).getString(0); first = first.replace("'", "\""); }else { first = n.getNode(0).getString(0); } return first + second; } else if (n.getNode(0).getName().equals("StringLiteral")) { String first = n.getNode(0).getString(0); String second = null; // special concatenation of characters if (n.getNode(2).getName().equals("CharacterLiteral")){ second = n.getNode(2).getString(0); second = second.replace("'", "\""); }else { second = n.getNode(2).getString(0); } return first + second; } else if(n.getNode(0).getName().equals("PrimaryIdentifier")){ String first = variableMap.get(n.getNode(0).getString(0)); String second = n.getNode(2).getString(0); return first + second; } else { result = concat(result, n.getNode(0), variableMap); result += n.getNode(2).getString(0); return result; } } public void makeTypeList() { for (ClassVisitor cv : classes) { typeList.add(cv.getIdentifier()); } typeList.add("Object"); typeList.add("String"); typeList.add("Class"); } }