package polyglot.visit; import polyglot.ast.*; import polyglot.util.*; import java.util.*; /** * The <code>AlphaRenamer</code> runs over the AST and alpha-renames any local * variable declarations that it encounters. **/ public class AlphaRenamer extends NodeVisitor { protected NodeFactory nf; // Each set in this stack tracks the set of local decls in a block that // we're traversing. protected Stack setStack; protected Map renamingMap; // Tracks the set of variables known to be fresh. protected Set freshVars; /** * Creates a visitor for alpha-renaming locals. * * @param nf The node factory to be used when generating new nodes. **/ public AlphaRenamer(NodeFactory nf) { this.nf = nf; this.setStack = new Stack(); this.setStack.push( new HashSet() ); this.renamingMap = new HashMap(); this.freshVars = new HashSet(); } public NodeVisitor enter( Node n ) { if ( n instanceof Block ) { // Push a new, empty set onto the stack. setStack.push( new HashSet() ); } if ( n instanceof LocalDecl ) { LocalDecl l = (LocalDecl)n; String name = l.name(); if ( !freshVars.contains(name) ) { // Add a new entry to the current renaming map. String name_ = UniqueID.newID(name); freshVars.add(name_); ((Set)setStack.peek()).add( name ); renamingMap.put( name, name_ ); } } return this; } public Node leave( Node old, Node n, NodeVisitor v ) { if ( n instanceof Block ) { // Pop the current name set off the stack and remove the corresponding // entries from the renaming map. Set s = (Set)setStack.pop(); renamingMap.keySet().removeAll(s); return n; } if ( n instanceof Local ) { // Rename the local if its name is in the renaming map. Local l = (Local)n; String name = l.name(); if ( !renamingMap.containsKey(name) ) { return n; } return l.name( (String)renamingMap.get(name) ); } if ( n instanceof LocalDecl ) { // Rename the local decl. LocalDecl l = (LocalDecl)n; String name = l.name(); if ( freshVars.contains(name) ) { return n; } if ( !renamingMap.containsKey(name) ) { throw new InternalCompilerError( "Unexpected error encountered while " + "alpha-renaming." ); } return l.name( (String)renamingMap.get(name) ); } return n; } }