Mercurial > projects > dang
diff sema/CheckScopes.d @ 194:08f68d684047
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.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Tue, 29 Jul 2008 13:54:44 +0200 |
parents | sema/ScopeCheck.d@01c2c49775ef |
children |
line wrap: on
line diff
--- /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; +} +