changeset 168:7982eb63c0eb

Some changes to get function overloading to work. Also class inherit works now - to some extend. needs vtables and all the complex stuff of it.
author Anders Johnsen <skabet@gmail.com>
date Thu, 24 Jul 2008 12:06:48 +0200
parents 9cfa33517526
children b4aab11a02df
files ast/Exp.d basic/Messages.d dang/compiler.d sema/ObjectOriented.d sema/Scope.d sema/ScopeBuilder.d sema/ScopeCheck.d sema/Symbol.d sema/TypeCheck.d tests/sema/class_1.d tests/sema/function_overload_1.d
diffstat 11 files changed, 286 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Exp.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/ast/Exp.d	Thu Jul 24 12:06:48 2008 +0200
@@ -115,6 +115,7 @@
 
     Exp exp;
     Exp[] args;
+    Symbol callSym;
     bool sret = false;
 
     override SourceRange sourceRange()
@@ -389,16 +390,16 @@
 
         if ( target.type.isStruct )
         {
-            DStruct st = target.type.asStruct;
-            if (auto t = st.typeOf(child.name))
-                myType = t;
+            Symbol st = target.getSymbol;
+            if (auto t = st.findMembers(child.name))
+                myType = t[0].type;
 //            else assert(0, "Referencing non-existant member");
         }
         else if ( target.type.isClass )
         {
-            DClass cl = target.type.asClass;
-            if (auto t = cl.typeOf(child.name))
-                myType = t;
+            Symbol cl = target.getSymbol;
+            if (auto t = cl.findMembers(child.name))
+                myType = t[0].type;
 //            else assert(0, "Referencing non-existant member");
         }
         else
@@ -605,9 +606,9 @@
     override Symbol getSymbol()
     {
         if (auto decl = env.find(this.get))
-            return decl.sym;
-        else
-            return null;
+            if(decl.length)
+                return decl[$-1].sym;
+        return null;
     }
 
     override DType type()
--- a/basic/Messages.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/basic/Messages.d	Thu Jul 24 12:06:48 2008 +0200
@@ -41,6 +41,8 @@
     NoConstructor,
     NoMachingCon,
     CandidateNr,
+    NoMethodByName,
+    NoMachingMethod,
 
     // Strings
     InvalidStrPrefix,
@@ -113,6 +115,8 @@
         NoConstructor       : E(Err, "No constructor avaible"),
         NoMachingCon        : E(Err, "No maching constructor. Candidates are:"),
         CandidateNr         : E(Err, "Candidate number %0"),
+        NoMethodByName      : E(Err, "No method with that name"),
+        NoMachingMethod     : E(Err, "No maching method. Candidates are:"),
         //   - switch
         MultipleDefaults
             : E(Err, "Switch statements can't have multiple defaults"),
--- a/dang/compiler.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/dang/compiler.d	Thu Jul 24 12:06:48 2008 +0200
@@ -29,6 +29,7 @@
        sema.LiteralInterpreter,
        sema.ScopeCheck,
        sema.VC,
+       sema.ObjectOriented,
        sema.TypeCheck;
 
 import tango.stdc.posix.unistd;
@@ -320,6 +321,11 @@
     auto type_check = watch2.stop;
 
     watch2.start;
+    (new ObjectOriented(messages)).visit(modules);
+    messages.checkErrors;
+    auto object_check = watch2.stop;
+
+    watch2.start;
     auto vc = new VC;
     vc.msg = messages;
     foreach (m; modules)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sema/ObjectOriented.d	Thu Jul 24 12:06:48 2008 +0200
