support for builtin iter(x, sentinel)
authorStefan Behnel <scoder@users.berlios.de>
Wed, 24 Feb 2010 13:23:58 +0000 (14:23 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Wed, 24 Feb 2010 13:23:58 +0000 (14:23 +0100)
Cython/Compiler/Builtin.py
Cython/Compiler/Optimize.py
tests/run/iter.pyx [new file with mode: 0644]

index b0ad215ed67ea732f041299f96746270e6208ed2..61bc1786411fc713b72cb146131e8b473ddcb1ed 100644 (file)
@@ -31,7 +31,7 @@ builtin_function_table = [
     ('intern',     "O",    "O",     "__Pyx_Intern"),
     ('isinstance', "OO",   "b",     "PyObject_IsInstance"),
     ('issubclass', "OO",   "b",     "PyObject_IsSubclass"),
-    ('iter',       "O",    "O",     "PyObject_GetIter"),
+    #('iter',       "O",    "O",     "PyObject_GetIter"),   # optimised later on
     ('len',        "O",    "Z",     "PyObject_Length"),
     ('locals',     "",     "O",     "__pyx_locals"),
     #('map',       "",     "",      ""),
index a3ef0966d34e0b7da6f4374c922641d49e21c70b..c3730cbe65ee6d31f4ba8200c7be029399eed7b4 100644 (file)
@@ -1173,6 +1173,32 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
             self._error_wrong_arg_count('getattr', node, pos_args, '2 or 3')
         return node
 
+    PyObject_GetIter_func_type = PyrexTypes.CFuncType(
+        PyrexTypes.py_object_type, [
+            PyrexTypes.CFuncTypeArg("object", PyrexTypes.py_object_type, None),
+            ])
+
+    PyCallIter_New_func_type = PyrexTypes.CFuncType(
+        PyrexTypes.py_object_type, [
+            PyrexTypes.CFuncTypeArg("object", PyrexTypes.py_object_type, None),
+            PyrexTypes.CFuncTypeArg("sentinel", PyrexTypes.py_object_type, None),
+            ])
+
+    def _handle_simple_function_iter(self, node, pos_args):
+        if len(pos_args) == 1:
+            return ExprNodes.PythonCapiCallNode(
+                node.pos, "PyObject_GetIter", self.PyObject_GetIter_func_type,
+                args = pos_args,
+                is_temp = node.is_temp)
+        elif len(pos_args) == 2:
+            return ExprNodes.PythonCapiCallNode(
+                node.pos, "PyCallIter_New", self.PyCallIter_New_func_type,
+                args = pos_args,
+                is_temp = node.is_temp)
+        else:
+            self._error_wrong_arg_count('iter', node, pos_args, '1 or 2')
+        return node
+
     Pyx_strlen_func_type = PyrexTypes.CFuncType(
         PyrexTypes.c_size_t_type, [
             PyrexTypes.CFuncTypeArg("bytes", PyrexTypes.c_char_ptr_type, None)
diff --git a/tests/run/iter.pyx b/tests/run/iter.pyx
new file mode 100644 (file)
index 0000000..2748fdd
--- /dev/null
@@ -0,0 +1,27 @@
+
+def call_iter1(x):
+    """
+    >>> [ i for i in iter([1,2,3]) ]
+    [1, 2, 3]
+    >>> [ i for i in call_iter1([1,2,3]) ]
+    [1, 2, 3]
+    """
+    return iter(x)
+
+class Ints(object):
+    def __init__(self):
+        self.i = 0
+    def __call__(self):
+        self.i += 1
+        if self.i > 10:
+            raise ValueError
+        return self.i
+
+def call_iter2(x, sentinel):
+    """
+    >>> [ i for i in iter(Ints(), 3) ]
+    [1, 2]
+    >>> [ i for i in call_iter2(Ints(), 3) ]
+    [1, 2]
+    """
+    return iter(x, sentinel)