Prevent incorrect syntax error with nonlocal of a parameter

Also includes a test for the error "name 'x' is assigned before nonlocal
declaration"

Fixes #175
This commit is contained in:
Terseus
2021-02-21 00:38:46 +01:00
parent 93206f6eba
commit e5d6663721
3 changed files with 37 additions and 0 deletions

View File

@@ -241,6 +241,7 @@ class _Context:
self.parent_context = parent_context
self._used_name_dict = {}
self._global_names = []
self._local_params_names = []
self._nonlocal_names = []
self._nonlocal_names_in_subscopes = []
self._add_syntax_error = add_syntax_error
@@ -264,6 +265,10 @@ class _Context:
self._global_names.append(name)
elif parent_type == 'nonlocal_stmt':
self._nonlocal_names.append(name)
elif parent_type == 'funcdef':
self._local_params_names.extend(
[param.name.value for param in name.parent.get_params()]
)
else:
self._used_name_dict.setdefault(name.value, []).append(name)
@@ -291,6 +296,8 @@ class _Context:
nonlocals_not_handled = []
for nonlocal_name in self._nonlocal_names_in_subscopes:
search = nonlocal_name.value
if search in self._local_params_names:
continue
if search in global_name_strs or self.parent_context is None:
message = "no binding for nonlocal '%s' found" % nonlocal_name.value
self._add_syntax_error(nonlocal_name, message)

View File

@@ -337,6 +337,13 @@ FAILING_EXAMPLES = [
def z():
nonlocal a
'''),
# Name is assigned before nonlocal declaration
dedent('''
def x(a):
def y():
a = 10
nonlocal a
'''),
]
if sys.version_info[:2] >= (3, 7):

View File

@@ -113,6 +113,29 @@ def x():
nonlocal a
def x(a):
def y():
nonlocal a
def x(a, b):
def y():
nonlocal b
nonlocal a
def x(a):
def y():
def z():
nonlocal a
def x():
def y(a):
def z():
nonlocal a
a = *args, *args
error[(*args, *args)] = 3
*args, *args