From 1ea2d20f74cea9c61817d4a5ed67c4fc47cafb51 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 30 Dec 2013 18:47:58 -0200 Subject: [PATCH] first implementation of '<<', '>>', and '~' (bitwise not) --- lapi.c | 8 ++++---- lcode.c | 16 +++++++++------- lcode.h | 5 +++-- llex.c | 15 +++++++++------ llex.h | 3 ++- lobject.c | 8 ++++++-- lopcodes.c | 8 +++++++- lopcodes.h | 5 ++++- lparser.c | 18 +++++++++++------- ltests.c | 13 +++++++++++-- ltm.c | 23 ++++++++++++++--------- ltm.h | 5 ++++- lua.h | 7 +++++-- lvm.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- lvm.h | 3 ++- 15 files changed, 139 insertions(+), 49 deletions(-) diff --git a/lapi.c b/lapi.c index ca37dbee..de13bd62 100644 --- a/lapi.c +++ b/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++; diff --git a/lcode.c b/lcode.c index 8b54d71d..2da5e73a 100644 --- a/lcode.c +++ b/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; } diff --git a/lcode.h b/lcode.h index 713f76aa..a3fdf520 100644 --- a/lcode.h +++ b/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]) diff --git a/llex.c b/llex.c index 7afe31b1..0a2d9916 100644 --- a/llex.c +++ b/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", - "//", "..", "...", "==", ">=", "<=", "~=", "::", "", + "//", "..", "...", "==", ">=", "<=", "~=", + "<<", ">>", "::", "", "", "", "", "" }; @@ -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); diff --git a/llex.h b/llex.h index e9c1ed99..b79da192 100644 --- a/llex.h +++ b/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 }; diff --git a/lobject.c b/lobject.c index 92c4d678..80f495a4 100644 --- a/lobject.c +++ b/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)); diff --git a/lopcodes.c b/lopcodes.c index ba7b9017..cf2c4d3d 100644 --- a/lopcodes.c +++ b/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 */ diff --git a/lopcodes.h b/lopcodes.h index 6894f45f..632dee64 100644 --- a/lopcodes.h +++ b/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) */ diff --git a/lparser.c b/lparser.c index fce6a04b..86582565 100644 --- a/lparser.c +++ b/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 */ /* diff --git a/ltests.c b/ltests.c index 1dccc934..d062d167 100644 --- a/ltests.c +++ b/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; diff --git a/ltm.c b/ltm.c index 6ca7e9d3..1aa25bf0 100644 --- a/ltm.c +++ b/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); + } } } diff --git a/ltm.h b/ltm.h index 237acc7f..a25247cc 100644 --- a/ltm.h +++ b/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, diff --git a/lua.h b/lua.h index bfb713a7..d40d1956 100644 --- a/lua.h +++ b/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); diff --git a/lvm.c b/lvm.c index b18ed3fd..9a2c1375 100644 --- a/lvm.c +++ b/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 #include #include #include @@ -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 */ diff --git a/lvm.h b/lvm.h index 56713c83..bb35d633 100644 --- a/lvm.h +++ b/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