changeset 153:ee202c72cd30

Merge
author Anders Halager <halager@gmail.com>
date Mon, 21 Jul 2008 21:32:20 +0200
parents 893f23a9de93 (diff) 393a1f47a6d2 (current diff)
children 0ea5d2f3e96b
files ast/Stmt.d parser/Action.d sema/AstAction.d
diffstat 12 files changed, 660 insertions(+), 619 deletions(-) [+]
line wrap: on
line diff
--- a/ast/Decl.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/ast/Decl.d	Mon Jul 21 21:32:20 2008 +0200
@@ -10,6 +10,7 @@
 import sema.Scope,
        sema.Symbol,
        sema.DType,
+       sema.VC,
        basic.SmallArray,
        basic.Attribute;
 
@@ -35,6 +36,10 @@
     {
     }
 
+    void verify(VC vc)
+    {
+    }
+
     DType type()
     {
         if (sym !is null)
@@ -80,10 +85,6 @@
         this.init = e;
     }
 
-    void simplify()
-    {
-    }
-
     override DType type()
     {
         return env.findType(varType.get);
@@ -171,6 +172,12 @@
             stmt.simplify();
     }
 
+    override void verify(VC vc)
+    {
+        foreach (stmt; statements)
+            stmt.verify(vc);
+    }
+
     override DFunction type()
     {
         if (myType !is null)
@@ -212,6 +219,12 @@
     {
     }
 
+    override void verify(VC vc)
+    {
+        foreach (decl; decls)
+            decl.verify(vc);
+    }
+
     override DType type()
     {
         return env.findType(identifier.get);
--- a/ast/Module.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/ast/Module.d	Mon Jul 21 21:32:20 2008 +0200
@@ -1,6 +1,7 @@
 module ast.Module;
 
 import sema.Scope,
+       sema.VC,
        sema.Symbol;
 
 import ast.Decl;
@@ -37,6 +38,12 @@
         decls ~= decl;
     }
 
+    void verify(VC vc)
+    {
+        foreach (decl; decls)
+            decl.verify(vc);
+    }
+
     VarDecl[]       vars;
     FuncDecl[]      functions;
     StructDecl[]    structs;
--- a/ast/Stmt.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/ast/Stmt.d	Mon Jul 21 21:32:20 2008 +0200
@@ -8,6 +8,8 @@
        ast.Decl;
 
 import sema.Scope,
+       sema.VC,
+       basic.Message,
        basic.SourceLocation;
 
 enum StmtType
@@ -23,7 +25,7 @@
     Switch,
 }
 
-class Stmt
+abstract class Stmt
 {
     this(StmtType stmtType = StmtType.Stmt)
     {
@@ -34,6 +36,17 @@
     {
     }
 
+    void verify(VC vc) {}
+
+    /// The "main" location of the expression.
+    SourceLocation loc;
+
+    /// Return the starting location of this statement
+    SourceLocation startLoc() { return loc; }
+
+    /// Get the full extents of the expression
+    SourceRange sourceRange() { return SourceRange(loc, loc + 1); }
+
     StmtType stmtType;
     Scope env;
     int stmtIndex;
@@ -191,60 +204,25 @@
 
 class SwitchStmt : Stmt
 {
-    this(Exp target)
+    this(SourceLocation loc, Exp target)
     {
         super(StmtType.Switch);
         cond = target;
+        this.loc = loc;
+    }
+
+    void addCase(SourceLocation _case, Exp[] values, Stmt[] stmts)
+    {
+        cases ~= Case(_case, values, stmts);
     }
 
-    void addCase(Exp[] values, Stmt[] stmts)
+    void setDefault(SourceLocation _default, 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);
+        if (defaultBlock !is null)
+            extraDefaultBlocks = true;
 
-            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;
+        defaultLoc = _default;
         if (cases.length > 0)
             cases[$ - 1].followedByDefault = true;
     }
@@ -259,18 +237,55 @@
                 stmt.simplify();
     }
 
+    override void verify(VC vc)
+    {
+        if (extraDefaultBlocks)
+            vc.msg.report(MultipleDefaults, defaultLoc);
+
+        if (cases.length == 0)
+            return;
+
+        scope long[] all_values;
+        foreach (ref Case; cases)
+        {
+            long[] new_values;
+            foreach (exp; Case.values)
+                if (auto lit = cast(IntegerLit)exp)
+                    new_values ~= Integer.parse(lit.get);
+                else
+                    // We flag all non-literals and ignore them
+                    vc.msg.report(InvalidCaseValue, exp.loc);
+            Case.values_converted = new_values;
+            all_values ~= new_values;
+        }
+
+        Array.sort(all_values);
+        char[][] overlapping;
+        size_t i = 0;
+        while ((i = Array.findAdj(all_values)) < all_values.length
+                && all_values.length > 0)
+        {
+            overlapping ~= Integer.toString(all_values[i]);
+            auto similar = Array.count(all_values, all_values[i]);
+            all_values = all_values[i + similar .. $];
+        }
+        if (overlapping.length > 0)
+            vc.msg.report(OverlappingCases, loc).arg(overlapping);
+    }
+
     Exp cond;
     Case[] cases;
     Stmt[] defaultBlock;
+    private bool extraDefaultBlocks = false;
+    private SourceLocation defaultLoc;
 
     struct Case
     {
+        SourceLocation caseLoc;
         Exp[] values;
         Stmt[] stmts;
         long[] values_converted;
         bool followedByDefault = false;
     }
-
-    private long[] old_values;
 }
 
