Number of arguments can grow with overridden cdef functions.
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 7 Feb 2008 12:00:51 +0000 (04:00 -0800)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 7 Feb 2008 12:00:51 +0000 (04:00 -0800)
Cython/Compiler/ExprNodes.py
Cython/Compiler/Nodes.py
Cython/Compiler/PyrexTypes.py
Cython/Compiler/Symtab.py

index 74a1cb919f6666c94ba9e67ced9663945a27a0a5..83f57e4747170badda1e7bc8ada8565c9f39e872 100644 (file)
@@ -1523,7 +1523,7 @@ class SimpleCallNode(ExprNode):
                 if func_type.has_varargs:
                     expected_str = "at least " + expected_str
                 elif func_type.optional_arg_count:
-                    if actual_nargs > max_nargs:
+                    if actual_nargs < max_nargs:
                         expected_str = "at least " + expected_str
                     else:
                         expected_str = "at most " + str(max_nargs)
@@ -1569,7 +1569,11 @@ class SimpleCallNode(ExprNode):
                 arg_list_code.append(arg_code)
         if func_type.optional_arg_count:
             if expected_nargs == actual_nargs:
-                arg_list_code.append(func_type.op_args.cast_code('NULL'))
+                if func_type.old_signature:
+                    struct_type = func_type.old_signature.op_args
+                else:
+                    struct_type = func_type.op_args
+                optional_args = struct_type.cast_code('NULL')
             else:
                 optional_arg_code = [str(actual_nargs - expected_nargs)]
                 for formal_arg, actual_arg in args[expected_nargs:actual_nargs]:
@@ -1578,7 +1582,11 @@ class SimpleCallNode(ExprNode):
 #                for formal_arg in formal_args[actual_nargs:max_nargs]:
 #                    optional_arg_code.append(formal_arg.type.cast_code('0'))
                 optional_arg_struct = '{%s}' % ','.join(optional_arg_code)
-                arg_list_code.append('&' + func_type.op_args.base_type.cast_code(optional_arg_struct))
+                optional_args = '&' + func_type.op_args.base_type.cast_code(optional_arg_struct)
+                if func_type.old_signature and \
+                        func_type.old_signature.op_args != func_type.op_args:
+                        optional_args = func_type.old_signature.op_args.cast_code(optional_args)
+            arg_list_code.append(optional_args)
         for actual_arg in self.args[len(formal_args):]:
             arg_list_code.append(actual_arg.result_code)
         result = "%s(%s)" % (self.function.result_code,
index 6f6ad2614818f31429e9d215bbcff050061774c0..fcc6acf2a680607d3a33a72ad039fb77ae559b5d 100644 (file)
@@ -345,7 +345,7 @@ class CFuncDeclaratorNode(CDeclaratorNode):
             scope.declare_var('n', PyrexTypes.c_int_type, self.pos)
             for arg in func_type_args[len(func_type_args)-self.optional_arg_count:]:
                 scope.declare_var(arg.name, arg.type, arg.pos, allow_pyobject = 1)
-            struct_cname = Naming.opt_arg_prefix + self.base.name
+            struct_cname = Naming.opt_arg_prefix + env.mangle(self.base.name)
             self.op_args_struct = env.global_scope().declare_struct_or_union(name = struct_cname,
                                         kind = 'struct',
                                         scope = scope,
index 9928dad771f42bf60d3680b9220bc8c9e2aa6c7d..ff3148cd27548c42ae97654cc71f9358e0cc570f 100644 (file)
@@ -584,6 +584,7 @@ class CFuncType(CType):
     #  with_gil         boolean    Acquire gil around function body
     
     is_cfunction = 1
+    old_signature = None
     
     def __init__(self, return_type, args, has_varargs = 0,
             exception_value = None, exception_check = 0, calling_convention = "",
@@ -648,6 +649,49 @@ class CFuncType(CType):
             return 0
         return 1
         
+    
+    def compatible_signature_with(self, other_type, as_cmethod = 0):
+        return self.compatible_signature_with_resolved_type(other_type.resolve(), as_cmethod)
+    
+    def compatible_signature_with_resolved_type(self, other_type, as_cmethod):
+        #print "CFuncType.same_c_signature_as_resolved_type:", \
+        #      self, other_type, "as_cmethod =", as_cmethod ###
+        if other_type is error_type:
+            return 1
+        if not other_type.is_cfunction:
+            return 0
+        if self.is_overridable != other_type.is_overridable:
+            return 0
+        nargs = len(self.args)
+        if nargs - self.optional_arg_count != len(other_type.args) - other_type.optional_arg_count:
+            return 0
+        if self.optional_arg_count < other_type.optional_arg_count:
+            return 0
+        # When comparing C method signatures, the first argument
+        # is exempt from compatibility checking (the proper check
+        # is performed elsewhere).
+        for i in range(as_cmethod, len(other_type.args)):
+            if not self.args[i].type.same_as(
+                other_type.args[i].type):
+                    return 0
+        if self.has_varargs != other_type.has_varargs:
+            return 0
+        if not self.return_type.same_as(other_type.return_type):
+            return 0
+        if not self.same_calling_convention_as(other_type):
+            return 0
+        self.old_signature = other_type
+        if as_cmethod:
+            self.args[0] = other_type.args[0]
+        if self.optional_arg_count and \
+                self.optional_arg_count == other_type.optional_arg_count:
+            self.op_args = other_type.op_args
+            print self.op_args, other_type.op_args, self.optional_arg_count, other_type.optional_arg_count
+        elif self.optional_arg_count:
+            print self.op_args, other_type.op_args, self.optional_arg_count, other_type.optional_arg_count
+        return 1
+        
+        
     def narrower_c_signature_than(self, other_type, as_cmethod = 0):
         return self.narrower_c_signature_than_resolved_type(other_type.resolve(), as_cmethod)
         
@@ -698,6 +742,7 @@ class CFuncType(CType):
                 arg.type.declaration_code("", for_display, pyrex = pyrex))
         if self.optional_arg_count:
             arg_decl_list.append(self.op_args.declaration_code(Naming.optional_args_cname))
+#            arg_decl_list.append(c_void_ptr_type.declaration_code(Naming.optional_args_cname))
         if self.has_varargs:
             arg_decl_list.append("...")
         arg_decl_code = string.join(arg_decl_list, ", ")
index aeeee9772073720e43104e4b47e1add80cf7dd7c..6b13e5407fe73501500a2618d25e4f70e0e51ff8 100644 (file)
@@ -1273,11 +1273,14 @@ class CClassScope(ClassScope):
                 if defining and entry.func_cname:
                     error(pos, "'%s' already defined" % name)
                 #print "CClassScope.declare_cfunction: checking signature" ###
-                if type.same_c_signature_as(entry.type, as_cmethod = 1):
-                    pass
+                if type.compatible_signature_with(entry.type, as_cmethod = 1):
+                    entry.type = type
+                elif type.same_c_signature_as(entry.type, as_cmethod = 1):
+                    print "not compatible", name
 #                if type.narrower_c_signature_than(entry.type, as_cmethod = 1):
 #                    entry.type = type
                 else:
+                    print "here"
                     error(pos, "Signature not compatible with previous declaration")
         else:
             if self.defined: