Mercurial > projects > dang
view ast/Stmt.d @ 143:d76cc5cad4fc
Added partial support for switches.
Added support for extern(C) in CodeGen.
author | Anders Johnsen <skabet@gmail.com> |
---|---|
date | Mon, 21 Jul 2008 01:05:20 +0200 |
parents | a22e3663de89 |
children | 393a1f47a6d2 6c5a3c0bb4fb |
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; 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; } override void simplify() { foreach (stmt; statements ) stmt.simplify(); } Stmt[] statements; } class ReturnStmt : Stmt { this() { super(StmtType.Return); } // Needed? override void simplify() { FuncDecl f = env.parentFunction; if (exp) 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, BinaryExp.Operator.Assign, 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; } override void simplify() { decl.simplify(); } public Decl decl; } class ExpStmt : Stmt { this(Exp exp) { super(StmtType.Exp); this.exp = exp; } override 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; } override void simplify() { cond = 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; } override void simplify() { cond = cond.simplify(); whileBody.simplify(); } Exp cond; Stmt whileBody; } class SwitchStmt : Stmt { this(Exp target) { super(StmtType.Switch); cond = target; } void addCase(Exp[] values, Stmt[] stmts) { // long[] new_values; // foreach (lit; values) // new_values ~= Integer.parse(lit.get); // cases ~= Case(values, stmts, new_values); cases ~= Case(values, stmts); // 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! // TODO: Move this to another sema file where it can be enforced. /+ 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) { // TODO: Move this to another sema file where it can be enforced. /* if (defaultBlock.length != 0) throw new Error("Switch statements can't have multiple defaults"); */ defaultBlock = stmts; if (cases.length > 0) cases[$ - 1].followedByDefault = true; } override void simplify() { cond = cond.simplify(); foreach ( stmt ; defaultBlock ) stmt.simplify(); foreach ( c ; cases ) foreach ( stmt ; c.stmts ) stmt.simplify(); } Exp cond; Case[] cases; Stmt[] defaultBlock; struct Case { Exp[] values; Stmt[] stmts; long[] values_converted; bool followedByDefault = false; } private long[] old_values; }