Commit d8813f05 authored by Stefan Behnel's avatar Stefan Behnel

manual merge of Haoyu's nonlocal implementation

parent 7d1a5f54
......@@ -3434,6 +3434,24 @@ class GlobalNode(StatNode):
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.
#
......
......@@ -84,6 +84,7 @@ cdef p_genexp(PyrexScanner s, expr)
#-------------------------------------------------------
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)
......
......@@ -1047,6 +1047,12 @@ def p_global_statement(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 == '=':
......@@ -1600,6 +1606,8 @@ def p_simple_statement(s, first_statement = 0):
#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':
......
......@@ -36,7 +36,7 @@ def get_lexicon():
#------------------------------------------------------------------
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",
......
......@@ -1271,6 +1271,15 @@ class LocalScope(Scope):
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.
......
......@@ -215,7 +215,8 @@ class SimpleAssignmentTypeInferer(object):
# 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
......
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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment