#include <stdio.h>
#include <math.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
const char *const code = " \
local t = setmetatable({}, { \
__le = function(...) \
print(...) \
return true \
end \
}) \
co = coroutine.create(function(...) \
print(\"le:\", 2 <= t) \
end) \
return co";
static void hook(lua_State *L, lua_Debug *ar)
{
lua_yield(L, 0);
}
int main(int argc, const char * argv[]) {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, code);
lua_State* co = lua_tothread(L, -1);
lua_sethook(co, hook, LUA_MASKLINE, 0);
for (;;) {
if (lua_resume(co, L, 0) != LUA_YIELD) break;
}
return 0;
}
OUTPUT:
2 table: 0x10010a010
le: false
-------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <math.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
const char *const code = " \
local t = setmetatable({}, { \
__le = function(...) \
print(...) \
return true \
end \
}) \
co = coroutine.create(function(...) \
print(\"le:\", 2 <= t) \
end) \
return co";
static void hook(lua_State *L, lua_Debug *ar)
{
//lua_yield(L, 0);
}
int main(int argc, const char * argv[]) {
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, code);
lua_State* co = lua_tothread(L, -1);
lua_sethook(co, hook, LUA_MASKLINE, 0);
for (;;) {
if (lua_resume(co, L, 0) != LUA_YIELD) break;
}
return 0;
}
OUTPUT:
2 table: 0x10010a010
le: true
-------------------------------------------------------------------------------------------------------------
it has different result when call or not call 'lua_yield' in 'hook' fun, i think there is a bug in when finish execution of an opcode(OP_LE) interrupted by an yield.
void luaV_finishOp (lua_State *L) {
CallInfo *ci = L->ci;
StkId base = ci->u.l.base;
Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */
OpCode op = GET_OPCODE(inst);
switch (op) { /* finish its execution */
......
case OP_LE: case OP_LT: case OP_EQ: {
int res = !l_isfalse(L->top - 1);
L->top--;
/* metamethod should not be called when operand is K */
lua_assert(!ISK(GETARG_B(inst)));
if (op == OP_LE && /* "<=" using "<" instead? */
ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
res = !res; /* invert result */
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
if (res != GETARG_A(inst)) /* condition failed? */
ci->u.l.savedpc++; /* skip jump instruction */
break;
}
......
in func luaV_finishOp, i think it is necessary to invert result when both R(B) and R(C) has no meta method 'TM_LE':
if (op == OP_LE && /* "<=" using "<" instead? */
ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)) &&
ttisnil(luaT_gettmbyobj(L, base + GETARG_C(inst), TM_LE)))
res = !res; /* invert result */