Added full comparator support.
authorDavid Anderson <dvander@alliedmods.net>
Sun Jul 15 19:48:15 2012 -0700 (2012-07-15)
changeset 7480e29e23eb4e
parent 73 ef5492aa8d8b
child 75 662e81d9ed1c
Added full comparator support.
jitcraft/BytecodeCompiler.cpp
jitcraft/Interpreter.cpp
jitcraft/Opcodes.cpp
jitcraft/Opcodes.tbl
jitcraft/Parser.cpp
jitcraft/Scanner.cpp
jitcraft/SemanticAnalysis.cpp
jitcraft/Token.h
     1.1 --- a/jitcraft/BytecodeCompiler.cpp	Sun Jul 15 14:40:11 2012 -0700
     1.2 +++ b/jitcraft/BytecodeCompiler.cpp	Sun Jul 15 19:48:15 2012 -0700
     1.3 @@ -95,6 +95,18 @@
     1.4          return OP_BITAND;
     1.5        case TOK_BITOR:
     1.6          return OP_BITOR;
     1.7 +      case TOK_GT:
     1.8 +          return OP_GT;
     1.9 +      case TOK_GE:
    1.10 +          return OP_GE;
    1.11 +      case TOK_LT:
    1.12 +          return OP_LT;
    1.13 +      case TOK_LE:
    1.14 +          return OP_LE;
    1.15 +      case TOK_EQUALS:
    1.16 +          return OP_EQ;
    1.17 +      case TOK_NOTEQUALS:
    1.18 +          return OP_NE;
    1.19        default:
    1.20          assert(kind == TOK_BITXOR);
    1.21          return OP_BITXOR;
    1.22 @@ -380,11 +392,23 @@
    1.23          assert(needed->primitive() == node->type()->primitive());
    1.24  }
    1.25  
    1.26 +static inline Type *
    1.27 +GetCoercionType(TokenKind tok, Type *left, Type *right)
    1.28 +{
    1.29 +    if (left->isFloat())
    1.30 +        return left;
    1.31 +    return right;
    1.32 +}
    1.33 +
    1.34  void
    1.35  BytecodeCompiler::visit(BinaryExpression *node)
    1.36  {
    1.37 -    visitForALU(node->type(), node->left());
    1.38 -    visitForALU(node->type(), node->right());
    1.39 +    Local<Type> leftType(zone_, node->left()->type());
    1.40 +    Local<Type> rightType(zone_, node->right()->type());
    1.41 +    Local<Type> coerce(zone_, GetCoercionType(node->token(), leftType, rightType));
    1.42 +
    1.43 +    visitForALU(coerce, node->left());
    1.44 +    visitForALU(coerce, node->right());
    1.45  
    1.46      Opcode op = TokenToOpcode(node->token());
    1.47      if (node->type()->isFloat())
    1.48 @@ -425,10 +449,12 @@
    1.49      TokenKind token = ToCompare(expression);
    1.50      if (token == TOK_EOF) {
    1.51          expression->accept(this);
    1.52 -        if (onTrue)
    1.53 -            __ j(OP_JT, label);
    1.54 -        else
    1.55 -            __ j(OP_JF, label);
    1.56 +
    1.57 +        Opcode op = (onTrue) ? OP_JT : OP_JF;
    1.58 +        if (expression->type()->isFloat())
    1.59 +            op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
    1.60 +
    1.61 +        __ j(op, label);
    1.62          return;
    1.63      }
    1.64  
    1.65 @@ -438,8 +464,15 @@
    1.66  
    1.67      assert(expression->isBinaryExpression());
    1.68      BinaryExpression *binary = expression->toBinaryExpression();
    1.69 -    binary->left()->accept(this);
    1.70 -    binary->right()->accept(this);
    1.71 +    Local<Type> leftType(zone_, binary->left()->type());
    1.72 +    Local<Type> rightType(zone_, binary->right()->type());
    1.73 +    Local<Type> coerce(zone_, GetCoercionType(binary->token(), leftType, rightType));
    1.74 +
    1.75 +    visitForALU(coerce, binary->left());
    1.76 +    visitForALU(coerce, binary->right());
    1.77 +    if (coerce->isFloat())
    1.78 +        op = (Opcode)(int(op) + (OP_JL_F - OP_JL));
    1.79 +
    1.80      __ j(op, label);
    1.81  }
    1.82  
     2.1 --- a/jitcraft/Interpreter.cpp	Sun Jul 15 14:40:11 2012 -0700
     2.2 +++ b/jitcraft/Interpreter.cpp	Sun Jul 15 19:48:15 2012 -0700
     2.3 @@ -235,6 +235,8 @@
     2.4      RELATIONAL_JUMP(!=);
     2.5      break;
     2.6  
     2.7 +#undef RELATIONAL_JUMP
     2.8 +
     2.9  case OP_JT:
    2.10  {
    2.11      int value = POP_I32(top);
    2.12 @@ -255,6 +257,60 @@
    2.13      break;
    2.14  }
    2.15  
    2.16 +#define RELATIONAL_JUMP_F(op)               \
    2.17 +    {                                       \
    2.18 +        float right = POP_F(top);           \
    2.19 +        float left = POP_F(top);            \
    2.20 +        if (left op right) {                \
    2.21 +            top.pc += READ_INT32(top.pc);   \
    2.22 +            continue;                       \
    2.23 +        }                                   \
    2.24 +    }
    2.25 +
    2.26 +case OP_JL_F:
    2.27 +    RELATIONAL_JUMP_F(<);
    2.28 +    break;
    2.29 +
    2.30 +case OP_JLE_F:
    2.31 +    RELATIONAL_JUMP_F(<=);
    2.32 +    break;
    2.33 +
    2.34 +case OP_JG_F:
    2.35 +    RELATIONAL_JUMP_F(>);
    2.36 +    break;
    2.37 +
    2.38 +case OP_JGE_F:
    2.39 +    RELATIONAL_JUMP_F(>=);
    2.40 +    break;
    2.41 +
    2.42 +case OP_JEQ_F:
    2.43 +    RELATIONAL_JUMP_F(==);
    2.44 +    break;
    2.45 +
    2.46 +case OP_JNE_F:
    2.47 +    RELATIONAL_JUMP_F(!=);
    2.48 +    break;
    2.49 +
    2.50 +case OP_JT_F:
    2.51 +{
    2.52 +    float value = POP_F(top);
    2.53 +    if (value) {
    2.54 +        top.pc += READ_INT32(top.pc);
    2.55 +        continue;
    2.56 +    }
    2.57 +    break;
    2.58 +}
    2.59 +
    2.60 +case OP_JF_F:
    2.61 +{
    2.62 +    float value = POP_F(top);
    2.63 +    if (!value) {
    2.64 +        top.pc += READ_INT32(top.pc);
    2.65 +        continue;
    2.66 +    }
    2.67 +    break;
    2.68 +}
    2.69 +
    2.70  case OP_JUMP:
    2.71      top.pc += READ_INT32(top.pc);
    2.72      continue;
    2.73 @@ -313,6 +369,48 @@
    2.74      break;
    2.75  }
    2.76  
    2.77 +case OP_LT:
    2.78 +{
    2.79 +    top.sp[-2].i32 = top.sp[-2].i32 < top.sp[-1].i32;
    2.80 +    top.sp--;
    2.81 +    break;
    2.82 +}
    2.83 +
    2.84 +case OP_LE:
    2.85 +{
    2.86 +    top.sp[-2].i32 = top.sp[-2].i32 <= top.sp[-1].i32;
    2.87 +    top.sp--;
    2.88 +    break;
    2.89 +}
    2.90 +
    2.91 +case OP_GT:
    2.92 +{
    2.93 +    top.sp[-2].i32 = top.sp[-2].i32 > top.sp[-1].i32;
    2.94 +    top.sp--;
    2.95 +    break;
    2.96 +}
    2.97 +
    2.98 +case OP_GE:
    2.99 +{
   2.100 +    top.sp[-2].i32 = top.sp[-2].i32 >= top.sp[-1].i32;
   2.101 +    top.sp--;
   2.102 +    break;
   2.103 +}
   2.104 +
   2.105 +case OP_EQ:
   2.106 +{
   2.107 +    top.sp[-2].i32 = (top.sp[-2].i32 == top.sp[-1].i32);
   2.108 +    top.sp--;
   2.109 +    break;
   2.110 +}
   2.111 +
   2.112 +case OP_NE:
   2.113 +{
   2.114 +    top.sp[-2].i32 = (top.sp[-2].i32 != top.sp[-1].i32);
   2.115 +    top.sp--;
   2.116 +    break;
   2.117 +}
   2.118 +
   2.119  case OP_ADD_F:
   2.120  {
   2.121      float right = POP_F(top);
   2.122 @@ -349,6 +447,48 @@
   2.123      break;
   2.124  }
   2.125  
   2.126 +case OP_LT_F:
   2.127 +{
   2.128 +    top.sp[-2].f = top.sp[-2].f < top.sp[-1].f;
   2.129 +    top.sp--;
   2.130 +    break;
   2.131 +}
   2.132 +
   2.133 +case OP_LE_F:
   2.134 +{
   2.135 +    top.sp[-2].f = top.sp[-2].f <= top.sp[-1].f;
   2.136 +    top.sp--;
   2.137 +    break;
   2.138 +}
   2.139 +
   2.140 +case OP_GT_F:
   2.141 +{
   2.142 +    top.sp[-2].f = top.sp[-2].f > top.sp[-1].f;
   2.143 +    top.sp--;
   2.144 +    break;
   2.145 +}
   2.146 +
   2.147 +case OP_GE_F:
   2.148 +{
   2.149 +    top.sp[-2].f = top.sp[-2].f >= top.sp[-1].f;
   2.150 +    top.sp--;
   2.151 +    break;
   2.152 +}
   2.153 +
   2.154 +case OP_EQ_F:
   2.155 +{
   2.156 +    top.sp[-2].i32 = (top.sp[-2].f == top.sp[-1].f);
   2.157 +    top.sp--;
   2.158 +    break;
   2.159 +}
   2.160 +
   2.161 +case OP_NE_F:
   2.162 +{
   2.163 +    top.sp[-2].i32 = (top.sp[-2].f != top.sp[-1].f);
   2.164 +    top.sp--;
   2.165 +    break;
   2.166 +}
   2.167 +
   2.168  case OP_SHL:
   2.169  {
   2.170      int right = POP_I32(top);
     3.1 --- a/jitcraft/Opcodes.cpp	Sun Jul 15 14:40:11 2012 -0700
     3.2 +++ b/jitcraft/Opcodes.cpp	Sun Jul 15 19:48:15 2012 -0700
     3.3 @@ -186,6 +186,18 @@
     3.4            case OP_PICK3:
     3.5            case OP_CALL:
     3.6            case OP_MODULE:
     3.7 +          case OP_LT:
     3.8 +          case OP_LE:
     3.9 +          case OP_GE:
    3.10 +          case OP_GT:
    3.11 +          case OP_EQ:
    3.12 +          case OP_NE:
    3.13 +          case OP_LT_F:
    3.14 +          case OP_LE_F:
    3.15 +          case OP_GE_F:
    3.16 +          case OP_GT_F:
    3.17 +          case OP_EQ_F:
    3.18 +          case OP_NE_F:
    3.19              break;
    3.20  
    3.21            case OP_STOP:
    3.22 @@ -208,6 +220,14 @@
    3.23            case OP_JNE:
    3.24            case OP_JT:
    3.25            case OP_JF:
    3.26 +          case OP_JL_F:
    3.27 +          case OP_JLE_F:
    3.28 +          case OP_JG_F:
    3.29 +          case OP_JGE_F:
    3.30 +          case OP_JEQ_F:
    3.31 +          case OP_JNE_F:
    3.32 +          case OP_JT_F:
    3.33 +          case OP_JF_F:
    3.34            case OP_JUMP:
    3.35              fprintf(fp, "%u (%+d)", unsigned((pc + READ_INT32(pc)) - code->start()), READ_INT32(pc));
    3.36              break;
     4.1 --- a/jitcraft/Opcodes.tbl	Sun Jul 15 14:40:11 2012 -0700
     4.2 +++ b/jitcraft/Opcodes.tbl	Sun Jul 15 19:48:15 2012 -0700
     4.3 @@ -52,56 +52,72 @@
     4.4  OPDEF(OP_JT,            9,          "jt",           5,      1,  0)
     4.5  OPDEF(OP_JF,            10,         "jf",           5,      1,  0)
     4.6  
     4.7 +OPDEF(OP_JL_F,          11,         "jl.f",         5,      2,  0)
     4.8 +OPDEF(OP_JLE_F,         12,         "jle.f",        5,      2,  0)
     4.9 +OPDEF(OP_JG_F,          13,         "jg.f",         5,      2,  0)
    4.10 +OPDEF(OP_JGE_F,         14,         "jge.f",        5,      2,  0)
    4.11 +OPDEF(OP_JEQ_F,         15,         "jeq.f",        5,      2,  0)
    4.12 +OPDEF(OP_JNE_F,         16,         "jne.f",        5,      2,  0)
    4.13 +OPDEF(OP_JT_F,          17,         "jt.f",         5,      1,  0)
    4.14 +OPDEF(OP_JF_F,          18,         "jf.f",         5,      1,  0)
    4.15 +
    4.16  // Unconditional jump.
    4.17 -OPDEF(OP_JUMP,          11,         "jump",         5,      0,  0)
    4.18 +OPDEF(OP_JUMP,          19,         "jump",         5,      0,  0)
    4.19  
    4.20  // Gets or sets the value of a local variable onto the stack. The local
    4.21  // variable is given by an immediate index.
    4.22 -OPDEF(OP_GETLOCAL,      12,         "getlocal",     5,      0,  1)
    4.23 -OPDEF(OP_SETLOCAL,      13,         "setlocal",     5,      1,  1)
    4.24 +OPDEF(OP_GETLOCAL,      20,         "getlocal",     5,      0,  1)
    4.25 +OPDEF(OP_SETLOCAL,      21,         "setlocal",     5,      1,  1)
    4.26  
    4.27  // Stack transitions for these binary operators:
    4.28  // rhs = pop()
    4.29  // lhs = pop()
    4.30  // push(lhs OP rhs)
    4.31 -OPDEF(OP_ADD,           14,         "add",          1,      2,  1)
    4.32 -OPDEF(OP_SUB,           15,         "sub",          1,      2,  1)
    4.33 -OPDEF(OP_MUL,           16,         "mul",          1,      2,  1)
    4.34 -OPDEF(OP_DIV,           17,         "div",          1,      2,  1)
    4.35 +OPDEF(OP_ADD,           22,         "add",          1,      2,  1)
    4.36 +OPDEF(OP_SUB,           23,         "sub",          1,      2,  1)
    4.37 +OPDEF(OP_MUL,           24,         "mul",          1,      2,  1)
    4.38 +OPDEF(OP_DIV,           25,         "div",          1,      2,  1)
    4.39  
    4.40 -OPDEF(OP_POP,           18,         "pop",          1,      1,  0)
    4.41 +OPDEF(OP_LT,            26,         "lt",           1,      2,  1)
    4.42 +OPDEF(OP_LE,            27,         "le",           1,      2,  1)
    4.43 +OPDEF(OP_GE,            28,         "ge",           1,      2,  1)
    4.44 +OPDEF(OP_GT,            29,         "gt",           1,      2,  1)
    4.45 +OPDEF(OP_EQ,            30,         "eq",           1,      2,  1)
    4.46 +OPDEF(OP_NE,            31,         "ne",           1,      2,  1)
    4.47 +
    4.48 +OPDEF(OP_POP,           32,         "pop",          1,      1,  0)
    4.49  
    4.50  // Unconditional terminator placed at the end of code. If a function returns
    4.51  // void, this acts as a RETURNVOID. Otherwise, it must be unreachable.
    4.52 -OPDEF(OP_STOP,          19,         "stop",         1,      0,  0)
    4.53 +OPDEF(OP_STOP,          33,         "stop",         1,      0,  0)
    4.54  
    4.55  // Call a function with N arguments. The target function must be the last item
    4.56  // on the stack.
    4.57 -OPDEF(OP_CALL,          20,         "call",         1,      -1, 1)
    4.58 +OPDEF(OP_CALL,          34,         "call",         1,      -1, 1)
    4.59  
    4.60  // Similar to GET/LOCAL, except for arguments.
    4.61 -OPDEF(OP_GETARG,        21,         "getarg",       5,      0,  1)
    4.62 -OPDEF(OP_SETARG,        22,         "setarg",       5,      1,  1)
    4.63 +OPDEF(OP_GETARG,        35,         "getarg",       5,      0,  1)
    4.64 +OPDEF(OP_SETARG,        36,         "setarg",       5,      1,  1)
    4.65  
    4.66  // Reads or writes an integer element to an unsafe array.
    4.67  //  index = pop()
    4.68  //  ref = pop()
    4.69  //  ref[index]
    4.70  //
    4.71 -OPDEF(OP_GETARRAY_I,    23,         "getarray.i",   1,      2,  1)
    4.72 -OPDEF(OP_SETARRAY_I,    24,         "setarray.i",   1,      3,  1)
    4.73 -OPDEF(OP_GETARRAY_F,    25,         "getarray.f",   1,      2,  1)
    4.74 -OPDEF(OP_SETARRAY_F,    26,         "setarray.f",   1,      3,  1)
    4.75 -OPDEF(OP_GETARRAY_C,    27,         "getarray.c",   1,      2,  1)
    4.76 -OPDEF(OP_SETARRAY_C,    28,         "setarray.c",   1,      3,  1)
    4.77 -OPDEF(OP_GETARRAY_O,    29,         "getarray.o",   1,      2,  1)
    4.78 +OPDEF(OP_GETARRAY_I,    37,         "getarray.i",   1,      2,  1)
    4.79 +OPDEF(OP_SETARRAY_I,    38,         "setarray.i",   1,      3,  1)
    4.80 +OPDEF(OP_GETARRAY_F,    39,         "getarray.f",   1,      2,  1)
    4.81 +OPDEF(OP_SETARRAY_F,    40,         "setarray.f",   1,      3,  1)
    4.82 +OPDEF(OP_GETARRAY_C,    41,         "getarray.c",   1,      2,  1)
    4.83 +OPDEF(OP_SETARRAY_C,    42,         "setarray.c",   1,      3,  1)
    4.84 +OPDEF(OP_GETARRAY_O,    43,         "getarray.o",   1,      2,  1)
    4.85  
    4.86  // Allocate an array, info LIFO space if possible. The ArrayMap to use is
    4.87  // specified as an index into the script's Map table.
    4.88  //
    4.89  // Format:
    4.90  //  [u8 op] [u32 index]
    4.91 -OPDEF(OP_NEWARRAY_LIFO, 30,         "newarray.lifo", 5,     0,  1)
    4.92 +OPDEF(OP_NEWARRAY_LIFO, 44,         "newarray.lifo", 5,     0,  1)
    4.93  
    4.94  // Performs a bounds check on an unsafe array.
    4.95  //
    4.96 @@ -109,63 +125,70 @@
    4.97  // array = pop()
    4.98  // push(array)
    4.99  // push(index)
   4.100 -OPDEF(OP_BOUNDS,        31,         "bounds",       1,      2,  2)
   4.101 +OPDEF(OP_BOUNDS,        45,         "bounds",       1,      2,  2)
   4.102  
   4.103  // Pushes a 32-bit IEEE-754 floating point immediate onto the stack.
   4.104 -OPDEF(OP_FLOAT,         32,         "float",        5,      0,  1)
   4.105 +OPDEF(OP_FLOAT,         46,         "float",        5,      0,  1)
   4.106  
   4.107  // Converts an integer to a 32-bit IEEE-754 floating point immediate.
   4.108 -OPDEF(OP_CVT_I2F,       33,         "cvt.i2f",      1,      1,  1)
   4.109 +OPDEF(OP_CVT_I2F,       47,         "cvt.i2f",      1,      1,  1)
   4.110  
   4.111  // Stack transitions for these binary operators:
   4.112  // rhs = pop()
   4.113  // lhs = pop()
   4.114  // push(lhs OP rhs)
   4.115 -OPDEF(OP_ADD_F,         34,         "add.f",        1,      2,  1)
   4.116 -OPDEF(OP_SUB_F,         35,         "sub.f",        1,      2,  1)
   4.117 -OPDEF(OP_MUL_F,         36,         "mul.f",        1,      2,  1)
   4.118 -OPDEF(OP_DIV_F,         37,         "div.f",        1,      2,  1)
   4.119 +OPDEF(OP_ADD_F,         48,         "add.f",        1,      2,  1)
   4.120 +OPDEF(OP_SUB_F,         49,         "sub.f",        1,      2,  1)
   4.121 +OPDEF(OP_MUL_F,         50,         "mul.f",        1,      2,  1)
   4.122 +OPDEF(OP_DIV_F,         51,         "div.f",        1,      2,  1)
   4.123 +
   4.124 +OPDEF(OP_LT_F,          52,         "lt.f",         1,      2,  1)
   4.125 +OPDEF(OP_LE_F,          53,         "le.f",         1,      2,  1)
   4.126 +OPDEF(OP_GE_F,          54,         "ge.f",         1,      2,  1)
   4.127 +OPDEF(OP_GT_F,          55,         "gt.f",         1,      2,  1)
   4.128 +OPDEF(OP_EQ_F,          56,         "eq.f",         1,      2,  1)
   4.129 +OPDEF(OP_NE_F,          57,         "ne.f",         1,      2,  1)
   4.130  
   4.131  // Bitwise operators.
   4.132 -OPDEF(OP_SHL,           38,         "shl",          1,      2,  1)
   4.133 -OPDEF(OP_SHR,           39,         "shr",          1,      2,  1)
   4.134 -OPDEF(OP_USHR,          40,         "ushr",         1,      2,  1)
   4.135 -OPDEF(OP_BITAND,        41,         "bitand",       1,      2,  1)
   4.136 -OPDEF(OP_BITOR,         42,         "bitor",        1,      2,  1)
   4.137 -OPDEF(OP_BITXOR,        43,         "bitxor",       1,      2,  1)
   4.138 +OPDEF(OP_SHL,           58,         "shl",          1,      2,  1)
   4.139 +OPDEF(OP_SHR,           59,         "shr",          1,      2,  1)
   4.140 +OPDEF(OP_USHR,          60,         "ushr",         1,      2,  1)
   4.141 +OPDEF(OP_BITAND,        61,         "bitand",       1,      2,  1)
   4.142 +OPDEF(OP_BITOR,         62,         "bitor",        1,      2,  1)
   4.143 +OPDEF(OP_BITXOR,        63,         "bitxor",       1,      2,  1)
   4.144  
   4.145  // Saves or restores the position of the LIFO heap to/from a local slot.
   4.146 -OPDEF(OP_SAVELIFO,      44,         "savelifo",     5,      0,  0)
   4.147 -OPDEF(OP_UNWINDLIFO,    45,         "unwindlifo",   5,      0,  0)
   4.148 +OPDEF(OP_SAVELIFO,      64,         "savelifo",     5,      0,  0)
   4.149 +OPDEF(OP_UNWINDLIFO,    65,         "unwindlifo",   5,      0,  0)
   4.150  
   4.151  // Composes a variable reference to a stack slot or argument.
   4.152 -OPDEF(OP_VARREF_LIFO,   46,         "varref.lifo",  5,      0,  1)
   4.153 -OPDEF(OP_ARGREF_LIFO,   47,         "argref.lifo",  5,      0,  1)
   4.154 -OPDEF(OP_SLOTREF_LIFO,  48,         "slotref.lifo", 1,      1,  1)
   4.155 -OPDEF(OP_ARRAYREF_LIFO, 49,         "arrayref.lifo",1,      2,  1)
   4.156 -OPDEF(OP_GETREF_I,      50,         "getref.i",     1,      1,  1)
   4.157 -OPDEF(OP_SETREF_I,      51,         "setref.i",     1,      2,  1)
   4.158 -OPDEF(OP_GETREF_F,      52,         "getref.f",     1,      1,  1)
   4.159 -OPDEF(OP_SETREF_F,      53,         "setref.f",     1,      2,  1)
   4.160 +OPDEF(OP_VARREF_LIFO,   66,         "varref.lifo",  5,      0,  1)
   4.161 +OPDEF(OP_ARGREF_LIFO,   67,         "argref.lifo",  5,      0,  1)
   4.162 +OPDEF(OP_SLOTREF_LIFO,  68,         "slotref.lifo", 1,      1,  1)
   4.163 +OPDEF(OP_ARRAYREF_LIFO, 69,         "arrayref.lifo",1,      2,  1)
   4.164 +OPDEF(OP_GETREF_I,      70,         "getref.i",     1,      1,  1)
   4.165 +OPDEF(OP_SETREF_I,      71,         "setref.i",     1,      2,  1)
   4.166 +OPDEF(OP_GETREF_F,      72,         "getref.f",     1,      1,  1)
   4.167 +OPDEF(OP_SETREF_F,      73,         "setref.f",     1,      2,  1)
   4.168  
   4.169  // Pushes an object reference onto the stack.
   4.170 -OPDEF(OP_OBJECT,        54,         "object",       5,      0,  1)
   4.171 +OPDEF(OP_OBJECT,        74,         "object",       5,      0,  1)
   4.172  
   4.173  // Performs an array-to-array assignment.
   4.174  //   Left = pop()
   4.175  //   Right = pop()
   4.176  //   copy(Left, Right)
   4.177  //   push(Left)
   4.178 -OPDEF(OP_ARRAYCOPY,     55,         "arraycopy",    1,      2,  1)
   4.179 +OPDEF(OP_ARRAYCOPY,     75,         "arraycopy",    1,      2,  1)
   4.180  
   4.181  // Duplicates the top item on the stack.
   4.182 -OPDEF(OP_DUP,           56,         "dup",          1,      1,  2)
   4.183 +OPDEF(OP_DUP,           76,         "dup",          1,      1,  2)
   4.184  
   4.185  // Duplicates the top two items on the stack.
   4.186 -OPDEF(OP_DUP2,          57,         "dup2",         1,      2,  4)
   4.187 +OPDEF(OP_DUP2,          77,         "dup2",         1,      2,  4)
   4.188  
   4.189  // Swaps the two items at the top of the stack.
   4.190 -OPDEF(OP_SWAP,          58,         "swap",         1,      2,  2)
   4.191 +OPDEF(OP_SWAP,          78,         "swap",         1,      2,  2)
   4.192  
   4.193  // Roll operation is the same as Forth. It steals a value on the stack,
   4.194  // shifting all stack values down, and then places the stolen value back at
   4.195 @@ -175,14 +198,14 @@
   4.196  //  sp[-3] = sp[-2]
   4.197  //  sp[-2] = sp[-1]
   4.198  //  sp[-1] = p
   4.199 -OPDEF(OP_ROLL3,         59,         "roll3",        1,      3, 3)
   4.200 +OPDEF(OP_ROLL3,         79,         "roll3",        1,      3, 3)
   4.201  
   4.202  // Pick operation is the same as Forth. It pushes a copy of a slot at a
   4.203  // specific depth.
   4.204  //
   4.205  // push(sp[-n])
   4.206 -OPDEF(OP_PICK2,         60,         "pick2",        1,      2, 3)
   4.207 -OPDEF(OP_PICK3,         61,         "pick3",        1,      3, 4)
   4.208 +OPDEF(OP_PICK2,         80,         "pick2",        1,      2, 3)
   4.209 +OPDEF(OP_PICK3,         81,         "pick3",        1,      3, 4)
   4.210  
   4.211  // Calls a native function. During the course of calling a native, arguments
   4.212  // on the stack are re-pushed to match the cell-based native calling
   4.213 @@ -193,14 +216,14 @@
   4.214  //
   4.215  // [u8 Opcode] [u32 Index] [u32 ArgCount]
   4.216  //
   4.217 -OPDEF(OP_CALLNATIVE,    62,         "callnative",   9,      -1, 1)
   4.218 +OPDEF(OP_CALLNATIVE,    82,         "callnative",   9,      -1, 1)
   4.219  
   4.220  // Returns from a function that does return a value.
   4.221 -OPDEF(OP_RETURNVOID,    63,         "returnvoid",   1,      0, 0)
   4.222 +OPDEF(OP_RETURNVOID,    83,         "returnvoid",   1,      0, 0)
   4.223  
   4.224  // Loads the module of the running function.
   4.225 -OPDEF(OP_MODULE,        64,         "module",       1,      0, 1)
   4.226 +OPDEF(OP_MODULE,        84,         "module",       1,      0, 1)
   4.227  
   4.228  // Loads a function from a module object. The operand is the slot number
   4.229  // in the module.
   4.230 -OPDEF(OP_GETMODULE_FN,  65,         "getmodule.fn", 5,      1, 1)
   4.231 +OPDEF(OP_GETMODULE_FN,  85,         "getmodule.fn", 5,      1, 1)
     5.1 --- a/jitcraft/Parser.cpp	Sun Jul 15 14:40:11 2012 -0700
     5.2 +++ b/jitcraft/Parser.cpp	Sun Jul 15 19:48:15 2012 -0700
     5.3 @@ -1009,6 +1009,13 @@
     5.4              break;
     5.5            }
     5.6  
     5.7 +          // case TOK_NEW:
     5.8 +          // {
     5.9 +          //   if ((statement = variableDeclaration()) == NULL)
    5.10 +          //       return NULL;
    5.11 +          //   break;
    5.12 +          // }
    5.13 +
    5.14            case TOK_ENUM:
    5.15              if ((statement = enum_()) == NULL)
    5.16                  return NULL;
     6.1 --- a/jitcraft/Scanner.cpp	Sun Jul 15 14:40:11 2012 -0700
     6.2 +++ b/jitcraft/Scanner.cpp	Sun Jul 15 19:48:15 2012 -0700
     6.3 @@ -476,6 +476,13 @@
     6.4            case ',': return TOK_COMMA;
     6.5            case '\0': return TOK_EOF;
     6.6  
     6.7 +          case '!':
     6.8 +            c = getChar();
     6.9 +            if (c == '=')
    6.10 +                return TOK_NOTEQUALS;
    6.11 +            putChar(c);
    6.12 +            return TOK_NOT;
    6.13 +
    6.14            case '=':
    6.15              c = getChar();
    6.16              if (c == '=')
     7.1 --- a/jitcraft/SemanticAnalysis.cpp	Sun Jul 15 14:40:11 2012 -0700
     7.2 +++ b/jitcraft/SemanticAnalysis.cpp	Sun Jul 15 19:48:15 2012 -0700
     7.3 @@ -207,6 +207,16 @@
     7.4          }
     7.5      }
     7.6  
     7.7 +    if (token >= TOK_EQUALS && token <= TOK_GE) {
     7.8 +        if ((left->isFloat() || (left->isInt32() && !left->tag())) &&
     7.9 +            (right->isFloat() || (right->isInt32() && !left->tag())))
    7.10 +        {
    7.11 +            return zone_->types()->getPrimitive(PrimitiveType_Int32);
    7.12 +        }
    7.13 +        binaryTypeError(node, token, left, right);
    7.14 +        return NULL;
    7.15 +    }
    7.16 +
    7.17      if ((!left->isInt32() || left->tag()) ||
    7.18          (!right->isInt32() || right->tag()))
    7.19      {
     8.1 --- a/jitcraft/Token.h	Sun Jul 15 14:40:11 2012 -0700
     8.2 +++ b/jitcraft/Token.h	Sun Jul 15 19:48:15 2012 -0700
     8.3 @@ -102,6 +102,7 @@
     8.4      _(GT,                 ">")                          \
     8.5      _(GE,                 ">=")                         \
     8.6      _(COMMA,              ",")                          \
     8.7 +    _(NOT,                "!")                          \
     8.8      _(EOF,                "<end-of-file>")
     8.9  
    8.10  enum TokenKind