--- a/basic/Message.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/basic/Message.d	Mon Jul 21 21:32:20 2008 +0200
@@ -146,7 +146,7 @@
 
     Message arg(char[] s)
     {
-        if (args.length == 11)
+        if (args.length > 10)
             throw new Exception("Sorry, errors only support up to 10 args");
         args ~= s;
         return this;
--- a/basic/Messages.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/basic/Messages.d	Mon Jul 21 21:32:20 2008 +0200
@@ -34,6 +34,10 @@
     UndefinedType,
     MissingMember,
     CannotRedeclare,
+    //   - switch
+    MultipleDefaults,
+    OverlappingCases,
+    InvalidCaseValue,
 
     // Strings
     InvalidStrPrefix,
@@ -103,6 +107,13 @@
         UndefinedType       : E(Err, "Undefined type '%0'"),
         MissingMember       : E(Err, "%0 %1 has no member %2"),
         CannotRedeclare     : E(Err, "Cannot redeclare '%0'"),
+        //   - switch
+        MultipleDefaults
+            : E(Err, "Switch statements can't have multiple defaults"),
+        OverlappingCases
+            : E(Err, "Can't have multiple cases with the same value."
+                     " Values appearing in multiple cases: %0"),
+        InvalidCaseValue    : E(Err, "Case values must be integers"),
 
         // literals
         InvalidStrPrefix    : E(Err, "Invalid string literal prefix"),
--- a/dang/compiler.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/dang/compiler.d	Mon Jul 21 21:32:20 2008 +0200
@@ -28,6 +28,7 @@
        sema.ScopeBuilder,
        sema.LiteralInterpreter,
        sema.ScopeCheck,
+       sema.VC,
        sema.TypeCheck;
 
 import tango.stdc.posix.unistd;
@@ -185,7 +186,7 @@
                     gcc.stdin.copy(llc.stdout);
                     gcc.stdin.detach;
                     gcc.wait();
-                    timings ~= Measurement("Generating assemble bytecode", w.stop);
+                    timings ~= Measurement("Generating ASM", w.stop);
                 }
 
             });
@@ -310,13 +311,21 @@
     watch.start;
     watch2.start;
     (new ScopeCheck(messages)).visit(modules);
+    messages.checkErrors;
     auto scope_check = watch2.stop;
+
     watch2.start;
-    messages.checkErrors;
     (new TypeCheck(messages)).visit(modules);
+    messages.checkErrors;
     auto type_check = watch2.stop;
+
     watch2.start;
+    auto vc = new VC;
+    vc.msg = messages;
+    foreach (m; modules)
+        m.verify(vc);
     messages.checkErrors;
+    auto ast_verify = watch2.stop;
 
     foreach (m; modules)
         foreach (decl; m.decls)
--- a/parser/Action.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/parser/Action.d	Mon Jul 21 21:32:20 2008 +0200
@@ -300,16 +300,16 @@
         return null;
     }
 
-    StmtT actOnStartOfSwitchStmt(ExprT exp)
+    StmtT actOnStartOfSwitchStmt(Token _switch, ExprT exp)
     {
         return null;
     }
 
-    void actOnCaseStmt(StmtT stmt, ExprT[] exps, StmtT[] stmts)
+    void actOnCaseStmt(StmtT stmt, Token _case, ExprT[] exps, StmtT[] stmts)
     {
     }
 
-    void actOnDefaultStmt(StmtT stmt, StmtT[] stmts)
+    void actOnDefaultStmt(StmtT stmt, Token _default, StmtT[] stmts)
     {
     }
 
--- a/parser/Parser.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/parser/Parser.d	Mon Jul 21 21:32:20 2008 +0200
@@ -499,621 +499,605 @@
         return a;
     }
 
-enum : uint 
-       { 
-           Single, 
-           Scope, 
-           All 
-       }
-
-       struct Att
-       {
-           Attribute a;
-           uint nested;
-       }
+    enum : uint
+    { 
+        Single, 
+        Scope, 
+        All 
+    }
 
