Mercurial > projects > dang
diff ast/Stmt.d @ 36:ce17bea8e9bd new_gen
Switch statements support
Can only switch on IntegerLit's but multiple values per case and the
default are supported.
An error is emitted if a value is used multiple times or if theres is more
than one default block
author | Anders Halager <halager@gmail.com> |
---|---|
date | Sun, 20 Apr 2008 22:39:07 +0200 |
parents | 642c6a998fd9 |
children | 495188f9078e |
line wrap: on
line diff
--- a/ast/Stmt.d Sun Apr 20 21:33:50 2008 +0200 +++ b/ast/Stmt.d Sun Apr 20 22:39:07 2008 +0200 @@ -1,9 +1,13 @@ module ast.Stmt; +import Array = tango.core.Array, + Integer = tango.text.convert.Integer; + import ast.Exp, ast.Decl; -import sema.SymbolTable; +import sema.SymbolTable, + misc.Error; enum StmtType { @@ -13,6 +17,7 @@ Return, If, While, + Switch, } class Stmt @@ -86,3 +91,71 @@ Stmt[] stmts; } +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.token.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; + } + + Exp cond; + Case[] cases; + Stmt[] defaultBlock; + + struct Case + { + IntegerLit[] values; + Stmt[] stmts; + long[] values_converted; + bool followedByDefault = false; + } + + private long[] old_values; +} +