# HG changeset patch # User Anders Johnsen # Date 1217332484 -7200 # Node ID 08f68d6840477dbf77ef960c0ae966486fb05419 # Parent 6581781830180e00c74e44d6091077c5e303d2a8 Rename some files. Hopefully we can get a more iterative sema pass, that's a lot easier to "get startet with". Also added support for alias. diff -r 658178183018 -r 08f68d684047 ast/Decl.d --- a/ast/Decl.d Fri Jul 25 15:31:16 2008 +0200 +++ b/ast/Decl.d Tue Jul 29 13:54:44 2008 +0200 @@ -23,6 +23,7 @@ StructDecl, ClassDecl, InterfaceDecl, + AliasDecl, } class Decl @@ -309,3 +310,14 @@ private DType myType; } +class AliasDecl : Decl +{ + this(Decl decl) + { + super(DeclType.AliasDecl); + this.decl = decl; + } + + Decl decl; +} + diff -r 658178183018 -r 08f68d684047 ast/Exp.d --- a/ast/Exp.d Fri Jul 25 15:31:16 2008 +0200 +++ b/ast/Exp.d Tue Jul 29 13:54:44 2008 +0200 @@ -30,13 +30,14 @@ CastExp, StringExp, NewExp, + NullExp, + ArrayLiteralExp, IdentifierTypeExp, ArrayTypeExp, StaticArrayTypeExp, PointerTypeExp, FunctionTypeExp, - ArrayLiteralExp, } abstract class Exp @@ -579,6 +580,19 @@ Symbol callSym; } +class NullExp : Exp +{ + this(SLoc loc) + { + super(ExpType.NullExp, loc); + } + + override DType type() + { + return new DPointer(DType.Int); + } +} + class Identifier : Exp { this(SLoc loc, char[] name) diff -r 658178183018 -r 08f68d684047 ast/Module.d --- a/ast/Module.d Fri Jul 25 15:31:16 2008 +0200 +++ b/ast/Module.d Tue Jul 29 13:54:44 2008 +0200 @@ -15,6 +15,8 @@ void addDecl(Decl decl) { + if(!decl) + return; switch(decl.declType) { case DeclType.FuncDecl: @@ -32,6 +34,9 @@ case DeclType.InterfaceDecl: interfaces ~= cast(InterfaceDecl)decl; break; + case DeclType.AliasDecl: + aliases ~= cast(AliasDecl)decl; + break; default: assert(0, "DeclType not implemented"); } @@ -49,6 +54,7 @@ StructDecl[] structs; ClassDecl[] classes; InterfaceDecl[] interfaces; + AliasDecl[] aliases; Decl[] decls; char[] moduleName; diff -r 658178183018 -r 08f68d684047 dang/compiler.d --- a/dang/compiler.d Fri Jul 25 15:31:16 2008 +0200 +++ b/dang/compiler.d Tue Jul 29 13:54:44 2008 +0200 @@ -25,12 +25,13 @@ import sema.Visitor, sema.AstAction, - sema.ScopeBuilder, + sema.BuildScopes, + sema.BuildSymbols, + sema.CheckScopes, + sema.CheckTypes, sema.LiteralInterpreter, - sema.ScopeCheck, sema.VC, - sema.ObjectOriented, - sema.TypeCheck; + sema.ObjectOriented; import tango.stdc.posix.unistd; import tango.stdc.stdlib; @@ -314,16 +315,17 @@ modules = (new ModuleLoader()).visit(modules, messages, src_mgr); messages.checkErrors; - (new ScopeBuilder).visit(modules); + (new BuildScopes).visit(modules); + (new BuildSymbols).visit(modules); StopWatch watch2; watch.start; watch2.start; - (new ScopeCheck(messages)).visit(modules); + (new CheckScopes(messages)).visit(modules); messages.checkErrors; auto scope_check = watch2.stop; watch2.start; - (new TypeCheck(messages)).visit(modules); + (new CheckTypes(messages)).visit(modules); messages.checkErrors; auto type_check = watch2.stop; diff -r 658178183018 -r 08f68d684047 lexer/Keyword.d --- a/lexer/Keyword.d Fri Jul 25 15:31:16 2008 +0200 +++ b/lexer/Keyword.d Tue Jul 29 13:54:44 2008 +0200 @@ -47,6 +47,7 @@ "alias" : Tok.Alias, "this" : Tok.This, "new" : Tok.New, + "null" : Tok.Null, // "super" : Tok.Super, // control flow diff -r 658178183018 -r 08f68d684047 lexer/Token.d --- a/lexer/Token.d Fri Jul 25 15:31:16 2008 +0200 +++ b/lexer/Token.d Tue Jul 29 13:54:44 2008 +0200 @@ -212,7 +212,7 @@ Module, Import, - New, + New, Null, /* Attributes */ Public, Private, Package, Export, Protected, @@ -321,6 +321,8 @@ Tok.Deprecated:"deprecated", Tok.Auto:"auto", Tok.Extern:"extern", - Tok.New:"new" + Tok.New:"new", + Tok.Null:"null", + Tok.Alias:"alias" ]; } diff -r 658178183018 -r 08f68d684047 parser/Action.d --- a/parser/Action.d Fri Jul 25 15:31:16 2008 +0200 +++ b/parser/Action.d Tue Jul 29 13:54:44 2008 +0200 @@ -175,6 +175,11 @@ return null; } + DeclT actOnAliasDecl(DeclT decl, Attribute att) + { + return null; + } + /** Add a struct member to a struct. */ @@ -430,6 +435,14 @@ { return null; } + + /** + Null expression. + */ + ExprT actOnNullExpr(SLoc pos) + { + return null; + } } /** diff -r 658178183018 -r 08f68d684047 parser/Parser.d --- a/parser/Parser.d Fri Jul 25 15:31:16 2008 +0200 +++ b/parser/Parser.d Tue Jul 29 13:54:44 2008 +0200 @@ -91,6 +91,11 @@ Id iden = Id(require(Tok.Identifier)); return parseInterface(type, iden, att); + case Tok.Alias: + next(); + auto decl = parseDecl(Attribute()); + return action.actOnAliasDecl(decl, att); + case Tok.Identifier: Id type = parseType; Id iden = Id(require(Tok.Identifier)); @@ -126,6 +131,7 @@ messages.report(UnexpectedTok, peek.location) .arg(sm.getText(peek.asRange)); + next(); return null; } messages.report(UnexpectedTok, peek.location) @@ -961,6 +967,8 @@ return iden; } } + else if (n.type == Tok.Null) + return action.actOnNullExpr(n.location); else if (n.type == Tok.Cast) return parseCast(n); else if (n.type == Tok.Integer) diff -r 658178183018 -r 08f68d684047 sema/AstAction.d --- a/sema/AstAction.d Fri Jul 25 15:31:16 2008 +0200 +++ b/sema/AstAction.d Tue Jul 29 13:54:44 2008 +0200 @@ -102,6 +102,13 @@ d.att = att; return d; } + + DeclT actOnAliasDecl(DeclT decl, Attribute att) + { + auto a = new AliasDecl(cast(Decl)decl); + a.att = att; + return a; + } void actOnStructMember(DeclT st_decl, DeclT m_decl) //ref Id type, ref Id name, ExprT init) { @@ -311,6 +318,11 @@ { return new ArrayLiteralExp(cast(Exp[])exps, start, end); } + + ExprT actOnNullExpr(SLoc pos) + { + return new NullExp(pos); + } } } diff -r 658178183018 -r 08f68d684047 sema/BuildScopes.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sema/BuildScopes.d Tue Jul 29 13:54:44 2008 +0200 @@ -0,0 +1,265 @@ +module sema.BuildScopes; + +import tango.io.Stdout, + tango.core.Array : find; + +import sema.Scope; + +import sema.Visitor; + +/** + Add scopes to everything, and add all identifiers that correspond to types. + Types/Symbols are added by ForwardReference. + **/ +class BuildScopes : Visitor!(void) +{ + static ModuleHandler mHandle; + + static this() + { + mHandle = new ModuleHandler; + } + + override void visit(Module[] modules) + { + foreach(m ; modules) + visitModule(m); + } + + private void registerBasicTypeTo(char[] n, DType t, Scope sc, Module m) + { + sc.types[n] = t; + auto id = new Identifier(n); + id.env = sc; + auto decl = new DummyDecl(); + auto sym = m.symbol.createMember(n, t, decl); + sym.decl = decl; + decl.sym = sym; + decl.env = sc; + sc.put(id.get, decl); + } + + override void visitModule(Module m) + { + auto root = new Scope; + table ~= root; + + m.symbol = new Symbol; + + registerBasicTypeTo("void", DType.Void, root, m); + registerBasicTypeTo("bool", DType.Bool, root, m); + registerBasicTypeTo("byte", DType.Byte, root, m); + registerBasicTypeTo("ubyte", DType.UByte, root, m); + registerBasicTypeTo("short", DType.Short, root, m); + registerBasicTypeTo("ushort", DType.UShort, root, m); + registerBasicTypeTo("int", DType.Int, root, m); + registerBasicTypeTo("uint", DType.UInt, root, m); + registerBasicTypeTo("long", DType.Long, root, m); + registerBasicTypeTo("ulong", DType.ULong, root, m); + + registerBasicTypeTo("char", DType.Char, root, m); + registerBasicTypeTo("wchar", DType.WChar, root, m); + registerBasicTypeTo("dchar", DType.DChar, root, m); + + registerBasicTypeTo("float", DType.Float, root, m); + registerBasicTypeTo("double", DType.Double, root, m); + registerBasicTypeTo("real", DType.Real, root, m); + + current().inModule = m; + current().mHandle = mHandle; + mHandle.add(m); + m.env = current(); + super.visitModule(m); + } + + override void visitDecl(Decl d) + { + d.env = current(); + super.visitDecl(d); + } + + override void visitImportDecl(ImportDecl i) + { + i.env.imports ~= i; + super.visitImportDecl(i); + } + + override void visitStmt(Stmt s) + { + s.env = current(); + s.stmtIndex = s.env.stmtIndex; + super.visitStmt(s); + } + + override void visitExp(Exp e) + { + e.env = current(); + e.stmtIndex = e.env.stmtIndex; + super.visitExp(e); + } + + override void visitFuncDecl(FuncDecl d) + { + current().put(d.identifier.get, d); + d.env = current(); + auto sc = push(); + + visitExp(d.returnType); + visitExp(d.identifier); + sc.parentFunction = d; + foreach (arg; d.funcArgs) + visitDecl(arg); + foreach (stmt; d.statements) + { + sc.currentStmtIndex++; + visitStmt(stmt); + } + pop(sc); + } + + override void visitVarDecl(VarDecl d) + { + if (d.init) + visitExp(d.init); + + if (need_push > 0 && current().parentFunction !is null) { + push(); + --need_push; + } + + if(d.identifier) + { + auto sc = current(); + sc.put(d.identifier.get, d); + d.env = sc; + visitExp(d.varType); + visitExp(d.identifier); + } + } + + override void visitStructDecl(StructDecl s) + { + auto sc = current(); + sc.put(s.identifier.get, s); + s.env = sc; + auto type = new DStruct(s.identifier); + + sc.types[s.identifier.get] = type; + + sc = push(); + super.visitStructDecl(s); + pop(sc); + } + + override void visitClassDecl(ClassDecl s) + { + auto sc = current(); + sc.put(s.identifier.get, s); + s.env = sc; + auto type = new DClass(s.identifier); + + sc.types[s.identifier.get] = type; + + sc = push(); + super.visitClassDecl(s); + pop(sc); + } + + override void visitInterfaceDecl(InterfaceDecl s) + { + auto sc = current(); + sc.put(s.identifier.get, s); + s.env = sc; + auto type = new DInterface(s.identifier); + + sc.types[s.identifier.get] = type; + + sc = push(); + super.visitInterfaceDecl(s); + pop(sc); + } + + override void visitAliasDecl(AliasDecl a) + { + a.env = current(); +// auto decl = cast(VarDecl)a.decl; +// auto sc = current(); +// super.visitDecl(a.decl); + } + + override void visitDeclStmt(DeclStmt d) + { + ++need_push; + super.visitDeclStmt(d); + } + private uint need_push = 0; + + override void visitIfStmt(IfStmt s) + { + s.env = current(); + visitExp(s.cond); + auto sc = push(); + visitStmt(s.then_body); + pop(sc); + + if (s.else_body !is null) + { + sc = push(); + visitStmt(s.else_body); + pop(sc); + } + } + + override void visitWhileStmt(WhileStmt s) + { + s.env = current(); + auto sc = push(); + super.visitWhileStmt(s); + pop(sc); + } + + override void visitForStmt(ForStmt s) + { + s.env = current(); + auto sc = push(); + super.visitForStmt(s); + pop(sc); + } + + override void visitCompoundStmt(CompoundStatement s) + { + s.env = current(); + auto sc = push(); + super.visitCompoundStmt(s); + pop(sc); + } + +private: + Scope[] table; + + Scope push() + { + auto sc = new Scope(current()); + table ~= sc; + return sc; + } + + Scope pop(Scope sc = null) + { + if (sc !is null) + { + table.length = table.find(sc); + return sc; + } + + auto res = table[$ - 1]; + table.length = table.length - 1; + return res; + } + + Scope current() + { + return table[$ - 1]; + } +} + diff -r 658178183018 -r 08f68d684047 sema/BuildSymbols.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sema/BuildSymbols.d Tue Jul 29 13:54:44 2008 +0200 @@ -0,0 +1,247 @@ +module sema.BuildSymbols; + +import tango.io.Stdout, + tango.core.Array : find; + +import sema.Scope, + sema.Symbol; + +import sema.Visitor, + basic.SmallArray; + +class SymbolFactory +{ + void put(Symbol symbol, DType type) + { + types[type] = symbol; + } + + Symbol get(Symbol owner, DType type, Identifier i, Decl decl) + { + if (type in types) + return owner.createAlias(i.get, types[type], decl); + else + return owner.createMember(i.get, type, decl); + } + + Symbol[DType] types; +} + +class BuildSymbols : Visitor!(void) +{ + this() + { + this.sf = new SymbolFactory; + } + + override void visit(Module[] modules) + { +// (new BuildSymbolTypes(sf)).visit(modules); + this.modules = modules; + inFunctionBodyStack.push(false); + foreach (mod; modules) + { + current = mod; + foreach (decl; mod.decls) + visitDecl(decl); + } + } + + override void visitFuncDecl(FuncDecl d) + { + + visitExp(d.returnType); + visitExp(d.identifier); + + d.sym = current.symbol.createMember( + d.identifier.get, + d.type, + d); + + auto old = current.symbol; + current.symbol = d.sym; + + foreach (arg; d.funcArgs) + visitDecl(arg); + + inFunctionBodyStack.push(true); + + foreach (stmt; d.statements) + visitStmt(stmt); + + inFunctionBodyStack.pop(); + + current.symbol = old; + + } + + override void visitVarDecl(VarDecl d) + { + visitExp(d.varType); + if(d.identifier) + visitExp(d.identifier); + + if (d.init) + visitExp(d.init); + + if(d.identifier) + { + DType t = typeOf(d.varType, d.env); + d.sym = sf.get(current.symbol, t, d.identifier, d); + d.sym.type = t; + } + } + + override void visitAliasDecl(AliasDecl a) + { + auto decl = cast(VarDecl)a.decl; + + if (a.env.findType(decl.varType.get)) // Alias "type" is a type. + { + auto t = typeOf(decl.varType, a.env); + a.sym = sf.get(current.symbol, t, + decl.identifier, a); + a.env.types[decl.identifier.get] = t; + } + else if(auto aliasOf = a.env.find(decl.varType.get)[0]) + { + a.env.put(decl.identifier.get, aliasOf); + a.sym = current.symbol.createAlias( + decl.identifier.get, + aliasOf.sym, + a); + } + decl.env = a.env; + } + + + override void visitStructDecl(StructDecl s) + { + auto st = s.env.findType(s.identifier.get).asStruct; + s.sym = current.symbol.createMember( + s.identifier.get, + st, + s.env.find(s.identifier.get)[0]); + sf.put(s.sym, st); + + foreach (decl; s.decls) + { + DType type; + char[] name; + if (auto varDecl = cast(VarDecl)decl) + { + type = typeOf(varDecl.varType, varDecl.env); + name = varDecl.identifier.get; + st.addMember(type, name); + } + /* + else if (auto fd = cast(FuncDecl)decl) + { + type = fd.type; + name = fd.identifier.get; + }*/ + } + auto old = current.symbol; + current.symbol = s.sym; + inFunctionBodyStack.push(false); + super.visitStructDecl(s); + inFunctionBodyStack.pop(); + current.symbol = old; + } + + override void visitClassDecl(ClassDecl s) + { + auto st = s.env.findType(s.identifier.get).asClass; + s.sym = current.symbol.createMember( + s.identifier.get, + st, + s.env.find(s.identifier.get)[0]); + + sf.put(s.sym, st); + + foreach (decl; s.decls) + { + DType type; + char[] name; + if (auto varDecl = cast(VarDecl)decl) + { + type = typeOf(varDecl.varType, varDecl.env); + name = varDecl.identifier.get; + st.addMember(type, name); + } + /* + else if (auto fd = cast(FuncDecl)decl) + { + type = fd.type; + name = fd.identifier.get; + }*/ + } + auto old = current.symbol; + current.symbol = s.sym; + inFunctionBodyStack.push(false); + super.visitClassDecl(s); + inFunctionBodyStack.pop(); + current.symbol = old; + } + + override void visitInterfaceDecl(InterfaceDecl s) + { + auto st = s.env.findType(s.identifier.get).asInterface; + s.sym = current.symbol.createMember( + s.identifier.get, + st, + s.env.find(s.identifier.get)[0]); + sf.put(s.sym, st); + + foreach (decl; s.decls) + { + DType type; + char[] name; + if (auto varDecl = cast(VarDecl)decl) + { + type = typeOf(varDecl.varType, varDecl.env); + name = varDecl.identifier.get; + st.addMember(type, name); + } + /* + else if (auto fd = cast(FuncDecl)decl) + { + type = fd.type; + name = fd.identifier.get; + }*/ + } + auto old = current.symbol; + current.symbol = s.sym; + inFunctionBodyStack.push(false); + super.visitInterfaceDecl(s); + inFunctionBodyStack.pop(); + current.symbol = old; + } + + override void visitFunctionTypeExp(FunctionTypeExp f) + { + } + + DType typeOf(Identifier id, Scope sc) + { + if(auto i = cast(PointerTypeExp)id) + return (typeOf(i.pointerOf, sc)).getPointerTo(); + else if(auto i = cast(StaticArrayTypeExp)id) + return typeOf(i.arrayOf, sc).getAsStaticArray(i.size); + else if(auto i = cast(FunctionTypeExp)id) + { + auto d = new DFunction(id); + d.returnType = typeOf(i.returnType, sc); + foreach (decl ; i.decls) + d.params ~= typeOf(decl.varType, sc); + return d.getPointerTo; + } + return sc.findType(id.get); + } + + Module[] modules; + Module current; + SmallArray!(bool) inFunctionBodyStack; + SymbolFactory sf; +} + diff -r 658178183018 -r 08f68d684047 sema/CheckScopes.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sema/CheckScopes.d Tue Jul 29 13:54:44 2008 +0200 @@ -0,0 +1,158 @@ +module sema.CheckScopes; + +import sema.Visitor, + sema.Symbol, + sema.Scope, + sema.DType; + +import basic.Message, + basic.Attribute; + +import tango.io.Stdout; + +class CheckScopes : Visitor!(void) +{ + + this(MessageHandler messages) + { + this.messages = messages; + } + + override void visitIdentifier(Identifier i) + { + auto symbol = i.env.find(i.get); + + if(symbol is null) + messages.report(UndefinedIdentifier, i.loc) + .arg(i.get); + } + + override void visitVarDecl(VarDecl d) + { + if(d.identifier.get is null) + messages.report(UndefinedType, d.varType.loc) + .arg(d.varType.get); + + auto env = d.env; + if (d.env.enclosing) + if (d.env.enclosing.find(d.identifier.get) !is null) + if (d.env.parentFunction !is null) + while( d.env.parentFunction.env !is 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; + } + + visitExp(d.identifier); + if (d.init) + visitExp(d.init); + } + + override void visitFuncDecl(FuncDecl f) + { + visitExp(f.identifier); + + inFunction = true; + foreach (stmt; f.statements) + visitStmt(stmt); + inFunction = false; + } + + override void visitImportDecl(ImportDecl) { } + + override void visitCastExp(CastExp exp) + { + visitExp(exp.exp); + } + + override void visitMemberReference(MemberReference m) + { + internalVisitMemberRef(m); + } + + 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: + 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; + return visitRef(m, cast(Identifier)m.target, s); + } + } + + override void visitExp(Exp exp) + { + if (exp.expType == ExpType.Identifier && inFunction + && exp.env.find((cast(Identifier)exp).get) !is null) + { + if (exp.env.findType((cast(Identifier)exp).get) is null) + internalCheckProtection( + exp.env.find((cast(Identifier)exp).get)[0].sym, + cast(Identifier)exp); + } + + super.visitExp(exp); + } + + private void internalCheckProtection(Symbol sym, Identifier iden) + { + if (isChildOf(sym.decl.env, iden.env)) + return; + + switch(sym.decl.att.getProtection) + { + case Protection.Private: +/* if (iden.env.inModule == sym.decl.getIdentifier.env.inModule + && sym.decl.getIdentifier.env.enclosing == iden.env.inModule) + {} + else*/ + messages.report(CannotAccessPrivate, iden.loc); + return; + default: + return; + } + } + + private bool isChildOf(Scope parent, Scope child) + { + if (child is parent) + return true; + + if (child.enclosing !is null) + return isChildOf(parent, child.enclosing); + + return false; + } + + private bool isType(char[] s) + { + return (s in types? true : false); + } + + int[char[]] types; + MessageHandler messages; + bool inFunction; +} + diff -r 658178183018 -r 08f68d684047 sema/CheckTypes.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sema/CheckTypes.d Tue Jul 29 13:54:44 2008 +0200 @@ -0,0 +1,477 @@ +module sema.CheckTypes; + +import sema.Visitor, + sema.Symbol, + sema.DType; + +import tango.io.Stdout, + Integer = tango.text.convert.Integer; + +import basic.SourceLocation, + basic.Message; + +class CheckTypes : Visitor!(void) +{ + this(MessageHandler messages) + { + this.messages = messages; + } + + override void visitBinaryExp(BinaryExp exp) + { + super.visitBinaryExp(exp); + + if(!(exp.left.type is exp.right.type)) + { + if (!exp.right.type.hasImplicitConversionTo(exp.left.type) && + !exp.left.type.hasImplicitConversionTo(exp.right.type)) + messages.report(InvalidImplicitCast, exp.loc) + .arg(exp.right.type.toString) + .arg(exp.left.type.toString); + else + { + CastExp castExp; + if(exp.left.type.isReal && exp.right.type.isReal) + if(exp.left.type.byteSize > exp.right.type.byteSize) + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.left.type.name), + exp.right); + else + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.right.type.name), + exp.left); + else if(exp.left.type.isReal || exp.right.type.isReal) + if(exp.left.type.isReal) + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.left.type.name), + exp.right); + else + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.right.type.name), + exp.left); + else + if(exp.left.type.byteSize > exp.right.type.byteSize) + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.left.type.name), + exp.right); + else if(exp.left.type.byteSize > exp.right.type.byteSize) + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.right.type.name), + exp.left); + else + castExp = new CastExp( + SLoc.Invalid, + new Identifier(exp.left.type.name), + exp.right); + + + if(castExp) + { + castExp.env = exp.env; + if(castExp.exp == exp.right) + exp.right = castExp; + else + exp.left = castExp; + + } + } + } + if (exp.op >= BinaryExp.Operator.LeftShift && + exp.op <= BinaryExp.Operator.UnsignedRightShift) + {} // FIXME: When we have const-system we need to check for + // right site being larger then the bitsize of the + // left + } + + override void visitDerefExp(DerefExp exp) + { + if (!exp.exp.type.isPointer) + { + messages.report(CanOnlyDerefPointers, + [exp.exp.sourceRange][], + [exp.loc]) + .arg(exp.exp.type.toString); + + exp._type = DType.Int; + } + } + + override void visitCallExp(CallExp exp) + { + super.visitCallExp(exp); + + if (auto iden = cast(MemberReference)exp.exp) + { + Symbol[] internalVisitMemberRef(MemberReference m) + { + Symbol[] visitRef(MemberReference m, Identifier target, Symbol st) + { + auto child = m.child; + auto res = st.findMembers(child.get); + return res; + } + switch(m.target.expType) + { + case ExpType.Identifier: + return visitRef(m, cast(Identifier)m.target, + (cast(Identifier)m.target).getSymbol); + case ExpType.MemberReference: + Symbol[] s = internalVisitMemberRef(cast(MemberReference)m.target); + if(s.length) + return s; + return visitRef(m, cast(Identifier)m.target, s[0]); + } + } + + Exp[] newArgs; + + DFunction function_type; + if (iden.type.isFunction()) + { + Symbol[] methods = internalVisitMemberRef(iden); + + if (!methods.length) + { + messages.report(NoMethodByName, iden.loc); + return; + } + + Symbol sel = getBestMatch(exp.args, methods); + exp.callSym = sel; + if (sel) + function_type = sel.type.asFunction(); + else + { + messages.report(NoMachingMethod, exp.loc); + foreach ( i, s ; methods ) + { + messages.report(CandidateNr, + (cast(FuncDecl)s.decl).identifier.loc) + .arg(Integer.toString(i+1)); + } + } + } + else if (iden.type.isCallable) + function_type = iden.type.asCallable(); + else assert(0, "Should not happen"); + + foreach (i, arg; exp.args) + { + auto argType = function_type.params[i]; + auto expType = arg.type; + if (argType.isSame(expType)) + { + 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 = iden.env; + newArgs ~= castExp; + } + else + newArgs ~= arg; + } + exp.args = newArgs; + } + else if (auto iden = cast(Identifier)exp.exp) + { + Exp[] newArgs; + + DFunction function_type; + if (iden.type.isFunction()) + { + 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); + exp.callSym = sel; + if (sel) + function_type = sel.type.asFunction(); + else + { + messages.report(NoMachingMethod, exp.loc); + foreach ( i, s ; methods ) + { + messages.report(CandidateNr, + (cast(FuncDecl)s.decl).identifier.loc) + .arg(Integer.toString(i+1)); + } + } + } + else if (iden.type.isCallable) + { + function_type = iden.type.asCallable(); + if (exp.args.length != function_type.params.length) + { + messages.report(CannotCallMethod, exp.loc) + .arg(iden.type.toString) + .arg(exp.callerType.toString); + } + } + else assert(0, "Should not happen"); + + foreach (i, arg; exp.args) + { + auto argType = function_type.params[i]; + auto expType = arg.type; + if (!argType.isSame(expType)) + { + 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 = iden.env; + newArgs ~= castExp; + } + else + newArgs ~= arg; + } + exp.args = newArgs; + } + else + { + Exp[] newArgs; + + foreach(i, arg; exp.args) + { + auto argType = exp.exp.type.asFunction.params[i]; + auto expType = arg.type; + if(!argType.isSame(expType)) + { + 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) + { + super.visitNewExp(exp); + + Exp[] newArgs; + + Symbol[] methods = exp.newType.getSymbol.findFunctionMembers("this"); + + if (!methods.length) + { + messages.report(NoConstructor, exp.newType.loc); + return; + } + + Symbol sel = getBestMatch(exp.c_args, methods); + + if (sel) + { + foreach (i, arg; exp.c_args) + { + auto argType = sel.type.asFunction.params[i]; + auto expType = arg.type; + if (!argType.isSame(expType)) + { + 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)); + } + } + } + + override void visitAssignExp(AssignExp exp) + { + super.visitAssignExp(exp); + + auto identifierType = exp.identifier.type; + auto expType = exp.exp.type; + + if(!identifierType.isSame(expType)) + { + if(!expType.hasImplicitConversionTo(identifierType)) + messages.report(InvalidImplicitCast, + [exp.identifier.sourceRange, exp.exp.sourceRange][], + [exp.loc]) + .arg(expType.toString) + .arg(identifierType.toString); + + auto castExp = new CastExp( + SLoc.Invalid, + new Identifier(identifierType.name), + exp.exp); + castExp.env = exp.exp.env; + exp.exp = castExp; + } + + if (expType.isStaticArray) + messages.report(CannotReassignSArray, + [exp.identifier.sourceRange, exp.exp.sourceRange][], + [exp.loc]); + } + + override void visitReturnStmt(ReturnStmt stmt) + { + super.visitReturnStmt(stmt); + + if(stmt.exp) + { + auto returnType = stmt.env.parentFunction.type.asFunction.returnType; + auto expType = stmt.exp.type; + if(!expType) + return; + if(!returnType.isSame(expType)) + { + if(!expType.hasImplicitConversionTo(returnType)) + messages.report(InvalidImplicitCast, stmt.exp.loc) + .arg(expType.toString) + .arg(returnType.toString); + + auto castExp = new CastExp( + SLoc.Invalid, + new Identifier(returnType.name), + stmt.exp); + castExp.env = stmt.exp.env; + stmt.exp = castExp; + } + } + } + + override void visitVarDecl(VarDecl decl) + { + super.visitVarDecl(decl); + + if(decl.init) + { + auto varType = decl.identifier.type; + auto expType = decl.init.type; + if(!varType.isSame(expType)) + { + if(!expType.hasImplicitConversionTo(varType)) + messages.report(InvalidImplicitCast, decl.init.loc) + .arg(expType.toString) + .arg(varType.toString); + + auto castExp = new CastExp( + SLoc.Invalid, + new Identifier(varType.name), + decl.init); + castExp.env = decl.init.env; + decl.init = castExp; + } + } + } + + private Symbol getBestMatch(Exp[] arg_list , Symbol[] available) + in + { + foreach (a ; available) + assert(a.type.isFunction, "A non-function found in available-list."); + } + body + { + assert(available.length, "No available methods in symbol-list."); + + Symbol[] possible; + Symbol perfect; + + bool per, work; + foreach (s ; available) + { + if (s.type.asFunction.params.length < arg_list.length) + continue; + + per = true; + work = true; + + foreach (i, arg; arg_list) + { + auto argType = s.type.asFunction.params[i]; + auto expType = arg.type; + if (argType.isSame(expType)) + { + per = false; + if( !expType.hasImplicitConversionTo(argType) ) + { + work = false; + break; + } + } + } + + 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) + return possible[0]; + + return null; + } + + MessageHandler messages; +} + diff -r 658178183018 -r 08f68d684047 sema/ScopeBuilder.d --- a/sema/ScopeBuilder.d Fri Jul 25 15:31:16 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,533 +0,0 @@ -module sema.ScopeBuilder; - -import tango.io.Stdout, - tango.core.Array : find; - -public -import sema.Scope, - sema.Symbol; - -import sema.Visitor, - basic.SmallArray; - -class SymbolFactory -{ - void put(Symbol symbol, DType type) - { - types[type] = symbol; - } - - Symbol get(Symbol owner, DType type, Identifier i, Decl decl) - { - if (type in types) - return owner.createAlias(i.get, types[type], decl); - else - return owner.createMember(i.get, type, decl); - } - - Symbol[DType] types; -} - -class ForwardReference : Visitor!(void) -{ - this(SymbolFactory sf) - { - this.sf = sf; - } - override void visit(Module[] modules) - { - (new TypeBuilder(sf)).visit(modules); - this.modules = modules; - inFunctionBodyStack.push(false); - foreach (mod; modules) - { - current = mod; - foreach (decl; mod.decls) - visitDecl(decl); - } - } - - override void visitFuncDecl(FuncDecl d) - { - - visitExp(d.returnType); - visitExp(d.identifier); - - d.sym = current.symbol.createMember( - d.identifier.get, - d.type, - d); - - auto old = current.symbol; - current.symbol = d.sym; - - foreach (arg; d.funcArgs) - visitDecl(arg); - - inFunctionBodyStack.push(true); - - foreach (stmt; d.statements) - visitStmt(stmt); - - inFunctionBodyStack.pop(); - - current.symbol = old; - - } - - override void visitVarDecl(VarDecl d) - { - visitExp(d.varType); - if(d.identifier) - visitExp(d.identifier); - - if (d.init) - visitExp(d.init); - - if(d.identifier) - { - DType t = typeOf(d.varType, d.env); - d.sym = sf.get(current.symbol, t, d.identifier, d); - d.sym.type = t; - } - } - - override void visitStructDecl(StructDecl s) - { - auto old = current.symbol; - current.symbol = s.sym; - inFunctionBodyStack.push(false); - super.visitStructDecl(s); - inFunctionBodyStack.pop(); - current.symbol = old; - } - - override void visitClassDecl(ClassDecl s) - { - auto old = current.symbol; - current.symbol = s.sym; - inFunctionBodyStack.push(false); - super.visitClassDecl(s); - inFunctionBodyStack.pop(); - current.symbol = old; - } - - override void visitInterfaceDecl(InterfaceDecl s) - { - auto old = current.symbol; - current.symbol = s.sym; - inFunctionBodyStack.push(false); - super.visitInterfaceDecl(s); - inFunctionBodyStack.pop(); - current.symbol = old; - } - - override void visitFunctionTypeExp(FunctionTypeExp f) - { - } - - DType typeOf(Identifier id, Scope sc) - { - if(auto i = cast(PointerTypeExp)id) - return (typeOf(i.pointerOf, sc)).getPointerTo(); - else if(auto i = cast(StaticArrayTypeExp)id) - return typeOf(i.arrayOf, sc).getAsStaticArray(i.size); - else if(auto i = cast(FunctionTypeExp)id) - { - auto d = new DFunction(id); - d.returnType = typeOf(i.returnType, sc); - foreach (decl ; i.decls) - d.params ~= typeOf(decl.varType, sc); - return d.getPointerTo; - } - return sc.findType(id.get); - } - - Module[] modules; - Module current; - SmallArray!(bool) inFunctionBodyStack; - SymbolFactory sf; -} - -class TypeBuilder : Visitor!(void) -{ - this(SymbolFactory sf) - { - this.sf = sf; - } - - override void visit(Module[] modules) - { - foreach (mod; modules) - { - current = mod; - foreach (decl; mod.decls) - visitDecl(decl); - } - } - - override void visitStructDecl(StructDecl s) - { - auto st = s.env.findType(s.identifier.get).asStruct; - s.sym = current.symbol.createMember( - s.identifier.get, - st, - s.env.find(s.identifier.get)[0]); - sf.put(s.sym, st); - - foreach (decl; s.decls) - { - DType type; - char[] name; - if (auto varDecl = cast(VarDecl)decl) - { - type = typeOf(varDecl.varType, varDecl.env); - name = varDecl.identifier.get; - st.addMember(type, name); - } - /* - else if (auto fd = cast(FuncDecl)decl) - { - type = fd.type; - name = fd.identifier.get; - }*/ - } - } - - override void visitClassDecl(ClassDecl s) - { - auto st = s.env.findType(s.identifier.get).asClass; - s.sym = current.symbol.createMember( - s.identifier.get, - st, - s.env.find(s.identifier.get)[0]); - - sf.put(s.sym, st); - - foreach (decl; s.decls) - { - DType type; - char[] name; - if (auto varDecl = cast(VarDecl)decl) - { - type = typeOf(varDecl.varType, varDecl.env); - name = varDecl.identifier.get; - st.addMember(type, name); - } - /* - else if (auto fd = cast(FuncDecl)decl) - { - type = fd.type; - name = fd.identifier.get; - }*/ - } - } - - override void visitInterfaceDecl(InterfaceDecl s) - { - auto st = s.env.findType(s.identifier.get).asInterface; - s.sym = current.symbol.createMember( - s.identifier.get, - st, - s.env.find(s.identifier.get)[0]); - sf.put(s.sym, st); - - foreach (decl; s.decls) - { - DType type; - char[] name; - if (auto varDecl = cast(VarDecl)decl) - { - type = typeOf(varDecl.varType, varDecl.env); - name = varDecl.identifier.get; - st.addMember(type, name); - } - /* - else if (auto fd = cast(FuncDecl)decl) - { - type = fd.type; - name = fd.identifier.get; - }*/ - } - } - - DType typeOf(Identifier id, Scope sc) - { - if(auto i = cast(PointerTypeExp)id) - return (typeOf(i.pointerOf, sc)).getPointerTo(); - else if(auto i = cast(StaticArrayTypeExp)id) - return typeOf(i.arrayOf, sc).getAsStaticArray(i.size); - else if(auto i = cast(FunctionTypeExp)id) - { - auto d = new DFunction(id); - d.returnType = typeOf(i.returnType, sc); - foreach (decl ; i.decls) - d.params ~= typeOf(decl.varType, sc); - return d.getPointerTo; - } - return sc.findType(id.get); - } - - Module current; - SymbolFactory sf; -} - - -/** - Add scopes to everything, and add all identifiers that correspond to types. - Types/Symbols are added by ForwardReference. - **/ -class ScopeBuilder : Visitor!(void) -{ - static ModuleHandler mHandle; - - static this() - { - mHandle = new ModuleHandler; - } - - this() - { - sf = new SymbolFactory(); - } - - override void visit(Module[] modules) - { - foreach(m ; modules) - visitModule(m); - - auto fr = new ForwardReference(sf); - - fr.visit(modules); - } - - private void registerBasicTypeTo(char[] n, DType t, Scope sc, Module m) - { - sc.types[n] = t; - auto id = new Identifier(n); - id.env = sc; - auto decl = new DummyDecl(); - auto sym = m.symbol.createMember(n, t, decl); - sym.decl = decl; - decl.sym = sym; - decl.env = sc; - sc.put(id.get, decl); - } - - override void visitModule(Module m) - { - auto root = new Scope; - table ~= root; - - m.symbol = new Symbol; - - registerBasicTypeTo("void", DType.Void, root, m); - registerBasicTypeTo("bool", DType.Bool, root, m); - registerBasicTypeTo("byte", DType.Byte, root, m); - registerBasicTypeTo("ubyte", DType.UByte, root, m); - registerBasicTypeTo("short", DType.Short, root, m); - registerBasicTypeTo("ushort", DType.UShort, root, m); - registerBasicTypeTo("int", DType.Int, root, m); - registerBasicTypeTo("uint", DType.UInt, root, m); - registerBasicTypeTo("long", DType.Long, root, m); - registerBasicTypeTo("ulong", DType.ULong, root, m); - - registerBasicTypeTo("char", DType.Char, root, m); - registerBasicTypeTo("wchar", DType.WChar, root, m); - registerBasicTypeTo("dchar", DType.DChar, root, m); - - registerBasicTypeTo("float", DType.Float, root, m); - registerBasicTypeTo("double", DType.Double, root, m); - registerBasicTypeTo("real", DType.Real, root, m); - - current().inModule = m; - current().mHandle = mHandle; - mHandle.add(m); - m.env = current(); - super.visitModule(m); - } - - override void visitDecl(Decl d) - { - d.env = current(); - super.visitDecl(d); - } - - override void visitImportDecl(ImportDecl i) - { - i.env.imports ~= i; - super.visitImportDecl(i); - } - - override void visitStmt(Stmt s) - { - s.env = current(); - s.stmtIndex = s.env.stmtIndex; - super.visitStmt(s); - } - - override void visitExp(Exp e) - { - e.env = current(); - e.stmtIndex = e.env.stmtIndex; - super.visitExp(e); - } - - override void visitFuncDecl(FuncDecl d) - { - current().put(d.identifier.get, d); - d.env = current(); - auto sc = push(); - - visitExp(d.returnType); - visitExp(d.identifier); - sc.parentFunction = d; - foreach (arg; d.funcArgs) - visitDecl(arg); - foreach (stmt; d.statements) - { - sc.currentStmtIndex++; - visitStmt(stmt); - } - pop(sc); - } - - override void visitVarDecl(VarDecl d) - { - if (d.init) - visitExp(d.init); - - if (need_push > 0 && current().parentFunction !is null) { - push(); - --need_push; - } - - if(d.identifier) - { - auto sc = current(); - sc.put(d.identifier.get, d); - d.env = sc; - visitExp(d.varType); - visitExp(d.identifier); - } - } - - override void visitStructDecl(StructDecl s) - { - auto sc = current(); - sc.put(s.identifier.get, s); - s.env = sc; - auto type = new DStruct(s.identifier); - - sc.types[s.identifier.get] = type; - - sc = push(); - super.visitStructDecl(s); - pop(sc); - } - - override void visitClassDecl(ClassDecl s) - { - auto sc = current(); - sc.put(s.identifier.get, s); - s.env = sc; - auto type = new DClass(s.identifier); - - sc.types[s.identifier.get] = type; - - sc = push(); - super.visitClassDecl(s); - pop(sc); - } - - override void visitInterfaceDecl(InterfaceDecl s) - { - auto sc = current(); - sc.put(s.identifier.get, s); - s.env = sc; - auto type = new DInterface(s.identifier); - - sc.types[s.identifier.get] = type; - - sc = push(); - super.visitInterfaceDecl(s); - pop(sc); - } - - override void visitDeclStmt(DeclStmt d) - { - ++need_push; - super.visitDeclStmt(d); - } - private uint need_push = 0; - - override void visitIfStmt(IfStmt s) - { - s.env = current(); - visitExp(s.cond); - auto sc = push(); - visitStmt(s.then_body); - pop(sc); - - if (s.else_body !is null) - { - sc = push(); - visitStmt(s.else_body); - pop(sc); - } - } - - override void visitWhileStmt(WhileStmt s) - { - s.env = current(); - auto sc = push(); - super.visitWhileStmt(s); - pop(sc); - } - - override void visitForStmt(ForStmt s) - { - s.env = current(); - auto sc = push(); - super.visitForStmt(s); - pop(sc); - } - - override void visitCompoundStmt(CompoundStatement s) - { - s.env = current(); - auto sc = push(); - super.visitCompoundStmt(s); - pop(sc); - } - -private: - Scope[] table; - SymbolFactory sf; - - Scope push() - { - auto sc = new Scope(current()); - table ~= sc; - return sc; - } - - Scope pop(Scope sc = null) - { - if (sc !is null) - { - table.length = table.find(sc); - return sc; - } - - auto res = table[$ - 1]; - table.length = table.length - 1; - return res; - } - - Scope current() - { - return table[$ - 1]; - } -} - diff -r 658178183018 -r 08f68d684047 sema/ScopeCheck.d --- a/sema/ScopeCheck.d Fri Jul 25 15:31:16 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -module sema.ScopeCheck; - -import sema.Visitor, - sema.Symbol, - sema.Scope, - sema.DType; - -import basic.Message, - basic.Attribute; - -import tango.io.Stdout; - -class ScopeCheck : Visitor!(void) -{ - - this(MessageHandler messages) - { - this.messages = messages; - } - - override void visitIdentifier(Identifier i) - { - auto symbol = i.env.find(i.get); - - if(symbol is null) - messages.report(UndefinedIdentifier, i.loc) - .arg(i.get); - } - - override void visitVarDecl(VarDecl d) - { - if(d.identifier.get is null) - messages.report(UndefinedType, d.varType.loc) - .arg(d.varType.get); - - auto env = d.env; - if (d.env.enclosing) - if (d.env.enclosing.find(d.identifier.get) !is null) - if (d.env.parentFunction !is null) - while( d.env.parentFunction.env !is 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; - } - - visitExp(d.identifier); - if (d.init) - visitExp(d.init); - } - - override void visitFuncDecl(FuncDecl f) - { - visitExp(f.identifier); - - inFunction = true; - foreach (stmt; f.statements) - visitStmt(stmt); - inFunction = false; - } - - override void visitImportDecl(ImportDecl) { } - - override void visitCastExp(CastExp exp) - { - visitExp(exp.exp); - } - - override void visitMemberReference(MemberReference m) - { - internalVisitMemberRef(m); - } - - 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: - 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; - return visitRef(m, cast(Identifier)m.target, s); - } - } - - override void visitExp(Exp exp) - { - if (exp.expType == ExpType.Identifier && inFunction - && exp.env.find((cast(Identifier)exp).get) !is null) - { - if (exp.env.findType((cast(Identifier)exp).get) is null) - internalCheckProtection( - exp.env.find((cast(Identifier)exp).get)[0].sym, - cast(Identifier)exp); - } - - super.visitExp(exp); - } - - private void internalCheckProtection(Symbol sym, Identifier iden) - { - if (isChildOf(sym.decl.env, iden.env)) - return; - - switch(sym.decl.att.getProtection) - { - case Protection.Private: -/* if (iden.env.inModule == sym.decl.getIdentifier.env.inModule - && sym.decl.getIdentifier.env.enclosing == iden.env.inModule) - {} - else*/ - messages.report(CannotAccessPrivate, iden.loc); - return; - default: - return; - } - } - - private bool isChildOf(Scope parent, Scope child) - { - if (child is parent) - return true; - - if (child.enclosing !is null) - return isChildOf(parent, child.enclosing); - - return false; - } - - private bool isType(char[] s) - { - return (s in types? true : false); - } - - int[char[]] types; - MessageHandler messages; - bool inFunction; -} - diff -r 658178183018 -r 08f68d684047 sema/TypeCheck.d --- a/sema/TypeCheck.d Fri Jul 25 15:31:16 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,475 +0,0 @@ -module sema.TypeCheck; - -import sema.Visitor, - sema.Symbol, - sema.DType; - -import tango.io.Stdout, - Integer = tango.text.convert.Integer; - -import basic.SourceLocation, - basic.Message; - -class TypeCheck : Visitor!(void) -{ - this(MessageHandler messages) - { - this.messages = messages; - } - - override void visitBinaryExp(BinaryExp exp) - { - super.visitBinaryExp(exp); - - if(!(exp.left.type is exp.right.type)) - { - if (!exp.right.type.hasImplicitConversionTo(exp.left.type) && - !exp.left.type.hasImplicitConversionTo(exp.right.type)) - messages.report(InvalidImplicitCast, exp.loc) - .arg(exp.right.type.toString) - .arg(exp.left.type.toString); - else - { - CastExp castExp; - if(exp.left.type.isReal && exp.right.type.isReal) - if(exp.left.type.byteSize > exp.right.type.byteSize) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - else - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.right.type.name), - exp.left); - else if(exp.left.type.isReal || exp.right.type.isReal) - if(exp.left.type.isReal) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - else - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.right.type.name), - exp.left); - else - if(exp.left.type.byteSize > exp.right.type.byteSize) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - else if(exp.left.type.byteSize > exp.right.type.byteSize) - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.right.type.name), - exp.left); - else - castExp = new CastExp( - SLoc.Invalid, - new Identifier(exp.left.type.name), - exp.right); - - - if(castExp) - { - castExp.env = exp.env; - if(castExp.exp == exp.right) - exp.right = castExp; - else - exp.left = castExp; - - } - } - } - if (exp.op >= BinaryExp.Operator.LeftShift && - exp.op <= BinaryExp.Operator.UnsignedRightShift) - {} // FIXME: When we have const-system we need to check for - // right site being larger then the bitsize of the - // left - } - - override void visitDerefExp(DerefExp exp) - { - if (!exp.exp.type.isPointer) - { - messages.report(CanOnlyDerefPointers, - [exp.exp.sourceRange][], - [exp.loc]) - .arg(exp.exp.type.toString); - - exp._type = DType.Int; - } - } - - override void visitCallExp(CallExp exp) - { - super.visitCallExp(exp); - - if (auto iden = cast(MemberReference)exp.exp) - { - Symbol[] internalVisitMemberRef(MemberReference m) - { - Symbol[] visitRef(MemberReference m, Identifier target, Symbol st) - { - auto child = m.child; - auto res = st.findMembers(child.get); - return res; - } - switch(m.target.expType) - { - case ExpType.Identifier: - return visitRef(m, cast(Identifier)m.target, - (cast(Identifier)m.target).getSymbol); - case ExpType.MemberReference: - Symbol[] s = internalVisitMemberRef(cast(MemberReference)m.target); - if(s.length) - return s; - return visitRef(m, cast(Identifier)m.target, s[0]); - } - } - - Exp[] newArgs; - - DFunction function_type; - if (iden.type.isFunction()) - { - Symbol[] methods = internalVisitMemberRef(iden); - - if (!methods.length) - { - messages.report(NoMethodByName, iden.loc); - return; - } - - Symbol sel = getBestMatch(exp.args, methods); - exp.callSym = sel; - if (sel) - function_type = sel.type.asFunction(); - else - { - messages.report(NoMachingMethod, exp.loc); - foreach ( i, s ; methods ) - { - messages.report(CandidateNr, - (cast(FuncDecl)s.decl).identifier.loc) - .arg(Integer.toString(i+1)); - } - } - } - else if (iden.type.isCallable) - function_type = iden.type.asCallable(); - else assert(0, "Should not happen"); - - foreach (i, arg; exp.args) - { - auto argType = function_type.params[i]; - auto expType = arg.type; - if (argType.isSame(expType)) - { - 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 = iden.env; - newArgs ~= castExp; - } - else - newArgs ~= arg; - } - exp.args = newArgs; - } - else if (auto iden = cast(Identifier)exp.exp) - { - Exp[] newArgs; - - DFunction function_type; - if (iden.type.isFunction()) - { - 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); - exp.callSym = sel; - if (sel) - function_type = sel.type.asFunction(); - else - { - messages.report(NoMachingMethod, exp.loc); - foreach ( i, s ; methods ) - { - messages.report(CandidateNr, - (cast(FuncDecl)s.decl).identifier.loc) - .arg(Integer.toString(i+1)); - } - } - } - else if (iden.type.isCallable) - { - function_type = iden.type.asCallable(); - if (exp.args.length != function_type.params.length) - { - messages.report(CannotCallMethod, exp.loc) - .arg(iden.type.toString) - .arg(exp.callerType.toString); - } - } - else assert(0, "Should not happen"); - - foreach (i, arg; exp.args) - { - auto argType = function_type.params[i]; - auto expType = arg.type; - if (!argType.isSame(expType)) - { - 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 = iden.env; - newArgs ~= castExp; - } - else - newArgs ~= arg; - } - exp.args = newArgs; - } - else - { - Exp[] newArgs; - - foreach(i, arg; exp.args) - { - auto argType = exp.exp.type.asFunction.params[i]; - auto expType = arg.type; - if(!argType.isSame(expType)) - { - 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) - { - super.visitNewExp(exp); - - Exp[] newArgs; - - Symbol[] methods = exp.newType.getSymbol.findFunctionMembers("this"); - - if (!methods.length) - { - messages.report(NoConstructor, exp.newType.loc); - return; - } - - Symbol sel = getBestMatch(exp.c_args, methods); - - if (sel) - { - foreach (i, arg; exp.c_args) - { - auto argType = sel.type.asFunction.params[i]; - auto expType = arg.type; - if (!argType.isSame(expType)) - { - 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)); - } - } - } - - override void visitAssignExp(AssignExp exp) - { - super.visitAssignExp(exp); - - auto identifierType = exp.identifier.type; - auto expType = exp.exp.type; - - if(!identifierType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(identifierType)) - messages.report(InvalidImplicitCast, - [exp.identifier.sourceRange, exp.exp.sourceRange][], - [exp.loc]) - .arg(expType.toString) - .arg(identifierType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(identifierType.name), - exp.exp); - castExp.env = exp.exp.env; - exp.exp = castExp; - } - - if (expType.isStaticArray) - messages.report(CannotReassignSArray, - [exp.identifier.sourceRange, exp.exp.sourceRange][], - [exp.loc]); - } - - override void visitReturnStmt(ReturnStmt stmt) - { - super.visitReturnStmt(stmt); - - if(stmt.exp) - { - auto returnType = stmt.env.parentFunction.type.asFunction.returnType; - auto expType = stmt.exp.type; - if(!returnType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(returnType)) - messages.report(InvalidImplicitCast, stmt.exp.loc) - .arg(expType.toString) - .arg(returnType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(returnType.name), - stmt.exp); - castExp.env = stmt.exp.env; - stmt.exp = castExp; - } - } - } - - override void visitVarDecl(VarDecl decl) - { - super.visitVarDecl(decl); - - if(decl.init) - { - auto varType = decl.identifier.type; - auto expType = decl.init.type; - if(!varType.isSame(expType)) - { - if(!expType.hasImplicitConversionTo(varType)) - messages.report(InvalidImplicitCast, decl.init.loc) - .arg(expType.toString) - .arg(varType.toString); - - auto castExp = new CastExp( - SLoc.Invalid, - new Identifier(varType.name), - decl.init); - castExp.env = decl.init.env; - decl.init = castExp; - } - } - } - - private Symbol getBestMatch(Exp[] arg_list , Symbol[] available) - in - { - foreach (a ; available) - assert(a.type.isFunction, "A non-function found in available-list."); - } - body - { - assert(available.length, "No available methods in symbol-list."); - - Symbol[] possible; - Symbol perfect; - - bool per, work; - foreach (s ; available) - { - if (s.type.asFunction.params.length < arg_list.length) - continue; - - per = true; - work = true; - - foreach (i, arg; arg_list) - { - auto argType = s.type.asFunction.params[i]; - auto expType = arg.type; - if (argType.isSame(expType)) - { - per = false; - if( !expType.hasImplicitConversionTo(argType) ) - { - work = false; - break; - } - } - } - - 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) - return possible[0]; - - return null; - } - - MessageHandler messages; -} - diff -r 658178183018 -r 08f68d684047 sema/Visitor.d --- a/sema/Visitor.d Fri Jul 25 15:31:16 2008 +0200 +++ b/sema/Visitor.d Tue Jul 29 13:54:44 2008 +0200 @@ -49,6 +49,8 @@ return visitClassDecl(cast(ClassDecl)decl); case DeclType.InterfaceDecl: return visitInterfaceDecl(cast(InterfaceDecl)decl); + case DeclType.AliasDecl: + return visitAliasDecl(cast(AliasDecl)decl); default: throw new Exception("Unknown declaration type"); } @@ -119,6 +121,8 @@ return visitNewExp(cast(NewExp)exp); case ExpType.ArrayLiteralExp: return visitArrayLiteralExp(cast(ArrayLiteralExp)exp); + case ExpType.NullExp: + return visitNullExp(cast(NullExp)exp); default: throw new Exception("Unknown expression type"); } @@ -217,6 +221,14 @@ return DeclT.init; } + DeclT visitAliasDecl(AliasDecl a) + { + static if (is(DeclT == void)) + return; + else + return DeclT.init; + } + // Statements: StmtT visitReturnStmt(ReturnStmt s) { @@ -485,5 +497,13 @@ else return ExpT.init; } + + ExpT visitNullExp(NullExp n) + { + static if (is(ExpT == void)) + return; + else + return ExpT.init; + } } diff -r 658178183018 -r 08f68d684047 tests/parser/alias_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/parser/alias_1.d Tue Jul 29 13:54:44 2008 +0200 @@ -0,0 +1,21 @@ + +int foo(int x) +{ + return x + 6; +} + +alias foo bar; +alias int** i; +alias int A; +alias int B; + +int main() +{ + int x = bar(5); + i y = &x; + + A a = 5; + B b = a; + + return 11 - *y; +} diff -r 658178183018 -r 08f68d684047 tests/parser/null_1.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/parser/null_1.d Tue Jul 29 13:54:44 2008 +0200 @@ -0,0 +1,7 @@ + +int main() +{ + int* i = null; + + return 0; +}