-       /**
-         Parse statements.
-
-         This is the place to attack!
-        */
-       Stmt parseStatement()
-       {
-           Token t = peek;
+    struct Att
+    {
+        Attribute a;
+        uint nested;
+    }
 
-           if (t.isReturn)
-           {
-               Token ret = next();
-               Exp exp;
-               if (peek.type != Tok.Seperator)
-                   exp = parseExpression();
-               require(Tok.Seperator);
-               return action.actOnReturnStmt(ret, exp);
+    /**
+      Parse statements.
+
+      This is the place to attack!
+     */
+    Stmt parseStatement()
+    {
+        Token t = peek;
 
-               /*
-                  if (cond)
-                  single statement | compound statement
-                  [else
-                  single statement | compound statement]
-                */
-           }
-           else if (t.isIf)
-           {
-               Token _if = next();
+        if (t.isReturn)
+        {
+            Token ret = next();
+            Exp exp;
+            if (peek.type != Tok.Seperator)
+                exp = parseExpression();
+            require(Tok.Seperator);
+            return action.actOnReturnStmt(ret, exp);
+        }
+        /*
+           if (cond)
+           single statement | compound statement
+           [else
+           single statement | compound statement]
+         */
+        else if (t.isIf)
+        {
+            Token _if = next();
 
-               require(Tok.OpenParentheses);
-               Exp cond = parseExpression();
-               require(Tok.CloseParentheses);
+            require(Tok.OpenParentheses);
+            Exp cond = parseExpression();
+            require(Tok.CloseParentheses);
 
-               Stmt thenB = parseSingleOrCompoundStatement();
+            Stmt thenB = parseSingleOrCompoundStatement();
 
-               // if there is no else part we use the if as token, to have
-               // something than can be passed along
-               Token _else = _if;
-               Stmt elseB;
-               if (peek.type == Tok.Else)
-               {
-                   _else = next();
-                   elseB = parseSingleOrCompoundStatement();
-               }
+            // if there is no else part we use the if as token, to have
+            // something than can be passed along
+            Token _else = _if;
+            Stmt elseB;
+            if (peek.type == Tok.Else)
+            {
+                _else = next();
+                elseB = parseSingleOrCompoundStatement();
+            }
 
-               return action.actOnIfStmt(_if, cond, thenB, _else, elseB);
+            return action.actOnIfStmt(_if, cond, thenB, _else, elseB);
 
-               /*
-                  while (cond)
-                  single statement | compound statement
-                */
-           }
-           else if (t.isWhile)
-           {
-               Token _while = next();
-               require(Tok.OpenParentheses);
-               Exp cond = parseExpression();
-               require(Tok.CloseParentheses);
-               Stmt bodyStmt = parseSingleOrCompoundStatement();
-               return action.actOnWhileStmt(_while, cond, bodyStmt);
+        }
+        /*
+           while (cond)
+           single statement | compound statement
+         */
+        else if (t.isWhile)
+        {
+            Token _while = next();
+            require(Tok.OpenParentheses);
+            Exp cond = parseExpression();
+            require(Tok.CloseParentheses);
+            Stmt bodyStmt = parseSingleOrCompoundStatement();
+            return action.actOnWhileStmt(_while, cond, bodyStmt);
 
-               /*
-                  One of four things:
-                  A declaration of a function/variable `type id ...`
-                  A direct assignment `id = exp;`
-                  An indirect assignment `id.id = exp`
-                  Some sort of free standing expression
+        }
+        else if (t.isFor)
+        {
+            Token _for = next();
+            require(Tok.OpenParentheses);
+            Stmt init;
+            if ( isa(Tok.Seperator))
+                require(Tok.Seperator);
+            else
+                init = parseStatement();
+
+            Exp cond;
+            if ( !isa(Tok.Seperator))
+                cond = parseExpression();
+            require(Tok.Seperator);
 
-                  The assignments should be handled as binary expressions?
-                */
-           }
-           else if (t.isFor)
-           {
-               Token _for = next();
-               require(Tok.OpenParentheses);
-               Stmt init;
-               if ( isa(Tok.Seperator))
-                   require(Tok.Seperator);
-               else
-                   init = parseStatement();
+            Exp incre;
+            if ( !isa(Tok.CloseParentheses))
+                incre = parseExpression();
+            require(Tok.CloseParentheses);
 
-               Exp cond;
-               if ( !isa(Tok.Seperator))
-                   cond = parseExpression();
-               require(Tok.Seperator);
-
-               Exp incre;
-               if ( !isa(Tok.CloseParentheses))
-                   incre = parseExpression();
-               require(Tok.CloseParentheses);
+            Stmt bodyStmt = parseSingleOrCompoundStatement();
+            return action.actOnForStmt(_for, init, cond, incre, bodyStmt);
+        }
+        else if (t.isBasicType || t.isIdentifier)
+        {
+            Token iden = peek;
+            Token n = peek(1);
+            // Must be an decl, if we start with a basic type, or two
+            // identifiers in a row
+            if ( n.type == Tok.Star || n.type == Tok.OpenBracket)
+            {
+                int len = peekParseType;
+                if(peek(len).type == Tok.Identifier && len != 0)
+                    return action.actOnDeclStmt(parseVarDecl());
 
-               Stmt bodyStmt = parseSingleOrCompoundStatement();
-               return action.actOnForStmt(_for, init, cond, incre, bodyStmt);
-           }
-           else if (t.isBasicType || t.isIdentifier)
-           {
-               Token iden = peek;
-               Token n = peek(1);
-               // Must be an decl, if we start with a basic type, or two
-               // identifiers in a row
-               if ( n.type == Tok.Star || n.type == Tok.OpenBracket)
-               {
-                   int len = peekParseType;
-                   if(peek(len).type == Tok.Identifier && len != 0)
-                       return action.actOnDeclStmt(parseVarDecl());
+                Exp exp = parseExpression();
+                require(Tok.Seperator);
+                return action.actOnExprStmt(exp);
+            }
 
-                   Exp exp = parseExpression();
-                   require(Tok.Seperator);
-                   return action.actOnExprStmt(exp);
-               }
-
-               if (n.isIdentifier())
-                   return action.actOnDeclStmt(parseVarDecl());
+            if (n.isIdentifier())
+                return action.actOnDeclStmt(parseVarDecl());
 
-               // Expression: a.b, a = b, a(b) etc.
-               Exp exp = parseExpression();
-               require(Tok.Seperator);
-               return action.actOnExprStmt(exp);
-           }
-           else if(t.isSwitch)
-           {
-               next();
-               require(Tok.OpenParentheses);
-               auto target = parseExpression();
-               auto res = action.actOnStartOfSwitchStmt(target);
-               require(Tok.CloseParentheses);
-               require(Tok.OpenBrace);
-               while (true)
-               {
-                   Stmt[] statements;
-                   if (skip(Tok.Default))
-                   {
-                       require(Tok.Colon);
-                       statements.length = 0;
-                       while (peek.type != Tok.Case
-                               && peek.type != Tok.Default
-                               && peek.type != Tok.CloseBrace)
-                           statements ~= parseStatement();
-                       action.actOnDefaultStmt(res, statements);
-                       continue;
-                   }
+            // Expression: a.b, a = b, a(b) etc.
+            Exp exp = parseExpression();
+            require(Tok.Seperator);
+            return action.actOnExprStmt(exp);
+        }
+        else if (t.isSwitch)
+        {
+            next();
+            require(Tok.OpenParentheses);
+            auto target = parseExpression();
+            auto res = action.actOnStartOfSwitchStmt(t, target);
+            require(Tok.CloseParentheses);
+            require(Tok.OpenBrace);
+            while (true)
+            {
+                Stmt[] statements;
+                if (isa(Tok.Default))
+                {
+                    Token _default = next();
+                    require(Tok.Colon);
+                    statements.length = 0;
+                    while (peek.type != Tok.Case
+                            && peek.type != Tok.Default
+                            && peek.type != Tok.CloseBrace)
+                        statements ~= parseStatement();
+                    action.actOnDefaultStmt(res, _default, statements);
+                    continue;
+                }
+
+                Token _case = peek;
+                if (_case.type != Tok.Case)
+                    break;
+                next();
 
-                   Token _case = peek;
-                   if (_case.type != Tok.Case)
-                       break;
-                   next();
+                Exp[] literals;
+                do
+                {
+                    Exp e = parseExpression();
+                    literals ~= e;
+                }
+                while (skip(Tok.Comma));
+                require(Tok.Colon);
+
+                while (peek.type != Tok.Case
+                        && peek.type != Tok.Default
+                        && peek.type != Tok.CloseBrace)
+                    statements ~= parseStatement();
+
+                action.actOnCaseStmt(res, _case, literals, statements);
 
-                   Exp[] literals;
-                   do
-                   {
-                       Exp e = parseExpression();
-                       //                    IntegerLit lit = cast(IntegerLit)e;
-                       //                    if (lit is null)
-                       //                        messages.report(CaseValueMustBeInt, peek.location).arg(next.getType);
-                       //                    else
-                       literals ~= e;
-                   }
-                   while (skip(Tok.Comma));
-                   require(Tok.Colon);
-
-                   while (peek.type != Tok.Case
-                           && peek.type != Tok.Default
-                           && peek.type != Tok.CloseBrace)
-                       statements ~= parseStatement();
-
-                   action.actOnCaseStmt(res, literals, statements);
+                if (peek.type == Tok.CloseBrace)
+                    break;
+            }
+            require(Tok.CloseBrace);
+            return res;
+        }
+        else if (t.type == Tok.Star)
+        {
+            auto exp = parseExpression();
+            require(Tok.Seperator);
+            return action.actOnExprStmt(exp);
+        }
+        else
+        {
+            messages.report(UnexpectedBeginStmt, t.location).arg(t.getType);
+            return null;
+        }
+    }
 
-                   if (peek.type == Tok.CloseBrace)
-                       break;
-               }
-               require(Tok.CloseBrace);
-               return res;
-           }
-           else
-           {
-               if (t.type == Tok.Star)
-               {
-                   auto exp = parseExpression();
-                   require(Tok.Seperator);
-                   return action.actOnExprStmt(exp);
-               }
-               messages.report(UnexpectedBeginStmt, t.location).arg(t.getType);
-
-               return null;
-           }
-           messages.report(UnexpectedTok, t.location);
-           return null;
-       }
+    Decl parseVarDecl()
+    {
+        // manually hardcoded to only support "type id [= exp];"
+        // as that is the only thing the codegen understands
+        Id type = parseType;
+        Id id = Id(next());
+        Exp init;
+        if (skip(Tok.Assign))
+            init = parseExpression();
+        require(Tok.Seperator);
+        Attribute att;
+        Decl d = action.actOnDeclarator(type, id, init, att);
+        return d;
+    }
 
