Kaynağa Gözat

first implementation of bitwise operators '&' (band), '|' (bor),
and '~' (bxor)

Roberto Ierusalimschy 11 yıl önce
ebeveyn
işleme
c0edab0f6d
11 değiştirilmiş dosya ile 122 ekleme ve 47 silme
  1. 24 13
      lcode.c
  2. 2 1
      lcode.h
  3. 32 17
      lobject.c
  4. 7 1
      lopcodes.c
  5. 4 1
      lopcodes.h
  6. 11 7
      lparser.c
  7. 2 2
      ltests.c
  8. 2 1
      ltm.c
  9. 4 1
      ltm.h
  10. 5 2
      lua.h
  11. 29 1
      lvm.c

+ 24 - 13
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.73 2013/12/16 14:30:22 roberto Exp roberto $
+** $Id: lcode.c,v 2.74 2013/12/16 19:06:52 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -750,18 +750,27 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
 }
 
 
+/* return false if folding can raise an error */
+static int validop (OpCode op, TValue *v1, TValue *v2) {
+  lua_Integer i;
+  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 */
+      return (tointeger(v1, &i) && tointeger(v2, &i));
+    case OP_MOD:  /* integer module by 0 */
+      return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0);
+    case OP_POW:  /* negative integer exponentiation */
+      return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) < 0);
+    default: return 1;  /* everything else is valid */
+  }
+}
+
+
 static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
   TValue v1, v2, res;
-  lua_Integer i;
-  if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2))
-    return 0;  /* non-numeric operands */
-  if (op == OP_IDIV &&
-        (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0))
-    return 0;  /* avoid division by 0 and conversion errors */
-  if (ttisinteger(&v1) && ttisinteger(&v2) &&  /* for integer operations... */
-       ((op == OP_MOD && ivalue(&v2) == 0) ||   /* ...avoid module by 0... */
-        (op == OP_POW && ivalue(&v2) < 0)))  /* ...and negative exponents */
-    return 0;
+  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)) {
@@ -853,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_MOD: case OPR_POW:
+    case OPR_BAND: case OPR_BOR: case OPR_BXOR: {
       if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v);
       break;
     }
@@ -897,7 +907,8 @@ void luaK_posfix (FuncState *fs, BinOpr op,
       break;
     }
     case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:
-    case OPR_IDIV: case OPR_MOD: case OPR_POW: {
+    case OPR_IDIV: case OPR_MOD: case OPR_POW:
+    case OPR_BAND: case OPR_BOR: case OPR_BXOR: {
       codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line);
       break;
     }

+ 2 - 1
lcode.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.60 2013/04/26 13:07:53 roberto Exp roberto $
+** $Id: lcode.h,v 1.61 2013/12/16 19:06:52 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -27,6 +27,7 @@ typedef enum BinOpr {
   OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW,
   OPR_DIV,
   OPR_IDIV,
+  OPR_BAND, OPR_BOR, OPR_BXOR,
   OPR_CONCAT,
   OPR_EQ, OPR_LT, OPR_LE,
   OPR_NE, OPR_GT, OPR_GE,

+ 32 - 17
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 2.68 2013/07/10 17:15:12 roberto Exp roberto $
+** $Id: lobject.c,v 2.69 2013/12/16 14:30:22 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -78,6 +78,10 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
     case LUA_OPMUL:return intop(*, v1, v2);
     case LUA_OPMOD: return luaV_mod(L, v1, v2);
     case LUA_OPPOW: return luaV_pow(L, v1, v2);
+    case LUA_OPIDIV: return luaV_div(L, v1, v2);
+    case LUA_OPBAND: return intop(&, v1, v2);
+    case LUA_OPBOR: return intop(|, v1, v2);
+    case LUA_OPBXOR: return intop(^, v1, v2);
     case LUA_OPUNM: return intop(-, 0, v1);
     default: lua_assert(0); return 0;
   }
