# HG changeset patch # User Anders Johnsen # Date 1216679638 -7200 # Node ID 57b0b4464a0b84228b83a610c6ede483f4d0b4a5 # Parent bb01c1dc452acffca62cdbbe2441f37333ea16ab Parsing "new", putting it in AST and performs some tests on it. Eg. if the contructor exists and the params matches. diff -r bb01c1dc452a -r 57b0b4464a0b ast/Exp.d --- 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) diff -r bb01c1dc452a -r 57b0b4464a0b basic/Messages.d --- 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"), diff -r bb01c1dc452a -r 57b0b4464a0b lexer/Keyword.d --- 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 diff -r bb01c1dc452a -r 57b0b4464a0b lexer/Token.d --- 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" ]; } diff -r bb01c1dc452a -r 57b0b4464a0b parser/Action.d --- 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; + } } /** diff -r bb01c1dc452a -r 57b0b4464a0b parser/Parser.d --- 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); diff -r bb01c1dc452a -r 57b0b4464a0b sema/AstAction.d --- 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); + } } } diff -r bb01c1dc452a -r 57b0b4464a0b sema/ScopeBuilder.d --- 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; } diff -r bb01c1dc452a -r 57b0b4464a0b sema/ScopeCheck.d --- 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; } } diff -r bb01c1dc452a -r 57b0b4464a0b sema/Symbol.d --- 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; } /** diff -r bb01c1dc452a -r 57b0b4464a0b sema/TypeCheck.d --- 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); diff -r bb01c1dc452a -r 57b0b4464a0b sema/Visitor.d --- 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; + } } diff -r bb01c1dc452a -r 57b0b4464a0b tools/AstPrinter.d --- 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; } }