view ast/Stmt.d @ 88:eb5b2c719a39 new_gen

Major change to locations, tokens and expressions. A location (now SourceLocation or SLoc) is only 32 bit in size - disadvantage is that it can't find its own text. You have to go through the new SourceManager to do that. This has caused changes to a lot of stuff and removal of DataSource and the old Location Additionally Exp has gotten some location stuff, so we can give proper error messages. Not in Decl and Stmt yet, but thats coming too.
author Anders Halager <halager@gmail.com>
date Sun, 04 May 2008 18:13:46 +0200
parents 91f10c34cd7b
children 771ac63898e2
line wrap: on
line source

module ast.Stmt;

import Array = tango.core.Array,
       Integer = tango.text.convert.Integer,
       tango.io.Stdout;

import ast.Exp,
       ast.Decl;

import sema.SymbolTable,
       basic.SourceLocation,
       misc.Error;

enum StmtType
{
    Stmt,
    Compound,
    Decl,
    Exp,
    Return,
    If,
    While,
    Switch,
}

class Stmt
{
    this(StmtType stmtType = StmtType.Stmt)
    {
        this.stmtType = stmtType;
    }

    void simplify()
    {
    }

    StmtType stmtType;
    Scope env;
    int stmtIndex;
}

class CompoundStatement : Stmt
{
    this(Stmt[] stmts)
    {
        super(StmtType.Compound);
        this.statements = stmts;
    }

    void simplify()
    {
        foreach ( stmt ; statements )
            stmt.simplify;
    }

    Stmt[] statements;
}

class ReturnStmt : Stmt
{
    this()
    {
        super(StmtType.Return);
    }

    void simplify()
    {
        FuncDecl f = env.parentFunction;
        if(exp)
           exp.simplify;
        if(f !is null && f.sret)
        {
            auto i = new Identifier("ret.val");
            i.env = f.env;
            auto ass = new AssignExp(SLoc.Invalid, i, exp);
            ass.env = f.env;
            auto assStmt = new ExpStmt(ass);
            assStmt.env = f.env;

            Stmt[] stmts;
            foreach(index, stmt ; f.statements)
            {
                if(stmtIndex == index)
                    stmts ~= assStmt;

                stmts ~= stmt;
            }
            f.statements = stmts;
            
            exp = null;
        }
    }

    public Exp exp;
}

class DeclStmt : Stmt
{
    this(Decl decl)
    {
        super(StmtType.Decl);
        this.decl = decl;
    }

    void simplify()
    {
        decl.simplify;
    }

    public Decl decl;
}

class ExpStmt : Stmt
{
    this(Exp exp)
    {
        super(StmtType.Exp);
        this.exp = exp;
    }

    void simplify()
    {
        exp = exp.simplify;
    }

    public Exp exp;
}

class IfStmt : Stmt
{
    this(Exp cond, Stmt then, Stmt el = null)
    {
        super(StmtType.If);
        this.cond = cond;
        this.then_body = then;
        this.else_body = el;
    }

    void simplify()
    {
        cond.simplify;
        then_body.simplify;
        if (else_body)
            else_body.simplify;
    }

    Exp cond;
    Stmt then_body;
    Stmt else_body;
}

class WhileStmt : Stmt
{
    this(Exp cond, Stmt stmts)
    {
        super(StmtType.While);
        this.cond = cond;
        this.whileBody = stmts;
    }

    void simplify()
    {
        cond.simplify;
        whileBody.simplify;
    }

    Exp cond;
    Stmt whileBody;
}

class SwitchStmt : Stmt
{
    this(Exp target)
    {
        super(StmtType.Switch);
        cond = target;
    }

    void addCase(IntegerLit[] values, Stmt[] stmts)
    {
        long[] new_values;
        foreach (lit; values)
            new_values ~= Integer.parse(lit.get);
        cases ~= Case(values, stmts, new_values);

        // Make sure there is no two cases with the same value
        // Does it belong here?
        new_values = new_values.dup;
        Array.sort(new_values);
        long[] all_values = Array.unionOf(old_values, new_values);
        if (all_values.length != old_values.length + new_values.length)
        {
            // overlap!
            auto e = new Error(
                    "Can't have multiple cases with the same value."
                    " Values appearing in multiple cases: %0");
            //e.loc(values[0].token.location);

            all_values = Array.intersectionOf(old_values, new_values);
            char[][] vals;
            foreach (val; all_values)
                vals ~= Integer.toString(val);
            e.arg(vals);
            /*
            foreach (c; cases)
                foreach (i, v; c.values_converted)
                    if (Array.bsearch(all_values, v))
                        e.tok(c.values[i].token);
            */
            throw e;
        }
        old_values = all_values;
    }

    void setDefault(Stmt[] stmts)
    {
        if (defaultBlock.length != 0)
            throw new Error("Switch statements can't have multiple defaults");
        defaultBlock = stmts;
        if (cases.length > 0)
            cases[$ - 1].followedByDefault = true;
    }

    void simplify()
    {
        cond.simplify;
        foreach ( stmt ; defaultBlock )
            stmt.simplify;
        foreach ( c ; cases )
            foreach ( stmt ; c.stmts )
                stmt.simplify;
    }

    Exp cond;
    Case[] cases;
    Stmt[] defaultBlock;

    struct Case
    {
        IntegerLit[] values;
        Stmt[] stmts;
        long[] values_converted;
        bool followedByDefault = false;
    }

    private long[] old_values;
}