Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d4be10d

Browse files
committed
Add generator detection to symbol table.
Fix bug in handling of statements like "l[x:y] = 2". The visitor was treating this as assignments to l, x, and y!
1 parent e4e9cd4 commit d4be10d

2 files changed

Lines changed: 70 additions & 18 deletions

File tree

Lib/compiler/symbols.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(self, name, module, klass=None):
2525
# nested is true if the class could contain free variables,
2626
# i.e. if it is nested within another function.
2727
self.nested = None
28+
self.generator = None
2829
self.klass = None
2930
if klass is not None:
3031
for i in range(len(klass)):
@@ -287,6 +288,27 @@ def visitImport(self, node, scope):
287288
name = name[:i]
288289
scope.add_def(asname or name)
289290

291+
def visitGlobal(self, node, scope):
292+
for name in node.names:
293+
scope.add_global(name)
294+
295+
def visitAssign(self, node, scope):
296+
"""Propagate assignment flag down to child nodes.
297+
298+
The Assign node doesn't itself contains the variables being
299+
assigned to. Instead, the children in node.nodes are visited
300+
with the assign flag set to true. When the names occur in
301+
those nodes, they are marked as defs.
302+
303+
Some names that occur in an assignment target are not bound by
304+
the assignment, e.g. a name occurring inside a slice. The
305+
visitor handles these nodes specially; they do not propagate
306+
the assign flag to their children.
307+
"""
308+
for n in node.nodes:
309+
self.visit(n, scope, 1)
310+
self.visit(node.expr, scope)
311+
290312
def visitAssName(self, node, scope, assign=1):
291313
scope.add_def(node.name)
292314

@@ -297,6 +319,13 @@ def visitSubscript(self, node, scope, assign=0):
297319
self.visit(node.expr, scope, 0)
298320
for n in node.subs:
299321
self.visit(n, scope, 0)
322+
323+
def visitSlice(self, node, scope, assign=0):
324+
self.visit(node.expr, scope, assign)
325+
if node.lower:
326+
self.visit(node.lower, scope, 0)
327+
if node.upper:
328+
self.visit(node.upper, scope, 0)
300329

301330
def visitAugAssign(self, node, scope):
302331
# If the LHS is a name, then this counts as assignment.
@@ -306,15 +335,6 @@ def visitAugAssign(self, node, scope):
306335
self.visit(node.node, scope, 1) # XXX worry about this
307336
self.visit(node.expr, scope)
308337

309-
def visitAssign(self, node, scope):
310-
for n in node.nodes:
311-
self.visit(n, scope, 1)
312-
self.visit(node.expr, scope)
313-
314-
def visitGlobal(self, node, scope):
315-
for name in node.names:
316-
scope.add_global(name)
317-
318338
# prune if statements if tests are false
319339

320340
_const_types = types.StringType, types.IntType, types.FloatType
@@ -330,6 +350,12 @@ def visitIf(self, node, scope):
330350
if node.else_:
331351
self.visit(node.else_, scope)
332352

353+
# a yield statement signals a generator
354+
355+
def visitYield(self, node, scope):
356+
self.generator = 1
357+
self.visit(node.value, scope)
358+
333359
def sort(l):
334360
l = l[:]
335361
l.sort()

Tools/compiler/compiler/symbols.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def __init__(self, name, module, klass=None):
2525
# nested is true if the class could contain free variables,
2626
# i.e. if it is nested within another function.
2727
self.nested = None
28+
self.generator = None
2829
self.klass = None
2930
if klass is not None:
3031
for i in range(len(klass)):
@@ -287,6 +288,27 @@ def visitImport(self, node, scope):
287288
name = name[:i]
288289
scope.add_def(asname or name)
289290

291+
def visitGlobal(self, node, scope):
292+
for name in node.names:
293+
scope.add_global(name)
294+
295+
def visitAssign(self, node, scope):
296+
"""Propagate assignment flag down to child nodes.
297+
298+
The Assign node doesn't itself contains the variables being
299+
assigned to. Instead, the children in node.nodes are visited
300+
with the assign flag set to true. When the names occur in
301+
those nodes, they are marked as defs.
302+
303+
Some names that occur in an assignment target are not bound by
304+
the assignment, e.g. a name occurring inside a slice. The
305+
visitor handles these nodes specially; they do not propagate
306+
the assign flag to their children.
307+
"""
308+
for n in node.nodes:
309+
self.visit(n, scope, 1)
310+
self.visit(node.expr, scope)
311+
290312
def visitAssName(self, node, scope, assign=1):
291313
scope.add_def(node.name)
292314

@@ -297,6 +319,13 @@ def visitSubscript(self, node, scope, assign=0):
297319
self.visit(node.expr, scope, 0)
298320
for n in node.subs:
299321
self.visit(n, scope, 0)
322+
323+
def visitSlice(self, node, scope, assign=0):
324+
self.visit(node.expr, scope, assign)
325+
if node.lower:
326+
self.visit(node.lower, scope, 0)
327+
if node.upper:
328+
self.visit(node.upper, scope, 0)
300329

301330
def visitAugAssign(self, node, scope):
302331
# If the LHS is a name, then this counts as assignment.
@@ -306,15 +335,6 @@ def visitAugAssign(self, node, scope):
306335
self.visit(node.node, scope, 1) # XXX worry about this
307336
self.visit(node.expr, scope)
308337

309-
def visitAssign(self, node, scope):
310-
for n in node.nodes:
311-
self.visit(n, scope, 1)
312-
self.visit(node.expr, scope)
313-
314-
def visitGlobal(self, node, scope):
315-
for name in node.names:
316-
scope.add_global(name)
317-
318338
# prune if statements if tests are false
319339

320340
_const_types = types.StringType, types.IntType, types.FloatType
@@ -330,6 +350,12 @@ def visitIf(self, node, scope):
330350
if node.else_:
331351
self.visit(node.else_, scope)
332352

353+
# a yield statement signals a generator
354+
355+
def visitYield(self, node, scope):
356+
self.generator = 1
357+
self.visit(node.value, scope)
358+
333359
def sort(l):
334360
l = l[:]
335361
l.sort()

0 commit comments

Comments
 (0)