mirror of
https://github.com/lua/lua
synced 2025-04-12 07:53:16 +03:00
new method to handle tests without values (negative values)
This commit is contained in:
parent
3390f9a35a
commit
3b19af44b0
69
lcode.c
69
lcode.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lcode.c,v 2.14 2005/06/07 18:53:45 roberto Exp roberto $
|
** $Id: lcode.c,v 2.15 2005/08/17 18:32:09 roberto Exp $
|
||||||
** Code generator for Lua
|
** Code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,11 @@ int luaK_jump (FuncState *fs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void luaK_ret (FuncState *fs, int first, int nret) {
|
||||||
|
luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
|
static int condjump (FuncState *fs, OpCode op, int A, int B, int C) {
|
||||||
luaK_codeABC(fs, op, A, B, C);
|
luaK_codeABC(fs, op, A, B, C);
|
||||||
return luaK_jump(fs);
|
return luaK_jump(fs);
|
||||||
@ -101,49 +106,50 @@ static Instruction *getjumpcontrol (FuncState *fs, int pc) {
|
|||||||
** check whether list has any jump that do not produce a value
|
** check whether list has any jump that do not produce a value
|
||||||
** (or produce an inverted value)
|
** (or produce an inverted value)
|
||||||
*/
|
*/
|
||||||
static int need_value (FuncState *fs, int list, int cond) {
|
static int need_value (FuncState *fs, int list) {
|
||||||
for (; list != NO_JUMP; list = getjump(fs, list)) {
|
for (; list != NO_JUMP; list = getjump(fs, list)) {
|
||||||
Instruction i = *getjumpcontrol(fs, list);
|
Instruction i = *getjumpcontrol(fs, list);
|
||||||
if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1;
|
if (GET_OPCODE(i) != OP_TESTSET) return 1;
|
||||||
}
|
}
|
||||||
return 0; /* not found */
|
return 0; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void patchtestreg (Instruction *i, int reg) {
|
static void patchtestreg (Instruction *i, int reg) {
|
||||||
if (reg == NO_REG) reg = GETARG_B(*i);
|
if (reg != NO_REG)
|
||||||
SETARG_A(*i, reg);
|
SETARG_A(*i, reg);
|
||||||
|
else /* no register to put value; change TESTSET to TEST */
|
||||||
|
*i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void patchlistaux (FuncState *fs, int list,
|
static void removevalues (FuncState *fs, int list) {
|
||||||
int ttarget, int treg, int ftarget, int freg, int dtarget) {
|
for (; list != NO_JUMP; list = getjump(fs, list)) {
|
||||||
|
Instruction *i = getjumpcontrol(fs, list);
|
||||||
|
if (GET_OPCODE(*i) == OP_TESTSET)
|
||||||
|
patchtestreg(i, NO_REG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void patchlistaux (FuncState *fs, int list, int vtarget, int reg,
|
||||||
|
int dtarget) {
|
||||||
while (list != NO_JUMP) {
|
while (list != NO_JUMP) {
|
||||||
int next = getjump(fs, list);
|
int next = getjump(fs, list);
|
||||||
Instruction *i = getjumpcontrol(fs, list);
|
Instruction *i = getjumpcontrol(fs, list);
|
||||||
if (GET_OPCODE(*i) != OP_TEST) {
|
if (GET_OPCODE(*i) == OP_TESTSET) {
|
||||||
lua_assert(dtarget != NO_JUMP);
|
patchtestreg(i, reg);
|
||||||
|
fixjump(fs, list, vtarget);
|
||||||
|
}
|
||||||
|
else
|
||||||
fixjump(fs, list, dtarget); /* jump to default target */
|
fixjump(fs, list, dtarget); /* jump to default target */
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (GETARG_C(*i)) {
|
|
||||||
lua_assert(ttarget != NO_JUMP);
|
|
||||||
patchtestreg(i, treg);
|
|
||||||
fixjump(fs, list, ttarget);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
lua_assert(ftarget != NO_JUMP);
|
|
||||||
patchtestreg(i, freg);
|
|
||||||
fixjump(fs, list, ftarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list = next;
|
list = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dischargejpc (FuncState *fs) {
|
static void dischargejpc (FuncState *fs) {
|
||||||
patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc);
|
patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
|
||||||
fs->jpc = NO_JUMP;
|
fs->jpc = NO_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +159,7 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
|
|||||||
luaK_patchtohere(fs, list);
|
luaK_patchtohere(fs, list);
|
||||||
else {
|
else {
|
||||||
lua_assert(target < fs->pc);
|
lua_assert(target < fs->pc);
|
||||||
patchlistaux(fs, list, target, NO_REG, target, NO_REG, target);
|
patchlistaux(fs, list, target, NO_REG, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +379,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
|
|||||||
int final; /* position after whole expression */
|
int final; /* position after whole expression */
|
||||||
int p_f = NO_JUMP; /* position of an eventual LOAD false */
|
int p_f = NO_JUMP; /* position of an eventual LOAD false */
|
||||||
int p_t = NO_JUMP; /* position of an eventual LOAD true */
|
int p_t = NO_JUMP; /* position of an eventual LOAD true */
|
||||||
if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) {
|
if (need_value(fs, e->t) || need_value(fs, e->f)) {
|
||||||
int fj = NO_JUMP; /* first jump (over LOAD ops.) */
|
int fj = NO_JUMP; /* first jump (over LOAD ops.) */
|
||||||
if (e->k != VJMP)
|
if (e->k != VJMP)
|
||||||
fj = luaK_jump(fs);
|
fj = luaK_jump(fs);
|
||||||
@ -382,8 +388,8 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) {
|
|||||||
luaK_patchtohere(fs, fj);
|
luaK_patchtohere(fs, fj);
|
||||||
}
|
}
|
||||||
final = luaK_getlabel(fs);
|
final = luaK_getlabel(fs);
|
||||||
patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
|
patchlistaux(fs, e->f, final, reg, p_f);
|
||||||
patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
|
patchlistaux(fs, e->t, final, reg, p_t);
|
||||||
}
|
}
|
||||||
e->f = e->t = NO_JUMP;
|
e->f = e->t = NO_JUMP;
|
||||||
e->info = reg;
|
e->info = reg;
|
||||||
@ -492,7 +498,8 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
|
|||||||
|
|
||||||
static void invertjump (FuncState *fs, expdesc *e) {
|
static void invertjump (FuncState *fs, expdesc *e) {
|
||||||
Instruction *pc = getjumpcontrol(fs, e->info);
|
Instruction *pc = getjumpcontrol(fs, e->info);
|
||||||
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TEST);
|
lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&
|
||||||
|
GET_OPCODE(*pc) != OP_TEST);
|
||||||
SETARG_A(*pc, !(GETARG_A(*pc)));
|
SETARG_A(*pc, !(GETARG_A(*pc)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,13 +509,13 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) {
|
|||||||
Instruction ie = getcode(fs, e);
|
Instruction ie = getcode(fs, e);
|
||||||
if (GET_OPCODE(ie) == OP_NOT) {
|
if (GET_OPCODE(ie) == OP_NOT) {
|
||||||
fs->pc--; /* remove previous OP_NOT */
|
fs->pc--; /* remove previous OP_NOT */
|
||||||
return condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond);
|
return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);
|
||||||
}
|
}
|
||||||
/* else go through */
|
/* else go through */
|
||||||
}
|
}
|
||||||
discharge2anyreg(fs, e);
|
discharge2anyreg(fs, e);
|
||||||
freeexp(fs, e);
|
freeexp(fs, e);
|
||||||
return condjump(fs, OP_TEST, NO_REG, e->info, cond);
|
return condjump(fs, OP_TESTSET, NO_REG, e->info, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -597,6 +604,8 @@ static void codenot (FuncState *fs, expdesc *e) {
|
|||||||
}
|
}
|
||||||
/* interchange true and false lists */
|
/* interchange true and false lists */
|
||||||
{ int temp = e->f; e->f = e->t; e->t = temp; }
|
{ int temp = e->f; e->f = e->t; e->t = temp; }
|
||||||
|
removevalues(fs, e->f);
|
||||||
|
removevalues(fs, e->t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
3
lcode.h
3
lcode.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lcode.h,v 1.43 2005/04/25 19:24:10 roberto Exp roberto $
|
** $Id: lcode.h,v 1.44 2005/05/20 15:53:42 roberto Exp $
|
||||||
** Code generator for Lua
|
** Code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -65,6 +65,7 @@ LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);
|
|||||||
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);
|
||||||
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
|
LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);
|
||||||
LUAI_FUNC int luaK_jump (FuncState *fs);
|
LUAI_FUNC int luaK_jump (FuncState *fs);
|
||||||
|
LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
|
||||||
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
|
LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
|
||||||
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
|
LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
|
||||||
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
|
LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lopcodes.c,v 1.33 2005/05/04 20:42:28 roberto Exp roberto $
|
** $Id: lopcodes.c,v 1.34 2005/05/20 15:53:42 roberto Exp $
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -43,6 +43,7 @@ const char *const luaP_opnames[NUM_OPCODES+1] = {
|
|||||||
"LT",
|
"LT",
|
||||||
"LE",
|
"LE",
|
||||||
"TEST",
|
"TEST",
|
||||||
|
"TESTSET",
|
||||||
"CALL",
|
"CALL",
|
||||||
"TAILCALL",
|
"TAILCALL",
|
||||||
"RETURN",
|
"RETURN",
|
||||||
@ -87,7 +88,8 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
|
|||||||
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
|
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */
|
||||||
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
|
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */
|
||||||
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
|
,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */
|
||||||
,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */
|
,opmode(1, 0, OpArgR, OpArgU, iABC) /* OP_TEST */
|
||||||
|
,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */
|
||||||
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
|
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */
|
||||||
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
|
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */
|
||||||
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
|
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lopcodes.h,v 1.120 2005/05/20 15:53:42 roberto Exp roberto $
|
** $Id: lopcodes.h,v 1.121 2005/06/06 13:30:25 roberto Exp $
|
||||||
** Opcodes for Lua virtual machine
|
** Opcodes for Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -186,7 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
|||||||
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
||||||
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
||||||
|
|
||||||
OP_TEST,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
|
||||||
|
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
||||||
|
|
||||||
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lparser.c,v 2.33 2005/08/22 18:54:32 roberto Exp roberto $
|
** $Id: lparser.c,v 2.34 2005/08/24 17:41:10 roberto Exp $
|
||||||
** Lua Parser
|
** Lua Parser
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -375,7 +375,7 @@ static void close_func (LexState *ls) {
|
|||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
Proto *f = fs->f;
|
Proto *f = fs->f;
|
||||||
removevars(ls, 0);
|
removevars(ls, 0);
|
||||||
luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */
|
luaK_ret(fs, 0, 0); /* final return */
|
||||||
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
|
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
|
||||||
f->sizecode = fs->pc;
|
f->sizecode = fs->pc;
|
||||||
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
|
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
|
||||||
@ -981,7 +981,6 @@ static int cond (LexState *ls) {
|
|||||||
expdesc v;
|
expdesc v;
|
||||||
expr(ls, &v); /* read condition */
|
expr(ls, &v); /* read condition */
|
||||||
if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
|
if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */
|
||||||
else if (v.k == VK) v.k = VTRUE; /* 'trues' too */
|
|
||||||
luaK_goiftrue(ls->fs, &v);
|
luaK_goiftrue(ls->fs, &v);
|
||||||
return v.f;
|
return v.f;
|
||||||
}
|
}
|
||||||
@ -1279,7 +1278,7 @@ static void retstat (LexState *ls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);
|
luaK_ret(fs, first, nret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
8
lvm.c
8
lvm.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lvm.c,v 2.52 2005/08/22 18:54:49 roberto Exp roberto $
|
** $Id: lvm.c,v 2.53 2005/08/24 16:15:49 roberto Exp $
|
||||||
** Lua virtual machine
|
** Lua virtual machine
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -592,6 +592,12 @@ void luaV_execute (lua_State *L, int nexeccalls) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_TEST: {
|
case OP_TEST: {
|
||||||
|
if (l_isfalse(ra) == GETARG_C(i)) pc++;
|
||||||
|
else
|
||||||
|
dojump(L, pc, GETARG_sBx(*pc) + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case OP_TESTSET: {
|
||||||
TValue *rb = RB(i);
|
TValue *rb = RB(i);
|
||||||
if (l_isfalse(rb) == GETARG_C(i)) pc++;
|
if (l_isfalse(rb) == GETARG_C(i)) pc++;
|
||||||
else {
|
else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user