Quellcode durchsuchen

first implementation of '<<', '>>', and '~' (bitwise not)

Roberto Ierusalimschy vor 11 Jahren
Ursprung
Commit
1ea2d20f74
15 geänderte Dateien mit 139 neuen und 49 gelöschten Zeilen
  1. 4 4
      lapi.c
  2. 9 7
      lcode.c
  3. 3 2
      lcode.h
  4. 9 6
      llex.c
  5. 2 1
      llex.h
  6. 6 2
      lobject.c
  7. 7 1
      lopcodes.c
  8. 4 1
      lopcodes.h
  9. 11 7
      lparser.c
  10. 11 2
      ltests.c
  11. 14 9
      ltm.c
  12. 4 1
      ltm.h
  13. 5 2
      lua.h
  14. 48 3
      lvm.c
  15. 2 1
      lvm.h

+ 4 - 4
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.190 2013/09/13 16:21:52 roberto Exp roberto $
+** $Id: lapi.c,v 2.191 2013/12/04 12:15:22 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -299,9 +299,9 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
 
 LUA_API void lua_arith (lua_State *L, int op) {
   lua_lock(L);
-  if (op != LUA_OPUNM) /* all other operations expect two operands */
-    api_checknelems(L, 2);
-  else {  /* for unary minus, add fake 2nd operand */
+  if (op != LUA_OPUNM && op != LUA_OPBNOT)
+    api_checknelems(L, 2);  /* all other operations expect two operands */
+  else {  /* for unary operations, add fake 2nd operand */
     api_checknelems(L, 1);
     setobjs2s(L, L->top, L->top - 1);
     L->top++;

+ 9 - 7
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.75 2013/12/18 14:12:03 roberto Exp roberto $
+** $Id: lcode.c,v 2.76 2013/12/18 18:44:42 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -756,7 +756,8 @@ static int validop (OpCode op, TValue *v1, TValue *v2) {
   switch (op) {
     case OP_IDIV:  /* division by 0 and conversion errors */
       return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0);
-    case OP_BAND: case OP_BOR: case OP_BXOR:  /* conversion errors */
+    case OP_BAND: case OP_BOR: case OP_BXOR:
+    case OP_SHL: case OP_SHR: case OP_BNOT:  /* conversion errors */
       return (tointeger(v1, &i) && tointeger(v2, &i));
     case OP_MOD:  /* integer module by 0 */
       return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0);
@@ -771,7 +772,6 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
   TValue v1, v2, res;
   if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2))
     return 0;  /* non-numeric operands or not safe to fold */
-  lua_assert(OP_IDIV - OP_ADD + LUA_OPADD == LUA_OPIDIV);
   luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res);
   if (ttisinteger(&res)) {
     e1->k = VKINT;
@@ -792,7 +792,7 @@ static void codearith (FuncState *fs, OpCode op,
                        expdesc *e1, expdesc *e2, int line) {
   if (!constfolding(op, e1, e2)) {  /* could not fold operation? */
     int o1, o2;
-    if (op == OP_UNM || op == OP_LEN) {
+    if (op == OP_UNM || op == OP_BNOT || op == OP_LEN) {
       o2 = 0;
       o1 = luaK_exp2anyreg(fs, e1);  /* cannot operate on constants */
     }
@@ -835,7 +835,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
   expdesc e2;
   e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
   switch (op) {
-    case OPR_MINUS: case OPR_LEN: {
+    case OPR_MINUS: case OPR_BNOT: case OPR_LEN: {
       codearith(fs, op - OPR_MINUS + OP_UNM, e, &e2, line);
       break;
     }
@@ -862,7 +862,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
     case OPR_ADD: case OPR_SUB:
     case OPR_MUL: case OPR_DIV: case OPR_IDIV:
     case OPR_MOD: case OPR_POW:
-    case OPR_BAND: case OPR_BOR: case OPR_BXOR: {
+    case OPR_BAND: case OPR_BOR: case OPR_BXOR:
+    case OPR_SHL: case OPR_SHR: {
       if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v);
       break;
     }
@@ -907,7 +908,8 @@ void luaK_posfix (FuncState *fs, BinOpr op,
     }
     case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
     case OPR_IDIV: case OPR_MOD: case OPR_POW:
-    case OPR_BAND: case OPR_BOR: case OPR_BXOR: {
+    case OPR_BAND: case OPR_BOR: case OPR_BXOR:
+    case OPR_SHL: case OPR_SHR: {
       codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
       break;
     }

+ 3 - 2
lcode.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.61 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: lcode.h,v 1.62 2013/12/18 14:12:03 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -28,6 +28,7 @@ typedef enum BinOpr {
   OPR_DIV,
   OPR_IDIV,
   OPR_BAND, OPR_BOR, OPR_BXOR,
+  OPR_SHL, OPR_SHR,
   OPR_CONCAT,
   OPR_EQ, OPR_LT, OPR_LE,
   OPR_NE, OPR_GT, OPR_GE,
@@ -36,7 +37,7 @@ typedef enum BinOpr {
 } BinOpr;
 
 
-typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
+typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
 
 
 #define getcode(fs,e)	((fs)->f->code[(e)->u.info])

+ 9 - 6
llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 2.68 2013/08/21 20:09:51 roberto Exp roberto $
+** $Id: llex.c,v 2.69 2013/08/30 16:01:37 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -39,7 +39,8 @@ static const char *const luaX_tokens [] = {
     "end", "false", "for", "function", "goto", "if",
     "in", "local", "nil", "not", "or", "repeat",
     "return", "then", "true", "until", "while",
-    "//", "..", "...", "==", ">=", "<=", "~=", "::", "<eof>",
+    "//", "..", "...", "==", ">=", "<=", "~=",
+    "<<", ">>", "::", "<eof>",
     "<number>", "<number>", "<name>", "<string>"
 };
 
@@ -462,13 +463,15 @@ static int llex (LexState *ls, SemInfo *seminfo) {
       }
       case '<': {
         next(ls);
-        if (ls->current != '=') return '<';
-        else { next(ls); return TK_LE; }
+        if (ls->current == '=') { next(ls); return TK_LE; }
+        if (ls->current == '<') { next(ls); return TK_SHL; }
+        return '<';
       }
       case '>': {
         next(ls);
-        if (ls->current != '=') return '>';
-        else { next(ls); return TK_GE; }
+        if (ls->current == '=') { next(ls); return TK_GE; }
+        if (ls->current == '>') { next(ls); return TK_SHR; }
+        return '>';
       }
       case '/': {
         next(ls);

+ 2 - 1
llex.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.74 2013/04/26 13:07:53 roberto Exp roberto $
+** $Id: llex.h,v 1.75 2013/08/30 16:01:37 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -27,6 +27,7 @@ enum RESERVED {
   TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
   /* other terminal symbols */
   TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
+  TK_SHL, TK_SHR,
   TK_DBCOLON, TK_EOS,
   TK_FLT, TK_INT, TK_NAME, TK_STRING
 };

+ 6 - 2
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 2.69 2013/12/16 14:30:22 roberto Exp roberto $
+** $Id: lobject.c,v 2.70 2013/12/18 14:12:03 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -82,7 +82,10 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
     case LUA_OPBAND: return intop(&, v1, v2);
     case LUA_OPBOR: return intop(|, v1, v2);
     case LUA_OPBXOR: return intop(^, v1, v2);
+    case LUA_OPSHL: return luaV_shiftl(v1, v2);
+    case LUA_OPSHR: return luaV_shiftl(v1, -v2);
     case LUA_OPUNM: return intop(-, 0, v1);
+    case LUA_OPBNOT: return intop(^, cast_integer(-1), v1);
     default: lua_assert(0); return 0;
   }
 }
@@ -106,7 +109,8 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
                  TValue *res) {
   switch (op) {
     case LUA_OPIDIV: case LUA_OPBAND: case LUA_OPBOR:
-    case LUA_OPBXOR: {  /* operates only on integers */
+    case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR:
+    case LUA_OPBNOT: {  /* operates only on integers */
       lua_Integer i1; lua_Integer i2;
       if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
         setivalue(res, intarith(L, op, i1, i2));

+ 7 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.51 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.52 2013/12/18 14:12:03 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -38,7 +38,10 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "BAND",
   "BOR",
   "BXOR",
+  "SHL",
+  "SHR",
   "UNM",
+  "BNOT",
   "NOT",
   "LEN",
   "CONCAT",
@@ -90,7 +93,10 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_BAND */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_BOR */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_BXOR */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_SHL */
+ ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_SHR */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_UNM */
+ ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_BNOT */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_NOT */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_LEN */
  ,opmode(0, 1, OpArgR, OpArgR, iABC)		/* OP_CONCAT */

+ 4 - 1
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.144 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.145 2013/12/18 14:12:03 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -194,7 +194,10 @@ OP_IDIV,/*	A B C	R(A) := RK(B) // RK(C)				*/
 OP_BAND,/*	A B C	R(A) := RK(B) & RK(C)				*/
 OP_BOR,/*	A B C	R(A) := RK(B) | RK(C)				*/
 OP_BXOR,/*	A B C	R(A) := RK(B) ~ RK(C)				*/
+OP_SHL,/*	A B C	R(A) := RK(B) << RK(C)				*/
+OP_SHR,/*	A B C	R(A) := RK(B) >> RK(C)				*/
 OP_UNM,/*	A B	R(A) := -R(B)					*/
+OP_BNOT,/*	A B	R(A) := ~R(B)					*/
 OP_NOT,/*	A B	R(A) := not R(B)				*/
 OP_LEN,/*	A B	R(A) := length of R(B)				*/
 

+ 11 - 7
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.136 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: lparser.c,v 2.137 2013/12/18 14:12:03 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -979,6 +979,7 @@ static UnOpr getunopr (int op) {
   switch (op) {
     case TK_NOT: return OPR_NOT;
     case '-': return OPR_MINUS;
+    case '~': return OPR_BNOT;
     case '#': return OPR_LEN;
     default: return OPR_NOUNOPR;
   }
@@ -997,6 +998,8 @@ static BinOpr getbinopr (int op) {
     case '&': return OPR_BAND;
     case '|': return OPR_BOR;
     case '~': return OPR_BXOR;
+    case TK_SHL: return OPR_SHL;
+    case TK_SHR: return OPR_SHR;
     case TK_CONCAT: return OPR_CONCAT;
     case TK_NE: return OPR_NE;
     case TK_EQ: return OPR_EQ;
@@ -1015,18 +1018,19 @@ static const struct {
   lu_byte left;  /* left priority for each binary operator */
   lu_byte right; /* right priority */
 } priority[] = {  /* ORDER OPR */
-   {8, 8}, {8, 8},           /* '+' '-' */
-   {9, 9}, {9, 9},           /* '*' '%' */
-   {12, 11},                  /* '^' (right associative) */
-   {9, 9}, {9, 9},           /* '/' '//' */
+   {10, 10}, {10, 10},           /* '+' '-' */
+   {11, 11}, {11, 11},           /* '*' '%' */
+   {14, 13},                  /* '^' (right associative) */
+   {11, 11}, {11, 11},           /* '/' '//' */
    {6, 6}, {4, 4}, {5, 5},   /* '&' '|' '~' */
-   {7, 6},                   /* '..' (right associative) */
+   {7, 7}, {7, 7},           /* '<<' '>>' */
+   {9, 8},                   /* '..' (right associative) */
    {3, 3}, {3, 3}, {3, 3},   /* ==, <, <= */
    {3, 3}, {3, 3}, {3, 3},   /* ~=, >, >= */
    {2, 2}, {1, 1}            /* and, or */
 };
 
-#define UNARY_PRIORITY	10  /* priority for unary operators */
+#define UNARY_PRIORITY	12  /* priority for unary operators */
 
 
 /*

+ 11 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.160 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: ltests.c,v 2.161 2013/12/18 14:12:03 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -1023,6 +1023,16 @@ static void pushcode (lua_State *L, int code) {
 static int testC (lua_State *L);
 static int Cfunck (lua_State *L);
 
+/*
+** arithmetic operation encoding for 'arith' instruction
+** LUA_OPIDIV  -> \
+** LUA_OPSHL   -> <
+** LUA_OPSHR   -> >
+** LUA_OPUNM   -> _
+** LUA_OPBNOT  -> !
+*/
+static char ops[] = "+-*%^/\\&|~<>_!";
+
 static int runC (lua_State *L, lua_State *L1, const char *pc) {
   char buff[300];
   int status = 0;
@@ -1198,7 +1208,6 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
       }
     }
     else if EQ("arith") {
-      static char ops[] = "+-*%^/\\&|~_";  /* '\'  -> '//'; '_' -> '..' */
       int op;
       skip(&pc);
       op = strchr(ops, *pc++) - ops;

+ 14 - 9
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.23 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: ltm.c,v 2.24 2013/12/18 14:12:03 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -38,8 +38,8 @@ void luaT_init (lua_State *L) {
     "__gc", "__mode", "__len", "__eq",
     "__add", "__sub", "__mul", "__mod", "__pow",
     "__div", "__idiv",
-    "__band", "__bor", "__bxor",
-    "__unm", "__lt", "__le",
+    "__band", "__bor", "__bxor", "__shl", "__shr",
+    "__unm", "__bnot", "__lt", "__le",
     "__concat", "__call"
   };
   int i;
@@ -112,12 +112,17 @@ int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
 void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
                     StkId res, TMS event) {
   if (!luaT_callbinTM(L, p1, p2, res, event)) {
-    if (event == TM_CONCAT)
-      luaG_concaterror(L, p1, p2);
-    else if (event == TM_IDIV && ttisnumber(p1) && ttisnumber(p2))
-      luaG_tointerror(L, p1, p2);
-    else
-      luaG_aritherror(L, p1, p2);
+    switch (event) {
+      case TM_CONCAT:
+        luaG_concaterror(L, p1, p2);
+      case TM_IDIV: case TM_BAND: case TM_BOR: case TM_BXOR:
+      case TM_SHL: case TM_SHR: case TM_BNOT:
+        if (ttisnumber(p1) && ttisnumber(p2))
+          luaG_tointerror(L, p1, p2);
+        /* else go through */
+      default:
+        luaG_aritherror(L, p1, p2);
+    }
   }
 }
 

+ 4 - 1
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.17 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: ltm.h,v 2.18 2013/12/18 14:12:03 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -32,7 +32,10 @@ typedef enum {
   TM_BAND,
   TM_BOR,
   TM_BXOR,
+  TM_SHL,
+  TM_SHR,
   TM_UNM,
+  TM_BNOT,
   TM_LT,
   TM_LE,
   TM_CONCAT,

+ 5 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.296 2013/12/16 19:06:52 roberto Exp roberto $
+** $Id: lua.h,v 1.297 2013/12/18 14:12:03 roberto Exp roberto $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
@@ -192,7 +192,10 @@ LUA_API const void     *(lua_topointer) (lua_State *L, int idx);
 #define LUA_OPBAND	7
 #define LUA_OPBOR	8
 #define LUA_OPBXOR	9
-#define LUA_OPUNM	10
+#define LUA_OPSHL	10
+#define LUA_OPSHR	11
+#define LUA_OPUNM	12
+#define LUA_OPBNOT	13
 
 LUA_API void  (lua_arith) (lua_State *L, int op);
 

+ 48 - 3
lvm.c

@@ -1,10 +1,11 @@
 /*
-** $Id: lvm.c,v 2.181 2013/12/16 14:30:22 roberto Exp roberto $
+** $Id: lvm.c,v 2.182 2013/12/18 14:12:03 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
 
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -379,6 +380,21 @@ lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y) {
 }
 
 
+/* number of bits in an integer */
+#define NBITS	cast_int(sizeof(lua_Integer) * CHAR_BIT)
+
+LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
+  if (y < 0) {  /* shift right? */
+    if (y <= -NBITS) return 0;
+    else return cast_integer(cast_unsigned(x) >> (-y));
+  }
+  else {  /* shift left */
+    if (y >= NBITS) return 0;
+    else return x << y;
+  }
+}
+
+
 /*
 ** check whether cached closure in prototype 'p' may be reused, that is,
 ** whether there is a cached closure with the same upvalues needed by
@@ -437,8 +453,9 @@ void luaV_finishOp (lua_State *L) {
   OpCode op = GET_OPCODE(inst);
   switch (op) {  /* finish its execution */
     case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV:
-    case OP_BAND: case OP_BOR: case OP_BXOR:
-    case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
+    case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR:
+    case OP_MOD: case OP_POW:
+    case OP_UNM: case OP_BNOT: case OP_LEN:
     case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
       setobjs2s(L, base + GETARG_A(inst), --L->top);
       break;
@@ -699,6 +716,24 @@ void luaV_execute (lua_State *L) {
         }
         else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); }
       )
+      vmcase(OP_SHL,
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, luaV_shiftl(ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); }
+      )
+      vmcase(OP_SHR,
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, luaV_shiftl(ib, -ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); }
+      )
       vmcase(OP_MOD,
         TValue *rb = RKB(i);
         TValue *rc = RKC(i);
@@ -739,6 +774,16 @@ void luaV_execute (lua_State *L) {
           Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));
         }
       )
+      vmcase(OP_BNOT,
+        TValue *rb = RB(i);
+        lua_Integer ib;
+        if (tointeger(rb, &ib)) {
+          setivalue(ra, intop(^, cast_integer(-1), ib));
+        }
+        else {
+          Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT));
+        }
+      )
       vmcase(OP_NOT,
         TValue *rb = RB(i);
         int res = l_isfalse(rb);  /* next assignment may change this value */

+ 2 - 1
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.23 2013/05/02 12:31:26 roberto Exp roberto $
+** $Id: lvm.h,v 2.24 2013/12/16 14:30:22 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -44,6 +44,7 @@ LUAI_FUNC void luaV_concat (lua_State *L, int total);
 LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y);
 LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y);
 LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y);
+LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y);
 LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);
 
 #endif