changeset 158:57b0b4464a0b

Parsing "new", putting it in AST and performs some tests on it. Eg. if the contructor exists and the params matches.
author Anders Johnsen <skabet@gmail.com>
date Tue, 22 Jul 2008 00:33:58 +0200
parents bb01c1dc452a
children a2d9121d6dff
files ast/Exp.d basic/Messages.d lexer/Keyword.d lexer/Token.d parser/Action.d parser/Parser.d sema/AstAction.d sema/ScopeBuilder.d sema/ScopeCheck.d sema/Symbol.d sema/TypeCheck.d sema/Visitor.d tools/AstPrinter.d
diffstat 13 files changed, 251 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Exp.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/ast/Exp.d	Tue Jul 22 00:33:58 2008 +0200
@@ -31,6 +31,7 @@
     CallExp,
     CastExp,
     StringExp,
+    NewExp,
 }
 
 abstract class Exp
@@ -371,7 +372,7 @@
     {
         auto s = target.getSymbol();
         if (s !is null)
-            return s.findMember(child.get);
+            return s.findMembers(child.get)[0];
         return null;
     }
 
@@ -489,6 +490,25 @@
     char[] str;
 }
 
+class NewExp : Exp
+{
+    this(Identifier newType, Exp[] a_args, Exp[] c_args)
+    {
+        super(ExpType.NewExp, newType.loc);
+        this.newType = newType;
+        this.a_args = a_args;
+        this.c_args = c_args;
+    }
+
+    override DType type() 
+    { 
+        return env.findType(this.newType.get); 
+    }
+
+    Exp[] a_args, c_args;
+    Identifier newType;
+}
+
 class PointerIdentifier : Identifier
 {
     this(Identifier pointerOf)
--- a/basic/Messages.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/basic/Messages.d	Tue Jul 22 00:33:58 2008 +0200
@@ -38,6 +38,9 @@
     MultipleDefaults,
     OverlappingCases,
     InvalidCaseValue,
+    NoConstructor,
+    NoMachingCon,
+    CandidateNr,
 
     // Strings
     InvalidStrPrefix,
@@ -107,6 +110,9 @@
         UndefinedType       : E(Err, "Undefined type '%0'"),
         MissingMember       : E(Err, "%0 %1 has no member %2"),
         CannotRedeclare     : E(Err, "Cannot redeclare '%0'"),
+        NoConstructor       : E(Err, "No constructor avaible"),
+        NoMachingCon        : E(Err, "No maching constructor. Candidates are:"),
+        CandidateNr         : E(Err, "Candidate number %0"),
         //   - switch
         MultipleDefaults
             : E(Err, "Switch statements can't have multiple defaults"),
--- a/lexer/Keyword.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/lexer/Keyword.d	Tue Jul 22 00:33:58 2008 +0200
@@ -46,6 +46,7 @@
         "sizeof"    : Tok.Sizeof,
         "alias"     : Tok.Alias,
         "this"      : Tok.This,
+        "new"       : Tok.New,
 //        "super"     : Tok.Super,
 
         // control flow
--- a/lexer/Token.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/lexer/Token.d	Tue Jul 22 00:33:58 2008 +0200
@@ -207,6 +207,8 @@
 
     Module, Import,
 
+    New,
+
     /* Attributes */
     Public, Private, Package, Export, Protected,
     Static,
@@ -311,6 +313,7 @@
         Tok.Override:"Override",
         Tok.Deprecated:"Deprecated",
         Tok.Auto:"Auto",
-        Tok.Extern:"Extern"
+        Tok.Extern:"Extern",
+        Tok.New:"New"
     ];
 }
--- a/parser/Action.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/parser/Action.d	Tue Jul 22 00:33:58 2008 +0200
@@ -386,7 +386,7 @@
     /**
       Called when function calls are encountered.
      */
