Changeset 333

Show
Ignore:
Timestamp:
07/24/08 16:22:10 (1 month ago)
Author:
JarrettBillingsley
Message:

CODEGEN, OH YES.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/v2new/minid/api.d

    r329 r333  
    155155} 
    156156 
    157 align(1) struct FileHeader 
     157/* align(1) struct FileHeader 
    158158{ 
    159159    uint magic = FOURCC!("MinD"); 
     
    197197    auto fd = funcdef.deserialize(t.vm, r); 
    198198    return pushFunction(t, func.create(t.vm.alloc, t.vm.globals, fd)); 
    199 } 
     199} */ 
  • branches/v2new/minid/ast.d

    r332 r333  
    8484    "FuncEnvStmt", 
    8585    "AppendStmt", 
     86    "TypecheckStmt", 
    8687 
    8788    "CondExp", 
     
    142143    "NamespaceCtorExp", 
    143144    "YieldExp", 
    144     "SuperCallExp", 
    145145    "RawNamespaceExp", 
    146146 
     
    275275    AstTag.NamespaceCtorExp:     "namespace constructor expression", 
    276276    AstTag.YieldExp:             "yield expression", 
    277     AstTag.SuperCallExp:         "super call expression", 
    278277 
    279278    AstTag.ForeachComprehension: "'foreach' comprehension", 
     
    548547    { 
    549548        super(c, location, code.endLocation, AstTag.FuncDef); 
    550         this.params = params; 
     549         
     550        if(params.length == 0) 
     551        { 
     552            scope dummy = new List!(Param)(c.alloc); 
     553            dummy ~= Param(new(c) Identifier(c, location, c.newString("this"))); 
     554            this.params = dummy.toArray(); 
     555        } 
     556        else 
     557        { 
     558            assert(params[0].name.name == "this"); 
     559            this.params = params; 
     560        } 
     561 
    551562        this.isVararg = isVararg; 
    552563        this.code = code; 
     
    13001311class CaseStmt : Statement 
    13011312{ 
     1313    struct CaseCond 
     1314    { 
     1315        Expression exp; 
     1316        uint dynJump; 
     1317    } 
     1318 
    13021319    /** 
    13031320    The list of values which will cause execution to jump to this case.  In the code 
     
    13051322    long. 
    13061323    */ 
    1307     public Expression[] conditions; 
    1308      
     1324    public CaseCond[] conditions; 
     1325 
    13091326    /** 
    13101327    The code of the case statement. 
     
    13121329    public Statement code; 
    13131330 
    1314 //  protected List!(InstRef*) mDynJumps; 
    1315 //  protected List!(int*) mConstJumps; 
    1316  
    1317     /** 
    1318     */ 
    1319     public this(ICompiler c, CompileLoc location, CompileLoc endLocation, Expression[] conditions, Statement code) 
     1331    /** 
     1332    */ 
     1333    public this(ICompiler c, CompileLoc location, CompileLoc endLocation, CaseCond[] conditions, Statement code) 
    13201334    { 
    13211335        super(c, location, endLocation, AstTag.CaseStmt); 
     
    17841798    /** 
    17851799    */ 
    1786     public Identifier arrayName; 
     1800    public IdentExp arrayName; 
    17871801 
    17881802    /** 
     
    17921806    /** 
    17931807    */ 
    1794     public this(ICompiler c, CompileLoc location, Identifier arrayName, Expression value) 
     1808    public this(ICompiler c, CompileLoc location, IdentExp arrayName, Expression value) 
    17951809    { 
    17961810        super(c, location, location, AstTag.AppendStmt); 
    17971811        this.arrayName = arrayName; 
    17981812        this.value = value; 
     1813    } 
     1814} 
     1815 
     1816/** 
     1817This node is an internal node inserted in function bodies if parameter type checking is enabled. 
     1818*/ 
     1819class TypecheckStmt : Statement 
     1820{ 
     1821    /** 
     1822    */ 
     1823    public FuncDef def; 
     1824 
     1825    /** 
     1826    */ 
     1827    public this(ICompiler c, CompileLoc location, FuncDef def) 
     1828    { 
     1829        super(c, location, location, AstTag.TypecheckStmt); 
     1830        this.def = def; 
    17991831    } 
    18001832} 
     
    25242556{ 
    25252557    /** 
     2558    */ 
     2559    public Expression method; 
     2560 
     2561    /** 
    25262562    The context to be used when calling the method.  This corresponds to 'x' in 
    25272563    the expression "a.f(with x)".  If this member is null, there is no custom 
     
    25292565    */ 
    25302566    public Expression context; 
    2531      
     2567 
    25322568    /** 
    25332569    The list of argument to pass to the method.  This can have 0 or more elements. 
     
    25362572 
    25372573    /** 
    2538     */ 
    2539     public this(ICompiler c, CompileLoc endLocation, Expression operand, Expression context, Expression[] args) 
    2540     { 
    2541         super(c, operand.location, endLocation, AstTag.MethodCallExp, operand); 
     2574    If this member is true, 'op' will be null (and will be interpreted as a "this"). 
     2575    */ 
     2576    public bool isSuperCall; 
     2577 
     2578    /** 
     2579    */ 
     2580    public this(ICompiler c, CompileLoc location, CompileLoc endLocation, Expression operand, Expression method, Expression context, Expression[] args, bool isSuperCall) 
     2581    { 
     2582        super(c, location, endLocation, AstTag.MethodCallExp, operand); 
     2583        this.method = method; 
    25422584        this.context = context; 
    25432585        this.args = args; 
     2586        this.isSuperCall = isSuperCall; 
    25442587    } 
    25452588     
     
    30833126    { 
    30843127        super(c, location, endLocation, AstTag.YieldExp); 
    3085         this.args = args; 
    3086     } 
    3087  
    3088     public bool hasSideEffects() 
    3089     { 
    3090         return true; 
    3091     } 
    3092  
    3093     public bool isMultRet() 
    3094     { 
    3095         return true; 
    3096     } 
    3097      
    3098     override void cleanup(ref Allocator alloc) 
    3099     { 
    3100         alloc.freeArray(args); 
    3101     } 
    3102 } 
    3103  
    3104 /** 
    3105 This node represents a super call exp, such as "super.f()" or "super.("f")()" 
    3106 (the former is sugar for the latter). 
    3107 */ 
    3108 class SuperCallExp : PrimaryExp 
    3109 { 
    3110     /** 
    3111     The method name.  This can be any expression as long as it evaluates to a string. 
    3112     */ 
    3113     public Expression method; 
    3114      
    3115     /** 
    3116     The arguments to pass to the function. 
    3117     */ 
    3118     public Expression[] args; 
    3119  
    3120     /** 
    3121     */ 
    3122     public this(ICompiler c, CompileLoc location, CompileLoc endLocation, Expression method, Expression[] args) 
    3123     { 
    3124         super(c, location, endLocation, AstTag.SuperCallExp); 
    3125         this.method = method; 
    31263128        this.args = args; 
    31273129    } 
  • branches/v2new/minid/compiler.d

    r332 r333  
    3434import minid.alloc; 
    3535import minid.astvisitor; 
     36import minid.codegen; 
    3637import minid.compilertypes; 
    3738import minid.interpreter; 
     
    4243import minid.types; 
    4344 
    44 //debug = REGPUSHPOP; 
    45 //debug = VARACTIVATE; 
    46 //debug = WRITECODE; 
    47 //debug = SHOWME; 
    48 //debug = PRINTEXPSTACK; 
    49  
    5045scope class Compiler : ICompiler 
    5146{ 
     
    7974        mLexer = Lexer(this); 
    8075        mParser = Parser(this, &mLexer); 
    81          
    82         mStringTab = newTable(t); 
    8376    } 
    8477 
     
    9588            n = next; 
    9689        } 
    97  
    98         assert(stackSize(t) - 1 == mStringTab, "OH NO String table is not in the right place!"); 
    99         pop(t); 
    10090    } 
    10191 
     
    161151    } 
    162152 
    163     public void testParse(char[] filename) 
    164     { 
     153    public word testParse(char[] filename) 
     154    { 
     155        mStringTab = newTable(t); 
     156         
     157        scope(failure) 
     158        { 
     159            assert(stackSize(t) - 1 == mStringTab, "OH NO String table is not in the right place!"); 
     160            pop(t); 
     161        } 
     162 
    165163        scope path = new FilePath(filename); 
    166164        scope file = new UnicodeFile!(dchar)(path, Encoding.Unknown); 
     
    176174        mod = sem.visit(mod); 
    177175 
    178         //scope test = new TestVisitor(this); 
    179         //test.visit(mod); 
     176        scope cg = new Codegen(this); 
     177        mod = cg.visit(mod); 
     178 
     179        insert(t, -2); 
     180        pop(t); 
     181         
     182        return stackSize(t) - 1; 
    180183    } 
    181184 
     
    338341+/ 
    339342} 
    340  
    341 /+ 
    342 struct Token 
    343 { 
    344     public static enum Type 
    345     { 
    346         As, 
    347         Assert, 
    348         Break, 
    349         Case, 
    350         Catch, 
    351         Continue, 
    352         Coroutine, 
    353         Default, 
    354         Do, 
    355         Else, 
    356         False, 
    357         Finally, 
    358         For, 
    359         Foreach, 
    360         Function, 
    361         Global, 
    362         If, 
    363         Import, 
    364         In, 
    365         Is, 
    366         Local, 
    367         Module, 
    368         Namespace, 
    369         Null, 
    370         Object, 
    371         Return, 
    372         Super, 
    373         Switch, 
    374         This, 
    375         Throw, 
    376         True, 
    377         Try, 
    378         Vararg, 
    379         While, 
    380         With, 
    381         Yield, 
    382  
    383         Add, 
    384         AddEq, 
    385         Inc, 
    386         Sub, 
    387         SubEq, 
    388         Dec, 
    389         Cat, 
    390         CatEq, 
    391         Cmp3, 
    392         Mul, 
    393         MulEq, 
    394         DefaultEq, 
    395         Div, 
    396         DivEq, 
    397         Mod, 
    398         ModEq, 
    399         LT, 
    400         LE, 
    401         Shl, 
    402         ShlEq, 
    403         GT, 
    404         GE, 
    405         Shr, 
    406         ShrEq, 
    407         UShr, 
    408         UShrEq, 
    409         And, 
    410         AndEq, 
    411         AndAnd, 
    412         Or, 
    413         OrEq, 
    414         OrOr, 
    415         Xor, 
    416         XorEq, 
    417         Assign, 
    418         EQ, 
    419         Dot, 
    420         DotDot, 
    421         Not, 
    422         NE, 
    423         LParen, 
    424         RParen, 
    425         LBracket, 
    426         RBracket, 
    427         LBrace, 
    428         RBrace, 
    429         LAttr, 
    430         RAttr, 
    431         Colon, 
    432         Comma, 
    433         Semicolon, 
    434         Length, 
    435         Question, 
    436         Backslash, 
    437         Arrow, 
    438         Dollar, 
    439  
    440         Ident, 
    441         CharLiteral, 
    442         StringLiteral, 
    443         IntLiteral, 
    444         FloatLiteral, 
    445         EOF 
    446     } 
    447  
    448     public static const dchar[][] tokenStrings = 
    449     [ 
    450         Type.As: "as", 
    451         Type.Assert: "assert", 
    452         Type.Break: "break", 
    453         Type.Case: "case", 
    454         Type.Catch: "catch", 
    455         Type.Continue: "continue", 
    456         Type.Coroutine: "coroutine", 
    457         Type.Default: "default", 
    458         Type.Do: "do", 
    459         Type.Else: "else", 
    460         Type.False: "false", 
    461         Type.Finally: "finally", 
    462         Type.For: "for", 
    463         Type.Foreach: "foreach", 
    464         Type.Function: "function", 
    465         Type.Global: "global", 
    466         Type.If: "if", 
    467         Type.Import: "import", 
    468         Type.In: "in", 
    469         Type.Is: "is", 
    470         Type.Local: "local", 
    471         Type.Module: "module", 
    472         Type.Namespace: "namespace", 
    473         Type.Null: "null", 
    474         Type.Object: "object", 
    475         Type.Return: "return", 
    476         Type.Super: "super", 
    477         Type.Switch: "switch", 
    478         Type.This: "this", 
    479         Type.Throw: "throw", 
    480         Type.True: "true", 
    481         Type.Try: "try", 
    482         Type.Vararg: "vararg", 
    483         Type.While: "while", 
    484         Type.With: "with", 
    485         Type.Yield: "yield", 
    486  
    487         Type.Add: "+", 
    488         Type.AddEq: "+=", 
    489         Type.Inc: "++", 
    490         Type.Sub: "-", 
    491         Type.SubEq: "-=", 
    492         Type.Dec: "--", 
    493         Type.Cat: "~", 
    494         Type.CatEq: "~=", 
    495         Type.Cmp3: "<=>", 
    496         Type.Mul: "*", 
    497         Type.MulEq: "*=", 
    498         Type.DefaultEq: "?=", 
    499         Type.Div: "/", 
    500         Type.DivEq: "/=", 
    501         Type.Mod: "%", 
    502         Type.ModEq: "%=", 
    503         Type.LT: "<", 
    504         Type.LE: "<=", 
    505         Type.Shl: "<<", 
    506         Type.ShlEq: "<<=", 
    507         Type.GT: ">", 
    508         Type.GE: ">=", 
    509         Type.Shr: ">>", 
    510         Type.ShrEq: ">>=", 
    511         Type.UShr: ">>>", 
    512         Type.UShrEq: ">>>=", 
    513         Type.And: "&", 
    514         Type.AndEq: "&=", 
    515         Type.AndAnd: "&&", 
    516         Type.Or: "|", 
    517         Type.OrEq: "|=", 
    518         Type.OrOr: "||", 
    519         Type.Xor: "^", 
    520         Type.XorEq: "^=", 
    521         Type.Assign: "=", 
    522         Type.EQ: "==", 
    523         Type.Dot: ".", 
    524         Type.DotDot: "..", 
    525         Type.Not: "!", 
    526         Type.NE: "!=", 
    527         Type.LParen: "(", 
    528         Type.RParen: ")", 
    529         Type.LBracket: "[", 
    530         Type.RBracket: "]", 
    531         Type.LBrace: "{", 
    532         Type.RBrace: "}", 
    533         Type.LAttr: "</", 
    534         Type.RAttr: "/>", 
    535         Type.Colon: ":", 
    536         Type.Comma: ",", 
    537         Type.Semicolon: ";", 
    538         Type.Length: "#", 
    539         Type.Question: "?", 
    540         Type.Backslash: "\\", 
    541         Type.Arrow: "->", 
    542         Type.Dollar: "$", 
    543  
    544         Type.Ident: "Identifier", 
    545         Type.CharLiteral: "Char Literal", 
    546         Type.StringLiteral: "String Literal", 
    547         Type.IntLiteral: "Int Literal", 
    548         Type.FloatLiteral: "Float Literal", 
    549         Type.EOF: "<EOF>" 
    550     ]; 
    551  
    552     public static Type[dchar[]] stringToType; 
    553  
    554     static this() 
    555     { 
    556         foreach(i, val; tokenStrings[0 .. Type.Ident]) 
    557             stringToType[val] = cast(Type)i; 
    558  
    559         stringToType.rehash; 
    560     } 
    561  
    562     public char[] toString() 
    563     { 
    564         switch(type) 
    565         { 
    566             case Type.Ident:         return "Identifier: " ~ utf.toString(stringValue); 
    567             case Type.CharLiteral:   return "Character Literal"; 
    568             case Type.StringLiteral: return "String Literal"; 
    569             case Type.IntLiteral:    return "Integer Literal: " ~ Integer.toString(intValue); 
    570             case Type.FloatLiteral:  return "Float Literal: " ~ Float.toString(floatValue); 
    571             default:                 return utf.toString(tokenStrings[cast(uint)type]); 
    572         } 
    573          
    574         assert(false); 
    575     } 
    576  
    577     public void expect(Type t) 
    578     { 
    579         if(type != t) 
    580             expected(tokenStrings[t]); 
    581     } 
    582      
    583     public void expected(dchar[] message) 
    584     { 
    585         auto e = new OldCompileException(location, "'{}' expected; found '{}' instead", message, tokenStrings[type]); 
    586         e.atEOF = type == Type.EOF; 
    587         throw e; 
    588     } 
    589  
    590     public bool isOpAssign() 
    591     { 
    592         switch(type) 
    593         { 
    594             case Token.AddEq, 
    595                 Token.SubEq, 
    596                 Token.CatEq, 
    597                 Token.MulEq, 
    598                 Token.DivEq, 
    599                 Token.ModEq, 
    600                 Token.ShlEq, 
    601                 Token.ShrEq, 
    602                 Token.UShrEq, 
    603                 Token.OrEq, 
    604                 Token.XorEq, 
    605                 Token.AndEq, 
    606                 Token.DefaultEq: 
    607                 return true; 
    608  
    609             default: 
    610                 return false; 
    611         } 
    612          
    613         assert(false); 
    614     } 
    615  
    616     public Type type; 
    617  
    618     union 
    619     { 
    620         public bool boolValue; 
    621         public dchar[] stringValue; 
    622         public int intValue; 
    623         public mdfloat floatValue; 
    624     } 
    625  
    626     public CompileLoc location; 
    627 } 
    628  
    629 class Lexer 
    630 { 
    631     protected dchar[] mSource; 
    632     protected CompileLoc mLoc; 
    633     protected uword mPosition; 
    634     protected dchar mCharacter; 
    635     protected dchar mLookaheadCharacter; 
    636     protected bool mHaveLookahead = false; 
    637     protected bool mIsJSON = false; 
    638     protected Token mTok; 
    639     protected Token mPeekTok; 
    640     protected bool mHavePeekTok = false; 
    641     protected bool mNewlineSinceLastTok = false; 
    642  
    643     public this(char[] name, dchar[] source, bool isJSON = false) 
    644     { 
    645         mLoc = CompileLoc(utf.toString32(name), 1, 0); 
    646  
    647         mSource = source; 
    648         mPosition = 0; 
    649         mIsJSON = isJSON; 
    650  
    651         nextChar(); 
    652  
    653         if(mSource.length >= 2 && mSource[0 .. 2] == "#!") 
    654             while(!isEOL()) 
    655                 nextChar(); 
    656  
    657         next(); 
    658     } 
    659  
    660     public final Token* tok() 
    661     { 
    662         return &mTok; 
    663     } 
    664      
    665     public final CompileLoc loc() 
    666     { 
    667         return mTok.location; 
    668     } 
    669  
    670     public final Token.Type type() 
    671     { 
    672         return mTok.type; 
    673     } 
    674  
    675     public final Token expect(Token.Type t) 
    676     { 
    677         mTok.expect(t); 
    678         Token ret = mTok; 
    679  
    680         if(t != Token.EOF) 
    681             next(); 
    682  
    683         return ret; 
    684     } 
    685      
    686     public final bool isStatementTerm() 
    687     { 
    688         return mNewlineSinceLastTok || 
    689             mTok.type == Token.EOF || 
    690             mTok.type == Token.Semicolon || 
    691             mTok.type == Token.RBrace || 
    692             mTok.type == Token.RParen || 
    693             mTok.type == Token.RBracket; 
    694     } 
    695  
    696     public final void statementTerm() 
    697     { 
    698         if(mNewlineSinceLastTok) 
    699             return; 
    700         else 
    701         { 
    702             if(mTok.type == Token.EOF || mTok.type == Token.RBrace || mTok.type == Token.RParen || mTok.type == Token.RBracket) 
    703                 return; 
    704             else if(mTok.type == Token.Semicolon) 
    705                 next(); 
    706             else 
    707                 throw new OldCompileException(mLoc, "Statement terminator expected, not '{}'", mTok.toString()); 
    708         } 
    709     } 
    710  
    711     public final Token peek() 
    712     { 
    713         if(mHavePeekTok) 
    714             return mPeekTok; 
    715  
    716         auto t = mTok; 
    717         nextToken(); 
    718         mHavePeekTok = true; 
    719         mPeekTok = mTok; 
    720         mTok = t; 
    721  
    722         return mPeekTok; 
    723     } 
    724      
    725     public final void next() 
    726     { 
    727         if(mHavePeekTok) 
    728         { 
    729             mHavePeekTok = false; 
    730             mTok = mPeekTok; 
    731         } 
    732         else 
    733             nextToken(); 
    734     } 
    735  
    736     protected final bool isEOF() 
    737     { 
    738         return (mCharacter == '\0') || (mCharacter == dchar.init); 
    739     } 
    740  
    741     protected final bool isEOL() 
    742     { 
    743         return isNewline() || isEOF(); 
    744     } 
    745  
    746     protected final bool isWhitespace() 
    747     { 
    748         return (mCharacter == ' ') || (mCharacter == '\t') || (mCharacter == '\v') || (mCharacter == '\u000C') || isEOL(); 
    749     } 
    750  
    751     protected final bool isNewline() 
    752     { 
    753         return (mCharacter == '\r') || (mCharacter == '\n'); 
    754     } 
    755  
    756     protected final bool isBinaryDigit() 
    757     { 
    758         return (mCharacter == '0') || (mCharacter == '1'); 
    759     } 
    760  
    761     protected final bool isOctalDigit() 
    762     { 
    763         return (mCharacter >= '0') && (mCharacter <= '7'); 
    764     } 
    765  
    766     protected final bool isHexDigit() 
    767     { 
    768         return ((mCharacter >= '0') && (mCharacter <= '9')) || 
    769             ((mCharacter >= 'a') && (mCharacter <= 'f')) || 
    770             ((mCharacter >= 'A') && (mCharacter <= 'F')); 
    771     } 
    772  
    773     protected final bool isDecimalDigit() 
    774     { 
    775         return (mCharacter >= '0') && (mCharacter <= '9'); 
    776     } 
    777  
    778     protected final bool isAlpha() 
    779     { 
    780         return ((mCharacter >= 'a') && (mCharacter <= 'z')) || ((mCharacter >= 'A') && (mCharacter <= 'Z')); 
    781     } 
    782  
    783     protected final ubyte hexDigitToInt(dchar c) 
    784     { 
    785         assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'), "hexDigitToInt"); 
    786  
    787         if(c >= '0' && c <= '9') 
    788             return cast(ubyte)(c - '0'); 
    789  
    790         if(Uni.isUpper(c)) 
    791             return cast(ubyte)(c - 'A' + 10); 
    792         else 
    793             return cast(ubyte)(c - 'a' + 10); 
    794     } 
    795  
    796     protected final dchar readChar() 
    797     { 
    798         if(mPosition >= mSource.length) 
    799             return dchar.init; 
    800         else 
    801             return mSource[mPosition++]; 
    802     } 
    803  
    804     protected final dchar lookaheadChar() 
    805     { 
    806         assert(mHaveLookahead == false, "looking ahead too far"); 
    807  
    808         mLookaheadCharacter = readChar(); 
    809         mHaveLookahead = true; 
    810         return mLookaheadCharacter; 
    811     } 
    812  
    813     protected final void nextChar() 
    814     { 
    815         mLoc.column++; 
    816  
    817         if(mHaveLookahead) 
    818         { 
    819             mCharacter = mLookaheadCharacter; 
    820             mHaveLookahead = false; 
    821         } 
    822         else 
    823         { 
    824             mCharacter = readChar(); 
    825         } 
    826     } 
    827  
    828     protected final void nextLine() 
    829     { 
    830         while(isNewline() && !isEOF()) 
    831         { 
    832             dchar old = mCharacter; 
    833  
    834             nextChar(); 
    835  
    836             if(isNewline() && mCharacter != old) 
    837                 nextChar(); 
    838  
    839             mLoc.line++; 
    840             mLoc.column = 1; 
    841         } 
    842     } 
    843  
    844     protected final bool readNumLiteral(bool prependPoint, out mdfloat fret, out int iret) 
    845     { 
    846         CompileLoc beginning = mLoc; 
    847         dchar[100] buf; 
    848         uint i = 0; 
    849  
    850         void add(dchar c) 
    851         { 
    852             buf[i] = c; 
    853             i++; 
    854         } 
    855  
    856         bool hasPoint = false; 
    857  
    858         if(prependPoint) 
    859         { 
    860             hasPoint = true; 
    861             add('.'); 
    862         } 
    863         else 
    864         { 
    865             if(mCharacter == '0') 
    866             { 
    867                 nextChar(); 
    868  
    869                 switch(mCharacter) 
    870                 { 
    871                     case 'b', 'B': 
    872                         nextChar(); 
    873  
    874                         if(!isBinaryDigit() && mCharacter != '_') 
    875                             throw new OldCompileException(mLoc, "Binary digit expected, not '{}'", mCharacter); 
    876  
    877                         while(isBinaryDigit() || mCharacter == '_') 
    878                         { 
    879                             if(mCharacter != '_') 
    880                                 add(mCharacter); 
    881  
    882                             nextChar(); 
    883                         } 
    884  
    885                         try 
    886                             iret = Integer.toInt(buf[0 .. i], 2); 
    887                         catch(IllegalArgumentException e) 
    888                             throw new OldCompileException(beginning, e.toString()); 
    889  
    890                         return true; 
    891  
    892                     case 'c', 'C': 
    893                         nextChar(); 
    894  
    895                         if(!isOctalDigit() && mCharacter != '_') 
    896                             throw new OldCompileException(mLoc, "Octal digit expected, not '{}'", mCharacter); 
    897  
    898                         while(isOctalDigit() || mCharacter == '_') 
    899                         { 
    900                             if(mCharacter != '_') 
    901                                 add(mCharacter); 
    902  
    903                             nextChar(); 
    904                         } 
    905  
    906                         try 
    907                             iret = Integer.toInt(buf[0 .. i], 8); 
    908                         catch(IllegalArgumentException e) 
    909                             throw new OldCompileException(beginning, e.toString()); 
    910  
    911                         return true; 
    912  
    913                     case 'x', 'X': 
    914                         nextChar(); 
    915  
    916                         if(!isHexDigit() && mCharacter != '_') 
    917                             throw new OldCompileException(mLoc, "Hexadecimal digit expected, not '{}'", mCharacter); 
    918  
    919                         while(isHexDigit() || mCharacter == '_') 
    920                         { 
    921                             if(mCharacter != '_') 
    922                                 add(mCharacter); 
    923  
    924                             nextChar(); 
    925                         } 
    926  
    927                         try 
    928                             iret = Integer.toInt(buf[0 .. i], 16); 
    929                         catch(IllegalArgumentException e) 
    930                             throw new OldCompileException(beginning, e.toString()); 
    931  
    932                         return true; 
    933  
    934                     default: 
    935                         add('0'); 
    936                         break; 
    937                 } 
    938             } 
    939         } 
    940  
    941         while(hasPoint == false) 
    942         { 
    943             if(isDecimalDigit()) 
    944             { 
    945                 add(mCharacter); 
    946                 nextChar(); 
    947             } 
    948             else if(mCharacter == '.') 
    949             { 
    950                 auto ch = lookaheadChar(); 
    951  
    952                 if((ch >= '0' && ch <= '9') || ch == '_') 
    953                 { 
    954                     hasPoint = true; 
    955                     add(mCharacter); 
    956                     nextChar(); 
    957                 } 
    958                 else 
    959                 { 
    960                     // next token is either a .. or maybe it's .something 
    961                     break; 
    962                 } 
    963             } 
    964             else if(mCharacter == '_') 
    965             { 
    966                 //REACHABLE? 
    967                 nextChar(); 
    968                 continue; 
    969             } 
    970             else 
    971                 // this will still handle exponents on literals without a decimal point 
    972                 break; 
    973         } 
    974  
    975         if(hasPoint) 
    976         { 
    977             if(isDecimalDigit()) 
    978             { 
    979                 add(mCharacter); 
    980                 nextChar(); 
    981             } 
    982             else if(mCharacter == '_') 
    983                 nextChar(); 
    984             else 
    985             { 
    986                 // REACHABLE? 
    987                 throw new OldCompileException(mLoc, "Floating point literal '{}' must have at least one digit after decimal point", buf[0 .. i]); 
    988             } 
    989         } 
    990          
    991         bool hasExponent = false; 
    992  
    993         while(true) 
    994         { 
    995             if(isDecimalDigit()) 
    996             { 
    997                 add(mCharacter); 
    998                 nextChar(); 
    999             } 
    1000             else if(mCharacter == 'e' || mCharacter == 'E') 
    1001             { 
    1002                 hasExponent = true; 
    1003  
    1004                 add(mCharacter); 
    1005  
    1006                 nextChar(); 
    1007  
    1008                 if(mCharacter == '-' || mCharacter == '+') 
    1009                 { 
    1010                     add(mCharacter); 
    1011                     nextChar(); 
    1012                 } 
    1013  
    1014                 if(!isDecimalDigit() && mCharacter != '_') 
    1015                     throw new OldCompileException(mLoc, "Exponent value expected in float literal '{}'", buf[0 .. i]); 
    1016  
    1017                 while(isDecimalDigit() || mCharacter == '_') 
    1018                 { 
    1019                     if(mCharacter != '_') 
    1020                         add(mCharacter); 
    1021  
    1022                     nextChar(); 
    1023                 } 
    1024  
    1025                 break; 
    1026             } 
    1027             else if(mCharacter == '_') 
    1028             { 
    1029                 nextChar(); 
    1030                 continue; 
    1031             } 
    1032             else 
    1033                 break; 
    1034         } 
    1035  
    1036         if(hasPoint == false && hasExponent == false) 
    1037         { 
    1038             try 
    1039                 iret = Integer.toInt(buf[0 .. i], 10); 
    1040             catch(IllegalArgumentException e) 
    1041                 throw new OldCompileException(beginning, e.toString()); 
    1042  
    1043             return true; 
    1044         } 
    1045         else 
    1046         { 
    1047             try 
    1048                 fret = Float.toFloat(utf.toString(buf[0 .. i])); 
    1049             catch(IllegalArgumentException e) 
    1050                 throw new OldCompileException(beginning, e.toString()); 
    1051  
    1052             return false; 
    1053         } 
    1054     } 
    1055  
    1056     protected final dchar readEscapeSequence(CompileLoc beginning) 
    1057     { 
    1058         uint readHexDigits(uint num) 
    1059         { 
    1060             uint ret = 0; 
    1061  
    1062             for(uint i = 0; i < num; i++) 
    1063             { 
    1064                 if(isHexDigit() == false) 
    1065                     throw new OldCompileException(mLoc, "Hexadecimal escape digits expected"); 
    1066  
    1067                 ret <<= 4; 
    1068                 ret |= hexDigitToInt(mCharacter); 
    1069                 nextChar(); 
    1070             } 
    1071  
    1072             return ret; 
    1073         } 
    1074  
    1075         dchar ret; 
    1076  
    1077         assert(mCharacter == '\\', "escape seq - must start on backslash"); 
    1078  
    1079         nextChar(); 
    1080         if(isEOF()) 
    1081         { 
    1082             auto e = new OldCompileException(beginning, "Unterminated string or character literal"); 
    1083             e.atEOF = true; 
    1084             throw e; 
    1085         } 
    1086  
    1087         switch(mCharacter) 
    1088         { 
    1089             case 'a':  nextChar(); return '\a'; 
    1090             case 'b':  nextChar(); return '\b'; 
    1091           &nb