view sema/SymbolTableBuilder.d @ 28:69464d465284 new_gen

Now supporting structs - both read and write. Still a few errors though, so watch out.
author Anders Johnsen <skabet@gmail.com>
date Sun, 20 Apr 2008 11:20:28 +0200
parents 9031487e97d7
children 495188f9078e
line wrap: on
line source

module sema.SymbolTableBuilder;

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

public
import sema.SymbolTable;

import sema.Visitor;

class SymbolTableBuilder : 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);
    }

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

    override void visitStmt(Stmt s)
    {
        s.env = current();
        super.visitStmt(s);
    }

    override void visitExp(Exp e)
    {
        e.env = current();
        super.visitExp(e);
    }

    override void visitFuncDecl(FuncDecl d)
    {
        auto sym = current().add(d.identifier);
        auto sc = push();
        sym.type = typeOf(d.type, sc);
        visitExp(d.type);
        visitExp(d.identifier);
        d.env = current();
        sc.parentFunction = sym;
        foreach (arg; d.funcArgs)
            visitDecl(arg);
        foreach (stmt; d.statements)
            visitStmt(stmt);
        pop(sc);
    }

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

        if (need_push > 0) {
            push();
            --need_push;
        }

        auto sc = current();
        auto sym = sc.add(d.identifier);
        sym.type = typeOf(d.type, sc);
        d.env = sc;
        visitExp(d.type);
        visitExp(d.identifier);
    }

    override void visitStructDecl(StructDecl s)
    {
        auto sc = current();
        auto sym = sc.add(s.identifier);
        DType[char[]] types;
        foreach(varDecl ; s.vars)
        {
            types[varDecl.identifier.get] = typeOf(varDecl.type, sc);
        }

        auto type = new DStruct(s.identifier);
        
        type.setMembers(types);

        sc.types[s.identifier.get] = type;
        sym.type = type;
        s.env = sc;
        super.visitStructDecl(s);
    }

    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();
        foreach (stmt; s.then_body)
            visitStmt(stmt);
        pop(sc);

        sc = push();
        foreach (stmt; s.else_body)
            visitStmt(stmt);
        pop(sc);
    }

    override void visitWhileStmt(WhileStmt s)
    {
        s.env = current();
        auto sc = push();
        super.visitWhileStmt(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];
    }

    DType typeOf(Identifier id, Scope sc)
    {
        return sc.findType(id);

        /*
        if (auto type = id.get in types)
            return *type;
        DType res = new DType(id);
        types[id.get] = res;
        return res;*/
    }
    DType[char[]] types;
}