-    ExprT actOnIndexEpr(ExprT array, ref Token left_bracket, ExprT index,
+    ExprT actOnIndexExpr(ExprT array, ref Token left_bracket, ExprT index,
                         ref Token right_bracket)
     {
         return null;
@@ -399,6 +399,14 @@
     {
         return null;
     }
+
+    /**
+      New expression.
+     */
+    ExprT actOnNewExpr(ref Id type, ExprT[] a_args, ExprT[] c_args)
+    {
+        return null;
+    }
 }
 
 /**
--- a/parser/Parser.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/parser/Parser.d	Tue Jul 22 00:33:58 2008 +0200
@@ -368,6 +368,7 @@
                 case Tok.This:
                     auto id = Id(next);
                     auto m_decl = parseFunc(iden, id, nes[$-1].a);
+                    action.actOnClassMember(decl, m_decl);
                     break;
                     
                 default:
@@ -920,7 +921,7 @@
                 Token open = next();
                 Exp index = parseExpression();
                 Token close = require(Tok.CloseBracket);
-                return action.actOnIndexEpr(target, open, index, close);
+                return action.actOnIndexExpr(target, open, index, close);
             default:
                 return target;
         }
@@ -983,6 +984,50 @@
             return action.actOnNumericConstant(n);
         else if (n.type == Tok.String)
             return action.actOnStringExp(n);
+        else if (n.type == Tok.New)
+        {
+            Exp[] allocator_args;
+            Exp[] constructor_args;
+
+            if ( isa(Tok.OpenParentheses))
+            {
+                next(); // Remove OpenParentheses
+
+                if ( !isa(Tok.CloseParentheses ) )
+                {
+                    allocator_args ~= parseExpression;
+                
+                    while ( isa(Tok.Comma) )
+                    {
+                        next(); // Remove Comma 
+
+                        allocator_args ~= parseExpression;
+                    }
+                }
+                require(Tok.CloseParentheses);
+            }
+
+            auto type = parseType;
+
+            if ( isa(Tok.OpenParentheses))
+            {
+                next(); // Remove OpenParentheses
+
+                if ( !isa(Tok.CloseParentheses ) )
+                {
+                    constructor_args ~= parseExpression;
+
+                    while ( isa(Tok.Comma) )
+                    {
+                        next(); // Remove Comma 
+
+                        constructor_args ~= parseExpression;
+                    }
+                }
+                require(Tok.CloseParentheses);
+            }
+            return action.actOnNewExpr(type, allocator_args, constructor_args);
+        }
 
         messages.report(ExpectedExp, n.location)
             .fatal(ExitLevel.Parser);
--- a/sema/AstAction.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/sema/AstAction.d	Tue Jul 22 00:33:58 2008 +0200
@@ -287,13 +287,20 @@
         return new CastExp(_cast.location, target_type, target);
     }
 
-    ExprT
-        actOnIndexEpr(ExprT arr, ref Token lb, ExprT index, ref Token rb)
+    ExprT actOnIndexExpr(ExprT arr, ref Token lb, ExprT index, ref Token rb)
     {
         Exp target = cast(Exp)arr;
         Exp idx = cast(Exp)index;
         return new IndexExp(target, lb.location, idx, rb.location);
     }
+
+    ExprT actOnNewExpr(ref Id type, ExprT[] a_args, ExprT[] c_args)
+    {
+        auto id = identifierFromTok(type.tok);
+        Exp[] _a_args = cast(Exp[])a_args;
+        Exp[] _c_args = cast(Exp[])c_args;
+        return new NewExp(id, _a_args, _c_args);
+    }
 }
 }
 
--- a/sema/ScopeBuilder.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/sema/ScopeBuilder.d	Tue Jul 22 00:33:58 2008 +0200
@@ -43,7 +43,7 @@
         d.sym = current.symbol.createMember(
                 d.identifier.get, 
                 d.type, 
-                d.env.find(d.identifier.get));
+                d);
     }
 
     override void visitVarDecl(VarDecl d)
@@ -58,7 +58,7 @@
         d.sym = current.symbol.createAlias(
                 d.identifier.get,
                 d.env.find(d.varType.get).sym,
-                d.env.find(d.identifier.get));
+                d);
         d.sym.type = t;
     }
 
--- a/sema/ScopeCheck.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/sema/ScopeCheck.d	Tue Jul 22 00:33:58 2008 +0200
@@ -80,34 +80,34 @@
                 auto target = cast(Identifier)m.target;
                 auto child = m.child;
                 auto st = target.getSymbol;
-                auto res = st.findMember(child.get);
+                auto res = st.findMembers(child.get);
 
-                if(!res)
+                if(!res.length)
                     messages.report(MissingMember, m.loc)
                         .arg(st.type.name)
                         .arg(target.get)
                         .arg(child.get);
                 else
-                    internalCheckProtection(res, child);
+                    internalCheckProtection(res[0], child);
 
-                return res;
+                return res.length ? res[0] : null;
             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.findMember(child.get);
+                auto res = s.findMembers(child.get);
 
-                if(!res)
+                if(!res.length)
                     messages.report(MissingMember, m.loc)
                         .arg(s.type.name)
-                        .arg(s.getFQN)
+                        .arg(target.get)
                         .arg(child.get);
                 else
-                    internalCheckProtection(res, child);
+                    internalCheckProtection(res[0], child);
 
-                return res;
+                return res.length ? res[0] : null;
         }
     }
 
--- a/sema/Symbol.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/sema/Symbol.d	Tue Jul 22 00:33:58 2008 +0200
@@ -43,12 +43,13 @@
       Try to find a contained symbol with the given name - returns null if not
       found
      **/
-    Symbol findMember(char[] member)
+    Symbol[] findMembers(char[] member)
     {
+        Symbol[] res;
         foreach (possible; actual.contained)
             if (possible.name == member)
-                return possible;
-        return null;
+                res ~= possible;
+        return res;
     }
 
     /**
--- a/sema/TypeCheck.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/sema/TypeCheck.d	Tue Jul 22 00:33:58 2008 +0200
@@ -1,9 +1,11 @@
 module sema.TypeCheck;
 
 import sema.Visitor,
+       sema.Symbol,
        sema.DType;
 
-import tango.io.Stdout;
+import tango.io.Stdout,
+       Integer = tango.text.convert.Integer;
 
 import basic.SourceLocation,
        basic.Message;
@@ -90,7 +92,7 @@
 
         foreach(i, arg; exp.args)
         {
-            auto argType = (cast(DFunction)exp.exp.type).params[i];
+            auto argType = exp.exp.type.asFunction.params[i];
             auto expType = arg.type;
             if(argType.byteSize != expType.byteSize)
             {
@@ -113,6 +115,95 @@
         exp.args = newArgs;
     }
 
+    override void visitNewExp(NewExp exp)
+    {
+        super.visitNewExp(exp);
+
+        Exp[] newArgs;
+        
+        Symbol[] methods = exp.newType.getSymbol.findMembers("this");
+
+        if ( exp.c_args.length )
+        {
+            if ( !methods.length )
+            {
+                messages.report(NoConstructor, exp.newType.loc);
+                return;
+            }
+
+            Symbol[] possible;
+            Symbol perfect;
+
+            foreach( s ; methods )
+            {
+                bool per = true;
+
+                foreach(i, arg; exp.c_args)
+                {
+                    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 ( perfect )
+                sel = perfect;
+            else
+                if ( possible.length )
+                    sel = possible[0];
+
+            if ( sel )
+            {
+                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;
+            }
+            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));
+                }
+            }
+        }
+    }
+
     override void visitAssignExp(AssignExp exp)
     {
         super.visitAssignExp(exp);
--- a/sema/Visitor.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/sema/Visitor.d	Tue Jul 22 00:33:58 2008 +0200
@@ -109,6 +109,8 @@
                 return visitIndexExp(cast(IndexExp)exp);
             case ExpType.MemberReference:
                 return visitMemberReference(cast(MemberReference)exp);
+            case ExpType.NewExp:
+                return visitNewExp(cast(NewExp)exp);
             default:
                 throw new Exception("Unknown expression type");
         }
@@ -423,5 +425,21 @@
         else
             return ExpT.init;
     }
+
+    ExpT visitNewExp(NewExp n)
+    {
+        visitExp(n.newType);
+
+        foreach( a ; n.a_args )
+            visitExp(a);
+
+        foreach( c ; n.c_args )
+            visitExp(c);
+
+        static if (is(ExpT == void))
+            return;
+        else
+            return ExpT.init;
+    }
 }
 
--- a/tools/AstPrinter.d	Mon Jul 21 22:14:06 2008 +0200
+++ b/tools/AstPrinter.d	Tue Jul 22 00:33:58 2008 +0200
@@ -33,14 +33,14 @@
         printEndLine();
     }
 
-    void printDecl(Decl decl)
+    void printDecl(Decl decl, bool printAtt = true)
     {
         switch(decl.declType)
         {
             case DeclType.FuncDecl:
                 auto funcDecl = cast(FuncDecl)decl;
                 printBeginLine();
-                printAttribute(decl.att);
+                if(printAtt) printAttribute(decl.att);
                 printIdentifier(funcDecl.returnType);
                 space;
                 printIdentifier(funcDecl.identifier);
@@ -54,7 +54,7 @@
             case DeclType.VarDecl:
                 auto varDecl = cast(VarDecl)decl;
                 printBeginLine();
-                printAttribute(decl.att);
+                if(printAtt) printAttribute(decl.att);
                 printExp(varDecl.varType);
                 space;
                 printExp(varDecl.identifier);
@@ -68,7 +68,7 @@
 
             case DeclType.StructDecl:
                 auto structDecl = cast(StructDecl)decl;
-                printAttribute(decl.att);
+                if(printAtt) printAttribute(decl.att);
                 printBeginLine("struct ");
                 printIdentifier(structDecl.identifier);
                 printEndLine;
@@ -80,7 +80,7 @@
 
             case DeclType.ClassDecl:
                 auto classDecl = cast(ClassDecl)decl;
-                printAttribute(decl.att);
+                if(printAtt) printAttribute(decl.att);
                 printBeginLine("class ");
                 printIdentifier(classDecl.identifier);
                 foreach(i, iden ; classDecl.baseClasses )
@@ -97,7 +97,7 @@
 
             case DeclType.InterfaceDecl:
                 auto interfaceDecl = cast(InterfaceDecl)decl;
-                printAttribute(decl.att);
+                if(printAtt) printAttribute(decl.att);
                 printBeginLine("interface ");
                 printIdentifier(interfaceDecl.identifier);
                 foreach(i, iden ; interfaceDecl.baseClasses )
@@ -114,7 +114,7 @@
 
             case DeclType.ImportDecl:
                 auto i = cast(ImportDecl)decl;
-                printAttribute(decl.att);
+                if(printAtt) printAttribute(decl.att);
                 printBeginLine("import ");
                 printEndLine(i.get);
                 break;
@@ -138,7 +138,7 @@
                 break;
             case StmtType.Decl:
                 auto declStmt = cast(DeclStmt)stmt;
-                printDecl(declStmt.decl);
+                printDecl(declStmt.decl, false);
                 break;
             case StmtType.Exp:
                 auto expStmt = cast(ExpStmt)stmt;
@@ -219,6 +219,27 @@
                 print(")");
                 printExp(castExp.exp);
                 break;
+            case ExpType.NewExp:
+                auto newExp = cast(NewExp)exp;
+                print("new ");
+                if(newExp.a_args.length)
+                {
+                    foreach( i, a ; newExp.a_args )
+                    {
+                        print(i ? ", " : "(");
+                        printExp(a);
+                    }
+                    print(")");
+                }
+                printExp(newExp.newType);
+                print("(");
+                foreach( i, c ; newExp.c_args )
+                {
+                    print(i ? ", " : "");
+                    printExp(c);
+                }
+                print(")");
+                break;
         }
         
     }