-       Decl parseVarDecl()
-       {
-           // manually hardcoded to only support "type id [= exp];"
-           // as that is the only thing the codegen understands
-           Id type = parseType;
-           Id id = Id(next());
-           Exp init;
-           if (skip(Tok.Assign))
-               init = parseExpression();
-           require(Tok.Seperator);
-           Attribute att;
-           Decl d = action.actOnDeclarator(type, id, init, att);
-           return d;
-       }
+    /**
+      Parses a function/method given the already parsed return type and name
+     */
+    Decl parseFunc(ref Id type, ref Id name, Attribute att)
+    {
+        Decl func = action.actOnStartOfFunctionDef(type, name, att);
+        parseFuncArgs(func);
 
-       /**
-         Parses a function/method given the already parsed return type and name
-        */
-       Decl parseFunc(ref Id type, ref Id name, Attribute att)
-       {
-           Decl func = action.actOnStartOfFunctionDef(type, name, att);
-           parseFuncArgs(func);
+        if(peek.type == Tok.Seperator)
+        {
+            next();
+            return func;
+        }
+        Stmt stmt = parseCompoundStatement();
 
-           if(peek.type == Tok.Seperator)
-           {
-               next();
-               return func;
-           }
-           Stmt stmt = parseCompoundStatement();
+        return action.actOnEndOfFunction(func, stmt);
+    }
 
-           return action.actOnEndOfFunction(func, stmt);
-       }
+    /**
+      Parse the function arguments, assumes current token is (.
 
-       /**
-         Parse the function arguments, assumes current token is (.
+      Both the intitial paren and the ending paren is consumed.
+     */
+    void parseFuncArgs(Decl func)
+    {
+        require(Tok.OpenParentheses); // Remove the "(" token.
 
-         Both the intitial paren and the ending paren is consumed.
-        */
-       void parseFuncArgs(Decl func)
-       {
-           require(Tok.OpenParentheses); // Remove the "(" token.
+        while(peek.type != Tok.CloseParentheses)
+        {
+            auto t = parseType();
+            Id i;
+            if(peek.type == Tok.Identifier)
+                i = parseIdentifier();
+            action.addFuncArg(func, t, i);
 
-           while(peek.type != Tok.CloseParentheses)
-           {
-               auto t = parseType();
-               Id i;
-               if(peek.type == Tok.Identifier)
-                   i = parseIdentifier();
-               action.addFuncArg(func, t, i);
+            if(peek.type == Tok.Comma)
+                next();
+        }
 
-               if(peek.type == Tok.Comma)
-                   next();
-           }
-
-           require(Tok.CloseParentheses); // Remove the ")"
-       }
+        require(Tok.CloseParentheses); // Remove the ")"
+    }
 