@@ -0,0 +1,64 @@
+module sema.ObjectOriented;
+
+import sema.Visitor,
+       sema.Symbol,
+       sema.DType;
+
+import tango.io.Stdout,
+       Array = tango.core.Array;
+
+import basic.SourceLocation,
+       basic.Message;
+
+class ObjectOriented : Visitor!(void)
+{
+    this(MessageHandler messages)
+    {
+        this.messages = messages;
+    }
+
+    override void visit(Module[] m)
+    {
+        super.visit(m);
+
+        ClassDecl[] visitBaseClass(ClassDecl current, ClassDecl[] visited)
+        {
+            visited ~= current;
+            foreach (d ; current.baseClasses)
+                if (d.type.isClass)
+                    if(Array.find(visited,
+                                (cast(ClassDecl)d.getSymbol.decl)) - visited.length)
+                        assert(0,"Circulair base class");
+                    else
+                        return visitBaseClass((cast(ClassDecl)d.getSymbol.decl), visited);
+            return visited;
+        }
+
+        while (classes.length)
+        {
+            ClassDecl current = classes[$-1];
+            ClassDecl[] visited;
+            visited = visitBaseClass(current, visited);
+            foreach (v; visited)
+                classes.length = Array.remove(classes, v);
+        }
+    }
+
+    override void visitClassDecl(ClassDecl decl)
+    {
+        classes ~= decl;
+    }
+
+    ClassDecl[] classNoBase;
+    ClassDecl[] classes;
+    MessageHandler messages;
+}
+
+class FindClassNoBase : Visitor!(void)
+{
+    override void visitClassDecl(ClassDecl decl)
+    {
+    }
+
+    ClassDecl[] classes;
+}
--- a/sema/Scope.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/sema/Scope.d	Thu Jul 24 12:06:48 2008 +0200
@@ -30,23 +30,23 @@
 
     void put(char[] id, Decl d)
     {
-        symbols[id] = d;
+        symbols[id] ~= d;
     }
 
-    Decl find(char[] id)
+    Decl[] find(char[] id)
     {
-        if(id is null)
+        if(id is "")
             return null;
         else if (auto sym = id in symbols)
+        {
             return *sym;
+        }
         else if (enclosing !is null)
         {
-            auto res = enclosing.find(id);
-            if (res is null)
-                return mHandle.find(getImports, id);
+            auto res = enclosing.find(id) ~ mHandle.find(getImports, id);
             return res;
         }
-        return null;
+        return [];
     }
 
     ImportDecl[] getImports()
@@ -110,7 +110,7 @@
     DType[char[]] types;
     int currentStmtIndex = -1;
 private:
-    Decl[char[]] symbols;
+    Decl[][char[]] symbols;
     FuncDecl func;
 }
 
@@ -138,7 +138,7 @@
         return null;
     }
 
-    Decl find(ImportDecl[] imports, char[] id)
+    Decl[] find(ImportDecl[] imports, char[] id)
     {
         foreach(i ; imports)
             if(i.get in modules)
@@ -147,7 +147,7 @@
                 if(t !is null)
                     return t;
             }
-        return null;
+        return [];
     }
 
     char[][char[]] fileToModule;
--- a/sema/ScopeBuilder.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/sema/ScopeBuilder.d	Thu Jul 24 12:06:48 2008 +0200
@@ -64,7 +64,7 @@
         DType t = typeOf(d.varType, d.env);
         d.sym = current.symbol.createAlias(
                 d.identifier.get,
-                d.env.find(d.varType.get).sym,
+                d.env.find(d.varType.get)[0].sym,
                 d);
         d.sym.type = t;
     }
