]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/d/dmd/expression.d
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
[thirdparty/gcc.git] / gcc / d / dmd / expression.d
index 2a6233244547a5f5a178695e3b0c52ced8992f71..e6b7e3014f18894ea0e32628931f962db27b5188 100644 (file)
@@ -60,6 +60,7 @@ import dmd.optimize;
 import dmd.root.ctfloat;
 import dmd.root.filename;
 import dmd.common.outbuffer;
+import dmd.root.optional;
 import dmd.root.rmem;
 import dmd.root.rootobject;
 import dmd.root.string;
@@ -116,7 +117,7 @@ enum ModifyFlags
 inout(Expression) firstComma(inout Expression e)
 {
     Expression ex = cast()e;
-    while (ex.op == TOK.comma)
+    while (ex.op == EXP.comma)
         ex = (cast(CommaExp)ex).e1;
     return cast(inout)ex;
 
@@ -133,7 +134,7 @@ inout(Expression) firstComma(inout Expression e)
 inout(Expression) lastComma(inout Expression e)
 {
     Expression ex = cast()e;
-    while (ex.op == TOK.comma)
+    while (ex.op == EXP.comma)
         ex = (cast(CommaExp)ex).e2;
     return cast(inout)ex;
 
@@ -286,7 +287,7 @@ extern (C++) void expandTuples(Expressions* exps)
         }
 
         // Inline expand all the tuples
-        while (arg.op == TOK.tuple)
+        while (arg.op == EXP.tuple)
         {
             TupleExp te = cast(TupleExp)arg;
             exps.remove(i); // remove arg
@@ -356,7 +357,7 @@ int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
                 printf("expansion ->\n");
                 foreach (e; exps)
                 {
-                    printf("\texps[%d] e = %s %s\n", i, Token.tochars[e.op], e.toChars());
+                    printf("\texps[%d] e = %s %s\n", i, EXPtoString(e.op), e.toChars());
                 }
             }
             return cast(int)u;
@@ -528,15 +529,15 @@ extern (C++) struct UnionExp
     extern (C++) Expression copy()
     {
         Expression e = exp();
-        //if (e.size > sizeof(u)) printf("%s\n", Token::toChars(e.op));
+        //if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr);
         assert(e.size <= u.sizeof);
         switch (e.op)
         {
-            case TOK.cantExpression:    return CTFEExp.cantexp;
-            case TOK.voidExpression:    return CTFEExp.voidexp;
-            case TOK.break_:            return CTFEExp.breakexp;
-            case TOK.continue_:         return CTFEExp.continueexp;
-            case TOK.goto_:             return CTFEExp.gotoexp;
+            case EXP.cantExpression:    return CTFEExp.cantexp;
+            case EXP.voidExpression:    return CTFEExp.voidexp;
+            case EXP.break_:            return CTFEExp.breakexp;
+            case EXP.continue_:         return CTFEExp.continueexp;
+            case EXP.goto_:             return CTFEExp.gotoexp;
             default:                    return e.copy();
         }
     }
@@ -610,14 +611,14 @@ VarDeclaration expToVariable(Expression e)
     {
         switch (e.op)
         {
-            case TOK.variable:
+            case EXP.variable:
                 return (cast(VarExp)e).var.isVarDeclaration();
 
-            case TOK.dotVariable:
+            case EXP.dotVariable:
                 e = (cast(DotVarExp)e).e1;
                 continue;
 
-            case TOK.index:
+            case EXP.index:
             {
                 IndexExp ei = cast(IndexExp)e;
                 e = ei.e1;
@@ -627,7 +628,7 @@ VarDeclaration expToVariable(Expression e)
                 return null;
             }
 
-            case TOK.slice:
+            case EXP.slice:
             {
                 SliceExp ei = cast(SliceExp)e;
                 e = ei.e1;
@@ -637,8 +638,8 @@ VarDeclaration expToVariable(Expression e)
                 return null;
             }
 
-            case TOK.this_:
-            case TOK.super_:
+            case EXP.this_:
+            case EXP.super_:
                 return (cast(ThisExp)e).var.isVarDeclaration();
 
             default:
@@ -662,13 +663,13 @@ enum WANTexpand = 1;    // expand const/immutable variables if possible
  */
 extern (C++) abstract class Expression : ASTNode
 {
-    const TOK op;   // to minimize use of dynamic_cast
+    const EXP op;   // to minimize use of dynamic_cast
     ubyte size;     // # of bytes in Expression so we can copy() it
     ubyte parens;   // if this is a parenthesized expression
     Type type;      // !=null means that semantic() has been run
     Loc loc;        // file location
 
-    extern (D) this(const ref Loc loc, TOK op, int size)
+    extern (D) this(const ref Loc loc, EXP op, int size)
     {
         //printf("Expression::Expression(op = %d) this = %p\n", op, this);
         this.loc = loc;
@@ -678,12 +679,12 @@ extern (C++) abstract class Expression : ASTNode
 
     static void _init()
     {
-        CTFEExp.cantexp = new CTFEExp(TOK.cantExpression);
-        CTFEExp.voidexp = new CTFEExp(TOK.voidExpression);
-        CTFEExp.breakexp = new CTFEExp(TOK.break_);
-        CTFEExp.continueexp = new CTFEExp(TOK.continue_);
-        CTFEExp.gotoexp = new CTFEExp(TOK.goto_);
-        CTFEExp.showcontext = new CTFEExp(TOK.showCtfeContext);
+        CTFEExp.cantexp = new CTFEExp(EXP.cantExpression);
+        CTFEExp.voidexp = new CTFEExp(EXP.voidExpression);
+        CTFEExp.breakexp = new CTFEExp(EXP.break_);
+        CTFEExp.continueexp = new CTFEExp(EXP.continue_);
+        CTFEExp.gotoexp = new CTFEExp(EXP.goto_);
+        CTFEExp.showcontext = new CTFEExp(EXP.showCtfeContext);
     }
 
     /**
@@ -874,13 +875,13 @@ extern (C++) abstract class Expression : ASTNode
      */
     extern (D) static Expression extractLast(Expression e, out Expression e0)
     {
-        if (e.op != TOK.comma)
+        if (e.op != EXP.comma)
         {
             return e;
         }
 
         CommaExp ce = cast(CommaExp)e;
-        if (ce.e2.op != TOK.comma)
+        if (ce.e2.op != EXP.comma)
         {
             e0 = ce.e1;
             return ce.e2;
@@ -890,11 +891,11 @@ extern (C++) abstract class Expression : ASTNode
             e0 = e;
 
             Expression* pce = &ce.e2;
-            while ((cast(CommaExp)(*pce)).e2.op == TOK.comma)
+            while ((cast(CommaExp)(*pce)).e2.op == EXP.comma)
             {
                 pce = &(cast(CommaExp)(*pce)).e2;
             }
-            assert((*pce).op == TOK.comma);
+            assert((*pce).op == EXP.comma);
             ce = cast(CommaExp)(*pce);
             *pce = ce.e1;
 
@@ -918,14 +919,14 @@ extern (C++) abstract class Expression : ASTNode
 
     dinteger_t toInteger()
     {
-        //printf("Expression %s\n", Token::toChars(op));
+        //printf("Expression %s\n", EXPtoString(op).ptr);
         error("integer constant expression expected instead of `%s`", toChars());
         return 0;
     }
 
     uinteger_t toUInteger()
     {
-        //printf("Expression %s\n", Token::toChars(op));
+        //printf("Expression %s\n", EXPtoString(op).ptr);
         return cast(uinteger_t)toInteger();
     }
 
@@ -976,7 +977,7 @@ extern (C++) abstract class Expression : ASTNode
         else if (!loc.isValid())
             loc = e.loc;
 
-        if (e.op == TOK.type)
+        if (e.op == EXP.type)
             error("`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind());
         else
             error("`%s` is not an lvalue and cannot be modified", e.toChars());
@@ -1079,7 +1080,7 @@ extern (C++) abstract class Expression : ASTNode
 
     extern (D) final bool checkScalar()
     {
-        if (op == TOK.error)
+        if (op == EXP.error)
             return true;
         if (type.toBasetype().ty == Terror)
             return true;
@@ -1093,7 +1094,7 @@ extern (C++) abstract class Expression : ASTNode
 
     extern (D) final bool checkNoBool()
     {
-        if (op == TOK.error)
+        if (op == EXP.error)
             return true;
         if (type.toBasetype().ty == Terror)
             return true;
@@ -1107,7 +1108,7 @@ extern (C++) abstract class Expression : ASTNode
 
     extern (D) final bool checkIntegral()
     {
-        if (op == TOK.error)
+        if (op == EXP.error)
             return true;
         if (type.toBasetype().ty == Terror)
             return true;
@@ -1121,7 +1122,7 @@ extern (C++) abstract class Expression : ASTNode
 
     extern (D) final bool checkArithmetic()
     {
-        if (op == TOK.error)
+        if (op == EXP.error)
             return true;
         if (type.toBasetype().ty == Terror)
             return true;
@@ -1492,9 +1493,9 @@ extern (C++) abstract class Expression : ASTNode
 
     extern (D) final bool checkRightThis(Scope* sc)
     {
-        if (op == TOK.error)
+        if (op == EXP.error)
             return true;
-        if (op == TOK.variable && type.ty != Terror)
+        if (op == EXP.variable && type.ty != Terror)
         {
             VarExp ve = cast(VarExp)this;
             if (isNeedThisScope(sc, ve.var))
@@ -1513,7 +1514,7 @@ extern (C++) abstract class Expression : ASTNode
      * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
      * Returns true if error occurs.
      */
-    extern (D) final bool checkReadModifyWrite(TOK rmwOp, Expression ex = null)
+    extern (D) final bool checkReadModifyWrite(EXP rmwOp, Expression ex = null)
     {
         //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex.toChars() : "");
         if (!type || !type.isShared() || type.isTypeStruct() || type.isTypeClass())
@@ -1522,13 +1523,13 @@ extern (C++) abstract class Expression : ASTNode
         // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
         switch (rmwOp)
         {
-        case TOK.plusPlus:
-        case TOK.prePlusPlus:
-            rmwOp = TOK.addAssign;
+        case EXP.plusPlus:
+        case EXP.prePlusPlus:
+            rmwOp = EXP.addAssign;
             break;
-        case TOK.minusMinus:
-        case TOK.preMinusMinus:
-            rmwOp = TOK.minAssign;
+        case EXP.minusMinus:
+        case EXP.preMinusMinus:
+            rmwOp = EXP.minAssign;
             break;
         default:
             break;
@@ -1536,7 +1537,7 @@ extern (C++) abstract class Expression : ASTNode
 
         error("read-modify-write operations are not allowed for `shared` variables");
         errorSupplemental("Use `core.atomic.atomicOp!\"%s\"(%s, %s)` instead",
-                          Token.toChars(rmwOp), toChars(), ex ? ex.toChars() : "1");
+                          EXPtoString(rmwOp).ptr, toChars(), ex ? ex.toChars() : "1");
         return true;
     }
 
@@ -1558,7 +1559,7 @@ extern (C++) abstract class Expression : ASTNode
         //printf("Expression::addressOf()\n");
         debug
         {
-            assert(op == TOK.error || isLvalue());
+            assert(op == EXP.error || isLvalue());
         }
         Expression e = new AddrExp(loc, this, type.pointerTo());
         return e;
@@ -1597,12 +1598,11 @@ extern (C++) abstract class Expression : ASTNode
         return .isConst(this);
     }
 
-    /********************************
-     * Does this expression statically evaluate to a boolean 'result' (true or false)?
-     */
-    bool isBool(bool result)
+    /// Statically evaluate this expression to a `bool` if possible
+    /// Returns: an optional thath either contains the value or is empty
+    Optional!bool toBool()
     {
-        return false;
+        return typeof(return)();
     }
 
     bool hasCode()
@@ -1612,127 +1612,127 @@ extern (C++) abstract class Expression : ASTNode
 
     final pure inout nothrow @nogc @safe
     {
-        inout(IntegerExp)   isIntegerExp() { return op == TOK.int64 ? cast(typeof(return))this : null; }
-        inout(ErrorExp)     isErrorExp() { return op == TOK.error ? cast(typeof(return))this : null; }
-        inout(VoidInitExp)  isVoidInitExp() { return op == TOK.void_ ? cast(typeof(return))this : null; }
-        inout(RealExp)      isRealExp() { return op == TOK.float64 ? cast(typeof(return))this : null; }
-        inout(ComplexExp)   isComplexExp() { return op == TOK.complex80 ? cast(typeof(return))this : null; }
-        inout(IdentifierExp) isIdentifierExp() { return op == TOK.identifier ? cast(typeof(return))this : null; }
-        inout(DollarExp)    isDollarExp() { return op == TOK.dollar ? cast(typeof(return))this : null; }
-        inout(DsymbolExp)   isDsymbolExp() { return op == TOK.dSymbol ? cast(typeof(return))this : null; }
-        inout(ThisExp)      isThisExp() { return op == TOK.this_ ? cast(typeof(return))this : null; }
-        inout(SuperExp)     isSuperExp() { return op == TOK.super_ ? cast(typeof(return))this : null; }
-        inout(NullExp)      isNullExp() { return op == TOK.null_ ? cast(typeof(return))this : null; }
-        inout(StringExp)    isStringExp() { return op == TOK.string_ ? cast(typeof(return))this : null; }
-        inout(TupleExp)     isTupleExp() { return op == TOK.tuple ? cast(typeof(return))this : null; }
-        inout(ArrayLiteralExp) isArrayLiteralExp() { return op == TOK.arrayLiteral ? cast(typeof(return))this : null; }
-        inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == TOK.assocArrayLiteral ? cast(typeof(return))this : null; }
-        inout(StructLiteralExp) isStructLiteralExp() { return op == TOK.structLiteral ? cast(typeof(return))this : null; }
-        inout(CompoundLiteralExp) isCompoundLiteralExp() { return op == TOK.compoundLiteral ? cast(typeof(return))this : null; }
-        inout(TypeExp)      isTypeExp() { return op == TOK.type ? cast(typeof(return))this : null; }
-        inout(ScopeExp)     isScopeExp() { return op == TOK.scope_ ? cast(typeof(return))this : null; }
-        inout(TemplateExp)  isTemplateExp() { return op == TOK.template_ ? cast(typeof(return))this : null; }
-        inout(NewExp) isNewExp() { return op == TOK.new_ ? cast(typeof(return))this : null; }
-        inout(NewAnonClassExp) isNewAnonClassExp() { return op == TOK.newAnonymousClass ? cast(typeof(return))this : null; }
-        inout(SymOffExp)    isSymOffExp() { return op == TOK.symbolOffset ? cast(typeof(return))this : null; }
-        inout(VarExp)       isVarExp() { return op == TOK.variable ? cast(typeof(return))this : null; }
-        inout(OverExp)      isOverExp() { return op == TOK.overloadSet ? cast(typeof(return))this : null; }
-        inout(FuncExp)      isFuncExp() { return op == TOK.function_ ? cast(typeof(return))this : null; }
-        inout(DeclarationExp) isDeclarationExp() { return op == TOK.declaration ? cast(typeof(return))this : null; }
-        inout(TypeidExp)    isTypeidExp() { return op == TOK.typeid_ ? cast(typeof(return))this : null; }
-        inout(TraitsExp)    isTraitsExp() { return op == TOK.traits ? cast(typeof(return))this : null; }
-        inout(HaltExp)      isHaltExp() { return op == TOK.halt ? cast(typeof(return))this : null; }
-        inout(IsExp)        isExp() { return op == TOK.is_ ? cast(typeof(return))this : null; }
-        inout(MixinExp)     isMixinExp() { return op == TOK.mixin_ ? cast(typeof(return))this : null; }
-        inout(ImportExp)    isImportExp() { return op == TOK.import_ ? cast(typeof(return))this : null; }
-        inout(AssertExp)    isAssertExp() { return op == TOK.assert_ ? cast(typeof(return))this : null; }
-        inout(DotIdExp)     isDotIdExp() { return op == TOK.dotIdentifier ? cast(typeof(return))this : null; }
-        inout(DotTemplateExp) isDotTemplateExp() { return op == TOK.dotTemplateDeclaration ? cast(typeof(return))this : null; }
-        inout(DotVarExp)    isDotVarExp() { return op == TOK.dotVariable ? cast(typeof(return))this : null; }
-        inout(DotTemplateInstanceExp) isDotTemplateInstanceExp() { return op == TOK.dotTemplateInstance ? cast(typeof(return))this : null; }
-        inout(DelegateExp)  isDelegateExp() { return op == TOK.delegate_ ? cast(typeof(return))this : null; }
-        inout(DotTypeExp)   isDotTypeExp() { return op == TOK.dotType ? cast(typeof(return))this : null; }
-        inout(CallExp)      isCallExp() { return op == TOK.call ? cast(typeof(return))this : null; }
-        inout(AddrExp)      isAddrExp() { return op == TOK.address ? cast(typeof(return))this : null; }
-        inout(PtrExp)       isPtrExp() { return op == TOK.star ? cast(typeof(return))this : null; }
-        inout(NegExp)       isNegExp() { return op == TOK.negate ? cast(typeof(return))this : null; }
-        inout(UAddExp)      isUAddExp() { return op == TOK.uadd ? cast(typeof(return))this : null; }
-        inout(ComExp)       isComExp() { return op == TOK.tilde ? cast(typeof(return))this : null; }
-        inout(NotExp)       isNotExp() { return op == TOK.not ? cast(typeof(return))this : null; }
-        inout(DeleteExp)    isDeleteExp() { return op == TOK.delete_ ? cast(typeof(return))this : null; }
-        inout(CastExp)      isCastExp() { return op == TOK.cast_ ? cast(typeof(return))this : null; }
-        inout(VectorExp)    isVectorExp() { return op == TOK.vector ? cast(typeof(return))this : null; }
-        inout(VectorArrayExp) isVectorArrayExp() { return op == TOK.vectorArray ? cast(typeof(return))this : null; }
-        inout(SliceExp)     isSliceExp() { return op == TOK.slice ? cast(typeof(return))this : null; }
-        inout(ArrayLengthExp) isArrayLengthExp() { return op == TOK.arrayLength ? cast(typeof(return))this : null; }
-        inout(ArrayExp)     isArrayExp() { return op == TOK.array ? cast(typeof(return))this : null; }
-        inout(DotExp)       isDotExp() { return op == TOK.dot ? cast(typeof(return))this : null; }
-        inout(CommaExp)     isCommaExp() { return op == TOK.comma ? cast(typeof(return))this : null; }
-        inout(IntervalExp)  isIntervalExp() { return op == TOK.interval ? cast(typeof(return))this : null; }
-        inout(DelegatePtrExp)     isDelegatePtrExp() { return op == TOK.delegatePointer ? cast(typeof(return))this : null; }
-        inout(DelegateFuncptrExp) isDelegateFuncptrExp() { return op == TOK.delegateFunctionPointer ? cast(typeof(return))this : null; }
-        inout(IndexExp)     isIndexExp() { return op == TOK.index ? cast(typeof(return))this : null; }
-        inout(PostExp)      isPostExp()  { return (op == TOK.plusPlus || op == TOK.minusMinus) ? cast(typeof(return))this : null; }
-        inout(PreExp)       isPreExp()   { return (op == TOK.prePlusPlus || op == TOK.preMinusMinus) ? cast(typeof(return))this : null; }
-        inout(AssignExp)    isAssignExp()    { return op == TOK.assign ? cast(typeof(return))this : null; }
-        inout(ConstructExp) isConstructExp() { return op == TOK.construct ? cast(typeof(return))this : null; }
-        inout(BlitExp)      isBlitExp()      { return op == TOK.blit ? cast(typeof(return))this : null; }
-        inout(AddAssignExp) isAddAssignExp() { return op == TOK.addAssign ? cast(typeof(return))this : null; }
-        inout(MinAssignExp) isMinAssignExp() { return op == TOK.minAssign ? cast(typeof(return))this : null; }
-        inout(MulAssignExp) isMulAssignExp() { return op == TOK.mulAssign ? cast(typeof(return))this : null; }
-
-        inout(DivAssignExp) isDivAssignExp() { return op == TOK.divAssign ? cast(typeof(return))this : null; }
-        inout(ModAssignExp) isModAssignExp() { return op == TOK.modAssign ? cast(typeof(return))this : null; }
-        inout(AndAssignExp) isAndAssignExp() { return op == TOK.andAssign ? cast(typeof(return))this : null; }
-        inout(OrAssignExp)  isOrAssignExp()  { return op == TOK.orAssign ? cast(typeof(return))this : null; }
-        inout(XorAssignExp) isXorAssignExp() { return op == TOK.xorAssign ? cast(typeof(return))this : null; }
-        inout(PowAssignExp) isPowAssignExp() { return op == TOK.powAssign ? cast(typeof(return))this : null; }
-
-        inout(ShlAssignExp)  isShlAssignExp()  { return op == TOK.leftShiftAssign ? cast(typeof(return))this : null; }
-        inout(ShrAssignExp)  isShrAssignExp()  { return op == TOK.rightShiftAssign ? cast(typeof(return))this : null; }
-        inout(UshrAssignExp) isUshrAssignExp() { return op == TOK.unsignedRightShiftAssign ? cast(typeof(return))this : null; }
-
-        inout(CatAssignExp) isCatAssignExp() { return op == TOK.concatenateAssign
+        inout(IntegerExp)   isIntegerExp() { return op == EXP.int64 ? cast(typeof(return))this : null; }
+        inout(ErrorExp)     isErrorExp() { return op == EXP.error ? cast(typeof(return))this : null; }
+        inout(VoidInitExp)  isVoidInitExp() { return op == EXP.void_ ? cast(typeof(return))this : null; }
+        inout(RealExp)      isRealExp() { return op == EXP.float64 ? cast(typeof(return))this : null; }
+        inout(ComplexExp)   isComplexExp() { return op == EXP.complex80 ? cast(typeof(return))this : null; }
+        inout(IdentifierExp) isIdentifierExp() { return op == EXP.identifier ? cast(typeof(return))this : null; }
+        inout(DollarExp)    isDollarExp() { return op == EXP.dollar ? cast(typeof(return))this : null; }
+        inout(DsymbolExp)   isDsymbolExp() { return op == EXP.dSymbol ? cast(typeof(return))this : null; }
+        inout(ThisExp)      isThisExp() { return op == EXP.this_ ? cast(typeof(return))this : null; }
+        inout(SuperExp)     isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
+        inout(NullExp)      isNullExp() { return op == EXP.null_ ? cast(typeof(return))this : null; }
+        inout(StringExp)    isStringExp() { return op == EXP.string_ ? cast(typeof(return))this : null; }
+        inout(TupleExp)     isTupleExp() { return op == EXP.tuple ? cast(typeof(return))this : null; }
+        inout(ArrayLiteralExp) isArrayLiteralExp() { return op == EXP.arrayLiteral ? cast(typeof(return))this : null; }
+        inout(AssocArrayLiteralExp) isAssocArrayLiteralExp() { return op == EXP.assocArrayLiteral ? cast(typeof(return))this : null; }
+        inout(StructLiteralExp) isStructLiteralExp() { return op == EXP.structLiteral ? cast(typeof(return))this : null; }
+        inout(CompoundLiteralExp) isCompoundLiteralExp() { return op == EXP.compoundLiteral ? cast(typeof(return))this : null; }
+        inout(TypeExp)      isTypeExp() { return op == EXP.type ? cast(typeof(return))this : null; }
+        inout(ScopeExp)     isScopeExp() { return op == EXP.scope_ ? cast(typeof(return))this : null; }
+        inout(TemplateExp)  isTemplateExp() { return op == EXP.template_ ? cast(typeof(return))this : null; }
+        inout(NewExp) isNewExp() { return op == EXP.new_ ? cast(typeof(return))this : null; }
+        inout(NewAnonClassExp) isNewAnonClassExp() { return op == EXP.newAnonymousClass ? cast(typeof(return))this : null; }
+        inout(SymOffExp)    isSymOffExp() { return op == EXP.symbolOffset ? cast(typeof(return))this : null; }
+        inout(VarExp)       isVarExp() { return op == EXP.variable ? cast(typeof(return))this : null; }
+        inout(OverExp)      isOverExp() { return op == EXP.overloadSet ? cast(typeof(return))this : null; }
+        inout(FuncExp)      isFuncExp() { return op == EXP.function_ ? cast(typeof(return))this : null; }
+        inout(DeclarationExp) isDeclarationExp() { return op == EXP.declaration ? cast(typeof(return))this : null; }
+        inout(TypeidExp)    isTypeidExp() { return op == EXP.typeid_ ? cast(typeof(return))this : null; }
+        inout(TraitsExp)    isTraitsExp() { return op == EXP.traits ? cast(typeof(return))this : null; }
+        inout(HaltExp)      isHaltExp() { return op == EXP.halt ? cast(typeof(return))this : null; }
+        inout(IsExp)        isExp() { return op == EXP.is_ ? cast(typeof(return))this : null; }
+        inout(MixinExp)     isMixinExp() { return op == EXP.mixin_ ? cast(typeof(return))this : null; }
+        inout(ImportExp)    isImportExp() { return op == EXP.import_ ? cast(typeof(return))this : null; }
+        inout(AssertExp)    isAssertExp() { return op == EXP.assert_ ? cast(typeof(return))this : null; }
+        inout(DotIdExp)     isDotIdExp() { return op == EXP.dotIdentifier ? cast(typeof(return))this : null; }
+        inout(DotTemplateExp) isDotTemplateExp() { return op == EXP.dotTemplateDeclaration ? cast(typeof(return))this : null; }
+        inout(DotVarExp)    isDotVarExp() { return op == EXP.dotVariable ? cast(typeof(return))this : null; }
+        inout(DotTemplateInstanceExp) isDotTemplateInstanceExp() { return op == EXP.dotTemplateInstance ? cast(typeof(return))this : null; }
+        inout(DelegateExp)  isDelegateExp() { return op == EXP.delegate_ ? cast(typeof(return))this : null; }
+        inout(DotTypeExp)   isDotTypeExp() { return op == EXP.dotType ? cast(typeof(return))this : null; }
+        inout(CallExp)      isCallExp() { return op == EXP.call ? cast(typeof(return))this : null; }
+        inout(AddrExp)      isAddrExp() { return op == EXP.address ? cast(typeof(return))this : null; }
+        inout(PtrExp)       isPtrExp() { return op == EXP.star ? cast(typeof(return))this : null; }
+        inout(NegExp)       isNegExp() { return op == EXP.negate ? cast(typeof(return))this : null; }
+        inout(UAddExp)      isUAddExp() { return op == EXP.uadd ? cast(typeof(return))this : null; }
+        inout(ComExp)       isComExp() { return op == EXP.tilde ? cast(typeof(return))this : null; }
+        inout(NotExp)       isNotExp() { return op == EXP.not ? cast(typeof(return))this : null; }
+        inout(DeleteExp)    isDeleteExp() { return op == EXP.delete_ ? cast(typeof(return))this : null; }
+        inout(CastExp)      isCastExp() { return op == EXP.cast_ ? cast(typeof(return))this : null; }
+        inout(VectorExp)    isVectorExp() { return op == EXP.vector ? cast(typeof(return))this : null; }
+        inout(VectorArrayExp) isVectorArrayExp() { return op == EXP.vectorArray ? cast(typeof(return))this : null; }
+        inout(SliceExp)     isSliceExp() { return op == EXP.slice ? cast(typeof(return))this : null; }
+        inout(ArrayLengthExp) isArrayLengthExp() { return op == EXP.arrayLength ? cast(typeof(return))this : null; }
+        inout(ArrayExp)     isArrayExp() { return op == EXP.array ? cast(typeof(return))this : null; }
+        inout(DotExp)       isDotExp() { return op == EXP.dot ? cast(typeof(return))this : null; }
+        inout(CommaExp)     isCommaExp() { return op == EXP.comma ? cast(typeof(return))this : null; }
+        inout(IntervalExp)  isIntervalExp() { return op == EXP.interval ? cast(typeof(return))this : null; }
+        inout(DelegatePtrExp)     isDelegatePtrExp() { return op == EXP.delegatePointer ? cast(typeof(return))this : null; }
+        inout(DelegateFuncptrExp) isDelegateFuncptrExp() { return op == EXP.delegateFunctionPointer ? cast(typeof(return))this : null; }
+        inout(IndexExp)     isIndexExp() { return op == EXP.index ? cast(typeof(return))this : null; }
+        inout(PostExp)      isPostExp()  { return (op == EXP.plusPlus || op == EXP.minusMinus) ? cast(typeof(return))this : null; }
+        inout(PreExp)       isPreExp()   { return (op == EXP.prePlusPlus || op == EXP.preMinusMinus) ? cast(typeof(return))this : null; }
+        inout(AssignExp)    isAssignExp()    { return op == EXP.assign ? cast(typeof(return))this : null; }
+        inout(ConstructExp) isConstructExp() { return op == EXP.construct ? cast(typeof(return))this : null; }
+        inout(BlitExp)      isBlitExp()      { return op == EXP.blit ? cast(typeof(return))this : null; }
+        inout(AddAssignExp) isAddAssignExp() { return op == EXP.addAssign ? cast(typeof(return))this : null; }
+        inout(MinAssignExp) isMinAssignExp() { return op == EXP.minAssign ? cast(typeof(return))this : null; }
+        inout(MulAssignExp) isMulAssignExp() { return op == EXP.mulAssign ? cast(typeof(return))this : null; }
+
+        inout(DivAssignExp) isDivAssignExp() { return op == EXP.divAssign ? cast(typeof(return))this : null; }
+        inout(ModAssignExp) isModAssignExp() { return op == EXP.modAssign ? cast(typeof(return))this : null; }
+        inout(AndAssignExp) isAndAssignExp() { return op == EXP.andAssign ? cast(typeof(return))this : null; }
+        inout(OrAssignExp)  isOrAssignExp()  { return op == EXP.orAssign ? cast(typeof(return))this : null; }
+        inout(XorAssignExp) isXorAssignExp() { return op == EXP.xorAssign ? cast(typeof(return))this : null; }
+        inout(PowAssignExp) isPowAssignExp() { return op == EXP.powAssign ? cast(typeof(return))this : null; }
+
+        inout(ShlAssignExp)  isShlAssignExp()  { return op == EXP.leftShiftAssign ? cast(typeof(return))this : null; }
+        inout(ShrAssignExp)  isShrAssignExp()  { return op == EXP.rightShiftAssign ? cast(typeof(return))this : null; }
+        inout(UshrAssignExp) isUshrAssignExp() { return op == EXP.unsignedRightShiftAssign ? cast(typeof(return))this : null; }
+
+        inout(CatAssignExp) isCatAssignExp() { return op == EXP.concatenateAssign
                                                 ? cast(typeof(return))this
                                                 : null; }
 
-        inout(CatElemAssignExp) isCatElemAssignExp() { return op == TOK.concatenateElemAssign
+        inout(CatElemAssignExp) isCatElemAssignExp() { return op == EXP.concatenateElemAssign
                                                 ? cast(typeof(return))this
                                                 : null; }
 
-        inout(CatDcharAssignExp) isCatDcharAssignExp() { return op == TOK.concatenateDcharAssign
+        inout(CatDcharAssignExp) isCatDcharAssignExp() { return op == EXP.concatenateDcharAssign
                                                 ? cast(typeof(return))this
                                                 : null; }
 
-        inout(AddExp)      isAddExp() { return op == TOK.add ? cast(typeof(return))this : null; }
-        inout(MinExp)      isMinExp() { return op == TOK.min ? cast(typeof(return))this : null; }
-        inout(CatExp)      isCatExp() { return op == TOK.concatenate ? cast(typeof(return))this : null; }
-        inout(MulExp)      isMulExp() { return op == TOK.mul ? cast(typeof(return))this : null; }
-        inout(DivExp)      isDivExp() { return op == TOK.div ? cast(typeof(return))this : null; }
-        inout(ModExp)      isModExp() { return op == TOK.mod ? cast(typeof(return))this : null; }
-        inout(PowExp)      isPowExp() { return op == TOK.pow ? cast(typeof(return))this : null; }
-        inout(ShlExp)      isShlExp() { return op == TOK.leftShift ? cast(typeof(return))this : null; }
-        inout(ShrExp)      isShrExp() { return op == TOK.rightShift ? cast(typeof(return))this : null; }
-        inout(UshrExp)     isUshrExp() { return op == TOK.unsignedRightShift ? cast(typeof(return))this : null; }
-        inout(AndExp)      isAndExp() { return op == TOK.and ? cast(typeof(return))this : null; }
-        inout(OrExp)       isOrExp() { return op == TOK.or ? cast(typeof(return))this : null; }
-        inout(XorExp)      isXorExp() { return op == TOK.xor ? cast(typeof(return))this : null; }
-        inout(LogicalExp)  isLogicalExp() { return (op == TOK.andAnd || op == TOK.orOr) ? cast(typeof(return))this : null; }
-        //inout(CmpExp)    isCmpExp() { return op == TOK. ? cast(typeof(return))this : null; }
-        inout(InExp)       isInExp() { return op == TOK.in_ ? cast(typeof(return))this : null; }
-        inout(RemoveExp)   isRemoveExp() { return op == TOK.remove ? cast(typeof(return))this : null; }
-        inout(EqualExp)    isEqualExp() { return (op == TOK.equal || op == TOK.notEqual) ? cast(typeof(return))this : null; }
-        inout(IdentityExp) isIdentityExp() { return (op == TOK.identity || op == TOK.notIdentity) ? cast(typeof(return))this : null; }
-        inout(CondExp)     isCondExp() { return op == TOK.question ? cast(typeof(return))this : null; }
-        inout(GenericExp)  isGenericExp() { return op == TOK._Generic ? cast(typeof(return))this : null; }
+        inout(AddExp)      isAddExp() { return op == EXP.add ? cast(typeof(return))this : null; }
+        inout(MinExp)      isMinExp() { return op == EXP.min ? cast(typeof(return))this : null; }
+        inout(CatExp)      isCatExp() { return op == EXP.concatenate ? cast(typeof(return))this : null; }
+        inout(MulExp)      isMulExp() { return op == EXP.mul ? cast(typeof(return))this : null; }
+        inout(DivExp)      isDivExp() { return op == EXP.div ? cast(typeof(return))this : null; }
+        inout(ModExp)      isModExp() { return op == EXP.mod ? cast(typeof(return))this : null; }
+        inout(PowExp)      isPowExp() { return op == EXP.pow ? cast(typeof(return))this : null; }
+        inout(ShlExp)      isShlExp() { return op == EXP.leftShift ? cast(typeof(return))this : null; }
+        inout(ShrExp)      isShrExp() { return op == EXP.rightShift ? cast(typeof(return))this : null; }
+        inout(UshrExp)     isUshrExp() { return op == EXP.unsignedRightShift ? cast(typeof(return))this : null; }
+        inout(AndExp)      isAndExp() { return op == EXP.and ? cast(typeof(return))this : null; }
+        inout(OrExp)       isOrExp() { return op == EXP.or ? cast(typeof(return))this : null; }
+        inout(XorExp)      isXorExp() { return op == EXP.xor ? cast(typeof(return))this : null; }
+        inout(LogicalExp)  isLogicalExp() { return (op == EXP.andAnd || op == EXP.orOr) ? cast(typeof(return))this : null; }
+        //inout(CmpExp)    isCmpExp() { return op == EXP. ? cast(typeof(return))this : null; }
+        inout(InExp)       isInExp() { return op == EXP.in_ ? cast(typeof(return))this : null; }
+        inout(RemoveExp)   isRemoveExp() { return op == EXP.remove ? cast(typeof(return))this : null; }
+        inout(EqualExp)    isEqualExp() { return (op == EXP.equal || op == EXP.notEqual) ? cast(typeof(return))this : null; }
+        inout(IdentityExp) isIdentityExp() { return (op == EXP.identity || op == EXP.notIdentity) ? cast(typeof(return))this : null; }
+        inout(CondExp)     isCondExp() { return op == EXP.question ? cast(typeof(return))this : null; }
+        inout(GenericExp)  isGenericExp() { return op == EXP._Generic ? cast(typeof(return))this : null; }
         inout(DefaultInitExp)    isDefaultInitExp() { return isDefaultInitOp(op) ? cast(typeof(return))this: null; }
-        inout(FileInitExp)       isFileInitExp() { return (op == TOK.file || op == TOK.fileFullPath) ? cast(typeof(return))this : null; }
-        inout(LineInitExp)       isLineInitExp() { return op == TOK.line ? cast(typeof(return))this : null; }
-        inout(ModuleInitExp)     isModuleInitExp() { return op == TOK.moduleString ? cast(typeof(return))this : null; }
-        inout(FuncInitExp)       isFuncInitExp() { return op == TOK.functionString ? cast(typeof(return))this : null; }
-        inout(PrettyFuncInitExp) isPrettyFuncInitExp() { return op == TOK.prettyFunction ? cast(typeof(return))this : null; }
-        inout(ClassReferenceExp) isClassReferenceExp() { return op == TOK.classReference ? cast(typeof(return))this : null; }
-        inout(ThrownExceptionExp) isThrownExceptionExp() { return op == TOK.thrownException ? cast(typeof(return))this : null; }
+        inout(FileInitExp)       isFileInitExp() { return (op == EXP.file || op == EXP.fileFullPath) ? cast(typeof(return))this : null; }
+        inout(LineInitExp)       isLineInitExp() { return op == EXP.line ? cast(typeof(return))this : null; }
+        inout(ModuleInitExp)     isModuleInitExp() { return op == EXP.moduleString ? cast(typeof(return))this : null; }
+        inout(FuncInitExp)       isFuncInitExp() { return op == EXP.functionString ? cast(typeof(return))this : null; }
+        inout(PrettyFuncInitExp) isPrettyFuncInitExp() { return op == EXP.prettyFunction ? cast(typeof(return))this : null; }
+        inout(ClassReferenceExp) isClassReferenceExp() { return op == EXP.classReference ? cast(typeof(return))this : null; }
+        inout(ThrownExceptionExp) isThrownExceptionExp() { return op == EXP.thrownException ? cast(typeof(return))this : null; }
     }
 
     inout(BinAssignExp) isBinAssignExp() pure inout nothrow @nogc
@@ -1754,7 +1754,7 @@ extern (C++) final class IntegerExp : Expression
 
     extern (D) this(const ref Loc loc, dinteger_t value, Type type)
     {
-        super(loc, TOK.int64, __traits(classInstanceSize, IntegerExp));
+        super(loc, EXP.int64, __traits(classInstanceSize, IntegerExp));
         //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : "");
         assert(type);
         if (!type.isscalar())
@@ -1770,7 +1770,7 @@ extern (C++) final class IntegerExp : Expression
 
     extern (D) this(dinteger_t value)
     {
-        super(Loc.initial, TOK.int64, __traits(classInstanceSize, IntegerExp));
+        super(Loc.initial, EXP.int64, __traits(classInstanceSize, IntegerExp));
         this.type = Type.tint32;
         this.value = cast(d_int32)value;
     }
@@ -1827,10 +1827,10 @@ extern (C++) final class IntegerExp : Expression
         return complex_t(toReal());
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
         bool r = toInteger() != 0;
-        return result ? r : !r;
+        return typeof(return)(r);
     }
 
     override Expression toLvalue(Scope* sc, Expression e)
@@ -1969,7 +1969,7 @@ extern (C++) final class ErrorExp : Expression
 {
     private extern (D) this()
     {
-        super(Loc.initial, TOK.error, __traits(classInstanceSize, ErrorExp));
+        super(Loc.initial, EXP.error, __traits(classInstanceSize, ErrorExp));
         type = Type.terror;
     }
 
@@ -2015,7 +2015,7 @@ extern (C++) final class VoidInitExp : Expression
 
     extern (D) this(VarDeclaration var)
     {
-        super(var.loc, TOK.void_, __traits(classInstanceSize, VoidInitExp));
+        super(var.loc, EXP.void_, __traits(classInstanceSize, VoidInitExp));
         this.var = var;
         this.type = var.type;
     }
@@ -2040,7 +2040,7 @@ extern (C++) final class RealExp : Expression
 
     extern (D) this(const ref Loc loc, real_t value, Type type)
     {
-        super(loc, TOK.float64, __traits(classInstanceSize, RealExp));
+        super(loc, EXP.float64, __traits(classInstanceSize, RealExp));
         //printf("RealExp::RealExp(%Lg)\n", value);
         this.value = value;
         this.type = type;
@@ -2096,9 +2096,9 @@ extern (C++) final class RealExp : Expression
         return complex_t(toReal(), toImaginary());
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return result ? cast(bool)value : !cast(bool)value;
+        return typeof(return)(!!value);
     }
 
     override void accept(Visitor v)
@@ -2115,7 +2115,7 @@ extern (C++) final class ComplexExp : Expression
 
     extern (D) this(const ref Loc loc, complex_t value, Type type)
     {
-        super(loc, TOK.complex80, __traits(classInstanceSize, ComplexExp));
+        super(loc, EXP.complex80, __traits(classInstanceSize, ComplexExp));
         this.value = value;
         this.type = type;
         //printf("ComplexExp::ComplexExp(%s)\n", toChars());
@@ -2171,12 +2171,9 @@ extern (C++) final class ComplexExp : Expression
         return value;
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        if (result)
-            return cast(bool)value;
-        else
-            return !value;
+        return typeof(return)(!!value);
     }
 
     override void accept(Visitor v)
@@ -2193,7 +2190,7 @@ extern (C++) class IdentifierExp : Expression
 
     extern (D) this(const ref Loc loc, Identifier ident)
     {
-        super(loc, TOK.identifier, __traits(classInstanceSize, IdentifierExp));
+        super(loc, EXP.identifier, __traits(classInstanceSize, IdentifierExp));
         this.ident = ident;
     }
 
@@ -2243,7 +2240,7 @@ extern (C++) final class DsymbolExp : Expression
 
     extern (D) this(const ref Loc loc, Dsymbol s, bool hasOverloads = true)
     {
-        super(loc, TOK.dSymbol, __traits(classInstanceSize, DsymbolExp));
+        super(loc, EXP.dSymbol, __traits(classInstanceSize, DsymbolExp));
         this.s = s;
         this.hasOverloads = hasOverloads;
     }
@@ -2273,11 +2270,11 @@ extern (C++) class ThisExp : Expression
 
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.this_, __traits(classInstanceSize, ThisExp));
+        super(loc, EXP.this_, __traits(classInstanceSize, ThisExp));
         //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
     }
 
-    this(const ref Loc loc, const TOK tok)
+    this(const ref Loc loc, const EXP tok)
     {
         super(loc, tok, __traits(classInstanceSize, ThisExp));
         //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
@@ -2292,9 +2289,10 @@ extern (C++) class ThisExp : Expression
         return r;
     }
 
-    override final bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return result;
+        // `this` is never null (what about structs?)
+        return typeof(return)(true);
     }
 
     override final bool isLvalue()
@@ -2326,7 +2324,7 @@ extern (C++) final class SuperExp : ThisExp
 {
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.super_);
+        super(loc, EXP.super_);
     }
 
     override void accept(Visitor v)
@@ -2342,7 +2340,7 @@ extern (C++) final class NullExp : Expression
 {
     extern (D) this(const ref Loc loc, Type type = null)
     {
-        super(loc, TOK.null_, __traits(classInstanceSize, NullExp));
+        super(loc, EXP.null_, __traits(classInstanceSize, NullExp));
         this.type = type;
     }
 
@@ -2350,7 +2348,7 @@ extern (C++) final class NullExp : Expression
     {
         if (auto e = o.isExpression())
         {
-            if (e.op == TOK.null_ && type.equals(e.type))
+            if (e.op == EXP.null_ && type.equals(e.type))
             {
                 return true;
             }
@@ -2358,9 +2356,10 @@ extern (C++) final class NullExp : Expression
         return false;
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return result ? false : true;
+        // null in any type is false
+        return typeof(return)(false);
     }
 
     override StringExp toStringExp()
@@ -2400,7 +2399,7 @@ extern (C++) final class StringExp : Expression
 
     extern (D) this(const ref Loc loc, const(void)[] string)
     {
-        super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
+        super(loc, EXP.string_, __traits(classInstanceSize, StringExp));
         this.string = cast(char*)string.ptr; // note that this.string should be const
         this.len = string.length;
         this.sz = 1;                    // work around LDC bug #1286
@@ -2408,7 +2407,7 @@ extern (C++) final class StringExp : Expression
 
     extern (D) this(const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = NoPostfix)
     {
-        super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
+        super(loc, EXP.string_, __traits(classInstanceSize, StringExp));
         this.string = cast(char*)string.ptr; // note that this.string should be const
         this.len = len;
         this.sz = sz;
@@ -2681,9 +2680,11 @@ extern (C++) final class StringExp : Expression
         return cast(int)(len1 - len2);
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return result;
+        // Keep the old behaviour for this refactoring
+        // Should probably match language spec instead and check for length
+        return typeof(return)(true);
     }
 
     override bool isLvalue()
@@ -2810,7 +2811,7 @@ extern (C++) final class TupleExp : Expression
 
     extern (D) this(const ref Loc loc, Expression e0, Expressions* exps)
     {
-        super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
+        super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
         //printf("TupleExp(this = %p)\n", this);
         this.e0 = e0;
         this.exps = exps;
@@ -2818,14 +2819,14 @@ extern (C++) final class TupleExp : Expression
 
     extern (D) this(const ref Loc loc, Expressions* exps)
     {
-        super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
+        super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
         //printf("TupleExp(this = %p)\n", this);
         this.exps = exps;
     }
 
     extern (D) this(const ref Loc loc, TupleDeclaration tup)
     {
-        super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
+        super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
         this.exps = new Expressions();
 
         this.exps.reserve(tup.objects.dim);
@@ -2919,14 +2920,14 @@ extern (C++) final class ArrayLiteralExp : Expression
 
     extern (D) this(const ref Loc loc, Type type, Expressions* elements)
     {
-        super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
+        super(loc, EXP.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
         this.type = type;
         this.elements = elements;
     }
 
     extern (D) this(const ref Loc loc, Type type, Expression e)
     {
-        super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
+        super(loc, EXP.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
         this.type = type;
         elements = new Expressions();
         elements.push(e);
@@ -2934,7 +2935,7 @@ extern (C++) final class ArrayLiteralExp : Expression
 
     extern (D) this(const ref Loc loc, Type type, Expression basis, Expressions* elements)
     {
-        super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
+        super(loc, EXP.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
         this.type = type;
         this.basis = basis;
         this.elements = elements;
@@ -3000,10 +3001,10 @@ extern (C++) final class ArrayLiteralExp : Expression
         return el ? el : basis;
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
         size_t dim = elements ? elements.dim : 0;
-        return result ? (dim != 0) : (dim == 0);
+        return typeof(return)(dim != 0);
     }
 
     override StringExp toStringExp()
@@ -3023,7 +3024,7 @@ extern (C++) final class ArrayLiteralExp : Expression
                 foreach (i; 0 .. elements.dim)
                 {
                     auto ch = this[i];
-                    if (ch.op != TOK.int64)
+                    if (ch.op != EXP.int64)
                         return null;
                     if (sz == 1)
                         buf.writeByte(cast(uint)ch.toInteger());
@@ -3079,7 +3080,7 @@ extern (C++) final class AssocArrayLiteralExp : Expression
 
     extern (D) this(const ref Loc loc, Expressions* keys, Expressions* values)
     {
-        super(loc, TOK.assocArrayLiteral, __traits(classInstanceSize, AssocArrayLiteralExp));
+        super(loc, EXP.assocArrayLiteral, __traits(classInstanceSize, AssocArrayLiteralExp));
         assert(keys.dim == values.dim);
         this.keys = keys;
         this.values = values;
@@ -3119,10 +3120,10 @@ extern (C++) final class AssocArrayLiteralExp : Expression
         return new AssocArrayLiteralExp(loc, arraySyntaxCopy(keys), arraySyntaxCopy(values));
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
         size_t dim = keys.dim;
-        return result ? (dim != 0) : (dim == 0);
+        return typeof(return)(dim != 0);
     }
 
     override void accept(Visitor v)
@@ -3172,7 +3173,7 @@ extern (C++) final class StructLiteralExp : Expression
 
     extern (D) this(const ref Loc loc, StructDeclaration sd, Expressions* elements, Type stype = null)
     {
-        super(loc, TOK.structLiteral, __traits(classInstanceSize, StructLiteralExp));
+        super(loc, EXP.structLiteral, __traits(classInstanceSize, StructLiteralExp));
         this.sd = sd;
         if (!elements)
             elements = new Expressions();
@@ -3278,9 +3279,12 @@ extern (C++) final class StructLiteralExp : Expression
          */
         if (elements.dim)
         {
+            const sz = type.size();
+            if (sz == SIZE_INVALID)
+                return -1;
             foreach (i, v; sd.fields)
             {
-                if (offset == v.offset && type.size() == v.type.size())
+                if (offset == v.offset && sz == v.type.size())
                 {
                     /* context fields might not be filled. */
                     if (i >= sd.nonHiddenFields())
@@ -3348,7 +3352,7 @@ extern (C++) final class CompoundLiteralExp : Expression
 
     extern (D) this(const ref Loc loc, Type type_name, Initializer initializer)
     {
-        super(loc, TOK.compoundLiteral, __traits(classInstanceSize, CompoundLiteralExp));
+        super(loc, EXP.compoundLiteral, __traits(classInstanceSize, CompoundLiteralExp));
         super.type = type_name;
         this.initializer = initializer;
         //printf("CompoundLiteralExp::CompoundLiteralExp(%s)\n", toChars());
@@ -3367,7 +3371,7 @@ extern (C++) final class TypeExp : Expression
 {
     extern (D) this(const ref Loc loc, Type type)
     {
-        super(loc, TOK.type, __traits(classInstanceSize, TypeExp));
+        super(loc, EXP.type, __traits(classInstanceSize, TypeExp));
         //printf("TypeExp::TypeExp(%s)\n", type.toChars());
         this.type = type;
     }
@@ -3409,7 +3413,7 @@ extern (C++) final class ScopeExp : Expression
 
     extern (D) this(const ref Loc loc, ScopeDsymbol sds)
     {
-        super(loc, TOK.scope_, __traits(classInstanceSize, ScopeExp));
+        super(loc, EXP.scope_, __traits(classInstanceSize, ScopeExp));
         //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds.toChars());
         //static int count; if (++count == 38) *(char*)0=0;
         this.sds = sds;
@@ -3464,7 +3468,7 @@ extern (C++) final class TemplateExp : Expression
 
     extern (D) this(const ref Loc loc, TemplateDeclaration td, FuncDeclaration fd = null)
     {
-        super(loc, TOK.template_, __traits(classInstanceSize, TemplateExp));
+        super(loc, EXP.template_, __traits(classInstanceSize, TemplateExp));
         //printf("TemplateExp(): %s\n", td.toChars());
         this.td = td;
         this.fd = fd;
@@ -3519,7 +3523,7 @@ extern (C++) final class NewExp : Expression
 
     extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
     {
-        super(loc, TOK.new_, __traits(classInstanceSize, NewExp));
+        super(loc, EXP.new_, __traits(classInstanceSize, NewExp));
         this.thisexp = thisexp;
         this.newargs = newargs;
         this.newtype = newtype;
@@ -3558,7 +3562,7 @@ extern (C++) final class NewAnonClassExp : Expression
 
     extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, ClassDeclaration cd, Expressions* arguments)
     {
-        super(loc, TOK.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
+        super(loc, EXP.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
         this.thisexp = thisexp;
         this.newargs = newargs;
         this.cd = cd;
@@ -3584,7 +3588,7 @@ extern (C++) class SymbolExp : Expression
     Dsymbol originalScope; // original scope before inlining
     bool hasOverloads;
 
-    extern (D) this(const ref Loc loc, TOK op, int size, Declaration var, bool hasOverloads)
+    extern (D) this(const ref Loc loc, EXP op, int size, Declaration var, bool hasOverloads)
     {
         super(loc, op, size);
         assert(var);
@@ -3615,13 +3619,13 @@ extern (C++) final class SymOffExp : SymbolExp
                 .error(loc, "need `this` for address of `%s`", v.toChars());
             hasOverloads = false;
         }
-        super(loc, TOK.symbolOffset, __traits(classInstanceSize, SymOffExp), var, hasOverloads);
+        super(loc, EXP.symbolOffset, __traits(classInstanceSize, SymOffExp), var, hasOverloads);
         this.offset = offset;
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return result ? true : false;
+        return typeof(return)(true);
     }
 
     override void accept(Visitor v)
@@ -3641,7 +3645,7 @@ extern (C++) final class VarExp : SymbolExp
         if (var.isVarDeclaration())
             hasOverloads = false;
 
-        super(loc, TOK.variable, __traits(classInstanceSize, VarExp), var, hasOverloads);
+        super(loc, EXP.variable, __traits(classInstanceSize, VarExp), var, hasOverloads);
         //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars());
         //if (strcmp(var.ident.toChars(), "func") == 0) assert(0);
         this.type = var.type;
@@ -3725,7 +3729,7 @@ extern (C++) final class OverExp : Expression
 
     extern (D) this(const ref Loc loc, OverloadSet s)
     {
-        super(loc, TOK.overloadSet, __traits(classInstanceSize, OverExp));
+        super(loc, EXP.overloadSet, __traits(classInstanceSize, OverExp));
         //printf("OverExp(this = %p, '%s')\n", this, var.toChars());
         vars = s;
         type = Type.tvoid;
@@ -3755,11 +3759,11 @@ extern (C++) final class FuncExp : Expression
 {
     FuncLiteralDeclaration fd;
     TemplateDeclaration td;
-    TOK tok;
+    TOK tok;  // TOK.reserved, TOK.delegate_, TOK.function_
 
     extern (D) this(const ref Loc loc, Dsymbol s)
     {
-        super(loc, TOK.function_, __traits(classInstanceSize, FuncExp));
+        super(loc, EXP.function_, __traits(classInstanceSize, FuncExp));
         this.td = s.isTemplateDeclaration();
         this.fd = s.isFuncLiteralDeclaration();
         if (td)
@@ -3927,7 +3931,7 @@ extern (C++) final class FuncExp : Expression
             // Reset inference target for the later re-semantic
             fd.treq = null;
 
-            if (ex.op == TOK.error)
+            if (ex.op == EXP.error)
                 return MATCH.nomatch;
             if (auto ef = ex.isFuncExp())
                 return ef.matchType(to, sc, presult, flag);
@@ -4057,7 +4061,7 @@ extern (C++) final class DeclarationExp : Expression
 
     extern (D) this(const ref Loc loc, Dsymbol declaration)
     {
-        super(loc, TOK.declaration, __traits(classInstanceSize, DeclarationExp));
+        super(loc, EXP.declaration, __traits(classInstanceSize, DeclarationExp));
         this.declaration = declaration;
     }
 
@@ -4090,7 +4094,7 @@ extern (C++) final class TypeidExp : Expression
 
     extern (D) this(const ref Loc loc, RootObject o)
     {
-        super(loc, TOK.typeid_, __traits(classInstanceSize, TypeidExp));
+        super(loc, EXP.typeid_, __traits(classInstanceSize, TypeidExp));
         this.obj = o;
     }
 
@@ -4115,7 +4119,7 @@ extern (C++) final class TraitsExp : Expression
 
     extern (D) this(const ref Loc loc, Identifier ident, Objects* args)
     {
-        super(loc, TOK.traits, __traits(classInstanceSize, TraitsExp));
+        super(loc, EXP.traits, __traits(classInstanceSize, TraitsExp));
         this.ident = ident;
         this.args = args;
     }
@@ -4137,7 +4141,7 @@ extern (C++) final class HaltExp : Expression
 {
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.halt, __traits(classInstanceSize, HaltExp));
+        super(loc, EXP.halt, __traits(classInstanceSize, HaltExp));
     }
 
     override void accept(Visitor v)
@@ -4161,7 +4165,7 @@ extern (C++) final class IsExp : Expression
 
     extern (D) this(const ref Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters* parameters)
     {
-        super(loc, TOK.is_, __traits(classInstanceSize, IsExp));
+        super(loc, EXP.is_, __traits(classInstanceSize, IsExp));
         this.targ = targ;
         this.id = id;
         this.tok = tok;
@@ -4196,7 +4200,7 @@ extern (C++) abstract class UnaExp : Expression
     Expression e1;
     Type att1;      // Save alias this type to detect recursion
 
-    extern (D) this(const ref Loc loc, TOK op, int size, Expression e1)
+    extern (D) this(const ref Loc loc, EXP op, int size, Expression e1)
     {
         super(loc, op, size);
         this.e1 = e1;
@@ -4221,13 +4225,13 @@ extern (C++) abstract class UnaExp : Expression
         if (e1.type.toBasetype() == Type.terror)
             return e1;
 
-        if (e1.op == TOK.type)
+        if (e1.op == EXP.type)
         {
-            error("incompatible type for `%s(%s)`: cannot use `%s` with types", Token.toChars(op), e1.toChars(), Token.toChars(op));
+            error("incompatible type for `%s(%s)`: cannot use `%s` with types", EXPtoString(op).ptr, e1.toChars(), EXPtoString(op).ptr);
         }
         else
         {
-            error("incompatible type for `%s(%s)`: `%s`", Token.toChars(op), e1.toChars(), e1.type.toChars());
+            error("incompatible type for `%s(%s)`: `%s`", EXPtoString(op).ptr, e1.toChars(), e1.type.toChars());
         }
         return ErrorExp.get();
     }
@@ -4257,7 +4261,7 @@ extern (C++) abstract class UnaExp : Expression
 }
 
 alias fp_t = UnionExp function(const ref Loc loc, Type, Expression, Expression);
-alias fp2_t = bool function(const ref Loc loc, TOK, Expression, Expression);
+alias fp2_t = bool function(const ref Loc loc, EXP, Expression, Expression);
 
 /***********************************************************
  */
@@ -4268,7 +4272,7 @@ extern (C++) abstract class BinExp : Expression
     Type att1;      // Save alias this type to detect recursion
     Type att2;      // Save alias this type to detect recursion
 
-    extern (D) this(const ref Loc loc, TOK op, int size, Expression e1, Expression e2)
+    extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2)
     {
         super(loc, op, size);
         this.e1 = e1;
@@ -4298,22 +4302,22 @@ extern (C++) abstract class BinExp : Expression
             return e2;
 
         // CondExp uses 'a ? b : c' but we're comparing 'b : c'
-        TOK thisOp = (op == TOK.question) ? TOK.colon : op;
-        if (e1.op == TOK.type || e2.op == TOK.type)
+        const(char)* thisOp = (op == EXP.question) ? ":" : EXPtoString(op).ptr;
+        if (e1.op == EXP.type || e2.op == EXP.type)
         {
             error("incompatible types for `(%s) %s (%s)`: cannot use `%s` with types",
-                e1.toChars(), Token.toChars(thisOp), e2.toChars(), Token.toChars(op));
+                e1.toChars(), thisOp, e2.toChars(), EXPtoString(op).ptr);
         }
         else if (e1.type.equals(e2.type))
         {
             error("incompatible types for `(%s) %s (%s)`: both operands are of type `%s`",
-                e1.toChars(), Token.toChars(thisOp), e2.toChars(), e1.type.toChars());
+                e1.toChars(), thisOp, e2.toChars(), e1.type.toChars());
         }
         else
         {
             auto ts = toAutoQualChars(e1.type, e2.type);
             error("incompatible types for `(%s) %s (%s)`: `%s` and `%s`",
-                e1.toChars(), Token.toChars(thisOp), e2.toChars(), ts[0], ts[1]);
+                e1.toChars(), thisOp, e2.toChars(), ts[0], ts[1]);
         }
         return ErrorExp.get();
     }
@@ -4327,22 +4331,22 @@ extern (C++) abstract class BinExp : Expression
         // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
         // See issue 3841.
         // Should we also prevent double to float (type.isfloating() && type.size() < t2.size()) ?
-        if (op == TOK.addAssign || op == TOK.minAssign ||
-            op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign ||
-            op == TOK.powAssign)
+        if (op == EXP.addAssign || op == EXP.minAssign ||
+            op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign ||
+            op == EXP.powAssign)
         {
             if ((type.isintegral() && t2.isfloating()))
             {
-                warning("`%s %s %s` is performing truncating conversion", type.toChars(), Token.toChars(op), t2.toChars());
+                warning("`%s %s %s` is performing truncating conversion", type.toChars(), EXPtoString(op).ptr, t2.toChars());
             }
         }
 
         // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
-        if (op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign)
+        if (op == EXP.mulAssign || op == EXP.divAssign || op == EXP.modAssign)
         {
             // Any multiplication by an imaginary or complex number yields a complex result.
             // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
-            const(char)* opstr = Token.toChars(op);
+            const(char)* opstr = EXPtoString(op).ptr;
             if (t1.isreal() && t2.iscomplex())
             {
                 error("`%s %s %s` is undefined. Did you mean `%s %s %s.re`?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
@@ -4361,13 +4365,13 @@ extern (C++) abstract class BinExp : Expression
         }
 
         // generate an error if this is a nonsensical += or -=, eg real += imaginary
-        if (op == TOK.addAssign || op == TOK.minAssign)
+        if (op == EXP.addAssign || op == EXP.minAssign)
         {
             // Addition or subtraction of a real and an imaginary is a complex result.
             // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
             if ((t1.isreal() && (t2.isimaginary() || t2.iscomplex())) || (t1.isimaginary() && (t2.isreal() || t2.iscomplex())))
             {
-                error("`%s %s %s` is undefined (result is complex)", t1.toChars(), Token.toChars(op), t2.toChars());
+                error("`%s %s %s` is undefined (result is complex)", t1.toChars(), EXPtoString(op).ptr, t2.toChars());
                 return ErrorExp.get();
             }
             if (type.isreal() || type.isimaginary())
@@ -4376,7 +4380,7 @@ extern (C++) abstract class BinExp : Expression
                 e2 = e2.castTo(sc, t1);
             }
         }
-        if (op == TOK.mulAssign)
+        if (op == EXP.mulAssign)
         {
             if (t2.isfloating())
             {
@@ -4413,7 +4417,7 @@ extern (C++) abstract class BinExp : Expression
                 }
             }
         }
-        else if (op == TOK.divAssign)
+        else if (op == EXP.divAssign)
         {
             if (t2.isimaginary())
             {
@@ -4454,7 +4458,7 @@ extern (C++) abstract class BinExp : Expression
                 }
             }
         }
-        else if (op == TOK.modAssign)
+        else if (op == EXP.modAssign)
         {
             if (t2.iscomplex())
             {
@@ -4558,7 +4562,7 @@ extern (C++) abstract class BinExp : Expression
  */
 extern (C++) class BinAssignExp : BinExp
 {
-    extern (D) this(const ref Loc loc, TOK op, int size, Expression e1, Expression e2)
+    extern (D) this(const ref Loc loc, EXP op, int size, Expression e1, Expression e2)
     {
         super(loc, op, size, e1, e2);
     }
@@ -4600,7 +4604,7 @@ extern (C++) final class MixinExp : Expression
 
     extern (D) this(const ref Loc loc, Expressions* exps)
     {
-        super(loc, TOK.mixin_, __traits(classInstanceSize, MixinExp));
+        super(loc, EXP.mixin_, __traits(classInstanceSize, MixinExp));
         this.exps = exps;
     }
 
@@ -4643,7 +4647,7 @@ extern (C++) final class ImportExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.import_, __traits(classInstanceSize, ImportExp), e);
+        super(loc, EXP.import_, __traits(classInstanceSize, ImportExp), e);
     }
 
     override void accept(Visitor v)
@@ -4661,7 +4665,7 @@ extern (C++) final class AssertExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Expression msg = null)
     {
-        super(loc, TOK.assert_, __traits(classInstanceSize, AssertExp), e);
+        super(loc, EXP.assert_, __traits(classInstanceSize, AssertExp), e);
         this.msg = msg;
     }
 
@@ -4687,7 +4691,7 @@ extern (C++) final class DotIdExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Identifier ident)
     {
-        super(loc, TOK.dotIdentifier, __traits(classInstanceSize, DotIdExp), e);
+        super(loc, EXP.dotIdentifier, __traits(classInstanceSize, DotIdExp), e);
         this.ident = ident;
     }
 
@@ -4711,7 +4715,7 @@ extern (C++) final class DotTemplateExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, TemplateDeclaration td)
     {
-        super(loc, TOK.dotTemplateDeclaration, __traits(classInstanceSize, DotTemplateExp), e);
+        super(loc, EXP.dotTemplateDeclaration, __traits(classInstanceSize, DotTemplateExp), e);
         this.td = td;
     }
 
@@ -4745,7 +4749,7 @@ extern (C++) final class DotVarExp : UnaExp
         if (var.isVarDeclaration())
             hasOverloads = false;
 
-        super(loc, TOK.dotVariable, __traits(classInstanceSize, DotVarExp), e);
+        super(loc, EXP.dotVariable, __traits(classInstanceSize, DotVarExp), e);
         //printf("DotVarExp()\n");
         this.var = var;
         this.hasOverloads = hasOverloads;
@@ -4753,7 +4757,7 @@ extern (C++) final class DotVarExp : UnaExp
 
     override bool isLvalue()
     {
-        if (e1.op != TOK.structLiteral)
+        if (e1.op != EXP.structLiteral)
             return true;
         auto vd = var.isVarDeclaration();
         return !(vd && vd.isField());
@@ -4772,7 +4776,7 @@ extern (C++) final class DotVarExp : UnaExp
         }
         if (!isLvalue())
             return Expression.toLvalue(sc, e);
-        if (e1.op == TOK.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor))
+        if (e1.op == EXP.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor))
         {
             if (VarDeclaration vd = var.isVarDeclaration())
             {
@@ -4826,14 +4830,14 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Identifier name, Objects* tiargs)
     {
-        super(loc, TOK.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
+        super(loc, EXP.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
         //printf("DotTemplateInstanceExp()\n");
         this.ti = new TemplateInstance(loc, name, tiargs);
     }
 
     extern (D) this(const ref Loc loc, Expression e, TemplateInstance ti)
     {
-        super(loc, TOK.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
+        super(loc, EXP.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
         this.ti = ti;
     }
 
@@ -4853,29 +4857,29 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp
 
         Expression e = new DotIdExp(loc, e1, ti.name);
         e = e.expressionSemantic(sc);
-        if (e.op == TOK.dot)
+        if (e.op == EXP.dot)
             e = (cast(DotExp)e).e2;
 
         Dsymbol s = null;
         switch (e.op)
         {
-        case TOK.overloadSet:
+        case EXP.overloadSet:
             s = (cast(OverExp)e).vars;
             break;
 
-        case TOK.dotTemplateDeclaration:
+        case EXP.dotTemplateDeclaration:
             s = (cast(DotTemplateExp)e).td;
             break;
 
-        case TOK.scope_:
+        case EXP.scope_:
             s = (cast(ScopeExp)e).sds;
             break;
 
-        case TOK.dotVariable:
+        case EXP.dotVariable:
             s = (cast(DotVarExp)e).var;
             break;
 
-        case TOK.variable:
+        case EXP.variable:
             s = (cast(VarExp)e).var;
             break;
 
@@ -4926,7 +4930,7 @@ extern (C++) final class DelegateExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, FuncDeclaration f, bool hasOverloads = true, VarDeclaration vthis2 = null)
     {
-        super(loc, TOK.delegate_, __traits(classInstanceSize, DelegateExp), e);
+        super(loc, EXP.delegate_, __traits(classInstanceSize, DelegateExp), e);
         this.func = f;
         this.hasOverloads = hasOverloads;
         this.vthis2 = vthis2;
@@ -4946,7 +4950,7 @@ extern (C++) final class DotTypeExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Dsymbol s)
     {
-        super(loc, TOK.dotType, __traits(classInstanceSize, DotTypeExp), e);
+        super(loc, EXP.dotType, __traits(classInstanceSize, DotTypeExp), e);
         this.sym = s;
     }
 
@@ -4969,18 +4973,18 @@ extern (C++) final class CallExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Expressions* exps)
     {
-        super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+        super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
         this.arguments = exps;
     }
 
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+        super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
     }
 
     extern (D) this(const ref Loc loc, Expression e, Expression earg1)
     {
-        super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+        super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
         this.arguments = new Expressions();
         if (earg1)
             this.arguments.push(earg1);
@@ -4988,7 +4992,7 @@ extern (C++) final class CallExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Expression earg1, Expression earg2)
     {
-        super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
+        super(loc, EXP.call, __traits(classInstanceSize, CallExp), e);
         auto arguments = new Expressions(2);
         (*arguments)[0] = earg1;
         (*arguments)[1] = earg2;
@@ -5143,7 +5147,7 @@ extern (C++) final class AddrExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.address, __traits(classInstanceSize, AddrExp), e);
+        super(loc, EXP.address, __traits(classInstanceSize, AddrExp), e);
     }
 
     extern (D) this(const ref Loc loc, Expression e, Type t)
@@ -5164,14 +5168,14 @@ extern (C++) final class PtrExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.star, __traits(classInstanceSize, PtrExp), e);
+        super(loc, EXP.star, __traits(classInstanceSize, PtrExp), e);
         //if (e.type)
         //  type = ((TypePointer *)e.type).next;
     }
 
     extern (D) this(const ref Loc loc, Expression e, Type t)
     {
-        super(loc, TOK.star, __traits(classInstanceSize, PtrExp), e);
+        super(loc, EXP.star, __traits(classInstanceSize, PtrExp), e);
         type = t;
     }
 
@@ -5216,7 +5220,7 @@ extern (C++) final class NegExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.negate, __traits(classInstanceSize, NegExp), e);
+        super(loc, EXP.negate, __traits(classInstanceSize, NegExp), e);
     }
 
     override void accept(Visitor v)
@@ -5231,7 +5235,7 @@ extern (C++) final class UAddExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.uadd, __traits(classInstanceSize, UAddExp), e);
+        super(loc, EXP.uadd, __traits(classInstanceSize, UAddExp), e);
     }
 
     override void accept(Visitor v)
@@ -5246,7 +5250,7 @@ extern (C++) final class ComExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.tilde, __traits(classInstanceSize, ComExp), e);
+        super(loc, EXP.tilde, __traits(classInstanceSize, ComExp), e);
     }
 
     override void accept(Visitor v)
@@ -5261,7 +5265,7 @@ extern (C++) final class NotExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e)
     {
-        super(loc, TOK.not, __traits(classInstanceSize, NotExp), e);
+        super(loc, EXP.not, __traits(classInstanceSize, NotExp), e);
     }
 
     override void accept(Visitor v)
@@ -5278,7 +5282,7 @@ extern (C++) final class DeleteExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, bool isRAII)
     {
-        super(loc, TOK.delete_, __traits(classInstanceSize, DeleteExp), e);
+        super(loc, EXP.delete_, __traits(classInstanceSize, DeleteExp), e);
         this.isRAII = isRAII;
     }
 
@@ -5298,7 +5302,7 @@ extern (C++) final class CastExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Type t)
     {
-        super(loc, TOK.cast_, __traits(classInstanceSize, CastExp), e);
+        super(loc, EXP.cast_, __traits(classInstanceSize, CastExp), e);
         this.to = t;
     }
 
@@ -5306,7 +5310,7 @@ extern (C++) final class CastExp : UnaExp
      */
     extern (D) this(const ref Loc loc, Expression e, ubyte mod)
     {
-        super(loc, TOK.cast_, __traits(classInstanceSize, CastExp), e);
+        super(loc, EXP.cast_, __traits(classInstanceSize, CastExp), e);
         this.mod = mod;
     }
 
@@ -5360,7 +5364,7 @@ extern (C++) final class VectorExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e, Type t)
     {
-        super(loc, TOK.vector, __traits(classInstanceSize, VectorExp), e);
+        super(loc, EXP.vector, __traits(classInstanceSize, VectorExp), e);
         assert(t.ty == Tvector);
         to = cast(TypeVector)t;
     }
@@ -5396,7 +5400,7 @@ extern (C++) final class VectorArrayExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e1)
     {
-        super(loc, TOK.vectorArray, __traits(classInstanceSize, VectorArrayExp), e1);
+        super(loc, EXP.vectorArray, __traits(classInstanceSize, VectorArrayExp), e1);
     }
 
     override bool isLvalue()
@@ -5434,14 +5438,14 @@ extern (C++) final class SliceExp : UnaExp
     /************************************************************/
     extern (D) this(const ref Loc loc, Expression e1, IntervalExp ie)
     {
-        super(loc, TOK.slice, __traits(classInstanceSize, SliceExp), e1);
+        super(loc, EXP.slice, __traits(classInstanceSize, SliceExp), e1);
         this.upr = ie ? ie.upr : null;
         this.lwr = ie ? ie.lwr : null;
     }
 
     extern (D) this(const ref Loc loc, Expression e1, Expression lwr, Expression upr)
     {
-        super(loc, TOK.slice, __traits(classInstanceSize, SliceExp), e1);
+        super(loc, EXP.slice, __traits(classInstanceSize, SliceExp), e1);
         this.upr = upr;
         this.lwr = lwr;
     }
@@ -5473,9 +5477,9 @@ extern (C++) final class SliceExp : UnaExp
         return this;
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return e1.isBool(result);
+        return e1.toBool();
     }
 
     override void accept(Visitor v)
@@ -5490,7 +5494,7 @@ extern (C++) final class ArrayLengthExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e1)
     {
-        super(loc, TOK.arrayLength, __traits(classInstanceSize, ArrayLengthExp), e1);
+        super(loc, EXP.arrayLength, __traits(classInstanceSize, ArrayLengthExp), e1);
     }
 
     override void accept(Visitor v)
@@ -5513,7 +5517,7 @@ extern (C++) final class ArrayExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e1, Expression index = null)
     {
-        super(loc, TOK.array, __traits(classInstanceSize, ArrayExp), e1);
+        super(loc, EXP.array, __traits(classInstanceSize, ArrayExp), e1);
         arguments = new Expressions();
         if (index)
             arguments.push(index);
@@ -5521,7 +5525,7 @@ extern (C++) final class ArrayExp : UnaExp
 
     extern (D) this(const ref Loc loc, Expression e1, Expressions* args)
     {
-        super(loc, TOK.array, __traits(classInstanceSize, ArrayExp), e1);
+        super(loc, EXP.array, __traits(classInstanceSize, ArrayExp), e1);
         arguments = args;
     }
 
@@ -5558,7 +5562,7 @@ extern (C++) final class DotExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.dot, __traits(classInstanceSize, DotExp), e1, e2);
+        super(loc, EXP.dot, __traits(classInstanceSize, DotExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -5584,7 +5588,7 @@ extern (C++) final class CommaExp : BinExp
 
     extern (D) this(const ref Loc loc, Expression e1, Expression e2, bool generated = true)
     {
-        super(loc, TOK.comma, __traits(classInstanceSize, CommaExp), e1, e2);
+        super(loc, EXP.comma, __traits(classInstanceSize, CommaExp), e1, e2);
         allowCommaExp = isGenerated = generated;
     }
 
@@ -5605,9 +5609,9 @@ extern (C++) final class CommaExp : BinExp
         return this;
     }
 
-    override bool isBool(bool result)
+    override Optional!bool toBool()
     {
-        return e2.isBool(result);
+        return e2.toBool();
     }
 
     override Expression addDtorHook(Scope* sc)
@@ -5653,7 +5657,7 @@ extern (C++) final class IntervalExp : Expression
 
     extern (D) this(const ref Loc loc, Expression lwr, Expression upr)
     {
-        super(loc, TOK.interval, __traits(classInstanceSize, IntervalExp));
+        super(loc, EXP.interval, __traits(classInstanceSize, IntervalExp));
         this.lwr = lwr;
         this.upr = upr;
     }
@@ -5673,7 +5677,7 @@ extern (C++) final class DelegatePtrExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e1)
     {
-        super(loc, TOK.delegatePointer, __traits(classInstanceSize, DelegatePtrExp), e1);
+        super(loc, EXP.delegatePointer, __traits(classInstanceSize, DelegatePtrExp), e1);
     }
 
     override bool isLvalue()
@@ -5709,7 +5713,7 @@ extern (C++) final class DelegateFuncptrExp : UnaExp
 {
     extern (D) this(const ref Loc loc, Expression e1)
     {
-        super(loc, TOK.delegateFunctionPointer, __traits(classInstanceSize, DelegateFuncptrExp), e1);
+        super(loc, EXP.delegateFunctionPointer, __traits(classInstanceSize, DelegateFuncptrExp), e1);
     }
 
     override bool isLvalue()
@@ -5750,7 +5754,7 @@ extern (C++) final class IndexExp : BinExp
 
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.index, __traits(classInstanceSize, IndexExp), e1, e2);
+        super(loc, EXP.index, __traits(classInstanceSize, IndexExp), e1, e2);
         //printf("IndexExp::IndexExp('%s')\n", toChars());
     }
 
@@ -5763,10 +5767,10 @@ extern (C++) final class IndexExp : BinExp
 
     override bool isLvalue()
     {
-        if (e1.op == TOK.assocArrayLiteral)
+        if (e1.op == EXP.assocArrayLiteral)
             return false;
         if (e1.type.ty == Tsarray ||
-            (e1.op == TOK.index && e1.type.ty != Tarray))
+            (e1.op == EXP.index && e1.type.ty != Tarray))
         {
             return e1.isLvalue();
         }
@@ -5784,7 +5788,7 @@ extern (C++) final class IndexExp : BinExp
     {
         //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
         Expression ex = markSettingAAElem();
-        if (ex.op == TOK.error)
+        if (ex.op == EXP.error)
             return ex;
 
         return Expression.modifiableLvalue(sc, e);
@@ -5805,7 +5809,7 @@ extern (C++) final class IndexExp : BinExp
             if (auto ie = e1.isIndexExp())
             {
                 Expression ex = ie.markSettingAAElem();
-                if (ex.op == TOK.error)
+                if (ex.op == EXP.error)
                     return ex;
                 assert(ex == e1);
             }
@@ -5824,10 +5828,10 @@ extern (C++) final class IndexExp : BinExp
  */
 extern (C++) final class PostExp : BinExp
 {
-    extern (D) this(TOK op, const ref Loc loc, Expression e)
+    extern (D) this(EXP op, const ref Loc loc, Expression e)
     {
         super(loc, op, __traits(classInstanceSize, PostExp), e, IntegerExp.literal!1);
-        assert(op == TOK.minusMinus || op == TOK.plusPlus);
+        assert(op == EXP.minusMinus || op == EXP.plusPlus);
     }
 
     override void accept(Visitor v)
@@ -5841,10 +5845,10 @@ extern (C++) final class PostExp : BinExp
  */
 extern (C++) final class PreExp : UnaExp
 {
-    extern (D) this(TOK op, const ref Loc loc, Expression e)
+    extern (D) this(EXP op, const ref Loc loc, Expression e)
     {
         super(loc, op, __traits(classInstanceSize, PreExp), e);
-        assert(op == TOK.preMinusMinus || op == TOK.prePlusPlus);
+        assert(op == EXP.preMinusMinus || op == EXP.prePlusPlus);
     }
 
     override void accept(Visitor v)
@@ -5867,13 +5871,13 @@ extern (C++) class AssignExp : BinExp
     MemorySet memset;
 
     /************************************************************/
-    /* op can be TOK.assign, TOK.construct, or TOK.blit */
+    /* op can be EXP.assign, EXP.construct, or EXP.blit */
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.assign, __traits(classInstanceSize, AssignExp), e1, e2);
+        super(loc, EXP.assign, __traits(classInstanceSize, AssignExp), e1, e2);
     }
 
-    this(const ref Loc loc, TOK tok, Expression e1, Expression e2)
+    this(const ref Loc loc, EXP tok, Expression e1, Expression e2)
     {
         super(loc, tok, __traits(classInstanceSize, AssignExp), e1, e2);
     }
@@ -5882,7 +5886,7 @@ extern (C++) class AssignExp : BinExp
     {
         // Array-op 'x[] = y[]' should make an rvalue.
         // Setting array length 'x.length = v' should make an rvalue.
-        if (e1.op == TOK.slice || e1.op == TOK.arrayLength)
+        if (e1.op == EXP.slice || e1.op == EXP.arrayLength)
         {
             return false;
         }
@@ -5891,7 +5895,7 @@ extern (C++) class AssignExp : BinExp
 
     override final Expression toLvalue(Scope* sc, Expression ex)
     {
-        if (e1.op == TOK.slice || e1.op == TOK.arrayLength)
+        if (e1.op == EXP.slice || e1.op == EXP.arrayLength)
         {
             return Expression.toLvalue(sc, ex);
         }
@@ -5915,7 +5919,7 @@ extern (C++) final class ConstructExp : AssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.construct, e1, e2);
+        super(loc, EXP.construct, e1, e2);
     }
 
     // Internal use only. If `v` is a reference variable, the assignment
@@ -5925,7 +5929,7 @@ extern (C++) final class ConstructExp : AssignExp
         auto ve = new VarExp(loc, v);
         assert(v.type && ve.type);
 
-        super(loc, TOK.construct, ve, e2);
+        super(loc, EXP.construct, ve, e2);
 
         if (v.isReference())
             memset = MemorySet.referenceInit;
@@ -5943,7 +5947,7 @@ extern (C++) final class BlitExp : AssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.blit, e1, e2);
+        super(loc, EXP.blit, e1, e2);
     }
 
     // Internal use only. If `v` is a reference variable, the assinment
@@ -5953,7 +5957,7 @@ extern (C++) final class BlitExp : AssignExp
         auto ve = new VarExp(loc, v);
         assert(v.type && ve.type);
 
-        super(loc, TOK.blit, ve, e2);
+        super(loc, EXP.blit, ve, e2);
 
         if (v.isReference())
             memset = MemorySet.referenceInit;
@@ -5971,7 +5975,7 @@ extern (C++) final class AddAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.addAssign, __traits(classInstanceSize, AddAssignExp), e1, e2);
+        super(loc, EXP.addAssign, __traits(classInstanceSize, AddAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -5986,7 +5990,7 @@ extern (C++) final class MinAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.minAssign, __traits(classInstanceSize, MinAssignExp), e1, e2);
+        super(loc, EXP.minAssign, __traits(classInstanceSize, MinAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6001,7 +6005,7 @@ extern (C++) final class MulAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.mulAssign, __traits(classInstanceSize, MulAssignExp), e1, e2);
+        super(loc, EXP.mulAssign, __traits(classInstanceSize, MulAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6016,7 +6020,7 @@ extern (C++) final class DivAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.divAssign, __traits(classInstanceSize, DivAssignExp), e1, e2);
+        super(loc, EXP.divAssign, __traits(classInstanceSize, DivAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6031,7 +6035,7 @@ extern (C++) final class ModAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.modAssign, __traits(classInstanceSize, ModAssignExp), e1, e2);
+        super(loc, EXP.modAssign, __traits(classInstanceSize, ModAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6046,7 +6050,7 @@ extern (C++) final class AndAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.andAssign, __traits(classInstanceSize, AndAssignExp), e1, e2);
+        super(loc, EXP.andAssign, __traits(classInstanceSize, AndAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6061,7 +6065,7 @@ extern (C++) final class OrAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.orAssign, __traits(classInstanceSize, OrAssignExp), e1, e2);
+        super(loc, EXP.orAssign, __traits(classInstanceSize, OrAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6076,7 +6080,7 @@ extern (C++) final class XorAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.xorAssign, __traits(classInstanceSize, XorAssignExp), e1, e2);
+        super(loc, EXP.xorAssign, __traits(classInstanceSize, XorAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6091,7 +6095,7 @@ extern (C++) final class PowAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.powAssign, __traits(classInstanceSize, PowAssignExp), e1, e2);
+        super(loc, EXP.powAssign, __traits(classInstanceSize, PowAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6106,7 +6110,7 @@ extern (C++) final class ShlAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.leftShiftAssign, __traits(classInstanceSize, ShlAssignExp), e1, e2);
+        super(loc, EXP.leftShiftAssign, __traits(classInstanceSize, ShlAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6121,7 +6125,7 @@ extern (C++) final class ShrAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.rightShiftAssign, __traits(classInstanceSize, ShrAssignExp), e1, e2);
+        super(loc, EXP.rightShiftAssign, __traits(classInstanceSize, ShrAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6136,7 +6140,7 @@ extern (C++) final class UshrAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.unsignedRightShiftAssign, __traits(classInstanceSize, UshrAssignExp), e1, e2);
+        super(loc, EXP.unsignedRightShiftAssign, __traits(classInstanceSize, UshrAssignExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6148,21 +6152,21 @@ extern (C++) final class UshrAssignExp : BinAssignExp
 /***********************************************************
  * The ~= operator. It can have one of the following operators:
  *
- * TOK.concatenateAssign      - appending T[] to T[]
- * TOK.concatenateElemAssign  - appending T to T[]
- * TOK.concatenateDcharAssign - appending dchar to T[]
+ * EXP.concatenateAssign      - appending T[] to T[]
+ * EXP.concatenateElemAssign  - appending T to T[]
+ * EXP.concatenateDcharAssign - appending dchar to T[]
  *
- * The parser initially sets it to TOK.concatenateAssign, and semantic() later decides which
+ * The parser initially sets it to EXP.concatenateAssign, and semantic() later decides which
  * of the three it will be set to.
  */
 extern (C++) class CatAssignExp : BinAssignExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.concatenateAssign, __traits(classInstanceSize, CatAssignExp), e1, e2);
+        super(loc, EXP.concatenateAssign, __traits(classInstanceSize, CatAssignExp), e1, e2);
     }
 
-    extern (D) this(const ref Loc loc, TOK tok, Expression e1, Expression e2)
+    extern (D) this(const ref Loc loc, EXP tok, Expression e1, Expression e2)
     {
         super(loc, tok, __traits(classInstanceSize, CatAssignExp), e1, e2);
     }
@@ -6178,7 +6182,7 @@ extern (C++) final class CatElemAssignExp : CatAssignExp
 {
     extern (D) this(const ref Loc loc, Type type, Expression e1, Expression e2)
     {
-        super(loc, TOK.concatenateElemAssign, e1, e2);
+        super(loc, EXP.concatenateElemAssign, e1, e2);
         this.type = type;
     }
 
@@ -6193,7 +6197,7 @@ extern (C++) final class CatDcharAssignExp : CatAssignExp
 {
     extern (D) this(const ref Loc loc, Type type, Expression e1, Expression e2)
     {
-        super(loc, TOK.concatenateDcharAssign, e1, e2);
+        super(loc, EXP.concatenateDcharAssign, e1, e2);
         this.type = type;
     }
 
@@ -6210,7 +6214,7 @@ extern (C++) final class AddExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.add, __traits(classInstanceSize, AddExp), e1, e2);
+        super(loc, EXP.add, __traits(classInstanceSize, AddExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6225,7 +6229,7 @@ extern (C++) final class MinExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.min, __traits(classInstanceSize, MinExp), e1, e2);
+        super(loc, EXP.min, __traits(classInstanceSize, MinExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6241,7 +6245,7 @@ extern (C++) final class CatExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.concatenate, __traits(classInstanceSize, CatExp), e1, e2);
+        super(loc, EXP.concatenate, __traits(classInstanceSize, CatExp), e1, e2);
     }
 
     override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6264,7 +6268,7 @@ extern (C++) final class MulExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.mul, __traits(classInstanceSize, MulExp), e1, e2);
+        super(loc, EXP.mul, __traits(classInstanceSize, MulExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6280,7 +6284,7 @@ extern (C++) final class DivExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.div, __traits(classInstanceSize, DivExp), e1, e2);
+        super(loc, EXP.div, __traits(classInstanceSize, DivExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6296,7 +6300,7 @@ extern (C++) final class ModExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.mod, __traits(classInstanceSize, ModExp), e1, e2);
+        super(loc, EXP.mod, __traits(classInstanceSize, ModExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6312,7 +6316,7 @@ extern (C++) final class PowExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.pow, __traits(classInstanceSize, PowExp), e1, e2);
+        super(loc, EXP.pow, __traits(classInstanceSize, PowExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6327,7 +6331,7 @@ extern (C++) final class ShlExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.leftShift, __traits(classInstanceSize, ShlExp), e1, e2);
+        super(loc, EXP.leftShift, __traits(classInstanceSize, ShlExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6342,7 +6346,7 @@ extern (C++) final class ShrExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.rightShift, __traits(classInstanceSize, ShrExp), e1, e2);
+        super(loc, EXP.rightShift, __traits(classInstanceSize, ShrExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6357,7 +6361,7 @@ extern (C++) final class UshrExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.unsignedRightShift, __traits(classInstanceSize, UshrExp), e1, e2);
+        super(loc, EXP.unsignedRightShift, __traits(classInstanceSize, UshrExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6372,7 +6376,7 @@ extern (C++) final class AndExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.and, __traits(classInstanceSize, AndExp), e1, e2);
+        super(loc, EXP.and, __traits(classInstanceSize, AndExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6387,7 +6391,7 @@ extern (C++) final class OrExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.or, __traits(classInstanceSize, OrExp), e1, e2);
+        super(loc, EXP.or, __traits(classInstanceSize, OrExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6402,7 +6406,7 @@ extern (C++) final class XorExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.xor, __traits(classInstanceSize, XorExp), e1, e2);
+        super(loc, EXP.xor, __traits(classInstanceSize, XorExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6417,10 +6421,10 @@ extern (C++) final class XorExp : BinExp
  */
 extern (C++) final class LogicalExp : BinExp
 {
-    extern (D) this(const ref Loc loc, TOK op, Expression e1, Expression e2)
+    extern (D) this(const ref Loc loc, EXP op, Expression e1, Expression e2)
     {
         super(loc, op, __traits(classInstanceSize, LogicalExp), e1, e2);
-        assert(op == TOK.andAnd || op == TOK.orOr);
+        assert(op == EXP.andAnd || op == EXP.orOr);
     }
 
     override void accept(Visitor v)
@@ -6431,16 +6435,16 @@ extern (C++) final class LogicalExp : BinExp
 
 /***********************************************************
  * `op` is one of:
- *      TOK.lessThan, TOK.lessOrEqual, TOK.greaterThan, TOK.greaterOrEqual
+ *      EXP.lessThan, EXP.lessOrEqual, EXP.greaterThan, EXP.greaterOrEqual
  *
  * http://dlang.org/spec/expression.html#relation_expressions
  */
 extern (C++) final class CmpExp : BinExp
 {
-    extern (D) this(TOK op, const ref Loc loc, Expression e1, Expression e2)
+    extern (D) this(EXP op, const ref Loc loc, Expression e1, Expression e2)
     {
         super(loc, op, __traits(classInstanceSize, CmpExp), e1, e2);
-        assert(op == TOK.lessThan || op == TOK.lessOrEqual || op == TOK.greaterThan || op == TOK.greaterOrEqual);
+        assert(op == EXP.lessThan || op == EXP.lessOrEqual || op == EXP.greaterThan || op == EXP.greaterOrEqual);
     }
 
     override void accept(Visitor v)
@@ -6455,7 +6459,7 @@ extern (C++) final class InExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.in_, __traits(classInstanceSize, InExp), e1, e2);
+        super(loc, EXP.in_, __traits(classInstanceSize, InExp), e1, e2);
     }
 
     override void accept(Visitor v)
@@ -6471,7 +6475,7 @@ extern (C++) final class RemoveExp : BinExp
 {
     extern (D) this(const ref Loc loc, Expression e1, Expression e2)
     {
-        super(loc, TOK.remove, __traits(classInstanceSize, RemoveExp), e1, e2);
+        super(loc, EXP.remove, __traits(classInstanceSize, RemoveExp), e1, e2);
         type = Type.tbool;
     }
 
@@ -6484,16 +6488,16 @@ extern (C++) final class RemoveExp : BinExp
 /***********************************************************
  * `==` and `!=`
  *
- * TOK.equal and TOK.notEqual
+ * EXP.equal and EXP.notEqual
  *
  * http://dlang.org/spec/expression.html#equality_expressions
  */
 extern (C++) final class EqualExp : BinExp
 {
-    extern (D) this(TOK op, const ref Loc loc, Expression e1, Expression e2)
+    extern (D) this(EXP op, const ref Loc loc, Expression e1, Expression e2)
     {
         super(loc, op, __traits(classInstanceSize, EqualExp), e1, e2);
-        assert(op == TOK.equal || op == TOK.notEqual);
+        assert(op == EXP.equal || op == EXP.notEqual);
     }
 
     override void accept(Visitor v)
@@ -6505,16 +6509,16 @@ extern (C++) final class EqualExp : BinExp
 /***********************************************************
  * `is` and `!is`
  *
- * TOK.identity and TOK.notIdentity
+ * EXP.identity and EXP.notIdentity
  *
  *  http://dlang.org/spec/expression.html#identity_expressions
  */
 extern (C++) final class IdentityExp : BinExp
 {
-    extern (D) this(TOK op, const ref Loc loc, Expression e1, Expression e2)
+    extern (D) this(EXP op, const ref Loc loc, Expression e1, Expression e2)
     {
         super(loc, op, __traits(classInstanceSize, IdentityExp), e1, e2);
-        assert(op == TOK.identity || op == TOK.notIdentity);
+        assert(op == EXP.identity || op == EXP.notIdentity);
     }
 
     override void accept(Visitor v)
@@ -6534,7 +6538,7 @@ extern (C++) final class CondExp : BinExp
 
     extern (D) this(const ref Loc loc, Expression econd, Expression e1, Expression e2)
     {
-        super(loc, TOK.question, __traits(classInstanceSize, CondExp), e1, e2);
+        super(loc, EXP.question, __traits(classInstanceSize, CondExp), e1, e2);
         this.econd = econd;
     }
 
@@ -6623,9 +6627,9 @@ extern (C++) final class CondExp : BinExp
                         //printf("\t++v = %s, v.edtor = %s\n", v.toChars(), v.edtor.toChars());
                         Expression ve = new VarExp(vcond.loc, vcond);
                         if (isThen)
-                            v.edtor = new LogicalExp(v.edtor.loc, TOK.andAnd, ve, v.edtor);
+                            v.edtor = new LogicalExp(v.edtor.loc, EXP.andAnd, ve, v.edtor);
                         else
-                            v.edtor = new LogicalExp(v.edtor.loc, TOK.orOr, ve, v.edtor);
+                            v.edtor = new LogicalExp(v.edtor.loc, EXP.orOr, ve, v.edtor);
                         v.edtor = v.edtor.expressionSemantic(sc);
                         //printf("\t--v = %s, v.edtor = %s\n", v.toChars(), v.edtor.toChars());
                     }
@@ -6649,18 +6653,18 @@ extern (C++) final class CondExp : BinExp
 }
 
 /// Returns: if this token is the `op` for a derived `DefaultInitExp` class.
-bool isDefaultInitOp(TOK op) pure nothrow @safe @nogc
+bool isDefaultInitOp(EXP op) pure nothrow @safe @nogc
 {
-    return  op == TOK.prettyFunction    || op == TOK.functionString ||
-            op == TOK.line              || op == TOK.moduleString   ||
-            op == TOK.file              || op == TOK.fileFullPath   ;
+    return  op == EXP.prettyFunction    || op == EXP.functionString ||
+            op == EXP.line              || op == EXP.moduleString   ||
+            op == EXP.file              || op == EXP.fileFullPath   ;
 }
 
 /***********************************************************
  */
 extern (C++) class DefaultInitExp : Expression
 {
-    extern (D) this(const ref Loc loc, TOK op, int size)
+    extern (D) this(const ref Loc loc, EXP op, int size)
     {
         super(loc, op, size);
     }
@@ -6675,7 +6679,7 @@ extern (C++) class DefaultInitExp : Expression
  */
 extern (C++) final class FileInitExp : DefaultInitExp
 {
-    extern (D) this(const ref Loc loc, TOK tok)
+    extern (D) this(const ref Loc loc, EXP tok)
     {
         super(loc, tok, __traits(classInstanceSize, FileInitExp));
     }
@@ -6684,7 +6688,7 @@ extern (C++) final class FileInitExp : DefaultInitExp
     {
         //printf("FileInitExp::resolve() %s\n", toChars());
         const(char)* s;
-        if (op == TOK.fileFullPath)
+        if (op == EXP.fileFullPath)
             s = FileName.toAbsolute(loc.isValid() ? loc.filename : sc._module.srcfile.toChars());
         else
             s = loc.isValid() ? loc.filename : sc._module.ident.toChars();
@@ -6707,7 +6711,7 @@ extern (C++) final class LineInitExp : DefaultInitExp
 {
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.line, __traits(classInstanceSize, LineInitExp));
+        super(loc, EXP.line, __traits(classInstanceSize, LineInitExp));
     }
 
     override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6729,7 +6733,7 @@ extern (C++) final class ModuleInitExp : DefaultInitExp
 {
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.moduleString, __traits(classInstanceSize, ModuleInitExp));
+        super(loc, EXP.moduleString, __traits(classInstanceSize, ModuleInitExp));
     }
 
     override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6753,7 +6757,7 @@ extern (C++) final class FuncInitExp : DefaultInitExp
 {
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.functionString, __traits(classInstanceSize, FuncInitExp));
+        super(loc, EXP.functionString, __traits(classInstanceSize, FuncInitExp));
     }
 
     override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6783,7 +6787,7 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp
 {
     extern (D) this(const ref Loc loc)
     {
-        super(loc, TOK.prettyFunction, __traits(classInstanceSize, PrettyFuncInitExp));
+        super(loc, EXP.prettyFunction, __traits(classInstanceSize, PrettyFuncInitExp));
     }
 
     override Expression resolveLoc(const ref Loc loc, Scope* sc)
@@ -6828,7 +6832,7 @@ extern (C++) final class ObjcClassReferenceExp : Expression
 
     extern (D) this(const ref Loc loc, ClassDeclaration classDeclaration)
     {
-        super(loc, TOK.objcClassReference,
+        super(loc, EXP.objcClassReference,
             __traits(classInstanceSize, ObjcClassReferenceExp));
         this.classDeclaration = classDeclaration;
         type = objc.getRuntimeMetaclass(classDeclaration).getType();
@@ -6852,7 +6856,7 @@ extern (C++) final class GenericExp : Expression
 
     extern (D) this(const ref Loc loc, Expression cntlExp, Types* types, Expressions* exps)
     {
-        super(loc, TOK._Generic, __traits(classInstanceSize, GenericExp));
+        super(loc, EXP._Generic, __traits(classInstanceSize, GenericExp));
         this.cntlExp = cntlExp;
         this.types = types;
         this.exps = exps;
@@ -6883,18 +6887,18 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
 {
     switch(exp.op)
     {
-        case TOK.variable:
+        case EXP.variable:
             auto varExp = cast(VarExp)exp;
 
             //printf("VarExp::checkModifiable %s", varExp.toChars());
             assert(varExp.type);
             return varExp.var.checkModify(varExp.loc, sc, null, flag);
 
-        case TOK.dotVariable:
+        case EXP.dotVariable:
             auto dotVarExp = cast(DotVarExp)exp;
 
             //printf("DotVarExp::checkModifiable %s %s\n", dotVarExp.toChars(), dotVarExp.type.toChars());
-            if (dotVarExp.e1.op == TOK.this_)
+            if (dotVarExp.e1.op == EXP.this_)
                 return dotVarExp.var.checkModify(dotVarExp.loc, sc, dotVarExp.e1, flag);
 
             /* https://issues.dlang.org/show_bug.cgi?id=12764
@@ -6925,13 +6929,13 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
                             onlyUnion = false;
 
                         // Another DotVarExp left?
-                        if (!dve.e1 || dve.e1.op != TOK.dotVariable)
+                        if (!dve.e1 || dve.e1.op != EXP.dotVariable)
                             break;
 
                         dve = cast(DotVarExp) dve.e1;
                     }
 
-                    if (dve.e1.op == TOK.this_)
+                    if (dve.e1.op == EXP.this_)
                     {
                         scope v = dve.var.isVarDeclaration();
                         /* if v is a struct member field with no initializer, no default construction
@@ -6968,7 +6972,7 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
             //printf("\te1 = %s\n", e1.toChars());
             return dotVarExp.e1.checkModifiable(sc, flag);
 
-        case TOK.star:
+        case EXP.star:
             auto ptrExp = cast(PtrExp)exp;
             if (auto se = ptrExp.e1.isSymOffExp())
             {
@@ -6980,33 +6984,33 @@ extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag
             }
             return Modifiable.yes;
 
-        case TOK.slice:
+        case EXP.slice:
             auto sliceExp = cast(SliceExp)exp;
 
             //printf("SliceExp::checkModifiable %s\n", sliceExp.toChars());
             auto e1 = sliceExp.e1;
-            if (e1.type.ty == Tsarray || (e1.op == TOK.index && e1.type.ty != Tarray) || e1.op == TOK.slice)
+            if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice)
             {
                 return e1.checkModifiable(sc, flag);
             }
             return Modifiable.yes;
 
-        case TOK.comma:
+        case EXP.comma:
             return (cast(CommaExp)exp).e2.checkModifiable(sc, flag);
 
-        case TOK.index:
+        case EXP.index:
             auto indexExp = cast(IndexExp)exp;
             auto e1 = indexExp.e1;
             if (e1.type.ty == Tsarray ||
                 e1.type.ty == Taarray ||
-                (e1.op == TOK.index && e1.type.ty != Tarray) ||
-                e1.op == TOK.slice)
+                (e1.op == EXP.index && e1.type.ty != Tarray) ||
+                e1.op == EXP.slice)
             {
                 return e1.checkModifiable(sc, flag);
             }
             return Modifiable.yes;
 
-        case TOK.question:
+        case EXP.question:
             auto condExp = cast(CondExp)exp;
             if (condExp.e1.checkModifiable(sc, flag) != Modifiable.no
                 && condExp.e2.checkModifiable(sc, flag) != Modifiable.no)