view sema/ScopeBuilder.d @ 92:771ac63898e2 new_gen

A few better parser errors plus renaming most of the sema classes to match that they do now. Some have changes a lot.
author Anders Johnsen <skabet@gmail.com>
date Mon, 05 May 2008 18:44:20 +0200
parents sema/SymbolTableBuilder.d@29f486ccc203
children 621cedba53ea
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(Decl[] decls)
    {
        foreach (decl; decls)
            visitDecl(decl);
    }

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

        auto sym = d.env.find(d.identifier);
        sym.type = d.type;
    }

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

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

    override void visitStructDecl(StructDecl s)
    {
        DType[char[]] types;

        auto st = s.env.types[s.identifier.get].asStruct;
        foreach(varDecl ; s.vars)
            st.addMember(typeOf(varDecl.varType, varDecl.env), varDecl.identifier.get);

        super.visitStructDecl(s);
    }

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

class ScopeBuilder : Visitor!(void)
{
    this()
    {
        table ~= new Scope;
        table[0].types["void"]    = DType.Void;
        table[0].types["bool"]    = DType.Bool;
        table[0].types["byte"]    = DType.Byte;
        table[0].types["ubyte"]   = DType.UByte;
        table[0].types["short"]   = DType.Short;
        table[0].types["ushort"]  = DType.UShort;
        table[0].types["int"]     = DType.Int;
        table[0].types["uint"]    = DType.UInt;
        table[0].types["long"]    = DType.Long;
        table[0].types["ulong"]   = DType.ULong;
    }

    override void visit(Decl[] decls)
    {
        foreach (decl; decls)
            visitDecl(decl);
        auto fr = new ForwardReference();
        fr.visit(decls);
    }

    override void visitDecl(Decl d)
    {
        d.env = current();
        super.visitDecl(d);
    }

    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)
    {
        auto sym = 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();
        auto sym = sc.add(d.identifier);
        d.env = sc;
        visitExp(d.varType);
        visitExp(d.identifier);
    }

    override void visitStructDecl(StructDecl s)
    {
        auto sc = current();
        auto sym = 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];
    }
}