package xtc.translator.representation; import xtc.tree.Visitor; import xtc.tree.Node; import xtc.tree.GNode; import java.util.*; /** * A visitor that stores relevant information for a particular method which will * later be used to generate C++ vtable information */ public class MethodVisitor extends Visitor implements Cloneable{ private Node baseNode; private String identifier; private List<Map<String, String>> parameters; private List<String> modifiers; private String returnType; private boolean isOverride; private String implementation; private boolean isStatic; private ImplementationVisitor implementationVisitor; private Map<String, String> variableMap; private ArrayList<String> usedClasses; public MethodVisitor(Node baseNode) { super(); this.baseNode = baseNode; modifiers = new ArrayList<String>(); parameters = new ArrayList<Map<String, String>>(); this.isOverride = false; this.usedClasses = new ArrayList<String>(); this.isStatic = false; this.variableMap = null; } public MethodVisitor(String identifier, String returnType) { super(); this.identifier = identifier; this.returnType = returnType; modifiers = new ArrayList<String>(); parameters = new ArrayList<Map<String, String>>(); this.isOverride = false; this.usedClasses = new ArrayList<String>(); } public void visit(Node n) { for (Object o : n) if (o instanceof Node) dispatch((Node) o); } /** * Pull the method declaration apart, and get all the pieces for translation * **/ public void visitMethodDeclaration(GNode n) { for (Object o : n) { // If String, must be the method identifier if (o instanceof String) { this.identifier = (String) o; } if (o instanceof Node) { // If Block, its the method implementation if (((Node) o).getName() == "Block") { ImplementationVisitor iv = new ImplementationVisitor(); iv.dispatch((Node) o); this.setImplementation(iv.getImplementation()); this.usedClasses.addAll(iv.getUsedClasses()); this.implementationVisitor = iv; } // If modifiers... collect modifiers... if (((Node) o).getName() == "Modifiers") { dispatch((Node) o); } // If parameters... collect parameters... if (((Node) o).getName() == "FormalParameters") { dispatch((Node) o); } // Get return type if (((Node) o).getName() == "Type") { dispatch((Node) o); } else if (((Node) o).getName() == "VoidType") { returnType = "void"; } } } } public void visitFormalParameter(GNode n) { HashMap<String, String> param = new HashMap<String, String>(); for (Object o : n) { // String indicates variable name if (o instanceof String) { param.put("name", (String) o); } if (o instanceof Node) { if (((Node) o).getName() == "Type") { Node innerType = (Node) ((Node) o).get(0); String type = (String) innerType.get(0); param.put("type", type); } } } parameters.add(param); } public void visitType(GNode n) { for (Object o : n) { if (o instanceof Node) { dispatch((Node) o); } } } public void visitQualifiedIdentifier(GNode n) { for (Object o : n) { if (o instanceof String) { returnType = (String) o; } } } public void visitPrimitiveType(GNode n) { for (Object o : n) { if (o instanceof String) { returnType = (String) o; } } } public void visitModifier(GNode n) { for (Object o : n) { // If String, add to modifier list if (o instanceof String) { //if static set isStatic to true if (o.equals("static")) { this.isStatic = true; } modifiers.add((String) o); } } } /** * Helper method to add parameter to parameter list. * */ public void addParameter(String type, String name) { HashMap<String, String> map = new HashMap<String, String>(); map.put("type", type); map.put("name", name); parameters.add(map); } public String getSignature(ClassVisitor implicitThis) { String out = ""; out += "static " + this.returnType + " " + this.identifier + "("; if (this.identifier.equals("main")) { // do nothing } else { if (!isStatic){ out += implicitThis.getIdentifier(); out += ","; } // Print parameter types for (Map<String, String> p : this.parameters) { out += p.get("type"); out += ","; } if (out.charAt(out.length() - 1) == ','){ out = out.substring(0, out.length() - 1); } } out += ")"; return out; } public String parametersToString(){ String out = ""; for (Map<String, String> p : this.parameters) { out += ","; out += p.get("type"); out += " "; out += p.get("name"); } return out; } @Override public String toString() { return identifier; } public String getMethodPointer(ClassVisitor implicitThis) { String out = ""; out += this.returnType + " " + "(" + "*" + this.identifier + ")" + "("; // Implicit this... out += implicitThis.getIdentifier(); // Print parameter types for (Map<String, String> p : this.parameters) { out += ", "; out += p.get("type"); } out += ")"; return out; } public boolean isOverride() { return isOverride; } public void setOverride(boolean isOverride) { this.isOverride = isOverride; } //getter for isStatic private field public boolean isStatic() { return isStatic; } public MethodVisitor copy(){ MethodVisitor clone; try { clone = (MethodVisitor)this.clone(); return clone; } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } public List<Map<String, String>> getParameters() { return parameters; } public void setParameters(List<Map<String, String>> parameters) { this.parameters = parameters; } public List<String> getModifiers() { return modifiers; } public void setModifiers(List<String> modifiers) { this.modifiers = modifiers; } public String getReturnType() { return returnType; } public void setReturnType(String returnType) { this.returnType = returnType; } public String getIdentifier() { return identifier; } public void setIdentifier(String identifier) { this.identifier = identifier; } public String getImplementation() { return implementation; } public void setImplementation(String implementation) { this.implementation = implementation; } public List<String> getUsedClasses() { return this.usedClasses; } public ImplementationVisitor getImplementationVisitor() { return implementationVisitor; } public void setImplementationVisitor(ImplementationVisitor implementationVisitor) { this.implementationVisitor = implementationVisitor; } public void setStatic(boolean isStatic) { this.isStatic = isStatic; } public void setUsedClasses(ArrayList<String> usedClasses) { this.usedClasses = usedClasses; } public Node getBaseNode() { return baseNode; } public void setBaseNode(Node baseNode) { this.baseNode = baseNode; } public Map<String, String> getVariableMap() { return variableMap; } public void setVariableMap(Map<String, String> variableMap) { this.variableMap = variableMap; } public String parametersToStringNoComma() { String out = ""; for (Map<String, String> p : this.parameters) { out += p.get("type"); out += " "; out += p.get("name"); out += ","; } if (!parameters.isEmpty()) out = out.substring(0, out.length() - 1); return out; } }