Commit 15dce275 authored by Robert Bradshaw's avatar Robert Bradshaw

Merge remote-tracking branch 'main/0.17' into bugs

parents 402dc50d a1d5c022
...@@ -3117,11 +3117,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -3117,11 +3117,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
break break
else: else:
assert condition_result == False assert condition_result == False
# prevent killing generators, but simplify them as much as possible
yield_expr = self._find_genexpr_yield(if_clause.body)
if yield_expr is not None:
if_clause.condition = ExprNodes.BoolNode(if_clause.condition.pos, value=False)
yield_expr.arg = ExprNodes.NoneNode(yield_expr.arg.pos)
if_clauses.append(if_clause)
else:
# False clauses outside of generators can safely be deleted
pass
if not if_clauses: if not if_clauses:
return node.else_clause return node.else_clause
node.if_clauses = if_clauses node.if_clauses = if_clauses
return node return node
def _find_genexpr_yield(self, node):
body_node_types = (Nodes.ForInStatNode, Nodes.IfStatNode)
while isinstance(node, body_node_types):
node = node.body
if isinstance(node, Nodes.ExprStatNode):
node = node.expr
if isinstance(node, ExprNodes.YieldExprNode):
return node
return None
# in the future, other nodes can have their own handler method here # in the future, other nodes can have their own handler method here
# that can replace them with a constant result node # that can replace them with a constant result node
......
...@@ -1569,7 +1569,7 @@ class GeneratorExpressionScope(Scope): ...@@ -1569,7 +1569,7 @@ class GeneratorExpressionScope(Scope):
type = outer_entry.type # may still be 'unspecified_type' ! type = outer_entry.type # may still be 'unspecified_type' !
# the parent scope needs to generate code for the variable, but # the parent scope needs to generate code for the variable, but
# this scope must hold its name exclusively # this scope must hold its name exclusively
cname = '%s%s' % (self.genexp_prefix, self.parent_scope.mangle(Naming.var_prefix, name)) 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 = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1 entry.is_variable = 1
self.var_entries.append(entry) self.var_entries.append(entry)
......
...@@ -21,6 +21,16 @@ def genexpr_if(): ...@@ -21,6 +21,16 @@ def genexpr_if():
assert x == 'abc' # don't leak assert x == 'abc' # don't leak
return result return result
def genexpr_if_false():
"""
>>> genexpr_if_false()
[]
"""
x = 'abc'
result = list( x*2 for x in range(5) if False )
assert x == 'abc' # don't leak
return result
def genexpr_with_lambda(): def genexpr_with_lambda():
""" """
>>> genexpr_with_lambda() >>> genexpr_with_lambda()
......
# mode: run
# cython: language_level=3
"""
Adapted from CPython's test_grammar.py
"""
def genexpr_simple():
"""
>>> sum([ x**2 for x in range(10) ])
285
>>> sum(genexpr_simple())
285
"""
return (x**2 for x in range(10))
def genexpr_conditional():
"""
>>> sum([ x*x for x in range(10) if x%2 ])
165
>>> sum(genexpr_conditional())
165
"""
return (x*x for x in range(10) if x%2)
def genexpr_nested2():
"""
>>> sum([x for x in range(10)])
45
>>> sum(genexpr_nested2())
45
"""
return (x for x in (y for y in range(10)))
def genexpr_nested3():
"""
>>> sum([x for x in range(10)])
45
>>> sum(genexpr_nested3())
45
"""
return (x for x in (y for y in (z for z in range(10))))
def genexpr_nested_listcomp():
"""
>>> sum([x for x in range(10)])
45
>>> sum(genexpr_nested_listcomp())
45
"""
return (x for x in [y for y in (z for z in range(10))])
def genexpr_nested_conditional():
"""
>>> sum([ x for x in [y for y in [z for z in range(10) if True]] if True ])
45
>>> sum(genexpr_nested_conditional())
45
"""
return (x for x in (y for y in (z for z in range(10) if True)) if True)
def genexpr_nested2_conditional_empty():
"""
>>> sum(genexpr_nested2_conditional_empty())
0
"""
return (y for y in (z for z in range(10) if True) if False)
def genexpr_nested3_conditional_empty():
"""
>>> sum(genexpr_nested3_conditional_empty())
0
"""
return (x for x in (y for y in (z for z in range(10) if True) if False) if True)
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