-       /**
-         Parse either a block, or a single statement as allowed after if, while
-         and for.
-        */
-       Stmt parseSingleOrCompoundStatement()
-       {
-           if (peek.type == Tok.OpenBrace)
-               return parseCompoundStatement();
-           return parseStatement();
-       }
+    /**
+      Parse either a block, or a single statement as allowed after if, while
+      and for.
+     */
+    Stmt parseSingleOrCompoundStatement()
+    {
+        if (peek.type == Tok.OpenBrace)
+            return parseCompoundStatement();
+        return parseStatement();
+    }
 
-       /**
-         Parses a function-body or similar, expects an opening brace to be the
-         current token.
+    /**
+      Parses a function-body or similar, expects an opening brace to be the
+      current token.
 
-         Will consume both the starting { and ending }
-        */
-       Stmt parseCompoundStatement()
-       {
-           Token lbrace = require(Tok.OpenBrace);
-           SmallArray!(Stmt, 32) stmts; // Try to use the stack only
-           while ( !isa(Tok.CloseBrace) && !isa(Tok.EOF) )
-               stmts ~= parseStatement();
-           Token rbrace = require(Tok.CloseBrace);
-           return action.actOnCompoundStmt(lbrace, rbrace, stmts.unsafe());
-       }
+      Will consume both the starting { and ending }
+     */
+    Stmt parseCompoundStatement()
+    {
+        Token lbrace = require(Tok.OpenBrace);
+        SmallArray!(Stmt, 32) stmts; // Try to use the stack only
+        while ( !isa(Tok.CloseBrace) && !isa(Tok.EOF) )
+            stmts ~= parseStatement();
+        Token rbrace = require(Tok.CloseBrace);
+        return action.actOnCompoundStmt(lbrace, rbrace, stmts.unsafe());
+    }
 
-       Id parseIdentifier()
-       {
-           Token tok = next();
+    Id parseIdentifier()
+    {
+        Token tok = next();
 
-           if (tok.type is Tok.Identifier)
-               return Id(tok);
+        if (tok.type is Tok.Identifier)
+            return Id(tok);
 
-           messages.report(UnexpectedTokSingle, tok.location)
-               .arg(tok.getType)
-               .arg(Tok.Identifier);
-       }
+        messages.report(UnexpectedTokSingle, tok.location)
+            .arg(tok.getType)
+            .arg(Tok.Identifier);
+    }
 
-       ModuleName parseModuleName()
-       {
-           auto id = parseIdentifier();
-           ModuleName mod;
-           while (skip(Tok.Dot))
-           {
-               mod.packages ~= id;
-               if (peek.type != Tok.Identifier) {
-                   messages.report(ExpectedIdAfterPackage, peek.location);
-                   goto Lerror;
-               }
-               id = parseIdentifier();
-           }
-           mod.id = id;
-           return mod;
+    ModuleName parseModuleName()
+    {
+        auto id = parseIdentifier();
+        ModuleName mod;
+        while (skip(Tok.Dot))
+        {
+            mod.packages ~= id;
+            if (peek.type != Tok.Identifier) {
+                messages.report(ExpectedIdAfterPackage, peek.location);
+                goto Lerror;
+            }
+            id = parseIdentifier();
+        }
+        mod.id = id;
+        return mod;
 Lerror:
-           while (!skip(Tok.Seperator))
-               next();
-           return mod;
-       }
+        while (!skip(Tok.Seperator))
+            next();
+        return mod;
+    }
 
 
-       /**
-         Parse a type - this includes pointer and array(at some point) types.
-        */
-       Id parseType()
-       {
-           Token type = next();
+    /**
+      Parse a type - this includes pointer and array(at some point) types.
+     */
+    Id parseType()
+    {
+        Token type = next();
 
-           Id currentType;
+        Id currentType;
 
-           if ( !(type.isBasicType || type.type == Tok.Identifier) )
-               messages.report(InvalidType, type.location);
+        if ( !(type.isBasicType || type.type == Tok.Identifier) )
+            messages.report(InvalidType, type.location);
 
-           currentType = Id(type);
-           type = peek;
+        currentType = Id(type);
+        type = peek;
 
-           while(type.type == Tok.Star || type.type == Tok.OpenBracket)
-           {
-               if(type.type == Tok.Star)
-               {
-                   currentType = PointerId(currentType);
-                   next();
-               }
-               else
-               {
-                   next();
-                   if(peek.type == Tok.Integer)
-                       currentType = StaticArrayId(
-                               currentType, 
-                               action.actOnNumericConstant(
-                                   require(Tok.Integer)));
-                   require(Tok.CloseBracket);
+        while(type.type == Tok.Star || type.type == Tok.OpenBracket)
+        {
+            if(type.type == Tok.Star)
+            {
+                currentType = PointerId(currentType);
+                next();
+            }
+            else
+            {
+                next();
+                if(peek.type == Tok.Integer)
+                    currentType = StaticArrayId(
+                            currentType, 
+                            action.actOnNumericConstant(
+                                require(Tok.Integer)));
+                require(Tok.CloseBracket);
 
-               }
-               type = peek;
-           }
+            }
+            type = peek;
+        }
 
-           return currentType;
-       }
+        return currentType;
+    }
 
