fix 'self' argument type in generic builtin method overrides, test for None at call...
authorStefan Behnel <scoder@users.berlios.de>
Sun, 7 Nov 2010 09:10:31 +0000 (10:10 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Sun, 7 Nov 2010 09:10:31 +0000 (10:10 +0100)
Cython/Compiler/Builtin.py
Cython/Compiler/ExprNodes.py
Cython/Compiler/TypeSlots.py
tests/run/set.pyx

index e5226d7856ffe1237e01e522f4a575b01cf900f1..fbed2e3175cbc05078b07248516a177a2baf6026 100644 (file)
@@ -112,20 +112,20 @@ builtin_types_table = [
 
     ("tuple",   "PyTuple_Type",    []),
 
-    ("list",    "PyList_Type",     [("insert", "OzO",  "i", "PyList_Insert")]),
+    ("list",    "PyList_Type",     [("insert", "TzO",  "i", "PyList_Insert")]),
 
-    ("dict",    "PyDict_Type",     [("items", "O",   "O", "PyDict_Items"),
-                                    ("keys",  "O",   "O", "PyDict_Keys"),
-                                    ("values","O",   "O", "PyDict_Values"),
-                                    ("copy",  "O",   "O", "PyDict_Copy")]),
+    ("dict",    "PyDict_Type",     [("items", "T",   "O", "PyDict_Items"),
+                                    ("keys",  "T",   "O", "PyDict_Keys"),
+                                    ("values","T",   "O", "PyDict_Values"),
+                                    ("copy",  "T",   "O", "PyDict_Copy")]),
 
     ("slice",   "PySlice_Type",    []),
 #    ("file",    "PyFile_Type",     []),  # not in Py3
 
-    ("set",       "PySet_Type",    [("clear",   "O",  "i", "PySet_Clear"), 
-                                    ("discard", "OO", "i", "PySet_Discard"),
-                                    ("add",     "OO", "i", "PySet_Add"),
-                                    ("pop",     "O",  "O", "PySet_Pop")]),
+    ("set",       "PySet_Type",    [("clear",   "T",  "i", "PySet_Clear"), 
+                                    ("discard", "TO", "i", "PySet_Discard"),
+                                    ("add",     "TO", "i", "PySet_Add"),
+                                    ("pop",     "T",  "O", "PySet_Pop")]),
     ("frozenset", "PyFrozenSet_Type", []),
 ]
 
@@ -470,7 +470,11 @@ def init_builtin_types():
         builtin_types[name] = the_type
         for name, args, ret, cname in funcs:
             sig = Signature(args, ret)
-            the_type.scope.declare_cfunction(name, sig.function_type(), None, cname)
+            # override 'self' type (first argument)
+            self_arg = PyrexTypes.CFuncTypeArg("", the_type, None)
+            self_arg.not_none = True
+            method_type = sig.function_type(self_arg)
+            the_type.scope.declare_cfunction(name, method_type, None, cname)
 
 def init_builtin_structs():
     for name, cname, attribute_types in builtin_structs_table:
index 0bb334ded275918c66c9c8dc919eede9bd4ced18..5c63ff23dfc2dcfd4bd92d576f5cf8525ed3b41d 100755 (executable)
@@ -2836,7 +2836,11 @@ class SimpleCallNode(CallNode):
                 arg.analyse_types(env)
             if self.self and func_type.args:
                 # Coerce 'self' to the type expected by the method.
-                expected_type = func_type.args[0].type
+                self_arg = func_type.args[0]
+                if self_arg.not_none: # C methods must do the None test for self at *call* time
+                    self.self = self.self.as_none_safe_node(
+                        "'NoneType' object has no attribute '%s'" % self.function.entry.name)
+                expected_type = self_arg.type
                 self.coerced_self = CloneNode(self.self).coerce_to(
                     expected_type, env)
                 # Insert coerced 'self' argument into argument list.
index a85bbae1effb0a2e97cfa37e41630b4c5184d9e9..9f44eb4462b3216f4d4b9fbefa5b92922fd67f63 100644 (file)
@@ -100,12 +100,16 @@ class Signature(object):
     def exception_value(self):
         return self.error_value_map.get(self.ret_format)
     
-    def function_type(self):
+    def function_type(self, self_arg_override=None):
         #  Construct a C function type descriptor for this signature
         args = []
         for i in xrange(self.num_fixed_args()):
-            arg_type = self.fixed_arg_type(i)
-            args.append(PyrexTypes.CFuncTypeArg("", arg_type, None))
+            if self_arg_override is not None and self.is_self_arg(i):
+                assert isinstance(self_arg_override, PyrexTypes.CFuncTypeArg)
+                args.append(self_arg_override)
+            else:
+                arg_type = self.fixed_arg_type(i)
+                args.append(PyrexTypes.CFuncTypeArg("", arg_type, None))
         ret_type = self.return_type()
         exc_value = self.exception_value()
         return PyrexTypes.CFuncType(ret_type, args, exception_value = exc_value)
index d078a672b3c1a4b0bc9eaaae58396359f0ede9ab..343274a56cef4d6bb3e9274dcd062c7681affc9f 100644 (file)
@@ -56,6 +56,13 @@ def test_set_clear():
     s1.clear()
     return s1
 
+def test_set_clear_None():
+    """
+    >>> test_set_clear_None()
+    """
+    cdef set s1 = None
+    s1.clear()
+
 def test_set_list_comp():
     """
     >>> type(test_set_list_comp()) is _set