view ast/Stmt.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 eb5b2c719a39
children 3a0cd42de9cc
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.Scope,
       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;
}