-       int peekParseType()
-       {
-           int i;
-           Token type = peek(i);
+    int peekParseType()
+    {
+        int i;
+        Token type = peek(i);
 
-           Id currentType;
+        Id currentType;
 
-           if ( !(type.isBasicType || type.type == Tok.Identifier) )
-               return 0;
+        if ( !(type.isBasicType || type.type == Tok.Identifier) )
+            return 0;
 
-           currentType = Id(type);
-           type = peek(++i);
+        currentType = Id(type);
+        type = peek(++i);
 
-           while(type.type == Tok.Star || type.type == Tok.OpenBracket)
-           {
-               if(type.type == Tok.Star)
-               {
-                   i++;
-               }
-               else
-               {
-                   if(peek(i++).type != Tok.OpenBracket)
-                       return 0;
-                   if(peek(i).type == Tok.Integer)
-                   {
-                       i++;
-                       if(peek(i++).type != Tok.CloseBracket)    
-                           return 0;
-                   }
-                   else
-                       if(peek(i++).type != Tok.CloseBracket)
-                           return 0;
+        while(type.type == Tok.Star || type.type == Tok.OpenBracket)
+        {
+            if(type.type == Tok.Star)
+            {
+                i++;
+            }
+            else
+            {
+                if(peek(i++).type != Tok.OpenBracket)
+                    return 0;
+                if(peek(i).type == Tok.Integer)
+                {
+                    i++;
+                    if(peek(i++).type != Tok.CloseBracket)    
+                        return 0;
+                }
+                else
+                    if(peek(i++).type != Tok.CloseBracket)
+                        return 0;
 
-               }
-               type = peek(i);
-           }
+            }
+            type = peek(i);
+        }
 
-           return i;
-       }
+        return i;
+    }
 
 private:
-       // -- Expression parsing -- //
-       Exp parsePostfixExp(Exp target)
-       {
-           switch(peek.type)
-           {
-               case Tok.Dot:
-                   switch(peek(1).type)
-                   {
-                       case Tok.Identifier:
-                           Token op = next();
-                           Id member = Id(next());
-                           Exp exp = action.actOnMemberReference(target, op.location, member);
-                           return parsePostfixExp(exp);
-                       default:
-                           Token t = peek(1);
-                           messages.report(ExpectedIdAfterDot, t.location);
-                   }
-               case Tok.OpenBracket:
-                   Token open = next();
-                   Exp index = parseExpression();
-                   Token close = require(Tok.CloseBracket);
-                   return action.actOnIndexEpr(target, open, index, close);
-               default:
-                   return target;
-           }
-       }
+    // -- Expression parsing -- //
+    Exp parsePostfixExp(Exp target)
+    {
+        switch(peek.type)
+        {
+            case Tok.Dot:
+                switch(peek(1).type)
+                {
+                    case Tok.Identifier:
+                        Token op = next();
+                        Id member = Id(next());
+                        Exp exp = action.actOnMemberReference(target, op.location, member);
+                        return parsePostfixExp(exp);
+                    default:
+                        Token t = peek(1);
+                        messages.report(ExpectedIdAfterDot, t.location);
+                }
+            case Tok.OpenBracket:
+                Token open = next();
+                Exp index = parseExpression();
+                Token close = require(Tok.CloseBracket);
+                return action.actOnIndexEpr(target, open, index, close);
+            default:
+                return target;
+        }
+    }
 
-       Exp parseExpression(int p = 0)
-       {
-           auto exp = P();
-           Token n = peek();
-           BinOp* op = null;
-           while ((op = binary(n.type)) != null && op.prec >= p)
-           {
-               next();
-               int q = op.leftAssoc? 1 + op.prec : op.prec;
-               auto exp2 = parseExpression(q);
-               exp = action.actOnBinaryOp(n.location, op.operator, exp, exp2);
-               n = peek();
-           }
+    Exp parseExpression(int p = 0)
+    {
+        auto exp = P();
+        Token n = peek();
+        BinOp* op = null;
+        while ((op = binary(n.type)) != null && op.prec >= p)
+        {
+            next();
+            int q = op.leftAssoc? 1 + op.prec : op.prec;
+            auto exp2 = parseExpression(q);
+            exp = action.actOnBinaryOp(n.location, op.operator, exp, exp2);
+            n = peek();
+        }
 
-           return exp;
-       }
+        return exp;
+    }
 
