Mercurial > projects > dang
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; }