summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/compiler/symbols.py44
-rw-r--r--Tools/compiler/compiler/symbols.py44
2 files changed, 70 insertions, 18 deletions
diff --git a/Lib/compiler/symbols.py b/Lib/compiler/symbols.py
index 40fd127..946a8b1 100644
--- a/Lib/compiler/symbols.py
+++ b/Lib/compiler/symbols.py
@@ -25,6 +25,7 @@ class Scope:
# nested is true if the class could contain free variables,
# i.e. if it is nested within another function.
self.nested = None
+ self.generator = None
self.klass = None
if klass is not None:
for i in range(len(klass)):
@@ -287,6 +288,27 @@ class SymbolVisitor:
name = name[:i]
scope.add_def(asname or name)
+ def visitGlobal(self, node, scope):
+ for name in node.names:
+ scope.add_global(name)
+
+ def visitAssign(self, node, scope):
+ """Propagate assignment flag down to child nodes.
+
+ The Assign node doesn't itself contains the variables being
+ assigned to. Instead, the children in node.nodes are visited
+ with the assign flag set to true. When the names occur in
+ those nodes, they are marked as defs.
+
+ Some names that occur in an assignment target are not bound by
+ the assignment, e.g. a name occurring inside a slice. The
+ visitor handles these nodes specially; they do not propagate
+ the assign flag to their children.
+ """
+ for n in node.nodes:
+ self.visit(n, scope, 1)
+ self.visit(node.expr, scope)
+
def visitAssName(self, node, scope, assign=1):
scope.add_def(node.name)
@@ -297,6 +319,13 @@ class SymbolVisitor:
self.visit(node.expr, scope, 0)
for n in node.subs:
self.visit(n, scope, 0)
+
+ def visitSlice(self, node, scope, assign=0):
+ self.visit(node.expr, scope, assign)
+ if node.lower:
+ self.visit(node.lower, scope, 0)
+ if node.upper:
+ self.visit(node.upper, scope, 0)
def visitAugAssign(self, node, scope):
# If the LHS is a name, then this counts as assignment.
@@ -306,15 +335,6 @@ class SymbolVisitor:
self.visit(node.node, scope, 1) # XXX worry about this
self.visit(node.expr, scope)
- def visitAssign(self, node, scope):
- for n in node.nodes:
- self.visit(n, scope, 1)
- self.visit(node.expr, scope)
-
- def visitGlobal(self, node, scope):
- for name in node.names:
- scope.add_global(name)
-
# prune if statements if tests are false
_const_types = types.StringType, types.IntType, types.FloatType
@@ -330,6 +350,12 @@ class SymbolVisitor:
if node.else_:
self.visit(node.else_, scope)
+ # a yield statement signals a generator
+
+ def visitYield(self, node, scope):
+ self.generator = 1
+ self.visit(node.value, scope)
+
def sort(l):
l = l[:]
l.sort()
diff --git a/Tools/compiler/compiler/symbols.py b/Tools/compiler/compiler/symbols.py
index 40fd127..946a8b1 100644
--- a/Tools/compiler/compiler/symbols.py
+++ b/Tools/compiler/compiler/symbols.py
@@ -25,6 +25,7 @@ class Scope:
# nested is true if the class could contain free variables,
# i.e. if it is nested within another function.
self.nested = None
+ self.generator = None
self.klass = None
if klass is not None:
for i in range(len(klass)):
@@ -287,6 +288,27 @@ class SymbolVisitor:
name = name[:i]
scope.add_def(asname or name)
+ def visitGlobal(self, node, scope):
+ for name in node.names:
+ scope.add_global(name)
+
+ def visitAssign(self, node, scope):
+ """Propagate assignment flag down to child nodes.
+
+ The Assign node doesn't itself contains the variables being
+ assigned to. Instead, the children in node.nodes are visited
+ with the assign flag set to true. When the names occur in
+ those nodes, they are marked as defs.
+
+ Some names that occur in an assignment target are not bound by
+ the assignment, e.g. a name occurring inside a slice. The
+ visitor handles these nodes specially; they do not propagate
+ the assign flag to their children.
+ """
+ for n in node.nodes:
+ self.visit(n, scope, 1)
+ self.visit(node.expr, scope)
+
def visitAssName(self, node, scope, assign=1):
scope.add_def(node.name)
@@ -297,6 +319,13 @@ class SymbolVisitor:
self.visit(node.expr, scope, 0)
for n in node.subs:
self.visit(n, scope, 0)
+
+ def visitSlice(self, node, scope, assign=0):
+ self.visit(node.expr, scope, assign)
+ if node.lower:
+ self.visit(node.lower, scope, 0)
+ if node.upper:
+ self.visit(node.upper, scope, 0)
def visitAugAssign(self, node, scope):
# If the LHS is a name, then this counts as assignment.
@@ -306,15 +335,6 @@ class SymbolVisitor:
self.visit(node.node, scope, 1) # XXX worry about this
self.visit(node.expr, scope)
- def visitAssign(self, node, scope):
- for n in node.nodes:
- self.visit(n, scope, 1)
- self.visit(node.expr, scope)
-
- def visitGlobal(self, node, scope):
- for name in node.names:
- scope.add_global(name)
-
# prune if statements if tests are false
_const_types = types.StringType, types.IntType, types.FloatType
@@ -330,6 +350,12 @@ class SymbolVisitor:
if node.else_:
self.visit(node.else_, scope)
+ # a yield statement signals a generator
+
+ def visitYield(self, node, scope):
+ self.generator = 1
+ self.visit(node.value, scope)
+
def sort(l):
l = l[:]
l.sort()