@@ -100,25 +104,36 @@ static lua_Number numarith (int op, lua_Number v1, lua_Number v2) {
 
 void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
                  TValue *res) {
-  if (op == LUA_OPIDIV) {  /* operates only on integers */
-    lua_Integer i1; lua_Integer i2;
-    if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
-      setivalue(res, luaV_div(L, i1, i2));
-      return;
+  switch (op) {
+    case LUA_OPIDIV: case LUA_OPBAND: case LUA_OPBOR:
+    case LUA_OPBXOR: {  /* operates only on integers */
+      lua_Integer i1; lua_Integer i2;
+      if (tointeger(p1, &i1) && tointeger(p2, &i2)) {
+        setivalue(res, intarith(L, op, i1, i2));
+        return;
+      }
+      else break;  /* go to the end */
     }
-    /* else go to the end */
-  }
-  else {  /* other operations */
-    lua_Number n1; lua_Number n2;
-    if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV) {
-      setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
-      return;
+    case LUA_OPDIV: {  /* operates only on floats */
+      lua_Number n1; lua_Number n2;
+      if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+        setnvalue(res, numarith(op, n1, n2));
+        return;
+      }
+      else break;  /* go to the end */
     }
-    else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
-      setnvalue(res, numarith(op, n1, n2));
-      return;
+    default: {  /* other operations */
+      lua_Number n1; lua_Number n2;
+      if (ttisinteger(p1) && ttisinteger(p2)) {
+        setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
+        return;
+      }
+      else if (tonumber(p1, &n1) && tonumber(p2, &n2)) {
+        setnvalue(res, numarith(op, n1, n2));
+        return;
+      }
+      else break;  /* go to the end */
     }
-    /* else go to the end */
   }
   /* could not perform raw operation; try metmethod */
   lua_assert(L != NULL);  /* should not fail when folding (compile time) */

+ 7 - 1
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.50 2013/04/26 13:07:53 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.51 2013/12/16 19:06:52 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -35,6 +35,9 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "POW",
   "DIV",
   "IDIV",
+  "BAND",
+  "BOR",
+  "BXOR",
   "UNM",
   "NOT",
   "LEN",
@@ -84,6 +87,9 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_POW */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_DIV */
  ,opmode(0, 1, OpArgK, OpArgK, iABC)		/* OP_IDIV */
+ ,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, OpArgR, OpArgN, iABC)		/* OP_UNM */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_NOT */
  ,opmode(0, 1, OpArgR, OpArgN, iABC)		/* OP_LEN */

+ 4 - 1
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.143 2013/04/26 13:07:53 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.144 2013/12/16 19:06:52 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -191,6 +191,9 @@ OP_MOD,/*	A B C	R(A) := RK(B) % RK(C)				*/
 OP_POW,/*	A B C	R(A) := RK(B) ^ RK(C)				*/
 OP_DIV,/*	A B C	R(A) := RK(B) / RK(C)				*/
 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_UNM,/*	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.135 2013/08/30 16:01:37 roberto Exp roberto $
+** $Id: lparser.c,v 2.136 2013/12/16 19:06:52 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -994,6 +994,9 @@ static BinOpr getbinopr (int op) {
     case '^': return OPR_POW;
     case '/': return OPR_DIV;
     case TK_IDIV: return OPR_IDIV;
+    case '&': return OPR_BAND;
+    case '|': return OPR_BOR;
+    case '~': return OPR_BXOR;
     case TK_CONCAT: return OPR_CONCAT;
     case TK_NE: return OPR_NE;
     case TK_EQ: return OPR_EQ;
@@ -1012,17 +1015,18 @@ static const struct {
   lu_byte left;  /* left priority for each binary operator */
   lu_byte right; /* right priority */
 } priority[] = {  /* ORDER OPR */
-   {6, 6}, {6, 6},           /* '+' '-' */
-   {7, 7}, {7, 7},           /* '*' '%' */
-   {10, 9},                  /* '^' (right associative) */
-   {7, 7}, {7, 7},           /* '/' '//' */
-   {5, 4},                   /* '..' (right associative) */
+   {8, 8}, {8, 8},           /* '+' '-' */
+   {9, 9}, {9, 9},           /* '*' '%' */
+   {12, 11},                  /* '^' (right associative) */
+   {9, 9}, {9, 9},           /* '/' '//' */
+   {6, 6}, {4, 4}, {5, 5},   /* '&' '|' '~' */
+   {7, 6},                   /* '..' (right associative) */
    {3, 3}, {3, 3}, {3, 3},   /* ==, <, <= */
    {3, 3}, {3, 3}, {3, 3},   /* ~=, >, >= */
    {2, 2}, {1, 1}            /* and, or */
 };
 
