From 25432a57c991edf5775f75b7fc2cf3342bd293d7 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 27 May 2010 18:12:13 +0200 Subject: [PATCH] implement tuple(genexp) as tuple(list(genexp)) --- Cython/Compiler/Optimize.py | 15 +++++++++++++++ tests/run/inlined_generator_expressions.pyx | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 051a0b05..00c69c34 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -1186,6 +1186,21 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): gen_expr_node.pos, loop = exec_code, result_node = result_ref, expr_scope = gen_expr_node.expr_scope, orig_func = 'sum') + def _handle_simple_function_tuple(self, node, pos_args): + if len(pos_args) == 0: + return ExprNodes.TupleNode(node.pos, args=[], constant_result=()) + # This is a bit special - for iterables (including genexps), + # Python actually overallocates and resizes a newly created + # tuple incrementally while reading items, which we can't + # easily do without explicit node support. Instead, we read + # the items into a list and then copy them into a tuple of the + # final size. This takes up to twice as much memory, but will + # have to do until we have real support for genexps. + result = self._transform_list_set_genexpr(node, pos_args, ExprNodes.ListNode) + if result is not node: + return ExprNodes.AsTupleNode(node.pos, arg=result) + return node + def _handle_simple_function_list(self, node, pos_args): if len(pos_args) == 0: return ExprNodes.ListNode(node.pos, args=[], constant_result=[]) diff --git a/tests/run/inlined_generator_expressions.pyx b/tests/run/inlined_generator_expressions.pyx index 9e516531..3fd1bbde 100644 --- a/tests/run/inlined_generator_expressions.pyx +++ b/tests/run/inlined_generator_expressions.pyx @@ -1,6 +1,14 @@ cimport cython +def range_tuple_genexp(int N): + """ + >>> range_tuple_genexp(5) + (0, 1, 2, 3, 4) + """ + return tuple(i for i in range(N)) + + @cython.test_assert_path_exists('//ForFromStatNode', "//InlinedGeneratorExpressionNode") @cython.test_fail_if_path_exists('//SimpleCallNode', @@ -15,6 +23,7 @@ def range_sum(int N): result = sum(i for i in range(N)) return result + @cython.test_assert_path_exists('//ForFromStatNode', "//InlinedGeneratorExpressionNode") @cython.test_fail_if_path_exists('//SimpleCallNode', @@ -30,6 +39,7 @@ def range_sum_typed(int N): cdef int result = sum(i for i in range(N)) return result + @cython.test_assert_path_exists('//ForFromStatNode', "//InlinedGeneratorExpressionNode", "//ReturnStatNode//InlinedGeneratorExpressionNode", @@ -47,6 +57,7 @@ def return_range_sum_cast(int N): """ return sum(i for i in range(N)) + @cython.test_assert_path_exists('//ForFromStatNode', "//InlinedGeneratorExpressionNode") @cython.test_fail_if_path_exists('//SimpleCallNode', @@ -60,6 +71,7 @@ def return_range_sum(int N): """ return sum(i for i in range(N)) + @cython.test_assert_path_exists('//ForFromStatNode', "//InlinedGeneratorExpressionNode") @cython.test_fail_if_path_exists('//SimpleCallNode', @@ -78,6 +90,7 @@ def return_range_sum_squares(int N): """ return sum(i*i for i in range(N)) + @cython.test_assert_path_exists('//ForInStatNode', "//InlinedGeneratorExpressionNode") @cython.test_fail_if_path_exists('//SimpleCallNode') @@ -95,6 +108,7 @@ def return_sum_squares(seq): """ return sum(i*i for i in seq) + @cython.test_assert_path_exists('//ForInStatNode', "//InlinedGeneratorExpressionNode") @cython.test_fail_if_path_exists('//SimpleCallNode') -- 2.26.2