view sema/BuildSymbols.d @ 196:bb06ffcfb170 old_impl

Old impl branch.
author Anders Johnsen <skabet@gmail.com>
date Sun, 10 Aug 2008 16:16:55 +0200
parents 08f68d684047
children
line wrap: on
line source

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