Commit ffdc9b88 authored by Stefan Behnel's avatar Stefan Behnel

Repair compilation error for nested module level comprehensions.

Closes #1906.
parent 65c2cd5d
......@@ -7949,8 +7949,7 @@ class ScopedExprNode(ExprNode):
generate_inner_evaluation_code(code)
# normal (non-error) exit
for entry in py_entries:
code.put_var_xdecref_clear(entry)
self._generate_vars_cleanup(code, py_entries)
# error/loop body exit points
exit_scope = code.new_label('exit_scope')
......@@ -7959,8 +7958,7 @@ class ScopedExprNode(ExprNode):
list(zip(code.get_loop_labels(), old_loop_labels))):
if code.label_used(label):
code.put_label(label)
for entry in py_entries:
code.put_var_xdecref_clear(entry)
self._generate_vars_cleanup(code, py_entries)
code.put_goto(old_label)
code.put_label(exit_scope)
code.putln('} /* exit inner scope */')
......@@ -7968,6 +7966,14 @@ class ScopedExprNode(ExprNode):
code.set_loop_labels(old_loop_labels)
code.error_label = old_error_label
def _generate_vars_cleanup(self, code, py_entries):
for entry in py_entries:
if entry.is_cglobal:
code.put_var_gotref(entry)
code.put_decref_set(entry.cname, "Py_None")
else:
code.put_var_xdecref_clear(entry)
class ComprehensionNode(ScopedExprNode):
# A list/set/dict comprehension
......
......@@ -1704,7 +1704,10 @@ class LocalScope(Scope):
# Return None if not found.
entry = Scope.lookup(self, name)
if entry is not None:
if entry.scope is not self and entry.scope.is_closure_scope:
entry_scope = entry.scope
while entry_scope.is_genexpr_scope:
entry_scope = entry_scope.outer_scope
if entry_scope is not self and entry_scope.is_closure_scope:
if hasattr(entry.scope, "scope_class"):
raise InternalError("lookup() after scope class created.")
# The actual c fragment for the different scopes differs
......@@ -1740,8 +1743,12 @@ class GeneratorExpressionScope(Scope):
is_genexpr_scope = True
def __init__(self, outer_scope):
name = outer_scope.global_scope().next_id(Naming.genexpr_id_ref)
Scope.__init__(self, name, outer_scope, outer_scope)
parent_scope = outer_scope
# TODO: also ignore class scopes?
while parent_scope.is_genexpr_scope:
parent_scope = parent_scope.parent_scope
name = parent_scope.global_scope().next_id(Naming.genexpr_id_ref)
Scope.__init__(self, name, outer_scope, parent_scope)
self.directives = outer_scope.directives
self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name)
......@@ -1768,7 +1775,10 @@ class GeneratorExpressionScope(Scope):
cname = '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(Naming.var_prefix, name or self.next_id()))
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = True
entry.is_local = True
if self.parent_scope.is_module_scope:
entry.is_cglobal = True
else:
entry.is_local = True
entry.in_subscope = True
self.var_entries.append(entry)
self.entries[name] = entry
......
......@@ -57,3 +57,35 @@ def sorted(it):
l = list(it)
l.sort()
return l
# Copied from sre_compile.py in CPython 3.7. Previously failed to detect variable initialisation.
_equivalences = (
# LATIN SMALL LETTER I, LATIN SMALL LETTER DOTLESS I
(0x69, 0x131), # iı
# LATIN SMALL LETTER S, LATIN SMALL LETTER LONG S
(0x73, 0x17f), # sſ
# MICRO SIGN, GREEK SMALL LETTER MU
(0xb5, 0x3bc), # µμ
# COMBINING GREEK YPOGEGRAMMENI, GREEK SMALL LETTER IOTA, GREEK PROSGEGRAMMENI
(0x345, 0x3b9, 0x1fbe), # \u0345ιι
# ...
)
_ignorecase_fixes = {
i: tuple(j for j in t if i != j)
for t in _equivalences for i in t
}
def nested_tuple():
"""
>>> modlevel, funclevel = nested_tuple()
>>> modlevel == funclevel or (modlevel, funclevel)
True
"""
inner_ignorecase_fixes = {
i: tuple(j for j in t if i != j)
for t in _equivalences for i in t
}
return sorted(_ignorecase_fixes.items()), sorted(inner_ignorecase_fixes.items())
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