Mercurial > projects > dang
view sema/ScopeCheck.d @ 185:7b274cfdc1dc
Added support for array literals. Codegen is broken, though.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Fri, 25 Jul 2008 12:18:05 +0200 |
parents | 01c2c49775ef |
children |
line wrap: on
line source
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; }