self.value_expr.annotate(code)
-class GeneratorExpressionNode(ScopedExprNode):
- # A generator expression, e.g. (i for i in range(10))
- #
- # Result is a generator.
+class InlinedGeneratorExpressionNode(ScopedExprNode):
+ # An inlined generator expression for which the result is
+ # calculated inside of the loop. This will only be created by
+ # transforms when replacing builtin calls on generator
+ # expressions.
#
- # loop ForStatNode the for-loop, containing a YieldExprNode
+ # loop ForStatNode the for-loop, not containing any YieldExprNodes
+ # result_node ResultRefNode the reference to the result value temp
+ # orig_func String the name of the builtin function this node replaces
child_attrs = ["loop"]
-
+ loop_analysed = False
type = py_object_type
def analyse_scoped_declarations(self, env):
self.loop.analyse_expressions(env)
self.is_temp = True
- def analyse_scoped_expressions(self, env):
- if self.has_local_scope:
- self.loop.analyse_expressions(env)
-
def may_be_none(self):
return False
def annotate(self, code):
self.loop.annotate(code)
-
-class InlinedGeneratorExpressionNode(GeneratorExpressionNode):
- # An inlined generator expression for which the result is
- # calculated inside of the loop. This will only be created by
- # transforms when replacing builtin calls on generator
- # expressions.
- #
- # loop ForStatNode the for-loop, not containing any YieldExprNodes
- # result_node ResultRefNode the reference to the result value temp
- # orig_func String the name of the builtin function this node replaces
-
- child_attrs = ["loop"]
- loop_analysed = False
-
def infer_type(self, env):
return self.result_node.infer_type(env)
def analyse_scoped_expressions(self, env):
self.loop_analysed = True
- GeneratorExpressionNode.analyse_scoped_expressions(self, env)
+ if self.has_local_scope:
+ self.loop.analyse_expressions(env)
def coerce_to(self, dst_type, env):
if self.orig_func == 'sum' and dst_type.is_numeric and not self.loop_analysed:
# assignments.
self.result_node.type = self.type = dst_type
return self
- return GeneratorExpressionNode.coerce_to(self, dst_type, env)
+ return super(InlinedGeneratorExpressionNode, self).coerce_to(dst_type, env)
def generate_result_code(self, code):
self.result_node.result_code = self.result()
env.add_lambda_def(self.def_node)
+class GeneratorExpressionNode(LambdaNode):
+ # A generator expression, e.g. (i for i in range(10))
+ #
+ # Result is a generator.
+ #
+ # loop ForStatNode the for-loop, containing a YieldExprNode
+ # def_node DefNode the underlying generator 'def' node
+
+ child_attrs = ["loop", "def_node"]
+ name = StringEncoding.EncodedString('<genexpr>')
+ binding = False
+
+ def analyse_declarations(self, env):
+ # XXX: dirty hack to disable assignment synthesis
+ self.def_node.needs_assignment_synthesis = lambda *args, **kwargs: False
+ self.def_node.analyse_declarations(env)
+ #super(GeneratorExpressionNode, self).analyse_declarations(env)
+ env.add_lambda_def(self.def_node)
+
+ def generate_result_code(self, code):
+ code.putln(
+ '%s = %s(%s, NULL); %s' % (
+ self.result(),
+ self.def_node.entry.func_cname,
+ self.self_result_code(),
+ code.error_goto_if_null(self.result(), self.pos)))
+ code.put_gotref(self.py_result())
+
+
class YieldExprNode(ExprNode):
# Yield expression node
#
def visit_ModuleNode(self, node):
self.lambda_counter = 1
+ self.genexpr_counter = 1
return super(PostParse, self).visit_ModuleNode(node)
def visit_LambdaNode(self, node):
self.visitchildren(node)
return node
+ def visit_GeneratorExpressionNode(self, node):
+ # unpack a generator expression into the corresponding DefNode
+ genexpr_id = self.genexpr_counter
+ self.genexpr_counter += 1
+ node.genexpr_name = EncodedString(u'genexpr%d' % genexpr_id)
+
+ node.def_node = Nodes.DefNode(node.pos, name=node.genexpr_name,
+ doc=None,
+ args=[], star_arg=None,
+ starstar_arg=None,
+ body=node.loop)
+ self.visitchildren(node)
+ return node
+
# cdef variables
def handle_bufferdefaults(self, decl):
if not isinstance(decl.default, ExprNodes.DictNode):