changeset 165:7606387b2f0a

Better handling of param checking on method calls.
author Anders Johnsen <skabet@gmail.com>
date Tue, 22 Jul 2008 18:24:15 +0200
parents ba94fd563548
children 9cfa33517526
files sema/TypeCheck.d tests/parser/new_1.d
diffstat 2 files changed, 91 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/sema/TypeCheck.d	Tue Jul 22 16:53:47 2008 +0200
+++ b/sema/TypeCheck.d	Tue Jul 22 18:24:15 2008 +0200
@@ -123,84 +123,48 @@
         
         Symbol[] methods = exp.newType.getSymbol.findMembers("this");
 
-        if ( exp.c_args.length )
+        if (!methods.length)
         {
-            if ( !methods.length )
-            {
-                messages.report(NoConstructor, exp.newType.loc);
-                return;
-            }
+            messages.report(NoConstructor, exp.newType.loc);
+            return;
+        }
+
+        Symbol sel = getBestMatch(exp.c_args, methods);
 
-            Symbol[] possible;
-            Symbol perfect;
-
-            foreach( s ; methods )
+        if (sel)
+        {
+            foreach (i, arg; exp.c_args)
             {
-                bool per = true;
-
-                foreach(i, arg; exp.c_args)
+                auto argType = sel.type.asFunction.params[i];
+                auto expType = arg.type;
+                if (argType.byteSize != expType.byteSize)
                 {
-                    auto argType = s.type.asFunction.params[i];
-                    auto expType = arg.type;
-                    if(argType != expType)
-                    {
-                        per = false;
-                        if( !expType.hasImplicitConversionTo(argType) )
-                            break;
-                    }
-
-                    if ( i == exp.c_args.length-1 
-                            && i == s.type.asFunction.params.length-1)
-                        if (per)
-                            perfect = s;
-                        else
-                            possible ~= s;
-                }
-            }
-
-            Symbol sel;
+                    if (!expType.hasImplicitConversionTo(argType))
+                        messages.report(InvalidImplicitCast, exp.loc)
+                            .arg(expType.toString)
+                            .arg(argType.toString);
 
-            if ( perfect )
-                sel = perfect;
-            else
-                if ( possible.length )
-                    sel = possible[0];
-
-            if ( sel )
+                    auto castExp = new CastExp(
+                            SLoc.Invalid,
+                            new Identifier(argType.name),
+                            arg);
+                    castExp.env = exp.newType.env;
+                    newArgs ~= castExp;
+                }
+                else
+                    newArgs ~= arg;
+            }
+            exp.c_args = newArgs;
+            exp.callSym = sel;
+        }
+        else
+        {
+            messages.report(NoMachingCon, exp.newType.loc);
+            foreach ( i, s ; methods )
             {
-                foreach(i, arg; exp.c_args)
-                {
-                    auto argType = sel.type.asFunction.params[i];
-                    auto expType = arg.type;
-                    if(argType.byteSize != expType.byteSize)
-                    {
-                        if(!expType.hasImplicitConversionTo(argType))
-                            messages.report(InvalidImplicitCast, exp.loc)
-                                .arg(expType.toString)
-                                .arg(argType.toString);
-
-                        auto castExp = new CastExp(
-                                SLoc.Invalid,
-                                new Identifier(argType.name),
-                                arg);
-                        castExp.env = exp.newType.env;
-                        newArgs ~= castExp;
-                    }
-                    else
-                        newArgs ~= arg;
-                }
-                exp.c_args = newArgs;
-                exp.callSym = sel;
-            }
-            else
-            {
-                messages.report(NoMachingCon, exp.newType.loc);
-                foreach( i, s ; methods )
-                {
-                    messages.report(CandidateNr, 
-                            (cast(FuncDecl)s.decl).identifier.loc)
-                        .arg(Integer.toString(i+1));
-                }
+                messages.report(CandidateNr, 
+                        (cast(FuncDecl)s.decl).identifier.loc)
+                    .arg(Integer.toString(i+1));
             }
         }
     }
@@ -278,6 +242,60 @@
         }
     }
 
+    private Symbol getBestMatch(Exp[] arg_list , Symbol[] available)
+    body
+    {
+        Symbol[] _a;
+        foreach (a ; available)
+            if (a.type.isFunction)
+                _a ~= a;
+        available = _a;
+
+        assert(available.length, "No available methods in symbol-list.");
+
+        Symbol[] possible;
+        Symbol perfect;
+
+        foreach (s ; available)
+        {
+            if (s.type.asFunction.params.length < arg_list.length)
+                continue;
+
+            bool per = true;
+
+            foreach (i, arg; arg_list)
+            {
+                auto argType = s.type.asFunction.params[i];
+                auto expType = arg.type;
+                if (argType != expType)
+                {
+                    per = false;
+                    if( !expType.hasImplicitConversionTo(argType) )
+                        break;
+                }
+
+                if (i == arg_list.length-1)
+                {
+                    bool work = true;
+                    foreach (a ; (cast(FuncDecl)s.decl).funcArgs[i+1..$])
+                        if (a.init is null)
+                            work = false;
+
+                    if (work)
+                        if (per)
+                            return s;
+                        else
+                            possible ~= s;
+                }
+            }
+        }
+
+        if (possible.length)
+            return possible[0];
+
+        return null;
+    }
+
     MessageHandler messages;
 }
 
--- a/tests/parser/new_1.d	Tue Jul 22 16:53:47 2008 +0200
+++ b/tests/parser/new_1.d	Tue Jul 22 18:24:15 2008 +0200
@@ -1,2 +1,2 @@
 class A{this(int y){}int x;}struct B
-{}void main(){B b;long x;A a=new A(x);}
+{}void main(){B b;long x;A a=new A(x);} int x = 5; int foo(){int y = 5; y = y + x * 5; return y;}