@@ -131,7 +131,7 @@
         s.sym = current.symbol.createMember(
                 s.identifier.get, 
                 st,
-                s.env.find(s.identifier.get));
+                s.env.find(s.identifier.get)[0]);
 
         foreach (decl; s.decls)
         {
@@ -158,7 +158,7 @@
         s.sym = current.symbol.createMember(
                 s.identifier.get, 
                 st,
-                s.env.find(s.identifier.get));
+                s.env.find(s.identifier.get)[0]);
 
         foreach (decl; s.decls)
         {
@@ -185,7 +185,7 @@
         s.sym = current.symbol.createMember(
                 s.identifier.get, 
                 st,
-                s.env.find(s.identifier.get));
+                s.env.find(s.identifier.get)[0]);
 
         foreach (decl; s.decls)
         {
--- a/sema/ScopeCheck.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/sema/ScopeCheck.d	Thu Jul 24 12:06:48 2008 +0200
@@ -39,7 +39,7 @@
                 if (d.env.parentFunction !is null)
                     while( d.env.parentFunction.env !is env)
                     {
-                        if (d.env.enclosing.find(d.identifier.get).env == env)
+                        if (d.env.enclosing.find(d.identifier.get)[0].env == env)
                             messages.report(CannotRedeclare, d.identifier.loc)
                                 .arg(d.identifier.get);
                         env = env.enclosing;
@@ -74,40 +74,31 @@
 
     private Symbol internalVisitMemberRef(MemberReference m)
     {
+        Symbol visitRef(MemberReference m, Identifier target, Symbol st)
+        {
+            auto child = m.child;
+            auto res = st.findMembers(child.get);
+
+            if(!res.length)
+                messages.report(MissingMember, m.loc)
+                    .arg(st.type.name)
+                    .arg(target.get)
+                    .arg(child.get);
+            else
+                internalCheckProtection(res[0], child);
+
+            return res.length ? res[0] : null;
+        }
         switch(m.target.expType)
         {
             case ExpType.Identifier:
-                auto target = cast(Identifier)m.target;
-                auto child = m.child;
-                auto st = target.getSymbol;
-                auto res = st.findMembers(child.get);
-
-                if(!res.length)
-                    messages.report(MissingMember, m.loc)
-                        .arg(st.type.name)
-                        .arg(target.get)
-                        .arg(child.get);
-                else
-                    internalCheckProtection(res[0], child);
-
-                return res.length ? res[0] : null;
+                return visitRef(m, cast(Identifier)m.target,
+                        (cast(Identifier)m.target).getSymbol);
             case ExpType.MemberReference:
                 Symbol s = internalVisitMemberRef(cast(MemberReference)m.target);
                 if(!s)
                     return null;
-                auto target = cast(Identifier)m.target;
-                auto child = m.child;
-                auto res = s.findMembers(child.get);
-
-                if(!res.length)
-                    messages.report(MissingMember, m.loc)
-                        .arg(s.type.name)
-                        .arg(target.get)
-                        .arg(child.get);
-                else
-                    internalCheckProtection(res[0], child);
-
-                return res.length ? res[0] : null;
+                return visitRef(m, cast(Identifier)m.target, s);
         }
     }
 
@@ -118,7 +109,7 @@
         {
             if (exp.env.findType((cast(Identifier)exp).get) is null)
                 internalCheckProtection(
-                    exp.env.find((cast(Identifier)exp).get).sym, 
+                    exp.env.find((cast(Identifier)exp).get)[0].sym, 
                     cast(Identifier)exp);
         }
 
--- a/sema/Symbol.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/sema/Symbol.d	Thu Jul 24 12:06:48 2008 +0200
@@ -40,8 +40,7 @@
     }
 
     /**
-      Try to find a contained symbol with the given name - returns null if not
-      found
+      Try to find a contained symbol with the given name
      **/
     Symbol[] findMembers(char[] member)
     {
@@ -49,6 +48,25 @@
         foreach (possible; actual.contained)
             if (possible.name == member)
                 res ~= possible;
+
+        if (!res.length && actual.type.isClass)
+        {
+            foreach (base ; (cast(ClassDecl)actual.decl).baseClasses)
+                if (base.type.isClass)
+                    res ~= base.getSymbol.findMembers(member);
+        }
+        return res;
+    }
+
+    /**
+      Try to find a contained symbol with the given name, who's type is a DFunction
+     **/
+    Symbol[] findFunctionMembers(char[] member)
+    {
+        Symbol[] res;
+        foreach (possible; actual.contained)
+            if (possible.name == member && possible.type.isFunction)
+                res ~= possible;
         return res;
     }
 
@@ -103,6 +121,11 @@
     // to that symbol
     Symbol parent;
 
+    char[] toString()
+    {
+        return getMangledFQN;
+    }
+
 private:
     // Helper for getMangledFQN - gets the FQN without _D and the type
     char[] internalFQN()
--- a/sema/TypeCheck.d	Tue Jul 22 21:34:53 2008 +0200
+++ b/sema/TypeCheck.d	Thu Jul 24 12:06:48 2008 +0200
@@ -88,31 +88,89 @@
     {
         super.visitCallExp(exp);
 
-        Exp[] newArgs;
-
-        foreach(i, arg; exp.args)
+        if (auto iden = cast(Identifier)exp.exp)
         {
-            auto argType = exp.exp.type.asFunction.params[i];
-            auto expType = arg.type;
-            if(argType.byteSize != expType.byteSize)
+            Exp[] newArgs;
+
+            Symbol[] methods;
+            
+            foreach (decl ; iden.env.find(iden.get))
+                methods ~= decl.sym;
+
+            if (!methods.length)
+            {
+                messages.report(NoMethodByName, iden.loc);
+                return;
+            }
+
+            Symbol sel = getBestMatch(exp.args, methods);
+
+            if (sel)
             {
-                if(!expType.hasImplicitConversionTo(argType))
-                   messages.report(InvalidImplicitCast, exp.loc)
-                        .arg(expType.toString)
-                        .arg(argType.toString);
+                foreach (i, arg; exp.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.exp.env;
-                newArgs ~= castExp;
+                        auto castExp = new CastExp(
+                                SLoc.Invalid,
+                                new Identifier(argType.name),
+                                arg);
+                        castExp.env = iden.env;
+                        newArgs ~= castExp;
+                    }
+                    else
+                        newArgs ~= arg;
+                }
+                exp.args = newArgs;
+                exp.callSym = sel;
             }
             else
-                newArgs ~= arg;
+            {
+                messages.report(NoMachingMethod, exp.loc);
+                foreach ( i, s ; methods )
+                {
+                    messages.report(CandidateNr, 
+                            (cast(FuncDecl)s.decl).identifier.loc)
+                        .arg(Integer.toString(i+1));
+                }
+            }
+
         }
+        else
+        {
+            Exp[] newArgs;
 
-        exp.args = newArgs;
+            foreach(i, arg; exp.args)
+            {
+                auto argType = exp.exp.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.exp.env;
+                    newArgs ~= castExp;
+                }
+                else
+                    newArgs ~= arg;
+            }
+
+            exp.args = newArgs;
+        }
     }
 
     override void visitNewExp(NewExp exp)
