private static void FreeReg(FuncState fs, int reg) { if (!Instruction.ISK(reg) && reg >= fs.NumActVar) { fs.FreeReg--; Utl.Assert(reg == fs.FreeReg); } }
ThreadStatus ILuaAPI.PCallK(int numArgs, int numResults, int errFunc, int context, CSharpFunctionDelegate continueFunc) { Utl.ApiCheck(continueFunc == null || !CI.IsLua, "cannot use continuations inside hooks"); Utl.ApiCheckNumElems(this, numArgs + 1); Utl.ApiCheck(Status == ThreadStatus.LUA_OK, "cannot do calls on non-normal thread"); CheckResults(numArgs, numResults); int func; if (errFunc == 0) { func = 0; } else { StkId addr; if (!Index2Addr(errFunc, out addr)) { Utl.InvalidIndex(); } func = addr.Index; } ThreadStatus status; CallS c = new CallS(); c.L = this; c.FuncIndex = Top.Index - (numArgs + 1); if (continueFunc == null || NumNonYieldable > 0) // no continuation or no yieldable? { c.NumResults = numResults; status = D_PCall(DG_F_Call, ref c, c.FuncIndex, func); } else { int ciIndex = CI.Index; CI.ContinueFunc = continueFunc; CI.Context = context; CI.ExtraIndex = c.FuncIndex; CI.OldAllowHook = AllowHook; CI.OldErrFunc = ErrFunc; ErrFunc = func; CI.CallStatus |= CallStatus.CIST_YPCALL; D_Call(Stack[c.FuncIndex], numResults, true); CallInfo ci = BaseCI[ciIndex]; ci.CallStatus &= ~CallStatus.CIST_YPCALL; ErrFunc = ci.OldErrFunc; status = ThreadStatus.LUA_OK; } AdjustResults(numResults); return(status); }
private StkId NewTableKey(ref TValue k) { if (k.TtIsNil()) { L.G_RunError("table index is nil"); } if (k.TtIsNumber() && System.Double.IsNaN(k.NValue)) { L.G_RunError("table index is NaN"); } var mp = GetHashNode(ref k); // if main position is taken if (!mp.Val.V.TtIsNil() || mp == DummyNode) { var n = GetFreePos(); if (n == null) { Rehash(ref k); var cell = Get(ref k); if (cell != TheNilValue) { return(cell); } return(NewTableKey(ref k)); } Utl.Assert(n != DummyNode); var othern = GetHashNode(ref mp.Key.V); // is colliding node out of its main position? if (othern != mp) { while (othern.Next != mp) { othern = othern.Next; } othern.Next = n; n.CopyFrom(mp); mp.Next = null; mp.Val.V.SetNilValue(); } // colliding node is in its own main position else { n.Next = mp.Next; mp.Next = n; mp = n; } } mp.Key.V.SetObj(ref k); Utl.Assert(mp.Val.V.TtIsNil()); return(mp.Val); }
private static void InvertJump(FuncState fs, ExpDesc e) { InstructionPtr pc = GetJumpControl(fs, e.Info); Utl.Assert(TestTMode(pc.Value.GET_OPCODE()) && pc.Value.GET_OPCODE() != OpCode.OP_TESTSET && pc.Value.GET_OPCODE() != OpCode.OP_TEST); pc.Value = pc.Value.SETARG_A(pc.Value.GETARG_A() == 0 ? 1 : 0); }
private static void Discharge2Reg(FuncState fs, ExpDesc e, int reg) { DischargeVars(fs, e); switch (e.Kind) { case ExpKind.VNIL: { CodeNil(fs, reg, 1); break; } case ExpKind.VFALSE: case ExpKind.VTRUE: { CodeABC(fs, OpCode.OP_LOADBOOL, reg, (e.Kind == ExpKind.VTRUE ? 1 : 0), 0); break; } case ExpKind.VK: { CodeK(fs, reg, e.Info); break; } case ExpKind.VKNUM: { CodeK(fs, reg, NumberK(fs, e.NumberValue)); break; } case ExpKind.VRELOCABLE: { InstructionPtr pi = fs.GetCode(e); pi.Value = pi.Value.SETARG_A(reg); break; } case ExpKind.VNONRELOC: { if (reg != e.Info) { CodeABC(fs, OpCode.OP_MOVE, reg, e.Info, 0); } break; } default: { Utl.Assert(e.Kind == ExpKind.VVOID || e.Kind == ExpKind.VJMP); return; // nothing to do... } } e.Info = reg; e.Kind = ExpKind.VNONRELOC; }
private void V_GetTable(StkId t, StkId key, StkId val) { for (int loop = 0; loop < MAXTAGLOOP; ++loop) { StkId tmObj; if (t.V.TtIsTable()) { var tbl = t.V.HValue(); var res = tbl.Get(ref key.V); if (!res.V.TtIsNil()) { val.V.SetObj(ref res.V); return; } tmObj = FastTM(tbl.MetaTable, TMS.TM_INDEX); if (tmObj == null) { val.V.SetObj(ref res.V); return; } } else if (t.V.Tt == (int)LuaType.LUA_TLIGHTUSERDATA) { TValue res; if (Utl.GetLightUserDataPropValue(t.V, key.V, out res)) { val.V.SetObj(ref res); } else { G_RunError(res.SValue()); } return; // else will try the tag method } else { tmObj = T_GetTMByObj(ref t.V, TMS.TM_INDEX); if (tmObj.V.TtIsNil()) { G_SimpleTypeError(ref t.V, "index"); } } if (tmObj.V.TtIsFunction()) { CallTM(ref tmObj.V, ref t.V, ref key.V, val, true); return; } t = tmObj; } G_RunError("loop in gettable"); }
void ILuaAPI.Copy(int fromIndex, int toIndex) { StkId fr; if (!Index2Addr(fromIndex, out fr)) { Utl.InvalidIndex(); } MoveTo(fr, toIndex); }
public static int CodeABx(FuncState fs, OpCode op, int a, uint bc) { var mode = OpCodeInfo.GetMode(op); Utl.Assert(mode.OpMode == OpMode.iABx || mode.OpMode == OpMode.iAsBx); Utl.Assert(mode.CMode == OpArgMask.OpArgN); Utl.Assert(a < Instruction.MAXARG_A & bc <= Instruction.MAXARG_Bx); return(Code(fs, Instruction.CreateABx(op, a, bc))); }
private void V_Concat(int total) { Utl.Assert(total >= 2); do { var top = Top; int n = 2; var lhs = Stack[top.Index - 2]; var rhs = Stack[top.Index - 1]; if (!(lhs.V.TtIsString() || lhs.V.TtIsNumber()) || !ToString(ref rhs.V)) { if (!CallBinTM(lhs, rhs, lhs, TMS.TM_CONCAT)) { G_ConcatError(lhs, rhs); } } else if (rhs.V.SValue().Length == 0) { ToString(ref lhs.V); } else if (lhs.V.TtIsString() && lhs.V.SValue().Length == 0) { lhs.V.SetObj(ref rhs.V); } else { StringBuilder sb = new StringBuilder(); n = 0; for ( ; n < total; ++n) { var cur = Stack[top.Index - (n + 1)]; if (cur.V.TtIsString()) { sb.Insert(0, cur.V.SValue()); } else if (cur.V.TtIsNumber()) { sb.Insert(0, cur.V.NValue.ToString()); } else { break; } } var dest = Stack[top.Index - n]; dest.V.SetSValue(sb.ToString()); } total -= n - 1; Top = Stack[Top.Index - (n - 1)]; } while(total > 1); }
private void MoveTo(StkId fr, int index) { StkId to; if (!Index2Addr(index, out to)) { Utl.InvalidIndex(); } to.V.SetObj(ref fr.V); }
private bool Index2Addr(int index, out StkId addr) { CallInfo ci = CI; if (index > 0) { var addrIndex = ci.FuncIndex + index; Utl.ApiCheck(index <= ci.TopIndex - (ci.FuncIndex + 1), "unacceptable index"); if (addrIndex >= Top.Index) { addr = default(StkId); return(false); } addr = Stack[addrIndex]; return(true); } else if (index > LuaDef.LUA_REGISTRYINDEX) { Utl.ApiCheck(index != 0 && -index <= Top.Index - (ci.FuncIndex + 1), "invalid index"); addr = Stack[Top.Index + index]; return(true); } else if (index == LuaDef.LUA_REGISTRYINDEX) { addr = G.Registry; return(true); } // upvalues else { index = LuaDef.LUA_REGISTRYINDEX - index; Utl.ApiCheck(index <= LuaLimits.MAXUPVAL + 1, "upvalue index too large"); var func = Stack[ci.FuncIndex]; Utl.Assert(func.V.TtIsFunction()); if (func.V.ClIsLcsClosure()) { addr = default(StkId); return(false); } Utl.Assert(func.V.ClIsCsClosure()); var clcs = func.V.ClCsValue(); if (index > clcs.Upvals.Length) { addr = default(StkId); return(false); } addr = clcs.Upvals[index - 1]; return(true); } }
public static void PatchList(FuncState fs, int list, int target) { if (target == fs.Pc) { PatchToHere(fs, list); } else { Utl.Assert(target < fs.Pc); PatchListAux(fs, list, target, NO_REG, target); } }
private int CeilLog2(int x) { Utl.Assert(x > 0); int l = 0; x--; while (x >= 256) { l += 8; x >>= 8; } return(l + Log2_[x]); }
void ILuaAPI.PushValue(int index) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } Top.V.SetObj(ref addr.V); ApiIncrTop(); }
void ILuaAPI.SetField(int index, string key) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } StkId.inc(ref Top).V.SetSValue(key); V_SetTable(addr, Stack[Top.Index - 1], Stack[Top.Index - 2]); Top = Stack[Top.Index - 2]; }
void ILuaAPI.GetTable(int index) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } var below = Stack[Top.Index - 1]; V_GetTable(addr, below, below); }
void ILuaAPI.Concat(int n) { Utl.ApiCheckNumElems(this, n); if (n >= 2) { V_Concat(n); } else if (n == 0) { Top.V.SetSValue(""); ApiIncrTop(); } }
void ILuaAPI.Len(int index) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } V_ObjLen(Top, addr); ApiIncrTop(); }
private static void FixJump(FuncState fs, int pc, int dest) { Instruction jmp = fs.Proto.Code[pc]; int offset = dest - (pc + 1); Utl.Assert(dest != NO_JUMP); if (Math.Abs(offset) > Instruction.MAXARG_sBx) { fs.Lexer.SyntaxError("control structure too long"); } jmp.SETARG_sBx(offset); fs.Proto.Code[pc] = jmp; }
public static void PatchClose(FuncState fs, int list, int level) { level++; // argument is +1 to reserve 0 as non-op while (list != NO_JUMP) { int next = GetJump(fs, list); var pi = new InstructionPtr(fs.Proto.Code, list);; Utl.Assert(pi.Value.GET_OPCODE() == OpCode.OP_JMP && (pi.Value.GETARG_A() == 0 || pi.Value.GETARG_A() >= level)); pi.Value = pi.Value.SETARG_A(level); list = next; } }
bool ILuaAPI.SetMetaTable(int index) { Utl.ApiCheckNumElems(this, 1); StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } var below = Stack[Top.Index - 1]; LuaTable mt; if (below.V.TtIsNil()) { mt = null; } else { Utl.ApiCheck(below.V.TtIsTable(), "table expected"); mt = below.V.HValue(); } switch (addr.V.Tt) { case (int)LuaType.LUA_TTABLE: { var tbl = addr.V.HValue(); tbl.MetaTable = mt; break; } case (int)LuaType.LUA_TUSERDATA: { var ud = addr.V.RawUValue(); ud.MetaTable = mt; break; } default: { G.MetaTables[addr.V.Tt] = mt; break; } } Top = Stack[Top.Index - 1]; return(true); }
private static bool ConstFolding(OpCode op, ExpDesc e1, ExpDesc e2) { if (!IsNumeral(e1) || !IsNumeral(e2)) { return(false); } if ((op == OpCode.OP_DIV || op == OpCode.OP_MOD) && e2.NumberValue == 0.0) { return(false); // do not attempt to divide by 0 } switch (op) { case OpCode.OP_ADD: e1.NumberValue = e1.NumberValue + e2.NumberValue; break; case OpCode.OP_SUB: e1.NumberValue = e1.NumberValue - e2.NumberValue; break; case OpCode.OP_MUL: e1.NumberValue = e1.NumberValue * e2.NumberValue; break; case OpCode.OP_DIV: e1.NumberValue = e1.NumberValue / e2.NumberValue; break; case OpCode.OP_MOD: e1.NumberValue = Utl.LuaMod(e1.NumberValue, e2.NumberValue); break; case OpCode.OP_POW: e1.NumberValue = Math.Pow(e1.NumberValue, e2.NumberValue); break; case OpCode.OP_UNM: e1.NumberValue = -e1.NumberValue; break; default: throw new Exception("ConstFolding unknown op" + op); } return(true); }
void ILuaAPI.RawSet(int index) { Utl.ApiCheckNumElems(this, 2); StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } Utl.ApiCheck(addr.V.TtIsTable(), "table expected"); var tbl = addr.V.HValue(); tbl.Set(ref Stack[Top.Index - 2].V, ref Stack[Top.Index - 1].V); Top = Stack[Top.Index - 2]; }
public void RawSetI(int index, int n) { Utl.ApiCheckNumElems(this, 1); StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } Utl.ApiCheck(addr.V.TtIsTable(), "table expected"); var tbl = addr.V.HValue(); tbl.SetInt(n, ref Stack[Top.Index - 1].V); Top = Stack[Top.Index - 1]; }
void ILuaAPI.GetField(int index, string key) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } Top.V.SetSValue(key); var below = Top; ApiIncrTop(); V_GetTable(addr, below, below); }
private double _ReadNumber() { var expo = new char[] { 'E', 'e' }; Utl.Assert(_CurrentIsDigit()); var first = Current; _SaveAndNext(); if (first == '0' && (Current == 'X' || Current == 'x')) { expo = new char[] { 'P', 'p' }; _SaveAndNext(); } for (;;) { if (Current == expo[0] || Current == expo[1]) { _SaveAndNext(); if (Current == '+' || Current == '-') { _SaveAndNext(); } } if (_CurrentIsXDigit() || Current == '.') { _SaveAndNext(); } else { break; } } double ret; var str = _GetSavedString(); if (LuaState.O_Str2Decimal(str, out ret)) { return(ret); } else { _Error("malformed number: " + str); return(0.0); } }
// do the work for `lua_resume' in protected mode private void Resume(int firstArg) { int numCSharpCalls = NumCSharpCalls; CallInfo ci = CI; if (numCSharpCalls >= LuaLimits.LUAI_MAXCCALLS) { ResumeError("C stack overflow", firstArg); } if (Status == ThreadStatus.LUA_OK) // may be starting a coroutine { if (ci.Index > 0) // not in base level { ResumeError("cannot resume non-suspended coroutine", firstArg); } if (!D_PreCall(Stack[firstArg - 1], LuaDef.LUA_MULTRET)) // Lua function? { V_Execute(); // call it } } else if (Status != ThreadStatus.LUA_YIELD) { ResumeError("cannot resume dead coroutine", firstArg); } else // resume from previous yield { Status = ThreadStatus.LUA_OK; ci.FuncIndex = ci.ExtraIndex; if (ci.IsLua) // yielded inside a hook? { V_Execute(); // just continue running Lua code } else // `common' yield { if (ci.ContinueFunc != null) { ci.Status = ThreadStatus.LUA_YIELD; // `default' status ci.CallStatus |= CallStatus.CIST_YIELDED; int n = ci.ContinueFunc(this); // call continuation Utl.ApiCheckNumElems(this, n); firstArg = Top.Index - n; // yield results come from continuation } D_PosCall(firstArg); } Unroll(); } Utl.Assert(numCSharpCalls == NumCSharpCalls); }
void ILuaAPI.RawGetI(int index, int n) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.ApiCheck(false, "table expected"); } var tbl = addr.V.HValue(); Utl.ApiCheck(tbl != null, "table expected"); Top.V.SetObj(ref tbl.GetInt(n).V); ApiIncrTop(); }
void ILuaAPI.SetTable(int index) { StkId addr; Utl.ApiCheckNumElems(this, 2); if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } var key = Stack[Top.Index - 2]; var val = Stack[Top.Index - 1]; V_SetTable(addr, key, val); Top = Stack[Top.Index - 2]; }
void ILuaAPI.Remove(int index) { StkId addr; if (!Index2Addr(index, out addr)) { Utl.InvalidIndex(); } for (int i = addr.Index + 1; i < Top.Index; ++i) { Stack[i - 1].V.SetObj(ref Stack[i].V); } Top = Stack[Top.Index - 1]; }