view sema/ScopeBuilder.d @ 119:c0b531362ca6

Non compileing commit. Work on floating points and casts
author Anders Johnsen <skabet@gmail.com>
date Sun, 25 May 2008 19:13:07 +0200
parents 189c049cbfcc
children ed815b31479b
line wrap: on
line source

module sema.ScopeBuilder;

import tango.io.Stdout,
       tango.core.Array : find;

public
import sema.Scope;

import sema.Visitor,
       basic.SmallArray;

class ForwardReference : Visitor!(void)
{
    override void visit(Module[] modules)
    {
        this.modules = modules;
        super.visit(modules);
    }

    override void visitFuncDecl(FuncDecl d)
    {
        visitExp(d.returnType);
        visitExp(d.identifier);
        foreach (arg; d.funcArgs)
            visitDecl(arg);
        foreach (stmt; d.statements)
            visitStmt(stmt);

        d.env.find(d.identifier).setType(d.type);
    }

    override void visitVarDecl(VarDecl d)
    {
        visitExp(d.varType);
        visitExp(d.identifier);
        
        if (d.init)
            visitExp(d.init);

        d.env.find(d.identifier).setType( typeOf(d.varType, d.env) );
    }

    override void visitStructDecl(StructDecl s)
    {
        super.visitStructDecl(s);

        DType[char[]] types;

        auto st = s.env.types[s.identifier.get].asStruct;
        foreach (decl; s.decls)
            if (auto varDecl = cast(VarDecl)decl)
                st.addMember(typeOf(varDecl.varType, varDecl.env), varDecl.identifier.get);
            else if (auto fd = cast(FuncDecl)decl)
                st.addMember(fd.type, fd.identifier.get);
    }

    DType typeOf(Identifier id, Scope sc)
    {
        if(auto i = cast(PointerIdentifier)id)
            return (typeOf(i.pointerOf, sc)).getPointerTo();
        if(auto i = cast(ArrayIdentifier)id)
            return typeOf(i.arrayOf, sc).getAsArray(i.size);
        return sc.findType(id);
    }

    Module[] modules;
}

class ScopeBuilder : Visitor!(void)
{
    static ModuleHandler mHandle;

    static this()
    {
        mHandle = new ModuleHandler;
    }

    this()
    {
    }

    override void visit(Module[] modules)
    {
        foreach(m ; modules)
            visitModule(m);

        auto fr = new ForwardReference();

        fr.visit(modules);
    }

    override void visitModule(Module m)
    {
        table ~= new Scope;
        table[table.length-1].types["void"]    = DType.Void;
        table[table.length-1].types["bool"]    = DType.Bool;
        table[table.length-1].types["byte"]    = DType.Byte;
        table[table.length-1].types["ubyte"]   = DType.UByte;
        table[table.length-1].types["short"]   = DType.Short;
        table[table.length-1].types["ushort"]  = DType.UShort;
        table[table.length-1].types["int"]     = DType.Int;
        table[table.length-1].types["uint"]    = DType.UInt;
        table[table.length-1].types["long"]    = DType.Long;
        table[table.length-1].types["ulong"]   = DType.ULong;
        table[table.length-1].types["char"]    = DType.Char;
        table[table.length-1].types["wchar"]   = DType.WChar;
        table[table.length-1].types["dchar"]   = DType.DChar;

        table[table.length-1].types["float"]   = DType.Float;
        table[table.length-1].types["double"]  = DType.Double;
        table[table.length-1].types["real"]    = DType.Real;

        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().add(d.identifier);
        auto sc = push();

        visitExp(d.returnType);
        visitExp(d.identifier);
        d.env = current();
        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;
        }

        auto sc = current();
        sc.add(d.identifier);
        d.env = sc;
        visitExp(d.varType);
        visitExp(d.identifier);
    }

    override void visitStructDecl(StructDecl s)
    {
        auto sc = current();
        sc.add(s.identifier);
        s.env = sc;
        auto type = new DStruct(s.identifier);
        
        sc.types[s.identifier.get] = type;

        sc = push();
        super.visitStructDecl(s);
        pop(sc);
    }

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