package polyglot.visit; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.Stack; import polyglot.ast.Node; import polyglot.ast.NodeFactory; import polyglot.frontend.Job; import polyglot.main.Report; import polyglot.types.*; import polyglot.util.Enum; /** * A visitor which traverses the AST and remove ambiguities found in fields, * method signatures and the code itself. */ public class AmbiguityRemover extends ContextVisitor { public static class Kind extends Enum { protected Kind(String name) { super(name); } } public static final Kind SUPER = new Kind("disam-super"); public static final Kind SIGNATURES = new Kind("disam-sigs"); public static final Kind FIELDS = new Kind("disam-fields"); public static final Kind ALL = new Kind("disam-all"); protected Kind kind; public AmbiguityRemover(Job job, TypeSystem ts, NodeFactory nf, Kind kind) { super(job, ts, nf); this.kind = kind; } public Kind kind() { return kind; } protected NodeVisitor enterCall(Node n) throws SemanticException { if (Report.should_report(Report.visit, 2)) Report.report(2, ">> " + kind + "::enter " + n); NodeVisitor v = n.del().disambiguateEnter(this); if (Report.should_report(Report.visit, 2)) Report.report(2, "<< " + kind + "::enter " + n + " -> " + v); return v; } protected Node leaveCall(Node old, Node n, NodeVisitor v) throws SemanticException { if (Report.should_report(Report.visit, 2)) Report.report(2, ">> " + kind + "::leave " + n); Node m = n.del().disambiguate((AmbiguityRemover) v); if (Report.should_report(Report.visit, 2)) Report.report(2, "<< " + kind + "::leave " + n + " -> " + m); return m; } /** * Add dependencies for the job to the super classes and interface classes * of <code>ct</code>. */ public void addSuperDependencies(ClassType ct) { // track which classtypes we've seen, since it may be the // case that the class types are (incorrectly) circular. Set seen = new HashSet(); Stack s = new Stack(); s.push(ct); while (! s.isEmpty()) { Type t = (Type) s.pop(); if (t.isClass()) { ClassType classt = t.toClass(); if (seen.contains(classt)) { continue; } else { seen.add(classt); } // add a dependency if its a parsed class type. if (classt instanceof ParsedClassType) { this.job().extensionInfo().addDependencyToCurrentJob( ((ParsedClassType)classt).fromSource()); } // add all the interfaces to the stack. for (Iterator i = classt.interfaces().iterator(); i.hasNext(); ) { s.push(i.next()); } // add the superType to the stack. if (classt.superType() != null) { s.push(classt.superType()); } } } } public String toString() { return super.toString() + "(" + kind + ")"; } }