-#define UNARY_PRIORITY	8  /* priority for unary operators */
+#define UNARY_PRIORITY	10  /* priority for unary operators */
 
 
 /*

+ 2 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.159 2013/09/11 14:47:08 roberto Exp roberto $
+** $Id: ltests.c,v 2.160 2013/12/16 19:06:52 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -1198,7 +1198,7 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
       }
     }
     else if EQ("arith") {
-      static char ops[] = "+-*%^/\\_";  /* '\'  -> '//'; '_' -> '..' */
+      static char ops[] = "+-*%^/\\&|~_";  /* '\'  -> '//'; '_' -> '..' */
       int op;
       skip(&pc);
       op = strchr(ops, *pc++) - ops;

+ 2 - 1
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.22 2013/08/27 18:53:35 roberto Exp roberto $
+** $Id: ltm.c,v 2.23 2013/12/16 19:06:52 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -38,6 +38,7 @@ void luaT_init (lua_State *L) {
     "__gc", "__mode", "__len", "__eq",
     "__add", "__sub", "__mul", "__mod", "__pow",
     "__div", "__idiv",
+    "__band", "__bor", "__bxor",
     "__unm", "__lt", "__le",
     "__concat", "__call"
   };

+ 4 - 1
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.16 2013/04/29 16:56:50 roberto Exp roberto $
+** $Id: ltm.h,v 2.17 2013/12/16 19:06:52 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -29,6 +29,9 @@ typedef enum {
   TM_POW,
   TM_DIV,
   TM_IDIV,
+  TM_BAND,
+  TM_BOR,
+  TM_BXOR,
   TM_UNM,
   TM_LT,
   TM_LE,

+ 5 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.295 2013/12/09 14:21:10 roberto Exp roberto $
+** $Id: lua.h,v 1.296 2013/12/16 19:06:52 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
@@ -189,7 +189,10 @@ LUA_API const void     *(lua_topointer) (lua_State *L, int idx);
 #define LUA_OPPOW	4
 #define LUA_OPDIV	5
 #define LUA_OPIDIV	6
-#define LUA_OPUNM	7
+#define LUA_OPBAND	7
+#define LUA_OPBOR	8
+#define LUA_OPBXOR	9
+#define LUA_OPUNM	10
 
 LUA_API void  (lua_arith) (lua_State *L, int op);
 

+ 29 - 1
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.180 2013/08/29 13:49:57 roberto Exp roberto $
+** $Id: lvm.c,v 2.181 2013/12/16 14:30:22 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -437,6 +437,7 @@ 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_GETTABUP: case OP_GETTABLE: case OP_SELF: {
       setobjs2s(L, base + GETARG_A(inst), --L->top);
@@ -671,6 +672,33 @@ void luaV_execute (lua_State *L) {
         }
         else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
       )
+      vmcase(OP_BAND,
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, intop(&, ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); }
+      )
+      vmcase(OP_BOR,
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, intop(|, ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); }
+      )
+      vmcase(OP_BXOR,
+        TValue *rb = RKB(i);
+        TValue *rc = RKC(i);
+        lua_Integer ib; lua_Integer ic;
+        if (tointeger(rb, &ib) && tointeger(rc, &ic)) {
+          setivalue(ra, intop(^, ib, ic));
+        }
+        else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); }
+      )
       vmcase(OP_MOD,
         TValue *rb = RKB(i);
         TValue *rc = RKC(i);