From 18560bcca44f9f0fd2444a5b01b596e6e326d0e1 Mon Sep 17 00:00:00 2001
From: DaniloFreitas <dsurviver@gmail.com>
Date: Wed, 8 Jul 2009 05:44:31 -0300
Subject: [PATCH] Function overloading

---
 Cython/Compiler/ExprNodes.py | 45 +++++++++++++++++++++++++-----------
 Cython/Compiler/Symtab.py    | 11 +++++++--
 2 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index 1ef923cbe..0bb7be59e 100755
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -1090,6 +1090,7 @@ class NewExprNode(AtomicExprNode):
             print "no constructor declared"
             # create one
         self.class_entry = entry
+        self.entry = constructor
         self.type = constructor.type
    
     def generate_result_code(self, code):
@@ -2387,6 +2388,7 @@ class SimpleCallNode(CallNode):
                     expected_type, env)
                 # Insert coerced 'self' argument into argument list.
                 self.args.insert(0, self.coerced_self)
+            entry = self.function.entry
             self.analyse_c_function_call(env)
     
     def function_type(self):
@@ -2407,6 +2409,22 @@ class SimpleCallNode(CallNode):
             self.type = PyrexTypes.error_type
             self.result_code = "<error>"
             return
+        if not self.analyse_args(env, func_type):
+            entry = self.function.entry
+            has_overloaded = 0
+            for overloaded in entry.overloaded_alternatives:
+                if self.analyse_args(env, overloaded.type.base_type):
+                    has_overloaded = 1
+                    break
+            if not has_overloaded:
+                error(self.pos, "Call with wrong number of arguments")
+                #    "Call with wrong number of arguments (expected %s, got %s)"
+                #        % (expected_str, actual_nargs))
+                self.args = None
+                self.type = PyrexTypes.error_type
+                self.result_code = "<error>"            
+
+    def analyse_args(self, env, func_type):
         # Check no. of args
         max_nargs = len(func_type.args)
         expected_nargs = max_nargs - func_type.optional_arg_count
@@ -2421,18 +2439,13 @@ class SimpleCallNode(CallNode):
                         expected_str = "at least " + expected_str
                     else:
                         expected_str = "at most " + str(max_nargs)
-                error(self.pos, 
-                    "Call with wrong number of arguments (expected %s, got %s)"
-                        % (expected_str, actual_nargs))
-                self.args = None
-                self.type = PyrexTypes.error_type
-                self.result_code = "<error>"
-                return
-        if func_type.optional_arg_count and expected_nargs != actual_nargs:
-            self.has_optional_args = 1
-            self.is_temp = 1
-            self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
-            env.release_temp(self.opt_arg_struct)
+                #error(self.pos, 
+                #    "Call with wrong number of arguments (expected %s, got %s)"
+                #        % (expected_str, actual_nargs))
+                #self.args = None
+                #self.type = PyrexTypes.error_type
+                #self.result_code = "<error>"
+                return 0
         # Coerce arguments
         for i in range(min(max_nargs, actual_nargs)):
             formal_type = func_type.args[i].type
@@ -2459,7 +2472,13 @@ class SimpleCallNode(CallNode):
         # Check gil
         if not func_type.nogil:
             self.gil_check(env)
-
+        if func_type.optional_arg_count and expected_nargs != actual_nargs:
+            self.has_optional_args = 1
+            self.is_temp = 1
+            self.opt_arg_struct = env.allocate_temp(func_type.op_arg_struct.base_type)
+            env.release_temp(self.opt_arg_struct)
+        return 1
+    
     def calculate_result_code(self):
         return self.c_call_code()
     
diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py
index c18631138..a971803b6 100644
--- a/Cython/Compiler/Symtab.py
+++ b/Cython/Compiler/Symtab.py
@@ -172,6 +172,7 @@ class Entry(object):
         self.type = type
         self.pos = pos
         self.init = init
+        self.overloaded_alternatives = []
         
     def redeclared(self, pos):
         error(pos, "'%s' does not match previous declaration" % self.name)
@@ -301,16 +302,22 @@ class Scope(object):
             # See http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html#Reserved-Names 
             warning(pos, "'%s' is a reserved name in C." % cname, -1)
         entries = self.entries
+        overloaded = False
         if name and name in entries:
             if visibility == 'extern':
                 warning(pos, "'%s' redeclared " % name, 0)
             elif visibility != 'ignore':
-                error(pos, "'%s' redeclared " % name)
+                overloaded = True
+                #error(pos, "'%s' redeclared " % name)
         entry = Entry(name, cname, type, pos = pos)
         entry.in_cinclude = self.in_cinclude
         if name:
             entry.qualified_name = self.qualify_name(name)
-            entries[name] = entry
+            if overloaded:
+                entries[name].overloaded_alternatives.append(entry)
+                #print entries[name].overloaded_alternatives
+            else:
+                entries[name] = entry
         entry.scope = self
         entry.visibility = visibility
         return entry
-- 
2.30.9