Changeset 159

Show
Ignore:
Timestamp:
04/13/07 23:52:22 (2 years ago)
Author:
JarrettBillingsley
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/minid/baselib.d

    r147 r159  
    428428    } 
    429429 
    430     int classof(MDState s, uint numParams) 
    431     { 
    432         s.push(s.getParam!(MDInstance)(0).getClass()); 
    433         return 1; 
    434     } 
    435  
    436430    int mdtoString(MDState s, uint numParams) 
    437431    { 
     
    442436    int getTraceback(MDState s, uint numParams) 
    443437    { 
    444         s.push(new MDString(s.getTracebackString())); 
     438        s.push(new MDString(MDState.getTracebackString())); 
    445439        return 1; 
    446440    } 
     
    713707        setGlobal("getTraceback"d,  newClosure(&lib.getTraceback,          "getTraceback")); 
    714708        setGlobal("typeof"d,        newClosure(&lib.mdtypeof,              "typeof")); 
    715         setGlobal("classof"d,       newClosure(&lib.classof,               "classof")); 
    716709        setGlobal("fieldsOf"d,      newClosure(&lib.fieldsOf,              "fieldsOf")); 
    717710        setGlobal("methodsOf"d,     newClosure(&lib.methodsOf,             "methodsOf")); 
  • trunk/minid/compiler.d

    r133 r159  
    109109        Null, 
    110110        Return, 
     111        Super, 
    111112        Switch, 
    112113        This, 
     
    203204        Type.Null: "null", 
    204205        Type.Return: "return", 
     206        Type.Super: "super", 
    205207        Type.Switch: "switch", 
    206208        Type.This: "this", 
     
    299301        stringToType["null"] = Type.Null; 
    300302        stringToType["return"] = Type.Return; 
     303        stringToType["super"] = Type.Super; 
    301304        stringToType["switch"] = Type.Switch; 
    302305        stringToType["this"] = Type.This; 
     
    324327    public char[] toString() 
    325328    { 
    326         char[] ret; 
    327  
    328329        switch(type) 
    329330        { 
    330             case Type.Ident: 
    331                 ret = "Identifier: " ~ utf.toUTF8(stringValue); 
    332                 break; 
    333  
    334             case Type.CharLiteral: 
    335                 ret = "Character Literal"; 
    336                 break; 
    337  
    338             case Type.StringLiteral: 
    339                 ret = "String Literal"; 
    340                 break; 
    341  
    342             case Type.IntLiteral: 
    343                 ret = "Integer Literal: " ~ string.toString(intValue); 
    344                 break; 
    345  
    346             case Type.FloatLiteral: 
    347                 ret = "Float Literal: " ~ string.toString(floatValue); 
    348                 break; 
    349  
    350             default: 
    351                 ret = utf.toUTF8(tokenStrings[cast(uint)type]); 
    352                 break; 
    353         } 
    354  
    355         return ret; 
     331            case Type.Ident:         return "Identifier: " ~ utf.toUTF8(stringValue); 
     332            case Type.CharLiteral:   return "Character Literal"; 
     333            case Type.StringLiteral: return "String Literal"; 
     334            case Type.IntLiteral:    return "Integer Literal: " ~ string.toString(intValue); 
     335            case Type.FloatLiteral:  return "Float Literal: " ~ string.toString(floatValue); 
     336            default:                 return utf.toUTF8(tokenStrings[cast(uint)type]); 
     337        } 
    356338    } 
    357339 
     
    361343    } 
    362344 
    363     public void check(Type t) 
     345    public Token* expect(Type t) 
    364346    { 
    365347        if(type != t) 
    366348            throw new MDCompileException(location, "'%s' expected; found '%s' instead", tokenStrings[t], tokenStrings[type]); 
     349 
     350        return nextToken; 
    367351    } 
    368352     
     
    17321716    protected uint[] mLineInfo; 
    17331717    protected dchar[] mGuessedName; 
     1718    protected bool mIsMethod; 
    17341719 
    17351720    struct LocVarDesc 
     
    17541739    struct SwitchDesc 
    17551740    { 
    1756         bool isString; 
    17571741        uint switchPC; 
    1758  
    1759         union 
    1760         { 
    1761             int[int] intOffsets; 
    1762             int[dchar[]] stringOffsets; 
    1763         } 
    1764  
     1742        int[MDValue] offsets; 
    17651743        int defaultOffset = -1; 
    17661744 
     
    17721750    // ..and are then transfered to this array when they are done. 
    17731751    protected SwitchDesc*[] mSwitchTables; 
    1774  
    1775     public this(Location location, dchar[] guessedName, FuncState parent = null) 
     1752     
     1753    protected static ClassDef[] mCurrentClass; 
     1754    protected static uint mClassDefIndex = 0; 
     1755 
     1756    public static void enterClass(ClassDef def) 
     1757    { 
     1758        if(mClassDefIndex >= mCurrentClass.length) 
     1759            mCurrentClass.length = mCurrentClass.length + 3; 
     1760 
     1761        mCurrentClass[mClassDefIndex] = def; 
     1762        mClassDefIndex++; 
     1763    } 
     1764 
     1765    public static void leaveClass() 
     1766    { 
     1767        assert(mClassDefIndex != 0, "Number of classes underflow"); 
     1768        mClassDefIndex--; 
     1769    } 
     1770 
     1771    public static ClassDef currentClass() 
     1772    { 
     1773        if(mClassDefIndex == 0) 
     1774            return null; 
     1775        else 
     1776            return mCurrentClass[mClassDefIndex - 1]; 
     1777    } 
     1778 
     1779    public this(Location location, dchar[] guessedName, FuncState parent = null, bool isMethod = false) 
    17761780    { 
    17771781        mLocation = location; 
    17781782        mGuessedName = guessedName; 
     1783        mIsMethod = isMethod; 
    17791784 
    17801785        mParent = parent; 
     
    17901795            activateLocals(1); 
    17911796        } 
     1797    } 
     1798 
     1799    public bool isMethod() 
     1800    { 
     1801        return mIsMethod; 
    17921802    } 
    17931803 
     
    18771887    } 
    18781888 
    1879     public void beginStringSwitch(uint line, uint srcReg) 
     1889    public void beginSwitch(uint line, uint srcReg) 
    18801890    { 
    18811891        SwitchDesc* sd = new SwitchDesc; 
    1882         sd.switchPC = codeR(line, Op.SwitchString, 0, srcReg, 0); 
    1883         sd.isString = true; 
    1884  
     1892        sd.switchPC = codeR(line, Op.Switch, 0, srcReg, 0); 
    18851893        sd.prev = mSwitch; 
    1886         mSwitch = sd; 
    1887     } 
    1888  
    1889     public void beginIntSwitch(uint line, uint srcReg) 
    1890     { 
    1891         SwitchDesc* sd = new SwitchDesc; 
    1892         sd.switchPC = codeR(line, Op.SwitchInt, 0, srcReg, 0); 
    1893         sd.isString = false; 
    1894  
    1895         sd.prev = mSwitch; 
     1894 
    18961895        mSwitch = sd; 
    18971896    } 
     
    19071906    } 
    19081907 
    1909     public void addCase(Expression exp
     1908    public void addNullCase(Location location
    19101909    { 
    19111910        assert(mSwitch !is null, "adding case outside of a switch"); 
    1912  
    1913         IntExp intExp = cast(IntExp)exp; 
    1914  
    1915         if(intExp) 
    1916         { 
    1917             if(mSwitch.isString == true) 
    1918                 throw new MDCompileException(exp.mLocation, "Case value must be a string literal"); 
    1919  
    1920             int* oldOffset = (intExp.mValue in mSwitch.intOffsets); 
    1921  
    1922             if(oldOffset !is null) 
    1923                 throw new MDCompileException(exp.mLocation, "Duplicate case value '%s'", intExp.mValue); 
    1924  
    1925             mSwitch.intOffsets[intExp.mValue] = mCode.length - mSwitch.switchPC - 1; 
    1926  
    1927             return; 
    1928         } 
    1929  
    1930         StringExp stringExp = cast(StringExp)exp; 
    1931  
    1932         assert(stringExp, "added case is neither int nor string"); 
    1933  
    1934         if(mSwitch.isString == false) 
    1935             throw new MDCompileException(exp.mLocation, "Case value must be an integer literal"); 
    1936  
    1937         int* oldOffset = (stringExp.mValue in mSwitch.stringOffsets); 
     1911        int* oldOffset = (MDValue.nullValue in mSwitch.offsets); 
    19381912 
    19391913        if(oldOffset !is null) 
    1940             throw new MDCompileException(exp.mLocation, "Duplicate case value '%s'", stringExp.mValue); 
    1941  
    1942         mSwitch.stringOffsets[stringExp.mValue] = mCode.length - mSwitch.switchPC - 1; 
    1943     } 
    1944  
    1945     public void addDefault() 
    1946     { 
    1947         assert(mSwitch !is null, "adding default outside of a switch"); 
    1948         assert(mSwitch.defaultOffset == -1, "tried to add a second default"); 
     1914            throw new MDCompileException(location, "Duplicate case value 'null'"); 
     1915 
     1916        mSwitch.offsets[MDValue.nullValue] = mCode.length - mSwitch.switchPC - 1; 
     1917    } 
     1918     
     1919    public void addCase(T)(Location location, T v) 
     1920    { 
     1921        if(mSwitch is null) 
     1922            throw new MDCompileException(location, "Case statements may not exist outside of a switch"); 
     1923 
     1924        MDValue val = v; 
     1925 
     1926        int* oldOffset = (val in mSwitch.offsets); 
     1927 
     1928        if(oldOffset !is null) 
     1929            throw new MDCompileException(location, "Duplicate case value '%s'", v); 
     1930 
     1931        mSwitch.offsets[val] = mCode.length - mSwitch.switchPC - 1; 
     1932    } 
     1933 
     1934    public void addDefault(Location location) 
     1935    { 
     1936        if(mSwitch is null) 
     1937            throw new MDCompileException(location, "Default statements may not exist outside of a switch"); 
     1938 
     1939        if(mSwitch.defaultOffset != -1) 
     1940            throw new MDCompileException(location, "Multiple defaults in one switch"); 
    19491941 
    19501942        mSwitch.defaultOffset = mCode.length - mSwitch.switchPC - 1; 
     
    30012993        foreach(uint i, inout SwitchDesc* t; mSwitchTables) 
    30022994        { 
    3003             writef(string.repeat("\t", tab + 1), "Switch Table ", i); 
    3004  
    3005             if(t.isString) 
    3006             { 
    3007                 writefln(" - String"); 
    3008  
    3009                 foreach(dchar[] index; t.stringOffsets.keys.sort) 
    3010                     writefln(string.repeat("\t", tab + 2), "\"%s\" => %s", index, t.stringOffsets[index]); 
    3011             } 
    3012             else 
    3013             { 
    3014                 writefln(" - Int"); 
    3015  
    3016                 foreach(int index; t.intOffsets.keys.sort) 
    3017                     writefln(string.repeat("\t", tab + 2), "%s => %s", index, t.intOffsets[index]); 
    3018             } 
     2995            writefln(string.repeat("\t", tab + 1), "Switch Table ", i); 
     2996 
     2997            foreach(index; t.offsets.keys) 
     2998                writefln(string.repeat("\t", tab + 2), "%s => %s", index, t.offsets[index]); 
    30192999 
    30203000            writefln(string.repeat("\t", tab + 2), "Default: ", t.defaultOffset); 
     
    31033083            with(*mSwitchTables[i]) 
    31043084            { 
    3105                 ret.mSwitchTables[i].isString = isString; 
    3106  
    3107                 if(isString) 
    3108                     ret.mSwitchTables[i].stringOffsets = stringOffsets; 
    3109                 else 
    3110                     ret.mSwitchTables[i].intOffsets = intOffsets; 
    3111  
     3085                ret.mSwitchTables[i].offsets = offsets; 
    31123086                ret.mSwitchTables[i].defaultOffset = defaultOffset; 
    31133087            } 
     
    31473121    } 
    31483122 
    3149     public static void parseBody(Location location, inout Token* t, out FuncDef[] methods, out Field[] fields, out Location endLocation) 
    3150     { 
    3151         t.check(Token.Type.LBrace); 
    3152         t = t.nextToken; 
    3153          
    3154         methods = new FuncDef[10]; 
    3155         int iMethod = 0; 
     3123    public static void parseBody(Location location, inout Token* t, out FuncDef[] oMethods, out Field[] oFields, out Location oEndLocation) 
     3124    { 
     3125        t = t.expect(Token.Type.LBrace); 
     3126 
     3127        FuncDef[dchar[]] methods; 
    31563128 
    31573129        void addMethod(FuncDef m) 
    31583130        { 
    3159             if(iMethod >= methods.length) 
    3160                 methods.length = methods.length * 2; 
    3161  
    3162             methods[iMethod] = m; 
    3163             iMethod++; 
    3164         } 
    3165  
    3166         fields = new Field[10]; 
    3167         int iField = 0; 
    3168  
    3169         void addField(dchar[] name, Expression v) 
    3170         { 
    3171             if(iField >= fields.length) 
    3172                 fields.length = fields.length * 2; 
    3173  
    3174             fields[iField].name = name; 
    3175             fields[iField].initializer = v; 
    3176  
    3177             iField++; 
     3131            dchar[] name = m.mName.mName; 
     3132 
     3133            if(name in methods) 
     3134                throw new MDCompileException(m.mLocation, "Redeclaration of method '%s'", name); 
     3135 
     3136            methods[name] = m; 
     3137        } 
     3138 
     3139        Expression[dchar[]] fields; 
     3140 
     3141        void addField(Identifier name, Expression v) 
     3142        { 
     3143            if(name.mName in fields) 
     3144                throw new MDCompileException(name.mLocation, "Redeclaration of field '%s'", name.mName); 
     3145 
     3146            fields[name.mName] = v; 
    31783147        } 
    31793148 
     
    31823151            switch(t.type) 
    31833152            { 
     3153                case Token.Type.This: 
     3154                    Location ctorLocation = t.location; 
     3155                    Identifier name = new Identifier("constructor", t.location); 
     3156                    t = t.nextToken; 
     3157 
     3158                    bool isVararg; 
     3159                    Identifier[] params = FuncDef.parseParams(t, isVararg); 
     3160 
     3161                    CompoundStatement funcBody = CompoundStatement.parse(t); 
     3162                    addMethod(new FuncDef(ctorLocation, funcBody.mEndLocation, params, isVararg, funcBody, name)); 
     3163                    break; 
     3164 
    31843165                case Token.Type.Function: 
    31853166                    addMethod(FuncDef.parseSimple(t)); 
     
    31993180                        v = new NullExp(id.mLocation); 
    32003181 
    3201                     dchar[] name = id.mName; 
    3202  
    3203                     t.check(Token.Type.Semicolon); 
    3204                     t = t.nextToken; 
    3205                      
    3206                     addField(name, v); 
     3182                    t = t.expect(Token.Type.Semicolon); 
     3183                    addField(id, v); 
    32073184                    break; 
    32083185 
     
    32113188 
    32123189                default: 
     3190                    throw new MDCompileException(t.location, "Class method or field expected, not '%s'", t.toString()); 
    32133191                    break; 
    32143192            } 
    32153193        } 
    32163194 
    3217         methods.length = iMethod; 
    3218         fields.length = iField; 
    3219  
    3220         if(t.type != Token.Type.RBrace) 
    3221             throw new MDCompileException(t.location, "Class at ", location.toString(), " is missing its closing brace"); 
    3222              
    3223         endLocation = t.location; 
    3224  
     3195        oMethods = methods.values; 
     3196 
     3197        oFields.length = fields.length; 
     3198         
     3199        uint i = 0; 
     3200 
     3201        foreach(name, initializer; fields) 
     3202        { 
     3203            oFields[i].name = name; 
     3204            oFields[i].initializer = initializer; 
     3205            i++; 
     3206        } 
     3207 
     3208        t.expect(Token.Type.RBrace); 
     3209        oEndLocation = t.location; 
    32253210        t = t.nextToken; 
    32263211    } 
     
    32513236        uint nameConst = s.tagConst(s.codeStringConst(mName.mName)); 
    32523237        s.codeR(mLocation.line, Op.Class, destReg, nameConst, base.index); 
     3238         
     3239        FuncState.enterClass(this); 
    32533240 
    32543241        foreach(Field field; mFields) 
     
    32693256            uint index = s.tagConst(s.codeStringConst(method.mName.mName)); 
    32703257 
    3271             method.codeGen(s); 
     3258            method.codeGen(s, true); 
    32723259            Exp val; 
    32733260            s.popSource(method.mEndLocation.line, val); 
     
    32773264            s.freeExpTempRegs(&val); 
    32783265        } 
     3266         
     3267        FuncState.leaveClass(); 
    32793268 
    32803269        s.pushTempReg(destReg); 
     
    32933282        return this; 
    32943283    } 
     3284     
     3285    public bool hasBase() 
     3286    { 
     3287        return (mBaseClass !is null); 
     3288    } 
    32953289} 
    32963290 
     
    33183312        Location location = t.location; 
    33193313         
    3320         t.check(Token.Type.Function); 
    3321         t = t.nextToken; 
     3314        t = t.expect(Token.Type.Function); 
    33223315 
    33233316        Identifier name = Identifier.parse(t); 
     
    33353328        Location location = t.location; 
    33363329         
    3337         t.check(Token.Type.Function); 
    3338         t = t.nextToken; 
     3330        t = t.expect(Token.Type.Function); 
    33393331 
    33403332        Identifier name; 
     
    33643356        ret ~= new Identifier("this", t.location); 
    33653357 
    3366         t.check(Token.Type.LParen); 
    3367         t = t.nextToken; 
    3368              
     3358        t = t.expect(Token.Type.LParen); 
     3359         
    33693360        if(t.type == Token.Type.Vararg) 
    33703361        { 
     
    33883379                    break; 
    33893380 
    3390                 t.check(Token.Type.Comma); 
    3391                 t = t.nextToken; 
     3381                t = t.expect(Token.Type.Comma); 
    33923382            } 
    33933383        } 
    33943384         
    3395         t.check(Token.Type.RParen); 
    3396         t = t.nextToken; 
    3397          
     3385        t = t.expect(Token.Type.RParen); 
    33983386        return ret; 
    33993387    } 
    34003388 
    3401     public void codeGen(FuncState s
    3402     { 
    3403         FuncState fs = new FuncState(mLocation, mName.mName, s); 
     3389    public void codeGen(FuncState s, bool isMethod = false
     3390    { 
     3391        FuncState fs = new FuncState(mLocation, mName.mName, s, isMethod); 
    34043392 
    34053393        fs.mIsVararg = mIsVararg; 
     
    34483436        ModuleDeclaration modDecl = ModuleDeclaration.parse(t); 
    34493437 
    3450         Statement[] statements = new Statement[32]; 
    3451         uint i = 0; 
     3438        List!(Statement) statements; 
    34523439 
    34533440        bool[dchar[][]] imports; 
    3454  
    3455         void add(Statement s) 
    3456         { 
    3457             if(i >= statements.length) 
    3458                 statements.length = statements.length * 2; 
    3459  
    3460             statements[i] = s; 
    3461             i++; 
    3462         } 
    34633441 
    34643442        void addImport(ImportStatement imp) 
     
    34723450                addImport(ImportStatement.parse(t)); 
    34733451            else 
    3474                 add(Statement.parse(t)); 
    3475         } 
    3476  
    3477         t.check(Token.Type.EOF); 
    3478  
    3479         statements.length = i; 
    3480  
    3481         return new Module(location, t.location, modDecl, imports.keys.sort, statements); 
     3452                statements.add(Statement.parse(t)); 
     3453        } 
     3454 
     3455        t.expect(Token.Type.EOF); 
     3456 
     3457        return new Module(location, t.location, modDecl, imports.keys.sort, statements.toArray()); 
    34823458    } 
    34833459 
     
    35393515    public static ModuleDeclaration parse(inout Token* t) 
    35403516    { 
    3541         t.check(Token.Type.Module); 
    3542         t = t.nextToken; 
    3543          
     3517        t = t.expect(Token.Type.Module); 
     3518 
    35443519        Identifier[] names; 
    35453520        names ~= Identifier.parse(t); 
     
    35513526        } 
    35523527         
    3553         t.check(Token.Type.Semicolon); 
    3554         t = t.nextToken; 
    3555          
     3528        t = t.expect(Token.Type.Semicolon); 
     3529             
    35563530        return new ModuleDeclaration(names); 
    35573531    } 
     
    35763550        { 
    35773551            case 
    3578                 Token.Type.CharLiteral, 
    35793552                Token.Type.Dec, 
    3580                 Token.Type.Dot, 
    3581                 Token.Type.False, 
    3582                 Token.Type.FloatLiteral, 
    35833553                Token.Type.Ident, 
    35843554                Token.Type.Inc, 
    3585                 Token.Type.IntLiteral, 
    35863555                Token.Type.LParen, 
    3587                 Token.Type.Null, 
    3588                 Token.Type.StringLiteral, 
    3589                 Token.Type.Sub, 
     3556                Token.Type.Super, 
    35903557                Token.Type.This, 
    3591                 Token.Type.True, 
    35923558                Token.Type.Yield: 
    35933559 
     
    36183584            case Token.Type.Switch: 
    36193585                return SwitchStatement.parse(t); 
    3620  
     3586                 
    36213587            case Token.Type.Case: 
    36223588                return CaseStatement.parse(t); 
     
    36743640        Location location = t.location; 
    36753641 
    3676         t.check(Token.Type.Import); 
    3677         t = t.nextToken; 
    3678          
     3642        t = t.expect(Token.Type.Import); 
     3643 
    36793644        Identifier[] names; 
    36803645        names ~= Identifier.parse(t); 
     
    36863651        } 
    36873652 
    3688         t.check(Token.Type.Semicolon); 
     3653        t.expect(Token.Type.Semicolon); 
    36893654        Location endLocation = t.location; 
    36903655        t = t.nextToken; 
     
    37383703        Expression exp = Expression.parseStatement(t); 
    37393704 
    3740         t.check(Token.Type.Semicolon); 
     3705        t.expect(Token.Type.Semicolon); 
    37413706        Location endLocation = t.location; 
    37423707        t = t.nextToken; 
     
    38203785                VarDecl ret = VarDecl.parse(t); 
    38213786                 
    3822                 t.check(Token.Type.Semicolon); 
    3823                 t = t.nextToken; 
     3787                t = t.expect(Token.Type.Semicolon); 
    38243788 
    38253789                return ret; 
     
    38373801            return ClassDecl.parse(t); 
    38383802        else 
    3839             throw new MDCompileException(location, "Declaration expected"); 
     3803            throw new MDCompileException(location, "Declaration expected, not '%s'", t.toString()); 
    38403804    } 
    38413805 
     
    38763840            t = t.nextToken; 
    38773841 
    3878         t.check(Token.Type.Class); 
    3879         t = t.nextToken; 
     3842        t = t.expect(Token.Type.Class); 
    38803843 
    38813844        Identifier name = Identifier.parse(t); 
     
    39083871 
    39093872        mDef.codeGen(s); 
     3873 
    39103874        s.popAssign(mEndLocation.line); 
    39113875    } 
     
    39433907        } 
    39443908        else 
    3945         { 
    3946             t.check(Token.Type.Local); 
    3947             t = t.nextToken; 
    3948         } 
     3909            t = t.expect(Token.Type.Local); 
    39493910 
    39503911        Identifier[] names; 
     
    41444105    public static Identifier parse(inout Token* t) 
    41454106    { 
    4146         t.check(Token.Type.Ident); 
    4147  
     4107        t.expect(Token.Type.Ident); 
    41484108        Identifier id = new Identifier(t.stringValue, t.location); 
    41494109        t = t.nextToken; 
     
    41934153        Location location = t.location; 
    41944154 
    4195         t.check(Token.Type.LBrace); 
    4196         t = t.nextToken; 
    4197  
    4198         Statement[] statements = new Statement[10]; 
    4199         int i = 0; 
    4200  
    4201         void addStatement(Statement s) 
    4202         { 
    4203             if(i >= statements.length) 
    4204                 statements.length = statements.length * 2; 
    4205  
    4206             statements[i] = s; 
    4207             i++; 
    4208         } 
     4155        t = t.expect(Token.Type.LBrace); 
     4156 
     4157        List!(Statement) statements; 
    42094158 
    42104159        while(t.type != Token.Type.RBrace) 
    4211             addStatement(Statement.parse(t)); 
    4212  
    4213         statements.length = i; 
    4214  
    4215         t.check(Token.Type.RBrace); 
     4160            statements.add(Statement.parse(t)); 
     4161 
     4162        t.expect(Token.Type.RBrace); 
    42164163        Location endLocation = t.location; 
    42174164        t = t.nextToken; 
    42184165 
    4219         return new CompoundStatement(location, endLocation, statements); 
     4166        return new CompoundStatement(location, endLocation, statements.toArray()); 
    42204167    } 
    42214168 
     
    42544201        Location location = t.location; 
    42554202 
    4256         t.check(Token.Type.If); 
    4257         t = t.nextToken; 
    4258         t.check(Token.Type.LParen); 
    4259         t = t.nextToken; 
     4203        t = t.expect(Token.Type.If); 
     4204        t = t.expect(Token.Type.LParen); 
    42604205 
    42614206        Expression condition = Expression.parse(t); 
    42624207 
    4263         t.check(Token.Type.RParen); 
    4264         t = t.nextToken; 
     4208        t = t.expect(Token.Type.RParen); 
    42654209 
    42664210        Statement ifBody = Statement.parse(t); 
     
    43574301        Location location = t.location; 
    43584302 
    4359         t.check(Token.Type.While); 
    4360         t = t.nextToken; 
    4361         t.check(Token.Type.LParen); 
    4362         t = t.nextToken; 
     4303        t = t.expect(Token.Type.While); 
     4304        t = t.expect(Token.Type.LParen); 
    43634305 
    43644306        Expression condition = Expression.parse(t); 
    43654307 
    4366         t.check(Token.Type.RParen); 
    4367         t = t.nextToken; 
     4308        t = t.expect(Token.Type.RParen); 
    43684309 
    43694310        Statement whileBody = Statement.parse(t); 
     
    44434384        Location location = t.location; 
    44444385 
    4445         t.check(Token.Type.Do); 
    4446         t = t.nextToken; 
     4386        t = t.expect(Token.Type.Do); 
    44474387 
    44484388        Statement doBody = Statement.parse(t); 
    44494389 
    4450         t.check(Token.Type.While); 
    4451         t = t.nextToken; 
    4452         t.check(Token.Type.LParen); 
    4453         t = t.nextToken; 
     4390        t = t.expect(Token.Type.While); 
     4391        t = t.expect(Token.Type.LParen); 
    44544392 
    44554393        Expression condition = Expression.parse(t); 
    44564394 
    4457         t.check(Token.Type.RParen); 
     4395        t.expect(Token.Type.RParen); 
    44584396        Location endLocation = t.location; 
    44594397        t = t.nextToken; 
     
    45384476        Location location = t.location; 
    45394477 
    4540         t.check(Token.Type.For); 
    4541         t = t.nextToken; 
    4542         t.check(Token.Type.LParen); 
    4543         t = t.nextToken; 
    4544  
     4478        t = t.expect(Token.Type.For); 
     4479        t = t.expect(Token.Type.LParen); 
     4480         
    45454481        Expression init; 
    45464482        VarDecl initDecl; 
     
    45554491                init = Expression.parseStatement(t); 
    45564492 
    4557             t.check(Token.Type.Semicolon); 
    4558             t = t.nextToken; 
     4493            t = t.expect(Token.Type.Semicolon); 
    45594494        } 
    45604495 
     
    45664501        { 
    45674502            condition = Expression.parse(t); 
    4568             t.check(Token.Type.Semicolon); 
    4569             t = t.nextToken; 
     4503            t = t.expect(Token.Type.Semicolon); 
    45704504        } 
    45714505 
     
    45774511        { 
    45784512            increment = Expression.parseStatement(t); 
    4579             t.check(Token.Type.RParen); 
    4580             t = t.nextToken; 
     4513            t = t.expect(Token.Type.RParen); 
    45814514        } 
    45824515 
     
    46984631        Location location = t.location; 
    46994632 
    4700         t.check(Token.Type.Foreach); 
    4701         t = t.nextToken; 
    4702         t.check(Token.Type.LParen); 
    4703         t = t.nextToken; 
     4633        t = t.expect(Token.Type.Foreach); 
     4634        t = t.expect(Token.Type.LParen); 
    47044635 
    47054636        Identifier[] indices; 
    47064637 
    4707         if(t.type == Token.Type.Local) 
    4708         { 
    4709             derr.writefln("Warning ", t.location.toString(), ": 'local' in foreach indices will soon be illegal"); 
     4638        indices ~= Identifier.parse(t); 
     4639 
     4640        while(t.type == Token.Type.Comma) 
     4641        { 
    47104642            t = t.nextToken; 
    4711         } 
    4712  
    4713         indices ~= Identifier.parse(t); 
    4714  
    4715         while(t.type == Token.Type.Comma) 
    4716         { 
    4717             t = t.nextToken; 
    4718  
    4719             if(t.type == Token.Type.Local) 
    4720             { 
    4721                 derr.writefln("Warning ", t.location.toString(), ": 'local' in foreach indices will soon be illegal"); 
    4722                 t = t.nextToken; 
    4723             } 
    4724  
    47254643            indices ~= Identifier.parse(t); 
    47264644        } 
     
    47294647            indices = dummyIndex(indices[0].mLocation) ~ indices; 
    47304648 
    4731         t.check(Token.Type.Semicolon); 
    4732         t = t.nextToken; 
     4649        t = t.expect(Token.Type.Semicolon); 
    47334650 
    47344651        Expression[] container; 
     
    47444661            throw new MDCompileException(location, "'foreach' may have a maximum of three container expressions"); 
    47454662 
    4746         t.check(Token.Type.RParen); 
    4747         t = t.nextToken; 
     4663        t = t.expect(Token.Type.RParen); 
    47484664 
    47494665        Statement foreachBody = Statement.parse(t); 
     
    48824798        Location location = t.location; 
    48834799 
    4884         t.check(Token.Type.Switch); 
    4885         t = t.nextToken; 
    4886         t.check(Token.Type.LParen); 
    4887         t = t.nextToken; 
     4800        t = t.expect(Token.Type.Switch); 
     4801        t = t.expect(Token.Type.LParen); 
    48884802 
    48894803        Expression condition = Expression.parse(t); 
    48904804 
    4891         t.check(Token.Type.RParen); 
    4892         t = t.nextToken; 
    4893         t.check(Token.Type.LBrace); 
    4894         t = t.nextToken; 
    4895  
    4896         CaseStatement[] cases = new CaseStatement[10]; 
    4897         int i = 0; 
    4898  
    4899         void addCase(CaseStatement c) 
    4900         { 
    4901             if(i >= cases.length) 
    4902                 cases.length = cases.length * 2; 
    4903  
    4904             cases[i] = c; 
    4905             i++; 
    4906         } 
    4907  
    4908         while(true) 
    4909         { 
    4910             if(t.type == Token.Type.Case) 
    4911                 addCase(CaseStatement.parse(t)); 
    4912             else 
    4913                 break; 
    4914         } 
    4915  
    4916         cases.length = i; 
     4805        t = t.expect(Token.Type.RParen); 
     4806        t = t.expect(Token.Type.LBrace); 
     4807         
     4808        List!(CaseStatement) cases; 
     4809 
     4810        while(t.type == Token.Type.Case) 
     4811            cases.add(CaseStatement.parse(t)); 
    49174812 
    49184813        if(cases.length == 0) 
     
    49244819            caseDefault = DefaultStatement.parse(t); 
    49254820 
    4926         t.check(Token.Type.RBrace); 
     4821        t.expect(Token.Type.RBrace); 
    49274822        Location endLocation = t.location; 
    49284823        t = t.nextToken; 
    49294824 
    4930         return new SwitchStatement(location, endLocation, condition, cases, caseDefault); 
     4825        return new SwitchStatement(location, endLocation, condition, cases.toArray(), caseDefault); 
    49314826    } 
    49324827 
     
    49404835            s.popSource(mLocation.line, src); 
    49414836 
    4942             if(cast(IntExp)mCases[0].mCondition) 
    4943                 s.beginIntSwitch(mLocation.line, src.index); 
    4944             else 
    4945                 s.beginStringSwitch(mLocation.line, src.index); 
     4837            s.beginSwitch(mLocation.line, src.index); 
    49464838 
    49474839            s.freeExpTempRegs(&src); 
     
    49894881        Location location = t.location; 
    49904882 
    4991         t.check(Token.Type.Case); 
    4992         t = t.nextToken; 
    4993  
    4994         Expression[] cases = new Expression[10]; 
    4995         int i = 0; 
    4996  
    4997         void addCase(Expression c) 
    4998         { 
    4999             if(i >= cases.length) 
    5000                 cases.length = cases.length * 2; 
    5001  
    5002             cases[i] = c; 
    5003             i++; 
     4883        t = t.expect(Token.Type.Case); 
     4884 
     4885        List!(Expression) cases; 
     4886        cases.add(Expression.parse(t)); 
     4887 
     4888        while(t.type == Token.Type.Comma) 
     4889        { 
     4890            t = t.nextToken; 
     4891            cases.add(Expression.parse(t)); 
    50044892        } 
    50054893         
    5006         addCase(Expression.parse(t)); 
    5007          
    5008         while(t.type == Token.Type.Comma) 
    5009         { 
    5010             t = t.nextToken; 
    5011             addCase(Expression.parse(t)); 
    5012         } 
    5013  
    5014         cases.length = i; 
    5015  
    5016         t.check(Token.Type.Colon); 
    5017         t = t.nextToken; 
    5018  
    5019         Statement[] statements = new Statement[10]; 
    5020         i = 0; 
    5021  
    5022         void addStatement(Statement s) 
    5023         { 
    5024             if(i >= statements.length) 
    5025                 statements.length = statements.length * 2; 
    5026  
    5027             statements[i] = s; 
    5028             i++; 
    5029         } 
     4894        t = t.expect(Token.Type.Colon); 
     4895 
     4896        List!(Statement) statements; 
    50304897 
    50314898        while(t.type != Token.Type.Case && t.type != Token.Type.Default && t.type != Token.Type.RBrace) 
    5032             addStatement(Statement.parse(t)); 
    5033  
    5034         statements.length = i; 
     4899            statements.add(Statement.parse(t)); 
    50354900 
    50364901        Location endLocation = t.location; 
    50374902 
    5038         Statement ret = new CompoundStatement(location, endLocation, statements); 
     4903        Statement ret = new CompoundStatement(location, endLocation, statements.toArray()); 
    50394904        ret = new ScopeStatement(location, endLocation, ret); 
    50404905 
    5041         for(i = cases.length - 1; i >= 0; i--) 
     4906        for(int i = cases.length - 1; i >= 0; i--) 
    50424907            ret = new CaseStatement(location, endLocation, cases[i], ret); 
    50434908 
     
    50504915            throw new MDCompileException(mLocation, "Case value is not constant"); 
    50514916 
    5052         s.addCase(mCondition); 
     4917        IntExp intExp = cast(IntExp)mCondition; 
     4918         
     4919        if(intExp) 
     4920            s.addCase(mLocation, intExp.mValue); 
     4921        else 
     4922        { 
     4923            StringExp stringExp = cast(StringExp)mCondition; 
     4924 
     4925            if(stringExp) 
     4926                s.addCase(mLocation, stringExp.mValue); 
     4927            else 
     4928            { 
     4929                CharExp cha