1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""Module symbol-table generator"""
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom compiler import ast
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICIT, \
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    SC_FREE, SC_CELL, SC_UNKNOWN
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom compiler.misc import mangle
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport types
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehMANGLE_LEN = 256
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass Scope:
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # XXX how much information do I need about each name?
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, name, module, klass=None):
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.name = name
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.module = module
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.defs = {}
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.uses = {}
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.globals = {}
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.params = {}
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.frees = {}
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.cells = {}
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.children = []
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # nested is true if the class could contain free variables,
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # i.e. if it is nested within another function.
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.nested = None
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.generator = None
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.klass = None
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if klass is not None:
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for i in range(len(klass)):
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if klass[i] != '_':
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.klass = klass[i:]
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    break
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __repr__(self):
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return "<%s: %s>" % (self.__class__.__name__, self.name)
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def mangle(self, name):
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.klass is None:
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return name
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return mangle(name, self.klass)
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def add_def(self, name):
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.defs[self.mangle(name)] = 1
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def add_use(self, name):
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.uses[self.mangle(name)] = 1
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def add_global(self, name):
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        name = self.mangle(name)
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if name in self.uses or name in self.defs:
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            pass # XXX warn about global following def/use
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if name in self.params:
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            raise SyntaxError, "%s in %s is global and parameter" % \
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                  (name, self.name)
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.globals[name] = 1
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.module.add_def(name)
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def add_param(self, name):
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        name = self.mangle(name)
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.defs[name] = 1
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.params[name] = 1
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def get_names(self):
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        d = {}
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        d.update(self.defs)
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        d.update(self.uses)
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        d.update(self.globals)
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return d.keys()
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def add_child(self, child):
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.children.append(child)
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def get_children(self):
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.children
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def DEBUG(self):
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print >> sys.stderr, self.name, self.nested and "nested" or ""
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print >> sys.stderr, "\tglobals: ", self.globals
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print >> sys.stderr, "\tcells: ", self.cells
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print >> sys.stderr, "\tdefs: ", self.defs
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print >> sys.stderr, "\tuses: ", self.uses
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print >> sys.stderr, "\tfrees:", self.frees
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def check_name(self, name):
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Return scope of name.
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        The scope of a name could be LOCAL, GLOBAL, FREE, or CELL.
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if name in self.globals:
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return SC_GLOBAL_EXPLICIT
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if name in self.cells:
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return SC_CELL
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if name in self.defs:
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return SC_LOCAL
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.nested and (name in self.frees or name in self.uses):
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return SC_FREE
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if self.nested:
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return SC_UNKNOWN
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return SC_GLOBAL_IMPLICIT
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def get_free_vars(self):
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if not self.nested:
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            return ()
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        free = {}
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        free.update(self.frees)
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for name in self.uses.keys():
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if name not in self.defs and name not in self.globals:
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                free[name] = 1
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return free.keys()
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def handle_children(self):
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for child in self.children:
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            frees = child.get_free_vars()
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            globals = self.add_frees(frees)
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            for name in globals:
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                child.force_global(name)
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def force_global(self, name):
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Force name to be global in scope.
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        Some child of the current node had a free reference to name.
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        When the child was processed, it was labelled a free
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        variable.  Now that all its enclosing scope have been
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        processed, the name is known to be a global or builtin.  So
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        walk back down the child chain and set the name to be global
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        rather than free.
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        Be careful to stop if a child does not think the name is
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        free.
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.globals[name] = 1
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if name in self.frees:
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            del self.frees[name]
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for child in self.children:
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if child.check_name(name) == SC_FREE:
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                child.force_global(name)
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def add_frees(self, names):
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Process list of free vars from nested scope.
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        Returns a list of names that are either 1) declared global in the
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        parent or 2) undefined in a top-level parent.  In either case,
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        the nested scope should treat them as globals.
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        child_globals = []
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for name in names:
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            sc = self.check_name(name)
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if self.nested:
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if sc == SC_UNKNOWN or sc == SC_FREE \
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                   or isinstance(self, ClassScope):
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.frees[name] = 1
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                elif sc == SC_GLOBAL_IMPLICIT:
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    child_globals.append(name)
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                elif isinstance(self, FunctionScope) and sc == SC_LOCAL:
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.cells[name] = 1
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                elif sc != SC_CELL:
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    child_globals.append(name)
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if sc == SC_LOCAL:
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    self.cells[name] = 1
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                elif sc != SC_CELL:
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    child_globals.append(name)
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return child_globals
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def get_cell_vars(self):
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return self.cells.keys()
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass ModuleScope(Scope):
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __super_init = Scope.__init__
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self):
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.__super_init("global", self)
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass FunctionScope(Scope):
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    pass
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass GenExprScope(Scope):
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __super_init = Scope.__init__
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __counter = 1
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, module, klass=None):
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        i = self.__counter
188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.__counter += 1
189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.__super_init("generator expression<%d>"%i, module, klass)
190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.add_param('.0')
191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def get_names(self):
193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        keys = Scope.get_names(self)
194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return keys
195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass LambdaScope(FunctionScope):
197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __super_init = Scope.__init__
198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __counter = 1
200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, module, klass=None):
202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        i = self.__counter
203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.__counter += 1
204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.__super_init("lambda.%d" % i, module, klass)
205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass ClassScope(Scope):
207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    __super_init = Scope.__init__
208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self, name, module):
210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.__super_init(name, module, name)
211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass SymbolVisitor:
213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def __init__(self):
214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.scopes = {}
215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.klass = None
216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # node that define new scopes
218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitModule(self, node):
220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope = self.module = self.scopes[node] = ModuleScope()
221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.node, scope)
222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    visitExpression = visitModule
224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitFunction(self, node, parent):
226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if node.decorators:
227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(node.decorators, parent)
228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        parent.add_def(node.name)
229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for n in node.defaults:
230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(n, parent)
231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope = FunctionScope(node.name, self.module, self.klass)
232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if parent.nested or isinstance(parent, FunctionScope):
233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.nested = 1
234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.scopes[node] = scope
235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self._do_args(scope, node.argnames)
236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.code, scope)
237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.handle_free_vars(scope, parent)
238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitGenExpr(self, node, parent):
240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope = GenExprScope(self.module, self.klass);
241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if parent.nested or isinstance(parent, FunctionScope) \
242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                or isinstance(parent, GenExprScope):
243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.nested = 1
244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.scopes[node] = scope
246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.code, scope)
247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.handle_free_vars(scope, parent)
249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitGenExprInner(self, node, scope):
251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for genfor in node.quals:
252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(genfor, scope)
253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.expr, scope)
255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitGenExprFor(self, node, scope):
257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.assign, scope, 1)
258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.iter, scope)
259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for if_ in node.ifs:
260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(if_, scope)
261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitGenExprIf(self, node, scope):
263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.test, scope)
264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitLambda(self, node, parent, assign=0):
266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Lambda is an expression, so it could appear in an expression
267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # context where assign is passed.  The transformer should catch
268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # any code that has a lambda on the left-hand side.
269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        assert not assign
270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for n in node.defaults:
272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(n, parent)
273ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope = LambdaScope(self.module, self.klass)
274ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if parent.nested or isinstance(parent, FunctionScope):
275ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.nested = 1
276ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.scopes[node] = scope
277ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self._do_args(scope, node.argnames)
278ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.code, scope)
279ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.handle_free_vars(scope, parent)
280ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
281ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def _do_args(self, scope, args):
282ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for name in args:
283ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if type(name) == types.TupleType:
284ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                self._do_args(scope, name)
285ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            else:
286ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                scope.add_param(name)
287ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
288ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def handle_free_vars(self, scope, parent):
289ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        parent.add_child(scope)
290ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope.handle_children()
291ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
292ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitClass(self, node, parent):
293ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        parent.add_def(node.name)
294ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for n in node.bases:
295ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(n, parent)
296ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope = ClassScope(node.name, self.module)
297ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if parent.nested or isinstance(parent, FunctionScope):
298ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.nested = 1
299ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if node.doc is not None:
300ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.add_def('__doc__')
301ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope.add_def('__module__')
302ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.scopes[node] = scope
303ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        prev = self.klass
304ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.klass = node.name
305ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.code, scope)
306ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.klass = prev
307ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.handle_free_vars(scope, parent)
308ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
309ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # name can be a def or a use
310ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
311ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # XXX a few calls and nodes expect a third "assign" arg that is
312ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # true if the name is being used as an assignment.  only
313ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # expressions contained within statements may have the assign arg.
314ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
315ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitName(self, node, scope, assign=0):
316ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if assign:
317ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.add_def(node.name)
318ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        else:
319ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.add_use(node.name)
320ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
321ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # operations that bind new names
322ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
323ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitFor(self, node, scope):
324ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.assign, scope, 1)
325ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.list, scope)
326ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.body, scope)
327ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if node.else_:
328ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(node.else_, scope)
329ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
330ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitFrom(self, node, scope):
331ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for name, asname in node.names:
332ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if name == "*":
333ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                continue
334ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.add_def(asname or name)
335ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
336ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitImport(self, node, scope):
337ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for name, asname in node.names:
338ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            i = name.find(".")
339ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if i > -1:
340ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                name = name[:i]
341ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.add_def(asname or name)
342ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
343ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitGlobal(self, node, scope):
344ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for name in node.names:
345ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            scope.add_global(name)
346ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
347ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitAssign(self, node, scope):
348ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """Propagate assignment flag down to child nodes.
349ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
350ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        The Assign node doesn't itself contains the variables being
351ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        assigned to.  Instead, the children in node.nodes are visited
352ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        with the assign flag set to true.  When the names occur in
353ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        those nodes, they are marked as defs.
354ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
355ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        Some names that occur in an assignment target are not bound by
356ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        the assignment, e.g. a name occurring inside a slice.  The
357ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        visitor handles these nodes specially; they do not propagate
358ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        the assign flag to their children.
359ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        """
360ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for n in node.nodes:
361ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(n, scope, 1)
362ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.expr, scope)
363ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
364ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitAssName(self, node, scope, assign=1):
365ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope.add_def(node.name)
366ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
367ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitAssAttr(self, node, scope, assign=0):
368ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.expr, scope, 0)
369ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
370ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitSubscript(self, node, scope, assign=0):
371ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.expr, scope, 0)
372ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for n in node.subs:
373ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(n, scope, 0)
374ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
375ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitSlice(self, node, scope, assign=0):
376ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.expr, scope, 0)
377ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if node.lower:
378ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(node.lower, scope, 0)
379ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if node.upper:
380ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(node.upper, scope, 0)
381ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
382ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitAugAssign(self, node, scope):
383ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # If the LHS is a name, then this counts as assignment.
384ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Otherwise, it's just use.
385ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.node, scope)
386ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if isinstance(node.node, ast.Name):
387ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(node.node, scope, 1) # XXX worry about this
388ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.expr, scope)
389ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
390ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # prune if statements if tests are false
391ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
392ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    _const_types = types.StringType, types.IntType, types.FloatType
393ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
394ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitIf(self, node, scope):
395ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for test, body in node.tests:
396ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if isinstance(test, ast.Const):
397ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if type(test.value) in self._const_types:
398ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    if not test.value:
399ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        continue
400ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(test, scope)
401ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(body, scope)
402ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if node.else_:
403ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.visit(node.else_, scope)
404ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
405ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    # a yield statement signals a generator
406ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
407ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def visitYield(self, node, scope):
408ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scope.generator = 1
409ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.visit(node.value, scope)
410ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
411ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef list_eq(l1, l2):
412ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    return sorted(l1) == sorted(l2)
413ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
414ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == "__main__":
415ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    import sys
416ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    from compiler import parseFile, walk
417ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    import symtable
418ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
419ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def get_names(syms):
420ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        return [s for s in [s.get_name() for s in syms.get_symbols()]
421ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if not (s.startswith('_[') or s.startswith('.'))]
422ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
423ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    for file in sys.argv[1:]:
424ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        print file
425ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f = open(file)
426ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        buf = f.read()
427ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f.close()
428ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        syms = symtable.symtable(buf, file, "exec")
429ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        mod_names = get_names(syms)
430ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        tree = parseFile(file)
431ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        s = SymbolVisitor()
432ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        walk(tree, s)
433ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
434ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # compare module-level symbols
435ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        names2 = s.scopes[tree].get_names()
436ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
437ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        if not list_eq(mod_names, names2):
438ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            print
439ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            print "oops", file
440ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            print sorted(mod_names)
441ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            print sorted(names2)
442ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            sys.exit(-1)
443ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
444ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        d = {}
445ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        d.update(s.scopes)
446ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        del d[tree]
447ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        scopes = d.values()
448ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        del d
449ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
450ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        for s in syms.get_symbols():
451ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            if s.is_namespace():
452ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                l = [sc for sc in scopes
453ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                     if sc.name == s.get_name()]
454ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                if len(l) > 1:
455ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    print "skipping", s.get_name()
456ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                else:
457ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                    if not list_eq(get_names(s.get_namespace()),
458ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                                   l[0].get_names()):
459ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        print s.get_name()
460ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        print sorted(get_names(s.get_namespace()))
461ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        print sorted(l[0].get_names())
462ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                        sys.exit(-1)
463