pass
+class NonlocalNode(StatNode):
+ # Nonlocal variable declaration via the 'nonlocal' keyword.
+ #
+ # names [string]
+
+ child_attrs = []
+
+ def analyse_declarations(self, env):
+ for name in self.names:
+ env.declare_nonlocal(name, self.pos)
+
+ def analyse_expressions(self, env):
+ pass
+
+ def generate_execution_code(self, code):
+ pass
+
+
class ExprStatNode(StatNode):
# Expression used as a statement.
#
#-------------------------------------------------------
cdef p_global_statement(PyrexScanner s)
+cdef p_nonlocal_statement(PyrexScanner s)
cdef p_expression_or_assignment(PyrexScanner s)
cdef p_print_statement(PyrexScanner s)
cdef p_exec_statement(PyrexScanner s)
names = p_ident_list(s)
return Nodes.GlobalNode(pos, names = names)
+def p_nonlocal_statement(s):
+ pos = s.position()
+ s.next()
+ names = p_ident_list(s)
+ return Nodes.NonlocalNode(pos, names = names)
+
def p_expression_or_assignment(s):
expr_list = [p_testlist_star_expr(s)]
while s.sy == '=':
#print "p_simple_statement:", s.sy, s.systring ###
if s.sy == 'global':
node = p_global_statement(s)
+ elif s.sy == 'nonlocal':
+ node = p_nonlocal_statement(s)
elif s.sy == 'print':
node = p_print_statement(s)
elif s.sy == 'exec':
#------------------------------------------------------------------
py_reserved_words = [
- "global", "def", "class", "print", "del", "pass", "break",
+ "global", "nonlocal", "def", "class", "print", "del", "pass", "break",
"continue", "return", "raise", "import", "exec", "try",
"except", "finally", "while", "if", "elif", "else", "for",
"in", "assert", "and", "or", "not", "is", "in", "lambda",
else:
entry = self.global_scope().lookup_target(name)
self.entries[name] = entry
+
+ def declare_nonlocal(self, name, pos):
+ # Pull entry from outer scope into local scope
+ if self.lookup_here(name):
+ warning(pos, "'%s' redeclared" % name, 0)
+ else:
+ entry = self.lookup(name)
+ if entry is None or not entry.from_closure:
+ error(pos, "no binding for nonlocal '%s' found" % name)
def lookup(self, name):
# Look up name in this scope or an enclosing one.
# TODO: Implement a real type inference algorithm.
# (Something more powerful than just extending this one...)
def infer_types(self, scope):
- enabled = not scope.is_closure_scope and scope.directives['infer_types']
+ closure_or_inner = scope.is_closure_scope or (scope.outer_scope and scope.outer_scope.is_closure_scope)
+ enabled = not closure_or_inner and scope.directives['infer_types']
verbose = scope.directives['infer_types.verbose']
if enabled == True:
spanning_type = aggressive_spanning_type
--- /dev/null
+def simple():
+ """
+ >>> simple()
+ 1
+ 2
+ """
+ x = 1
+ y = 2
+ def f():
+ nonlocal x
+ nonlocal x, y
+ print(x)
+ print(y)
+ f()
+
+def assign():
+ """
+ >>> assign()
+ 1
+ """
+ xx = 0
+ def ff():
+ nonlocal xx
+ xx += 1
+ print(xx)
+ ff()
+
+def nested():
+ """
+ >>> nested()
+ 1
+ """
+ x = 0
+ def fx():
+ def gx():
+ nonlocal x
+ x=1
+ print(x)
+ return gx
+ fx()()
+
+def arg(x):
+ """
+ >>> arg('x')
+ xyy
+ """
+ def appendy():
+ nonlocal x
+ x += 'y'
+ x+='y'
+ appendy()
+ print x
+ return
+
+def argtype(int n):
+ """
+ >>> argtype(0)
+ 1
+ """
+ def inc():
+ nonlocal n
+ n += 1
+ inc()
+ print n
+ return
+