mirror of
https://github.com/lua/lua
synced 2024-11-25 14:20:41 +03:00
first implementation of bitwise operators '&' (band), '|' (bor),
and '~' (bxor)
This commit is contained in:
parent
a948054a19
commit
c0edab0f6d
37
lcode.c
37
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;
|
||||
}
|
||||
|
3
lcode.h
3
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,
|
||||
|
49
lobject.c
49
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) */
|
||||
|
@ -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 */
|
||||
|
@ -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) */
|
||||
|
18
lparser.c
18
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 */
|
||||
|
||||
|
||||
/*
|
||||
|
4
ltests.c
4
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;
|
||||
|
3
ltm.c
3
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"
|
||||
};
|
||||
|
5
ltm.h
5
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,
|
||||
|
7
lua.h
7
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);
|
||||
|
||||
|
30
lvm.c
30
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);
|
||||
|
Loading…
Reference in New Issue
Block a user