view sema/BuildScopes.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
children
line wrap: on
line source

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