@@ -121,7 +179,7 @@
 
         Exp[] newArgs;
         
-        Symbol[] methods = exp.newType.getSymbol.findMembers("this");
+        Symbol[] methods = exp.newType.getSymbol.findFunctionMembers("this");
 
         if (!methods.length)
         {
@@ -243,14 +301,13 @@
     }
 
     private Symbol getBestMatch(Exp[] arg_list , Symbol[] available)
+    in
+    {
+        foreach (a ; available)
+            assert(a.type.isFunction, "A non-function found in available-list.");
+    }
     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;
@@ -262,6 +319,7 @@
                 continue;
 
             bool per = true;
+            bool work = true;
 
             foreach (i, arg; arg_list)
             {
@@ -271,23 +329,22 @@
                 {
                     per = false;
                     if( !expType.hasImplicitConversionTo(argType) )
+                    {
+                        work = false;
                         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;
+                    }
                 }
             }
+
+            foreach (a ; (cast(FuncDecl)s.decl).funcArgs[arg_list.length..$])
+                if (a.init is null)
+                    work = false;
+
+            if (work)
+                if (per)
+                    return s;
+                else
+                    possible ~= s;
         }
 
         if (possible.length)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/sema/class_1.d	Thu Jul 24 12:06:48 2008 +0200
@@ -0,0 +1,35 @@
+
+class A
+{
+    this()
+    {
+    }
+
+    int foo()
+    {
+        return 1;
+    }
+
+    int boo()
+    {
+        return 0;
+    }
+}
+
+class B : A
+{
+    this()
+    {
+    }
+
+    int foo()
+    {
+        return 0;
+    }
+}
+
+int main()
+{
+    B a = new B();
+    return a.foo() + a.boo();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/sema/function_overload_1.d	Thu Jul 24 12:06:48 2008 +0200
@@ -0,0 +1,12 @@
+
+
+void main()
+{
+    int x = 5;
+    foo(x);
+    long y = 12;
+    foo(y);
+}
+
+int foo(long x);
+int foo(int x);