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;
+}
+