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;
+}
+