<s> __author__ = '<STR_LIT>' <EOL> from slimit import ast <EOL> from slimit . scope import VarSymbol , FuncSymbol , LocalScope , SymbolTable <EOL> class Visitor ( object ) : <EOL> def visit ( self , node ) : <EOL> method = '<STR_LIT>' % node . __class__ . __name__ <EOL> return getattr ( self , method , self . generic_visit ) ( node ) <EOL> def generic_visit ( self , node ) : <EOL> if node is None : <EOL> return <EOL> if isinstance ( node , list ) : <EOL> for child in node : <EOL> self . visit ( child ) <EOL> else : <EOL> for child in node . children ( ) : <EOL> self . visit ( child ) <EOL> class ScopeTreeVisitor ( Visitor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , sym_table ) : <EOL> self . sym_table = sym_table <EOL> self . current_scope = sym_table . globals <EOL> def visit_VarDecl ( self , node ) : <EOL> ident = node . identifier <EOL> symbol = VarSymbol ( name = ident . value ) <EOL> if symbol not in self . current_scope : <EOL> self . current_scope . define ( symbol ) <EOL> ident . scope = self . current_scope <EOL> self . visit ( node . initializer ) <EOL> def visit_Identifier ( self , node ) : <EOL> node . scope = self . current_scope <EOL> def visit_FuncDecl ( self , node ) : <EOL> if node . identifier is not None : <EOL> name = node . identifier . value <EOL> self . visit_Identifier ( node . identifier ) <EOL> else : <EOL> name = None <EOL> func_sym = FuncSymbol ( <EOL> name = name , enclosing_scope = self . current_scope ) <EOL> if name is not None : <EOL> self . current_scope . define ( func_sym ) <EOL> node . scope = self . current_scope <EOL> self . current_scope = func_sym <EOL> for ident in node . parameters : <EOL> self . current_scope . define ( VarSymbol ( ident . value ) ) <EOL> ident . scope = self . current_scope <EOL> for element in node . elements : <EOL> self . visit ( element ) <EOL> self . current_scope = self . current_scope . get_enclosing_scope ( ) <EOL> visit_FuncExpr = visit_FuncDecl <EOL> def visit_Catch ( self , node ) : <EOL> ident = node . identifier <EOL> existing_symbol = self . current_scope . symbols . get ( ident . value ) <EOL> if existing_symbol is None : <EOL> self . current_scope . define ( VarSymbol ( ident . value ) ) <EOL> ident . scope = self . current_scope <EOL> for element in node . elements : <EOL> self . visit ( element ) <EOL> class RefVisitor ( Visitor ) : <EOL> """<STR_LIT>""" <EOL> def visit_Identifier ( self , node ) : <EOL> if self . _is_id_in_expr ( node ) : <EOL> self . _fill_scope_refs ( node . value , node . scope ) <EOL> @ staticmethod <EOL> def _is_id_in_expr ( node ) : <EOL> """<STR_LIT>""" <EOL> return ( <EOL> getattr ( node , '<STR_LIT>' , None ) is not None and <EOL> getattr ( node , '<STR_LIT>' , False ) <EOL> ) <EOL> @ staticmethod <EOL> def _fill_scope_refs ( name , scope ) : <EOL> """<STR_LIT>""" <EOL> symbol = scope . resolve ( name ) <EOL> if symbol is None : <EOL> return <EOL> orig_scope = symbol . scope <EOL> scope . refs [ name ] = orig_scope <EOL> while scope is not orig_scope : <EOL> scope = scope . get_enclosing_scope ( ) <EOL> scope . refs [ name ] = orig_scope <EOL> def mangle_scope_tree ( root , toplevel ) : <EOL> """<STR_LIT>""" <EOL> def mangle ( scope ) : <EOL> if scope . get_enclosing_scope ( ) is None and not toplevel : <EOL> return <EOL> for name in scope . symbols : <EOL> mangled_name = scope . get_next_mangled_name ( ) <EOL> scope . mangled [ name ] = mangled_name <EOL> scope . rev_mangled [ mangled_name ] = name <EOL> def visit ( node ) : <EOL> mangle ( node ) <EOL> for child in node . children : <EOL> visit ( child ) <EOL> visit ( root ) <EOL> def fill_scope_references ( tree ) : <EOL> """<STR_LIT>""" <EOL> visitor = RefVisitor ( ) <EOL> visitor . visit ( tree ) <EOL> class NameManglerVisitor ( Visitor ) : <EOL> """<STR_LIT>""" <EOL> @ staticmethod <EOL> def _is_mangle_candidate ( id_node ) : <EOL> """<STR_LIT>""" <EOL> return getattr ( id_node , '<STR_LIT>' , False ) <EOL> def visit_Identifier ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if not self . _is_mangle_candidate ( node ) : <EOL> return <EOL> name = node . value <EOL> symbol = node . scope . resolve ( node . value ) <EOL> if symbol is None : <EOL> return <EOL> mangled = symbol . scope . mangled . get ( name ) <EOL> if mangled is not None : <EOL> node . value = mangled </s>