-       Exp P()
-       {
-           Token n = next();
-           if (auto op = unary(n.type))
-               return action.actOnUnaryOp(n, parseExpression(op.prec));
-           else if (n.type == Tok.OpenParentheses)
-           {
-               auto e = parseExpression(0);
-               require(Tok.CloseParentheses);
-               return e;
-           }
-           else if (n.type == Tok.Identifier)
-           {
-               Exp value = action.actOnIdentifierExp(Id(n));
-               Exp iden = parsePostfixExp(value);
-               switch(peek.type)
-               {
-                   case Tok.OpenParentheses:
-                       Token lp = next();
-                       SmallArray!(Exp, 8) args;
-                       while(peek.type != Tok.CloseParentheses)
-                       {
-                           if(peek.type == Tok.Comma)
-                               next();
-                           args ~= parseExpression();
-                       }
+    Exp P()
+    {
+        Token n = next();
+        if (auto op = unary(n.type))
+            return action.actOnUnaryOp(n, parseExpression(op.prec));
+        else if (n.type == Tok.OpenParentheses)
+        {
+            auto e = parseExpression(0);
+            require(Tok.CloseParentheses);
+            return e;
+        }
+        else if (n.type == Tok.Identifier)
+        {
+            Exp value = action.actOnIdentifierExp(Id(n));
+            Exp iden = parsePostfixExp(value);
+            switch(peek.type)
+            {
+                case Tok.OpenParentheses:
+                    Token lp = next();
+                    SmallArray!(Exp, 8) args;
+                    while(peek.type != Tok.CloseParentheses)
+                    {
+                        if(peek.type == Tok.Comma)
+                            next();
+                        args ~= parseExpression();
+                    }
 
-                       Token rp = next();
-                       return action.actOnCallExpr(iden, lp, args.unsafe(), rp);
+                    Token rp = next();
+                    return action.actOnCallExpr(iden, lp, args.unsafe(), rp);
 
-                   default:
-                       return iden;
-               }
-           }
-           else if (n.type == Tok.Cast)
-               return parseCast(n);
-           else if (n.type == Tok.Integer)
-               return action.actOnNumericConstant(n);
-           else if (n.type == Tok.String)
-               return action.actOnStringExp(n);
+                default:
+                    return iden;
+            }
+        }
+        else if (n.type == Tok.Cast)
+            return parseCast(n);
+        else if (n.type == Tok.Integer)
+            return action.actOnNumericConstant(n);
+        else if (n.type == Tok.String)
+            return action.actOnStringExp(n);
 
-           messages.report(ExpectedExp, n.location)
-               .fatal(ExitLevel.Parser);
-           return null;
-       }
+        messages.report(ExpectedExp, n.location)
+            .fatal(ExitLevel.Parser);
+        return null;
+    }
 
-       Exp parseCast(ref Token _cast)
-       {
-           require(Tok.OpenParentheses);
-           auto n = next();
-           if(!n.isBasicType && !n.isIdentifier)
-               messages.report(ExpectedCastType, n.location);
+    Exp parseCast(ref Token _cast)
+    {
+        require(Tok.OpenParentheses);
+        auto n = next();
+        if(!n.isBasicType && !n.isIdentifier)
+            messages.report(ExpectedCastType, n.location);
 
-           require(Tok.CloseParentheses);
-           auto exp = P();
-           return action.actOnCastExpr(_cast, Id(n), exp);
-       }
+        require(Tok.CloseParentheses);
+        auto exp = P();
+        return action.actOnCastExpr(_cast, Id(n), exp);
+    }
 
-       struct UnOp
-       {
-           Tok tokenType;
-           int prec;
-       }
+    struct UnOp
+    {
+        Tok tokenType;
+        int prec;
+    }
 
-       static const UnOp[] _unary =
-           [
-           {Tok.Minus, 4},
-           {Tok.Star, 4}
-       ];
-       UnOp* unary(Tok t)
-       {
-           foreach (ref op; _unary)
-               if (op.tokenType == t)
-                   return &op;
-           return null;
-       }
+    static const UnOp[] _unary =
+        [
+        {Tok.Minus, 4},
+        {Tok.Star, 4}
+    ];
+    UnOp* unary(Tok t)
+    {
+        foreach (ref op; _unary)
+            if (op.tokenType == t)
+                return &op;
+        return null;
+    }
 
-       struct BinOp
-       {
-           Tok tokenType;
-           int prec;
-           bool leftAssoc;
-           Operator operator;
-       }
+    struct BinOp
+    {
+        Tok tokenType;
+        int prec;
+        bool leftAssoc;
+        Operator operator;
+    }
 
-       static const BinOp[] _binary =
-           [
-           {Tok.Assign,        1, false, Operator.Assign},
-           {Tok.PlusAssign,    1, false, Operator.AddAssign},
-           {Tok.MinusAssign,   1, false, Operator.SubAssign},
-           {Tok.StarAssign,    1, false, Operator.MulAssign},
-           {Tok.SlashAssign,   1, false, Operator.DivAssign},
-           {Tok.PercentAssign, 1, false, Operator.ModAssign},
+    static const BinOp[] _binary =
+        [
+        {Tok.Assign,        1, false, Operator.Assign},
+        {Tok.PlusAssign,    1, false, Operator.AddAssign},
+        {Tok.MinusAssign,   1, false, Operator.SubAssign},
+        {Tok.StarAssign,    1, false, Operator.MulAssign},
+        {Tok.SlashAssign,   1, false, Operator.DivAssign},
+        {Tok.PercentAssign, 1, false, Operator.ModAssign},
 
-           // =, += etc. 1
-           // (need special-case for the ternary operator at this level)
-           // ||, 2
-           // &&, 3
-           // |, 4
-           // &, 5
-           // ^, 6
-           // ==, !=, is, !is, 7
-           // <, <= etc, 7
-           // in, 7
-           // <<, >>, >>>, 8
-           // +, -, ~, 9
-           // *, /, %, 10
-           // unary operators here
+        // =, += etc. 1
+        // (need special-case for the ternary operator at this level)
+        // ||, 2
+        // &&, 3
+        // |, 4
+        // &, 5
+        // ^, 6
+        // ==, !=, is, !is, 7
+        // <, <= etc, 7
+        // in, 7
+        // <<, >>, >>>, 8
+        // +, -, ~, 9
+        // *, /, %, 10
+        // unary operators here
 
-           {Tok.Eq,        2, true, Operator.Eq},
-           {Tok.Ne,        2, true, Operator.Ne},
+        {Tok.Eq,        2, true, Operator.Eq},
+        {Tok.Ne,        2, true, Operator.Ne},
 
-           {Tok.Lt,        2, true, Operator.Lt},
-           {Tok.Le,        2, true, Operator.Le},
-           {Tok.Gt,        2, true, Operator.Gt},
-           {Tok.Ge,        2, true, Operator.Ge},
+        {Tok.Lt,        2, true, Operator.Lt},
+        {Tok.Le,        2, true, Operator.Le},
+        {Tok.Gt,        2, true, Operator.Gt},
+        {Tok.Ge,        2, true, Operator.Ge},
 
-           {Tok.Plus,      3, true, Operator.Add},
-           {Tok.Minus,     3, true, Operator.Sub},
+        {Tok.Plus,      3, true, Operator.Add},
+        {Tok.Minus,     3, true, Operator.Sub},
 
-           {Tok.Star,      5, true, Operator.Mul},
-           {Tok.Slash,     5, true, Operator.Div},
-           {Tok.Percent,   5, true, Operator.Mod},
+        {Tok.Star,      5, true, Operator.Mul},
+        {Tok.Slash,     5, true, Operator.Div},
+        {Tok.Percent,   5, true, Operator.Mod},
 
-           {Tok.LeftShift,             8, true, Operator.LeftShift},
-           {Tok.RightShift,            8, true, Operator.RightShift},
-           {Tok.UnsignedRightShift,    8, true, Operator.UnsignedRightShift}
-       ];
-       BinOp* binary(Tok t)
-       {
-           foreach (ref op; _binary)
-               if (op.tokenType == t)
-                   return &op;
-           return null;
-       }
+        {Tok.LeftShift,             8, true, Operator.LeftShift},
+        {Tok.RightShift,            8, true, Operator.RightShift},
+        {Tok.UnsignedRightShift,    8, true, Operator.UnsignedRightShift}
+    ];
+    BinOp* binary(Tok t)
+    {
+        foreach (ref op; _binary)
+            if (op.tokenType == t)
+                return &op;
+        return null;
+    }
 
 private:
 
