From 66ffb55cd6fccfc628e374c1b36b56123e5926f1 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 19 Dec 2008 03:05:14 +0100 Subject: [PATCH] use a straight call to PyList_Tuple() on code like tuple([...]) --- Cython/Compiler/Optimize.py | 36 ++++++++++++++++++++++++++++++++++++ tests/run/tuple.pyx | 13 +++++++++++++ 2 files changed, 49 insertions(+) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 1f2836dc..1ddd9886 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -426,6 +426,16 @@ class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations): class FlattenBuiltinTypeCreation(Visitor.VisitorTransform): """Optimise some common instantiation patterns for builtin types. """ + PyList_AsTuple_func_type = PyrexTypes.CFuncType( + PyrexTypes.py_object_type, [ + PyrexTypes.CFuncTypeArg("list", Builtin.list_type, None) + ]) + + PyList_AsTuple_name = EncodedString("PyList_AsTuple") + + PyList_AsTuple_entry = Symtab.Entry( + PyList_AsTuple_name, PyList_AsTuple_name, PyList_AsTuple_func_type) + def visit_GeneralCallNode(self, node): self.visitchildren(node) handler = self._find_handler('general', node.function) @@ -486,6 +496,32 @@ class FlattenBuiltinTypeCreation(Visitor.VisitorTransform): else: return node + def _handle_simple_tuple(self, node, pos_args, kwargs): + """Replace tuple([...]) by a call to PyList_AsTuple. + """ + if not isinstance(pos_args, ExprNodes.TupleNode): + return node + if len(pos_args.args) != 1: + return node + list_arg = pos_args.args[0] + if list_arg.type is not Builtin.list_type: + return node + if not isinstance(list_arg, (ExprNodes.ComprehensionNode, + ExprNodes.ListNode)): + # everything else may be None => take the safe path + return node + + node.args = pos_args.args + node.arg_tuple = None + node.type = Builtin.tuple_type + node.result_ctype = Builtin.tuple_type + node.function = ExprNodes.NameNode( + pos = node.pos, + name = self.PyList_AsTuple_name, + type = self.PyList_AsTuple_func_type, + entry = self.PyList_AsTuple_entry) + return node + def visit_PyTypeTestNode(self, node): """Flatten redundant type checks after tree changes. """ diff --git a/tests/run/tuple.pyx b/tests/run/tuple.pyx index 48473112..869107a2 100644 --- a/tests/run/tuple.pyx +++ b/tests/run/tuple.pyx @@ -11,6 +11,12 @@ __doc__ = u""" (2, 3, 4) >>> l(1,2,3,4,5) (17, 42, 88) + >>> tuple_none() + Traceback (most recent call last): + TypeError: 'NoneType' object is not iterable + >>> tuple_none_list() + Traceback (most recent call last): + TypeError: 'NoneType' object is not iterable """ def f(obj1, obj2, obj3, obj4, obj5): @@ -51,3 +57,10 @@ def l(obj1, obj2, obj3, obj4, obj5): obj1 = (obj2, obj3, obj4,) obj1 = 17, 42, 88 return obj1 + +def tuple_none(): + return tuple(None) + +def tuple_none_list(): + cdef list none = None + return tuple(none) -- 2.26.2