package oop; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import oop.ccClass; import oop.ccManualBlock; import oop.ccMethod; import xtc.tree.GNode; import xtc.tree.Node; import xtc.tree.Visitor; public class ccMaster extends Visitor { private ccClass currentClass; private int mainCounter; private LinkedList<ccMainMethod> mainMethodList; private LinkedList<ccClass> classList; private LinkedList<String> modifierList; private String[] argumentType; private String[] argumentName; private ccBlock latestBlock; private HashSet mangleNames; private File directory; private String[] currentPackage; private LinkedList<LinkedList<String>> printToConstructors; private LinkedList<String> printToCurrentConstructor; public ccMaster(LinkedList<String> dependencies, HashSet mangleList, File dir){ ASTGenerator ast = new ASTGenerator(); mangleNames = mangleList; directory = dir; classList = new LinkedList<ccClass>(); mainMethodList = new LinkedList<ccMainMethod>(); javaLangMethods(); printToConstructors = new LinkedList<LinkedList<String>>(); for (String next : dependencies){ modifierList = new LinkedList<String>(); this.dispatch(ast.generateAST(next)); } currentClass = classList.get(2); mainCounter = 0; for (int count=0; count<dependencies.size(); count++){ modifierList = new LinkedList<String>(); String nextFile = dependencies.get(count); printToCurrentConstructor = printToConstructors.get(count); new Visitor() { private int constructorCounter; private boolean constructorFlag; private boolean addedConstructor; private int methodCounter; private HashMap<String, String> parameterNames; public void visitClassDeclaration(GNode n){ String name = (String)n.getString(1); for(int i=0; i < classList.size(); i++){ if(name.equals(classList.get(i).getName())){ currentClass = classList.get(i); } } constructorCounter = 1; if(currentClass.constructorOverWritten){ constructorCounter = 0; } constructorFlag = false; methodCounter = 0; addedConstructor = false; visit(n); } public void visitConstructorDeclaration(GNode n){ parameterNames = new HashMap<String, String>(); constructorFlag = true; visit(n); constructorFlag = false; currentClass.getConstructorAtIndex(constructorCounter).setBlock(latestBlock); constructorCounter++; } public void visitMethodDeclaration(GNode n){ String name = (String)n.getString(3); parameterNames = new HashMap<String, String>(); visit(n); if(name.trim().equals("main")){ latestBlock.addLineFront(currentClass.getName() + " __this = new __" + currentClass.getName() + "();\n" ); mainMethodList.get(mainCounter).setBlock(latestBlock); mainCounter++; } else{ currentClass.getMethodAtIndex(methodCounter).setBlock(latestBlock); methodCounter++; } } public void visitFormalParameter(GNode n){ parameterNames.put(n.getString(3),new ccStatement(n.getGeneric(1), latestBlock).publish()); } public void visitBlock (GNode n){ latestBlock = new ccBlock(n, currentClass.getFields(), parameterNames, classList, currentClass.getName(), constructorFlag); if(constructorFlag){ for(String iter : printToCurrentConstructor){ if(!latestBlock.hasDeclared(iter.substring(0, iter.indexOf('=')).trim())) latestBlock.addLineFront(iter); } } } public void visit(Node n) { for (Object o : n) if (o instanceof Node) dispatch((Node)o); } }.dispatch(ast.generateAST(nextFile)); } try{ this.publishToFiles(); } catch (IOException e){ e.printStackTrace(); } } /** * Adds Object, String and Class into the class list data structure. */ private void javaLangMethods(){ //Object currentClass = new ccClass("Object", "public", false); classList.add(currentClass); currentClass.addInheritedMethods(); //String currentClass = new ccClass("String", "public", false); classList.add(currentClass); argumentType = new String[0]; argumentName = new String[0]; currentClass.addMethod(new ccMethod("length", currentClass, "public", "int32_t", argumentType, argumentName)); currentClass.addMethod(new ccMethod("charAt", currentClass, "public", "char", argumentType, argumentName)); currentClass.addInheritedMethods(); //Class currentClass = new ccClass("Class", "public", false); classList.add(currentClass); argumentType = new String[0]; argumentName = new String[0]; currentClass.addMethod(new ccMethod("getName", currentClass, "public", "Class", argumentType, argumentName)); currentClass.addMethod(new ccMethod("getSuperclass", currentClass, "public", "String", argumentType, argumentName)); currentClass.addMethod(new ccMethod("isPrimitive", currentClass, "public", "Class", argumentType, argumentName)); currentClass.addMethod(new ccMethod("isArray", currentClass, "public", "String", argumentType, argumentName)); currentClass.addMethod(new ccMethod("getComponentType", currentClass, "public", "Class", argumentType, argumentName)); argumentType = new String[1]; argumentType[0] = "Object"; argumentName = new String[1]; argumentName[0] = "o"; currentClass.addMethod(new ccMethod("isInstance", currentClass, "public", "String", argumentType, argumentName)); currentClass.addInheritedMethods(); } /** * Printy Thingy * * @throws IOException */ public void publishToFiles() throws IOException{ LinkedList<String> blockLines; File file; FileWriter fw; BufferedWriter out; for(ccMainMethod mainMethod : mainMethodList){ file = new File(directory.getAbsolutePath() + "/main_" + mainMethod.getParentClass().getName() + ".cc"); fw = new FileWriter(file); out = new BufferedWriter(fw); //includes for(int i=3; i < classList.size(); i++){ out.write("#include \"" + classList.get(i).getName() + ".h\"\n"); } out.write("#include \"java_lang.h\"\n"); //usingNameSpace HashSet<String> usingNameSpaceList = new HashSet<String>(); for(int q = 3; q < classList.size(); q++){ String usingNameSpace = "using namespace "; for(int i = 0; i<classList.get(q).getPackage().size(); i++){ if(i>0){usingNameSpace += "::";} usingNameSpace += classList.get(q).getPackage().get(i); } usingNameSpaceList.add(usingNameSpace + ";\n"); } usingNameSpaceList.add("using namespace java::lang;\n"); for(String s : usingNameSpaceList){ out.write(s); } out.write(mainMethod.publishDeclaration() + "\n"); blockLines = mainMethod.publishBlock(); while(!blockLines.isEmpty()){; out.write(blockLines.remove(0)); } out.write("\n"); out.close(); } for(int i=3; i < classList.size(); i++){ file = new File(directory.getAbsolutePath() + "/" + classList.get(i).getName() + ".cc"); fw = new FileWriter(file); out = new BufferedWriter(fw); //includes out.write("#include \"" + classList.get(i).getName() + ".h\"\n"); out.write("#include \"java_lang.h\"\n"); out.write("#include \"ptr.h\"\n"); //namespaces int packageNumber = classList.get(i).getPackage().size(); for(int q = 0; q < packageNumber; q++){ out.write("namespace " + classList.get(i).getPackage().get(q)+ "{\n"); } out.write("\n"); //class variables that are set as they are declared for(int j=0; j < classList.get(i).getInstanceVariables().size(); j++){ out.write(classList.get(i).getInstanceVariables().get(j)); } out.write("\n"); for(int j=0; j < classList.get(i).getConstructorCount(); j++){ out.write(classList.get(i).getConstructorAtIndex(j).publishDeclaration() + " \n"); blockLines = classList.get(i).getConstructorAtIndex(j).publishBlock(); while(!blockLines.isEmpty()){ out.write(blockLines.remove(0)); } out.write("\n"); } for(int j=0; j < classList.get(i).getMethodCount(); j++){ out.write(classList.get(i).getMethodAtIndex(j).publishDeclaration() + " \n"); blockLines = classList.get(i).getMethodAtIndex(j).publishBlock(); while(!blockLines.isEmpty()){ out.write(blockLines.remove(0)); } out.write("\n"); } String qualifiedPackageName = ""; for(int q = 0; q < packageNumber; q++){ qualifiedPackageName += classList.get(i).getPackage().get(q) + "."; } //__class String superClass = classList.get(i).getSuperClass().getName(); out.write("Class " + classList.get(i).get_Name()+ "::__class() {\n"); out.write(" static Class k = \n" + " new __Class(__rt::literal(\""+ qualifiedPackageName + classList.get(i).getName() + "\"), __"+superClass+"::__class(), __rt::null(), false);\n" + " return k;\n" + "}\n"); //__vtable out.write(classList.get(i).get_Name() + "_VT" + " " + classList.get(i).get_Name() + "::__vtable;\n"); //namespace brackets for(int q = 1; q < packageNumber; q++){ out.write("}\n"); } out.write("}\n"); out.close(); } } public LinkedList<ccMainMethod> getMainMethodList(){ return mainMethodList; } public LinkedList<ccClass> getClassList(){ return classList; } public void visitCompilationUnit(GNode n){ visit(n); printToConstructors.add(new LinkedList<String>()); for(int i=3; i < classList.size(); i++){ classList.get(i).addInheritedMethods(); LinkedList<ccVariable> vars = new LinkedList(classList.get(i).getFields().values()); for(ccVariable nextVar : vars){ if(nextVar.somethingToDeclare()){ printToConstructors.getLast().add(nextVar.declare()); } } } /* It's the glorious visitor-within-a-visitor that makes the blocks! It's the blocker! */ } public void visitClassDeclaration(GNode n) throws Exception{ String name = (String)n.getString(1); String access = "public"; boolean isStatic = false; dispatch(n.getNode(0)); for(int i = 0; i < modifierList.size(); i++){ if(modifierList.get(i).matches("public|private|protected")){ access = modifierList.get(i); } else if(modifierList.get(i).matches("static")){ isStatic = true; } } modifierList.clear(); classList.add(new ccClass(name, access, isStatic)); currentClass = classList.getLast(); currentClass.addPackage(currentPackage); if(null != n.getNode(3)){ String extension = n.getNode(3).getNode(0).getNode(0).getString(0); boolean extensionCheck = false; for(int i = 3; i < classList.size()-1; i++){ if(classList.get(i).getName().contentEquals(extension)){ currentClass.addSuper(classList.get(i)); extensionCheck = true; break; } } if(!(extensionCheck || extension.contentEquals("Object"))){ System.out.println("Incorrect argument ordering: file containing class \"" + name + "\" should proceed file containing class \"" + extension + "\"."); throw new Exception(); } } else{ currentClass.addSuper(classList.get(0)); } visit(n); addDefaultMethods(currentClass); } public void visitPackageDeclaration(GNode n){ Node qualifiedIdentifier = n.getNode(1); currentPackage = new String[qualifiedIdentifier.size()]; for(int i = 0; i < qualifiedIdentifier.size(); i++){ currentPackage[i] = (qualifiedIdentifier.getString(i)); } } public void visitFieldDeclaration(GNode n){ String name = (String)n.getNode(2).getNode(0).getString(0); String type = (String)n.getNode(1).getNode(0).getString(0); ccDeclaration declarationStatement = new ccDeclaration(n, null); boolean isArray = (declarationStatement.getTypes().contains("__rt::Array")); boolean isStatic = declarationStatement.getModifiers().contains("static"); currentClass.addField(name, type, isStatic); String isConst = ""; if(declarationStatement.getModifiers().contains("const")){isConst="const";} if(isStatic){ currentClass.addInstanceVariable(isConst +" " + declarationStatement.getTypes() + " " + currentClass.get_Name() + "::" + declarationStatement.publishShort() + "\n"); } if((!isStatic)&&(declarationStatement.declaresToValue())){ currentClass.findField(name).setDeclarationStatement(declarationStatement.publishShort()); } } public void visitConstructorDeclaration(GNode n){ String name = (String)n.getString(2); String access = "public"; dispatch(n.getNode(0)); for(int i = 0; i < modifierList.size(); i++){ if(modifierList.get(i).matches("public|private|protected")){ access = modifierList.get(i); } } modifierList.clear(); Node param = n.getNode(3); argumentType = new String[param.size()]; argumentName = new String[param.size()]; for(int i = 0; i < param.size(); i++){ argumentType[i] = new ccStatement(param.getNode(i).getGeneric(1)).publish(); argumentName[i] = param.getNode(i).getString(3); } currentClass.addConstructor(new ccConstructor(name, access, argumentType, argumentName, currentClass)); } public void visitMethodDeclaration(GNode n){ String name = (String)n.getString(3); String access = "protected"; String returnType = "void"; boolean isStatic = false; dispatch(n.getNode(0)); for(int i = 0; i < modifierList.size(); i++){ if(modifierList.get(i).matches("public|private|protected")){ access = modifierList.get(i); } else if(modifierList.get(i).matches("static")){ isStatic = true; } } modifierList.clear(); if(n.getNode(2).hasName("VoidType")){ /* nope, we already good */} else{ returnType = new ccStatement(n.getGeneric(2)).publish(); } Node param = n.getNode(4); argumentType = new String[param.size()]; argumentName = new String[param.size()]; for(int i = 0; i < param.size(); i++){ argumentType[i] = new ccStatement(param.getNode(i).getGeneric(1)).publish(); argumentName[i] = param.getNode(i).getString(3); } if(name.matches("main")){ mainMethodList.add(new ccMainMethod(currentClass, access, returnType, argumentType, argumentName, isStatic)); } else{ ccMethod newMethod = new ccMethod(name, currentClass, access, returnType, argumentType, argumentName, isStatic); Iterator manIterate = mangleNames.iterator(); while (manIterate.hasNext()){ String mangleTest = currentClass.getName() + "^" + name; if(manIterate.next().toString().contains(mangleTest)) newMethod.mangleName(); } currentClass.addMethod(newMethod); } } public void visitModifier(GNode n){ for(Object s: n){ if (s instanceof String) modifierList.add((String)s); } } public void addDefaultMethods(ccClass clas){ ccManualBlock deleteBlock = new ccManualBlock(); deleteBlock.addCustomLine("{ delete __this;}"); ccMethod delete = new ccMethod("__delete", clas, "public", "void", new String[0], new String[0]); delete.setBlock(deleteBlock); delete.changeThisToPointer(); clas.addMethod(delete); } public void visit(Node n) { for (Object o : n) if (o instanceof Node) dispatch((Node)o); } }