-       Token require(Tok t)
-       {
-           if (peek().type != t)
-               messages.report(UnexpectedTokSingle, peek.location)
-                   .arg(peek.getType)
-                   .arg(t);
-           return next();
-       }
+    Token require(Tok t)
+    {
+        if (peek().type != t)
+            messages.report(UnexpectedTokSingle, peek.location)
+                .arg(peek.getType)
+                .arg(t);
+        return next();
+    }
 
-       bool skip(Tok t)
-       {
-           if (peek().type != t)
-               return false;
-           next();
-           return true;
-       }
+    bool skip(Tok t)
+    {
+        if (peek().type != t)
+            return false;
+        next();
+        return true;
+    }
 
-       bool isa(Tok t)
-       {
-           return peek.type == t;
-       }
+    bool isa(Tok t)
+    {
+        return peek.type == t;
+    }
 
-       Token next()
-       {
-           return lexer.next;
-       }
+    Token next()
+    {
+        return lexer.next;
+    }
 
-       Token peek(int i = 0)
-       {
-           return lexer.peek(i);
-       }
+    Token peek(int i = 0)
+    {
+        return lexer.peek(i);
+    }
 
-       Lexer lexer;   
-       SourceManager sm;
+    Lexer lexer;   
+    SourceManager sm;
 }
 
--- a/sema/AstAction.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/sema/AstAction.d	Mon Jul 21 21:32:20 2008 +0200
@@ -211,21 +211,21 @@
         return new DeclStmt(d);
     }
 
-    StmtT actOnStartOfSwitchStmt(ExprT exp)
+    StmtT actOnStartOfSwitchStmt(Token _switch, ExprT exp)
     {
-        return new SwitchStmt(cast(Exp)exp);
+        return new SwitchStmt(_switch.location, cast(Exp)exp);
     }
 
-    void actOnCaseStmt(StmtT stmt, ExprT[] exps, StmtT[] stmts)
+    void actOnCaseStmt(StmtT stmt, Token _case, ExprT[] exps, StmtT[] stmts)
     {
         auto sw = cast(SwitchStmt)stmt;
-        sw.addCase(cast(Exp[])exps, cast(Stmt[])stmts);
+        sw.addCase(_case.location, cast(Exp[])exps, cast(Stmt[])stmts);
     }
 
-    void actOnDefaultStmt(StmtT stmt, StmtT[] stmts)
+    void actOnDefaultStmt(StmtT stmt, Token _default, StmtT[] stmts)
     {
         auto sw = cast(SwitchStmt)stmt;
-        sw.setDefault(cast(Stmt[])stmts);
+        sw.setDefault(_default.location, cast(Stmt[])stmts);
     }
 
     // -- Expressions --
--- a/sema/Scope.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/sema/Scope.d	Mon Jul 21 21:32:20 2008 +0200
@@ -70,20 +70,6 @@
         return null;
     }
 
-    /*
-    char[][] names()
-    {
-        char[][] res;
-        if (parentFunction() !is null)
-            res ~= "pf: " ~ parentFunction().identifier.get;
-        if (enclosing)
-            res = enclosing.names;
-        foreach (id, sym; symbols)
-            res ~= sym.name ~ " : " ~ (sym.type is null? "?" : sym.type.name);
-        return res;
-    }
-    */
-
     FuncDecl parentFunction()
     {
         if (func !is null)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sema/VC.d	Mon Jul 21 21:32:20 2008 +0200
@@ -0,0 +1,14 @@
+module sema.VC;
+
+import basic.Message;
+
+/**
+    VC is short for verification context.
+
+    This class holds various things that are neccesary to verify validity
+    of the AST.
+**/
+class VC
+{
+    MessageHandler msg;
+}
--- a/tests/code/switch_6.d	Mon Jul 21 21:00:20 2008 +0200
+++ b/tests/code/switch_6.d	Mon Jul 21 21:32:20 2008 +0200
@@ -7,6 +7,8 @@
             return 0;
         case 2, 3:
             return 1;
+        case 1, 3:
+            return 1;
     }
 }