package xtc.translator.representation; import xtc.tree.Visitor; import xtc.tree.Node; import xtc.tree.GNode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * A Visitor that visits and stores the implementation details of a method. * * Catches everything inside of a block */ public class ImplementationVisitor extends Visitor { public int indent; private String implementation; private ArrayList<String> usedClasses; // key is variable, value is variable type private HashMap<String, String> varTypeDict; public static HashMap<String, String> varValues = new HashMap<String, String>(); private List<CppPrintable> cppPrintList; private ArrayList<CallExpressionPiece> callExpressions; private ArrayList<PostfixPiece> postfixPieces; private List<IPiece> ipieces; public ImplementationVisitor() { super(); // Set indent at nothing initially indent = 0; // Implementation is empty initially implementation = ""; // A list of classes found in visitQualifiedIdentifier usedClasses = new ArrayList<String>(); // A table that holds values of key varTypeDict = new HashMap<String, String>(); cppPrintList = new ArrayList<CppPrintable>(); callExpressions = new ArrayList<CallExpressionPiece>(); postfixPieces = new ArrayList<PostfixPiece>(); ipieces = new ArrayList<IPiece>(); } public void visit(Node n) { for (Object o : n) { if (o instanceof Node) dispatch((Node) o); } } public String getImplementation() { return implementation; } public void setImplementation(String implementation) { this.implementation = implementation; } public void visitBlock(GNode n) { addLn("{", n); visit(n); addLn("}", n); } public void visitNewClassExpression(GNode n) { add("new ", n); add("__", n); String identifier = n.getNode(2).getString(0); // Node arguments = n.getNode(3); add(identifier, n); add("( ", n); dispatch(n.getNode(3)); add(" )", n); } // SWITCH STATEMENTS START public void visitSwitchStatement(GNode n) { addLn("switch (" + n.getGeneric(0).getString(0) + ") {", n); // visit other children skipEldest(n); addLn("}", n); } public void visitCaseClause(GNode n) { addLn("case " + n.getGeneric(0).getString(0) + ":", n); skipEldest(n); } public void visitBreakStatement(GNode n) { addLn("break;", n); } public void visitDefaultClause(GNode n) { addLn("default: ", n); visit(n); } // SWITCH STATEMENTS END // DO WHILE LOOPS START public void visitDoWhileStatement(GNode n) { addLn("do", n); // in a do while loop, the youngest child is special skipYoungest(n); add("while (", n); dispatch(n.getGeneric(n.size() - 1)); addLn(");", n); } // DO WHILE LOOPS END // FUNNY RETURN STATEMENT STUFF START public void visitAdditiveExpression(GNode n) { add(n.getString(1), n); } public void visitMultiplicativeExpression(GNode n) { dispatch(n.getNode(0)); add(" " + n.getString(1) + " ", n); dispatch(n.getNode(2)); } // FUNNY RETURN STATEMENT STUFF END public void visitQualifiedIdentifier(GNode n) { /* * for (Object o : n) { if (o instanceof String) { add((String) o + * " "); } } */ for (int i = 0; i < n.size(); i++) { String identifier = n.getString(i); add(identifier + " ", n); usedClasses.add(identifier); } } public void visitLogicalNegationExpression(GNode n) { add("!", n); visit(n); } public void visitLogicalAndExpression(GNode n) { dispatch(n.getNode(0)); // bob2 add(" && ", n); dispatch(n.getNode(1)); } public void visitLogicalOrExpression(GNode n) { dispatch((Node) n.get(0)); add(" || ", n); dispatch((Node) n.get(1)); } public void visitWhileStatement(GNode n) { add("while (", n); dispatch((Node) n.get(0)); // while condition add(")", n); dispatch((Node) n.get(1)); // attached block } public void visitForStatement(GNode n) { add("for", n); visit(n); } public void visitBasicForControl(GNode n) { add("(", n); for (Object o : n) { if (o instanceof Node) { if (((Node) o).getName() == "Declarators") { dispatch((Node) o); add(";", n); } else if (((Node) o).getName() == "RelationalExpression") { dispatch((Node) o); add(";", n); } else { dispatch((Node) o); } } // add(";"); } add(")", n); } public void visitDeclarators(GNode n) { visit(n); } public void visitEqualityExpression(GNode n) { add("(", n); for (Object m : n) { if (m instanceof Node) { Node child = (Node) m; dispatch(child); } if (m instanceof String) { add((String) m, n); } } add(")",n); } public void visitRelationalExpression(GNode n) { for (Object o : n) { if (o instanceof Node) { dispatch((Node) o); } else if (o instanceof String) { add((String) o, n); // print operator } } } public void visitExpressionList(GNode n) { for (Object o : n) { if (o instanceof Node) { dispatch((Node) o); } else if (o instanceof String) { add((String) o, n); // Print operator } } } public void visitPostfixExpression(GNode n) { PostfixPiece p = new PostfixPiece(n); cppPrintList.add(p); postfixPieces.add(p); } public void visitUnaryExpression(GNode n) { for (Object o : n) { if (o instanceof Node) { dispatch((Node) o); } else if (o instanceof String) { add((String) o, n); // Print operator } } } public void visitExpressionStatement(GNode n) { visit(n); addLn(";", n); } public void visitExpression(GNode n) { for (Object o : n) { if (o instanceof Node) { dispatch((Node) o); } else if (o instanceof String) { add((String) o, n); // Print operator } } } public void visitConditionalStatement(GNode n) { add(getIndent(), n); add("if (", n); dispatch((Node) n.get(0)); add(")", n); dispatch((Node) n.get(1)); Node elseStatement = (Node) n.get(2); if (elseStatement != null) { add("else ", n); dispatch((Node) n.get(2)); } } public void visitArguments(GNode n) { // loop through children, record arguments // separated by commas if (n.size() > 0) { dispatch(n.getGeneric(0)); if (n.size() > 1) { for (int i = 1; i < n.size(); i++) { add(" , ", n); dispatch(n.getGeneric(i)); } } } } public void visitDeclarator(GNode n) { String declaratorName = n.getString(0); add(declaratorName, n); // The commented out code doesn't work in the case where // nothing is assigned to a declarator // add(" = "); // visit(n); if (GNode.test(n.get(2))) { add(" = ", n); dispatch(n.getGeneric(2)); // We want to get the declared variable's name and type! String varName = n.getString(0); String varType = evaluateClass(n.getGeneric(2)); varTypeDict.put(varName, varType); varValues.put(varName, varType); } } private String evaluateClass(GNode n) { // TDL: work with method chaining if (n.hasName("NewClassExpression")) { return n.getGeneric(2).getString(0); } // WARNING: THIS IS INCREDIBLY LAZY CODING!!!!!!!!!!! // IT SHOULD BE UPDATED IN THE FUTURE!!!! else if (n.hasName("NewArrayExpression")) { // String will be of the form numDimensions_Type // ie 323_int return n.getGeneric(1).size() + "_" + n.getGeneric(0).getString(0); } // otherwise type is n's name without the word Literal else if (n.getName().contains("Literal")) { if (!n.getName().equals("NullLiteral")) return n.getString(0); else return "seriously?"; } // uh oh we screwed up :(:(:( else { return "UH OH ITS A CALL EXPRESSION"; } } public void visitCallExpression(GNode n) { CallExpressionPiece cep = new CallExpressionPiece(n); this.cppPrintList.add(cep); this.callExpressions.add(cep); } private void addCheckNotNull(String name) { addLn("__rt::checkNotNull(" + name + ");", null); } public void visitSuperExpression(GNode n) { add("super", n); // add("."); visit(n); } public void visitSelectionExpression(GNode n) { // Visits the first part, prints it, puts the dot, then prints the rest // changed this from :: to -> add((String) n.get(1), n); } public void visitThisExpression(GNode n) { // use the runtime __this add("__this", n); visit(n); } public void visitPrimaryIdentifier(GNode n) { String word = (String) n.get(0); add(word, n); visit(n); } public void visitInstanceOfExpression(GNode n) { add(null, n); } public void visitModifiers(GNode n) { visit(n); } public void visitModifier(GNode n) { for (Object o : n) { if (o instanceof String) { add((String) o, n); } else if (o instanceof Node) { dispatch((Node) o); } } } public void visitVoidType(GNode n) { add("void", n); } public void visitFieldDeclaration(GNode n) { add(getIndent(), n); visit(n); addLn(";", n); } public void visitType(GNode n) { // for arrays if (GNode.test(n.get(1)) ) { add("__rt::Ptr<__rt::Array<", n); } visit(n); if (GNode.test(n.get(1)) ) { add("> >", n); } } // for arrays public void visitNewArrayExpression(GNode n) { add(" new __rt::Array<", n); dispatch(n.getGeneric(0)); add(">(", n); dispatch(n.getGeneric(1)); add(")", n); } // for arrays public void visitSubscriptExpression(GNode n) { add("(*", n); dispatch(n.getGeneric(0)); add(")[", n); dispatch(n.getGeneric(1)); add("]", n); } public void visitPrimitiveType(GNode n) { // add((String) n.get(0) + " "); add((String) n.get(0) + " ", n); } public void visitIntegerLiteral(GNode n) { add((String) n.get(0), n); } public void visitReturnStatement(GNode n) { add("return ", n); visit(n); addLn(";", n); } public void visitNullLiteral(GNode n) { add("__rt::null()", n); } public void visitStringLiteral(GNode n) { add("__rt::literal(" + n.getString(0) + ")", n); } public void visitBooleanLiteral(GNode n) { for (Object o : n) { if (o instanceof String) { add((String) o, n); } } } public void visitCastExpression(GNode n) { add("__rt::java_cast(", n); visit(n); add(")", n); } public void visitBasicCastExpression(GNode n) { add("(", n); visit(n.getNode(0)); add(") ", n); visit(n.getNode(2)); } public String getIndent() { String indentOut = ""; for (int i = 0; i < indent; i++) { indentOut += " "; } return indentOut; } /** * Protected method to add new part to implementation representation * **/ protected void add(String addition, Node baseNode) { // implementation += addition; IPiece i = new IPiece(baseNode, addition); cppPrintList.add(i); ipieces.add(i); } private void addLn(String addition, Node baseNode) { add(addition + "\n", baseNode); } // Dispatch on a node's children, skipping the eldest child private void skipEldest(Node n) { if (n.size() > 0) { for (int i = 1; i < n.size(); i++) { Object child = n.get(i); if (GNode.test(child)) { dispatch(GNode.cast(child)); } } } } // Dispatch on a node's children, skipping the youngest child private void skipYoungest(Node n) { if (n.size() > 0) { for (int i = 0; i < (n.size() - 1); i++) { Object child = n.get(i); if (GNode.test(child)) { dispatch(GNode.cast(child)); } } } } public ArrayList<String> getUsedClasses() { return usedClasses; } public HashMap<String, String> getVarTypeDict() { return varTypeDict; } public List<CppPrintable> getCppPrintList() { return cppPrintList; } public void setCppPrintList(List<CppPrintable> pieces) { this.cppPrintList = pieces; } public ArrayList<CallExpressionPiece> getCallExpressions() { return callExpressions; } public void setCallExpressions( ArrayList<CallExpressionPiece> callExpressions) { this.callExpressions = callExpressions; } public void setUsedClasses(ArrayList<String> usedClasses) { this.usedClasses = usedClasses; } public void setVarTypeDict(HashMap<String, String> varTypeDict) { this.varTypeDict = varTypeDict; } public ArrayList<PostfixPiece> getPostfixPieces() { return postfixPieces; } public void setPostfixPieces(ArrayList<PostfixPiece> postfixPieces) { this.postfixPieces = postfixPieces; } public List<IPiece> getIpieces() { return ipieces; } public void setIpieces(List<IPiece> pieces) { this.ipieces = pieces; } }