private static int patchtestreg(FuncState fs, int node, int reg) { InstructionPtr i = getjumpcontrol(fs, node); if (GET_OPCODE(i[0]) != OpCode.OP_TESTSET) { return(0); /* cannot patch other instructions */ } if (reg != NO_REG && reg != GETARG_B(i[0])) { SETARG_A(i, reg); } else /* no register to put value or register already has the value */ { i[0] = (uint)CREATE_ABC(OpCode.OP_TEST, GETARG_B(i[0]), 0, GETARG_C(i[0])); } return(1); }
//#define Protect(x) { L.savedpc = pc; {x;}; base = L.base_; } public static void arith_op(LuaState L, op_delegate op, TMS tm, StkId base_, Instruction i, TValue[] k, StkId ra, InstructionPtr pc) { TValue rb = RKB(L, base_, i, k); TValue rc = RKC(L, base_, i, k); if (ttisnumber(rb) && ttisnumber(rc)) { lua_Number nb = nvalue(rb), nc = nvalue(rc); setnvalue(ra, op(nb, nc)); } else { //Protect( L.savedpc = InstructionPtr.Assign(pc); Arith(L, ra, rb, rc, tm); base_ = L.base_; //); } }
private static void traceexec(LuaState L, InstructionPtr pc) { lu_byte mask = L.hookmask; InstructionPtr oldpc = InstructionPtr.Assign(L.savedpc); L.savedpc = InstructionPtr.Assign(pc); if (((mask & LUA_MASKCOUNT) != 0) && (L.hookcount == 0)) { resethookcount(L); luaD_callhook(L, LUA_HOOKCOUNT, -1); } if ((mask & LUA_MASKLINE) != 0) { Proto p = ci_func(L.ci).l.p; int npc = pcRel(pc, p); int newline = getline(p, npc); /* call linehook when enter a new function, when jump back (loop), or when enter a new line */ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) luaD_callhook(L, LUA_HOOKLINE, newline); } }
public static int luaD_precall(LuaState L, StkId func, int nresults) { LClosure cl; ptrdiff_t funcr; if (!ttisfunction(func)) /* `func' is not a function? */ { func = tryfuncTM(L, func); /* check the `function' tag method */ } funcr = savestack(L, func); cl = clvalue(func).l; L.ci.savedpc = InstructionPtr.Assign(L.savedpc); if (cl.isC == 0) { /* Lua function? prepare its call */ CallInfo ci; StkId st, base_; Proto p = cl.p; luaD_checkstack(L, p.maxstacksize); func = restorestack(L, funcr); if (p.is_vararg == 0) { /* no varargs? */ base_ = L.stack[func + 1]; if (L.top > base_ + p.numparams) { L.top = base_ + p.numparams; } } else { /* vararg function */ int nargs = L.top - func - 1; base_ = adjust_varargs(L, p, nargs); func = restorestack(L, funcr); /* previous call may change the stack */ } ci = inc_ci(L); /* now `enter' new function */ ci.func = func; L.base_ = ci.base_ = base_; ci.top = L.base_ + p.maxstacksize; lua_assert(ci.top <= L.stack_last); L.savedpc = new InstructionPtr(p.code, 0); /* starting point */ ci.tailcalls = 0; ci.nresults = nresults; for (st = L.top; st < ci.top; StkId.inc(ref st)) { setnilvalue(st); } L.top = ci.top; if ((L.hookmask & LUA_MASKCALL) != 0) { InstructionPtr.inc(ref L._savedpc); /* hooks assume 'pc' is already incremented */ luaD_callhook(L, LUA_HOOKCALL, -1); InstructionPtr.dec(ref L._savedpc); /* correct 'pc' */ } return(PCRLUA); } else { /* if is a C function, call it */ CallInfo ci; int n; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ci = inc_ci(L); /* now `enter' new function */ ci.func = restorestack(L, funcr); L.base_ = ci.base_ = ci.func + 1; ci.top = L.top + LUA_MINSTACK; lua_assert(ci.top <= L.stack_last); ci.nresults = nresults; if ((L.hookmask & LUA_MASKCALL) != 0) { luaD_callhook(L, LUA_HOOKCALL, -1); } lua_unlock(L); n = curr_func(L).c.f(L); /* do the actual call */ lua_lock(L); if (n < 0) /* yielding? */ { return(PCRYIELD); } else { luaD_poscall(L, L.top - n); return(PCRC); } } }
public static void dojump(LuaState L, InstructionPtr pc, int i) { pc.pc += i; luai_threadyield(L); }
public static InstructionPtr Assign(InstructionPtr ptr) { if (ptr == null) return null; return new InstructionPtr(ptr.codes, ptr.pc); }
private static void fixjump(FuncState fs, int pc, int dest) { InstructionPtr jmp = new InstructionPtr(fs.f.code, pc); int offset = dest - (pc + 1); lua_assert(dest != NO_JUMP); if (Math.Abs(offset) > MAXARG_sBx) luaX_syntaxerror(fs.ls, "control structure too long"); SETARG_sBx(jmp, offset); }
public static OpCode GET_OPCODE(InstructionPtr i) { return GET_OPCODE(i[0]); }
public static int GETARG_sBx(InstructionPtr i) { return GETARG_sBx(i[0]); }
public static void SET_OPCODE(InstructionPtr i, OpCode opcode) { SET_OPCODE(ref i.codes[i.pc], opcode); }
public static int pcRel(InstructionPtr pc, Proto p) { Debug.Assert(pc.codes == p.code); return(pc.pc - 1); }
public static void luaV_execute(LuaState L, int nexeccalls) { LClosure cl; StkId base_; TValue[] k; /*const*/ InstructionPtr pc; reentry: /* entry point */ lua_assert(isLua(L.ci)); pc = InstructionPtr.Assign(L.savedpc); cl = clvalue(L.ci.func).l; base_ = L.base_; k = cl.p.k; /* main loop of interpreter */ for (; ;) { /*const*/ Instruction i = InstructionPtr.inc(ref pc)[0]; StkId ra; if (((L.hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) != 0) && (((--L.hookcount) == 0) || ((L.hookmask & LUA_MASKLINE) != 0))) { traceexec(L, pc); if (L.status == LUA_YIELD) { /* did hook yield? */ L.savedpc = new InstructionPtr(pc.codes, pc.pc - 1); return; } base_ = L.base_; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(L, base_, i); lua_assert(base_ == L.base_ && L.base_ == L.ci.base_); lua_assert(base_ <= L.top && ((L.top - L.stack) <= L.stacksize)); lua_assert(L.top == L.ci.top || (luaG_checkopenop(i) != 0)); //Dump(pc.pc, i); switch (GET_OPCODE(i)) { case OpCode.OP_MOVE: { setobjs2s(L, ra, RB(L, base_, i)); continue; } case OpCode.OP_LOADK: { setobj2s(L, ra, KBx(L, i, k)); continue; } case OpCode.OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i) != 0) { InstructionPtr.inc(ref pc); /* skip next instruction (if C) */ } continue; } case OpCode.OP_LOADNIL: { TValue rb = RB(L, base_, i); do { setnilvalue(StkId.dec(ref rb)); } while (rb >= ra); continue; } case OpCode.OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(L, ra, cl.upvals[b].v); continue; } case OpCode.OP_GETGLOBAL: { TValue g = new TValue(); TValue rb = KBx(L, i, k); sethvalue(L, g, cl.env); lua_assert(ttisstring(rb)); //Protect( L.savedpc = InstructionPtr.Assign(pc); luaV_gettable(L, g, rb, ra); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); continue; } case OpCode.OP_GETTABLE: { //Protect( L.savedpc = InstructionPtr.Assign(pc); luaV_gettable(L, RB(L, base_, i), RKC(L, base_, i, k), ra); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); continue; } case OpCode.OP_SETGLOBAL: { TValue g = new TValue(); sethvalue(L, g, cl.env); lua_assert(ttisstring(KBx(L, i, k))); //Protect( L.savedpc = InstructionPtr.Assign(pc); luaV_settable(L, g, KBx(L, i, k), ra); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); continue; } case OpCode.OP_SETUPVAL: { UpVal uv = cl.upvals[GETARG_B(i)]; setobj(L, uv.v, ra); luaC_barrier(L, uv, ra); continue; } case OpCode.OP_SETTABLE: { //Protect( L.savedpc = InstructionPtr.Assign(pc); luaV_settable(L, ra, RKB(L, base_, i, k), RKC(L, base_, i, k)); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); continue; } case OpCode.OP_NEWTABLE: { int b = GETARG_B(i); int c = GETARG_C(i); sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); //Protect( L.savedpc = InstructionPtr.Assign(pc); luaC_checkGC(L); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); continue; } case OpCode.OP_SELF: { StkId rb = RB(L, base_, i); setobjs2s(L, ra + 1, rb); //Protect( L.savedpc = InstructionPtr.Assign(pc); luaV_gettable(L, rb, RKC(L, base_, i, k), ra); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); continue; } case OpCode.OP_ADD: { arith_op(L, luai_numadd, TMS.TM_ADD, base_, i, k, ra, pc); continue; } case OpCode.OP_SUB: { arith_op(L, luai_numsub, TMS.TM_SUB, base_, i, k, ra, pc); continue; } case OpCode.OP_MUL: { arith_op(L, luai_nummul, TMS.TM_MUL, base_, i, k, ra, pc); continue; } case OpCode.OP_DIV: { arith_op(L, luai_numdiv, TMS.TM_DIV, base_, i, k, ra, pc); continue; } case OpCode.OP_MOD: { arith_op(L, luai_nummod, TMS.TM_MOD, base_, i, k, ra, pc); continue; } case OpCode.OP_POW: { arith_op(L, luai_numpow, TMS.TM_POW, base_, i, k, ra, pc); continue; } case OpCode.OP_UNM: { TValue rb = RB(L, base_, i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); setnvalue(ra, luai_numunm(nb)); } else { //Protect( L.savedpc = InstructionPtr.Assign(pc); Arith(L, ra, rb, rb, TMS.TM_UNM); base_ = L.base_; //); L.savedpc = InstructionPtr.Assign(pc); } continue; } case OpCode.OP_NOT: { int res = l_isfalse(RB(L, base_, i)) == 0 ? 0 : 1; /* next assignment may change this value */ setbvalue(ra, res); continue; } case OpCode.OP_LEN: { TValue rb = RB(L, base_, i); switch (ttype(rb)) { case LUA_TTABLE: { setnvalue(ra, (lua_Number)luaH_getn(hvalue(rb))); break; } case LUA_TSTRING: { setnvalue(ra, (lua_Number)tsvalue(rb).len); break; } default: { /* try metamethod */ //Protect( L.savedpc = InstructionPtr.Assign(pc); if (call_binTM(L, rb, luaO_nilobject, ra, TMS.TM_LEN) == 0) { luaG_typeerror(L, rb, "get length of"); } base_ = L.base_; //) break; } } continue; } case OpCode.OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); //Protect( L.savedpc = InstructionPtr.Assign(pc); luaV_concat(L, c - b + 1, c); luaC_checkGC(L); base_ = L.base_; //); setobjs2s(L, RA(L, base_, i), base_ + b); continue; } case OpCode.OP_JMP: { dojump(L, pc, GETARG_sBx(i)); continue; } case OpCode.OP_EQ: { TValue rb = RKB(L, base_, i, k); TValue rc = RKC(L, base_, i, k); //Protect( L.savedpc = InstructionPtr.Assign(pc); if (equalobj(L, rb, rc) == GETARG_A(i)) { dojump(L, pc, GETARG_sBx(pc[0])); } base_ = L.base_; //); InstructionPtr.inc(ref pc); continue; } case OpCode.OP_LT: { //Protect( L.savedpc = InstructionPtr.Assign(pc); if (luaV_lessthan(L, RKB(L, base_, i, k), RKC(L, base_, i, k)) == GETARG_A(i)) { dojump(L, pc, GETARG_sBx(pc[0])); } base_ = L.base_; //); InstructionPtr.inc(ref pc); continue; } case OpCode.OP_LE: { //Protect( L.savedpc = InstructionPtr.Assign(pc); if (lessequal(L, RKB(L, base_, i, k), RKC(L, base_, i, k)) == GETARG_A(i)) { dojump(L, pc, GETARG_sBx(pc[0])); } base_ = L.base_; //); InstructionPtr.inc(ref pc); continue; } case OpCode.OP_TEST: { if (l_isfalse(ra) != GETARG_C(i)) { dojump(L, pc, GETARG_sBx(pc[0])); } InstructionPtr.inc(ref pc); continue; } case OpCode.OP_TESTSET: { TValue rb = RB(L, base_, i); if (l_isfalse(rb) != GETARG_C(i)) { setobjs2s(L, ra, rb); dojump(L, pc, GETARG_sBx(pc[0])); } InstructionPtr.inc(ref pc); continue; } case OpCode.OP_CALL: { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) { L.top = ra + b; /* else previous instruction set top */ } L.savedpc = InstructionPtr.Assign(pc); switch (luaD_precall(L, ra, nresults)) { case PCRLUA: { nexeccalls++; goto reentry; /* restart luaV_execute over new Lua function */ } case PCRC: { /* it was a C function (`precall' called it); adjust results */ if (nresults >= 0) { L.top = L.ci.top; } base_ = L.base_; continue; } default: { return; /* yield */ } } } case OpCode.OP_TAILCALL: { int b = GETARG_B(i); if (b != 0) { L.top = ra + b; /* else previous instruction set top */ } L.savedpc = InstructionPtr.Assign(pc); lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); switch (luaD_precall(L, ra, LUA_MULTRET)) { case PCRLUA: { /* tail call: put new frame in place of previous one */ CallInfo ci = L.ci - 1; /* previous frame */ int aux; StkId func = ci.func; StkId pfunc = (ci + 1).func; /* previous function index */ if (L.openupval != null) { luaF_close(L, ci.base_); } L.base_ = ci.base_ = ci.func + (ci[1].base_ - pfunc); for (aux = 0; pfunc + aux < L.top; aux++) /* move frame down */ { setobjs2s(L, func + aux, pfunc + aux); } ci.top = L.top = func + aux; /* correct top */ lua_assert(L.top == L.base_ + clvalue(func).l.p.maxstacksize); ci.savedpc = InstructionPtr.Assign(L.savedpc); ci.tailcalls++; /* one more call lost */ CallInfo.dec(ref L.ci); /* remove new frame */ goto reentry; } case PCRC: { /* it was a C function (`precall' called it) */ base_ = L.base_; continue; } default: { return; /* yield */ } } } case OpCode.OP_RETURN: { int b = GETARG_B(i); if (b != 0) { L.top = ra + b - 1; } if (L.openupval != null) { luaF_close(L, base_); } L.savedpc = InstructionPtr.Assign(pc); b = luaD_poscall(L, ra); if (--nexeccalls == 0) /* was previous function running `here'? */ { return; /* no: return */ } else { /* yes: continue its execution */ if (b != 0) { L.top = L.ci.top; } lua_assert(isLua(L.ci)); lua_assert(GET_OPCODE(L.ci.savedpc[-1]) == OpCode.OP_CALL); goto reentry; } } case OpCode.OP_FORLOOP: { lua_Number step = nvalue(ra + 2); lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ lua_Number limit = nvalue(ra + 1); if (luai_numlt(0, step) ? luai_numle(idx, limit) : luai_numle(limit, idx)) { dojump(L, pc, GETARG_sBx(i)); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra + 3, idx); /* ...and external index */ } continue; } case OpCode.OP_FORPREP: { TValue init = ra; TValue plimit = ra + 1; TValue pstep = ra + 2; L.savedpc = InstructionPtr.Assign(pc); /* next steps may throw errors */ if (tonumber(ref init, ra) == 0) { luaG_runerror(L, LUA_QL("for") + " initial value must be a number"); } else if (tonumber(ref plimit, ra + 1) == 0) { luaG_runerror(L, LUA_QL("for") + " limit must be a number"); } else if (tonumber(ref pstep, ra + 2) == 0) { luaG_runerror(L, LUA_QL("for") + " step must be a number"); } setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); dojump(L, pc, GETARG_sBx(i)); continue; } case OpCode.OP_TFORLOOP: { StkId cb = ra + 3; /* call base */ setobjs2s(L, cb + 2, ra + 2); setobjs2s(L, cb + 1, ra + 1); setobjs2s(L, cb, ra); L.top = cb + 3; /* func. + 2 args (state and index) */ //Protect( L.savedpc = InstructionPtr.Assign(pc); luaD_call(L, cb, GETARG_C(i)); base_ = L.base_; //); L.top = L.ci.top; cb = RA(L, base_, i) + 3; /* previous call may change the stack */ if (!ttisnil(cb)) { /* continue loop? */ setobjs2s(L, cb - 1, cb); /* save control variable */ dojump(L, pc, GETARG_sBx(pc[0])); /* jump back */ } InstructionPtr.inc(ref pc); continue; } case OpCode.OP_SETLIST: { int n = GETARG_B(i); int c = GETARG_C(i); int last; Table h; if (n == 0) { n = cast_int(L.top - ra) - 1; L.top = L.ci.top; } if (c == 0) { c = cast_int(pc[0]); InstructionPtr.inc(ref pc); } runtime_check(L, ttistable(ra)); h = hvalue(ra); last = ((c - 1) * LFIELDS_PER_FLUSH) + n; if (last > h.sizearray) /* needs more space? */ { luaH_resizearray(L, h, last); /* pre-alloc it at once */ } for (; n > 0; n--) { TValue val = ra + n; setobj2t(L, luaH_setnum(L, h, last--), val); luaC_barriert(L, h, val); } continue; } case OpCode.OP_CLOSE: { luaF_close(L, ra); continue; } case OpCode.OP_CLOSURE: { Proto p; Closure ncl; int nup, j; p = cl.p.p[GETARG_Bx(i)]; nup = p.nups; ncl = luaF_newLclosure(L, nup, cl.env); ncl.l.p = p; for (j = 0; j < nup; j++, InstructionPtr.inc(ref pc)) { if (GET_OPCODE(pc[0]) == OpCode.OP_GETUPVAL) { ncl.l.upvals[j] = cl.upvals[GETARG_B(pc[0])]; } else { lua_assert(GET_OPCODE(pc[0]) == OpCode.OP_MOVE); ncl.l.upvals[j] = luaF_findupval(L, base_ + GETARG_B(pc[0])); } } setclvalue(L, ra, ncl); //Protect( L.savedpc = InstructionPtr.Assign(pc); luaC_checkGC(L); base_ = L.base_; //); continue; } case OpCode.OP_VARARG: { int b = GETARG_B(i) - 1; int j; CallInfo ci = L.ci; int n = cast_int(ci.base_ - ci.func) - cl.p.numparams - 1; if (b == LUA_MULTRET) { //Protect( L.savedpc = InstructionPtr.Assign(pc); luaD_checkstack(L, n); base_ = L.base_; //); ra = RA(L, base_, i); /* previous call may change the stack */ b = n; L.top = ra + n; } for (j = 0; j < b; j++) { if (j < n) { setobjs2s(L, ra + j, ci.base_ - n + j); } else { setnilvalue(ra + j); } } continue; } case OpCode.OP_RSHIFT: arith_op(L, luai_numrshift, TMS.TM_RSHIFT, base_, i, k, ra, pc); continue; case OpCode.OP_LSHIFT: arith_op(L, luai_numlshift, TMS.TM_LSHIFT, base_, i, k, ra, pc); continue; case OpCode.OP_BITAND: arith_op(L, luai_numbitand, TMS.TM_BITAND, base_, i, k, ra, pc); continue; case OpCode.OP_BITOR: arith_op(L, luai_numbitor, TMS.TM_BITOR, base_, i, k, ra, pc); continue; } } }
public static void SETARG_A(InstructionPtr i, int u) { i[0] = (Instruction)((i[0] & MASK0(SIZE_A, POS_A)) | ((u << POS_A) & MASK1(SIZE_A, POS_A))); }
public static void SETARG_Bx(InstructionPtr i, int b) { i[0] = (Instruction)((i[0] & MASK0(SIZE_Bx, POS_Bx)) | ((b << POS_Bx) & MASK1(SIZE_Bx, POS_Bx))); }
public static void SETARG_sBx(InstructionPtr i, int b) { SETARG_Bx(i, b + MAXARG_sBx); }
public static int GETARG_sBx(InstructionPtr i) { return(GETARG_sBx(i[0])); }
public static void luaK_nil(FuncState fs, int from, int n) { InstructionPtr previous; if (fs.pc > fs.lasttarget) { /* no jumps to current position? */ if (fs.pc == 0) { /* function start? */ if (from >= fs.nactvar) return; /* positions are already clean */ } else { previous = new InstructionPtr(fs.f.code, fs.pc - 1); if (GET_OPCODE(previous) == OpCode.OP_LOADNIL) { int pfrom = GETARG_A(previous); int pto = GETARG_B(previous); if (pfrom <= from && from <= pto + 1) { /* can connect both? */ if (from + n - 1 > pto) SETARG_B(previous, from + n - 1); return; } } } } luaK_codeABC(fs, OpCode.OP_LOADNIL, from, from + n - 1, 0); /* else no optimization */ }
public static OpCode GET_OPCODE(InstructionPtr i) { return(GET_OPCODE(i[0])); }
private static InstructionPtr getjumpcontrol(FuncState fs, int pc) { InstructionPtr pi = new InstructionPtr(fs.f.code, pc); if (pc >= 1 && (testTMode(GET_OPCODE(pi[-1])) != 0)) return new InstructionPtr(pi.codes, pi.pc - 1); else return new InstructionPtr(pi.codes, pi.pc); }
public static int pcRel(InstructionPtr pc, Proto p) { Debug.Assert(pc.codes == p.code); return pc.pc - 1; }
public static InstructionPtr dec(ref InstructionPtr ptr) { InstructionPtr result = new InstructionPtr(ptr.codes, ptr.pc); ptr.pc--; return result; }
static int gettablescope(LuaState L, TValue ra, TValue rb, InstructionPtr pc, LClosure cl, StkId pbase) { /* Look for closest containing "o {....}" where o has a __scope metamethod. */ StkId base_ = pbase; InstructionPtr pi; TValue tm = null; int previousIndex = pc.pc; for (pi = new InstructionPtr(pc.codes, pc.pc); ; pi.pc++) { /* Search forward for end of any "o {....}". Note: "o {....}" is terminated by (NEWTABLE,CALL) for empty table (SETLIST,CALL) for table with array part or "..." (SETTABLE,CALL) for table with hash part only */ if (pi.pc >= /*cl.p.code + */cl.p.sizecode)// || pi.pc >= pi.codes.Length) break; if (GET_OPCODE(pi.codes[pi.pc]) == OpCode.OP_CALL && (GET_OPCODE(pi.codes[pi.pc - 1]) == OpCode.OP_SETLIST || GET_OPCODE(pi.codes[pi.pc - 1]) == OpCode.OP_SETTABLE)) { /* Determine whether this "o {....}" contains the GETGLOBAL by searching for start of this "o {....}", which is implied by condition RA(NEWTABLE) == RA(SETLIST or SETTABLE). */ InstructionPtr pi2; bool is_containing = false; for (pi2 = new InstructionPtr(pi.codes, pi.pc); ; pi2.pc--) { lua_assert(pi2.pc >= /*cl.p.code*/cl.p.sizecode); if (GET_OPCODE(pi2.codes[pi2.pc]) == OpCode.OP_NEWTABLE && RA(L, base_, pi2.codes[pi2.pc]) == RA(L, base_, pi.codes[pi.pc - 1])) { is_containing = (pi2 < pc); break; } } /* Search complete if o has __scope metamethod (tm). */ if (is_containing && !ttisnil(tm = luaT_gettmbyobj(L, RA(L, base_, pi.codes[pi.pc]), TMS.TM_SCOPE))) { break; } } //Console.WriteLine(pi.pc); } /* pi */ pc.pc = previousIndex; /* Lookup key first in __scope (if available). Found if non-nil. */ if (tm != null && !ttisnil(tm)) { luaV_gettable(L, tm, rb, ra); if (!ttisnil(ra)) { //Console.WriteLine("Found __scope object!"); return 1; } } return 0; }