void ILuaAPI.CallK(int numArgs, int numResults, 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); var func = Stack[Top.Index - (numArgs + 1)]; // need to prepare continuation? if (continueFunc != null && NumNonYieldable == 0) { CI.ContinueFunc = continueFunc; CI.Context = context; D_Call(func, numResults, true); } // no continuation or no yieldable else { D_Call(func, numResults, false); } AdjustResults(numResults); }
private void ApiIncrTop() { StkId.inc(ref Top); // ULDebug.Log( "[ApiIncrTop] ==== Top.Index:" + Top.Index ); // ULDebug.Log( "[ApiIncrTop] ==== CI.Top.Index:" + CI.Top.Index ); Utl.ApiCheck(Top.Index <= CI.TopIndex, "stack overflow"); }
bool ILuaAPI.Compare(int index1, int index2, LuaEq op) { StkId addr1; if (!Index2Addr(index1, out addr1)) { Utl.InvalidIndex(); } StkId addr2; if (!Index2Addr(index2, out addr2)) { Utl.InvalidIndex(); } switch (op) { case LuaEq.LUA_OPEQ: return(EqualObj(ref addr1.V, ref addr2.V, false)); case LuaEq.LUA_OPLT: return(V_LessThan(addr1, addr2)); case LuaEq.LUA_OPLE: return(V_LessEqual(addr1, addr2)); default: Utl.ApiCheck(false, "invalid option"); return(false); } }
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 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); } }
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); }
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.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.SetTop(int index) { if (index >= 0) { Utl.ApiCheck(index <= StackLast - (CI.FuncIndex + 1), "new top too large"); int newTop = CI.FuncIndex + 1 + index; for (int i = Top.Index; i < newTop; ++i) { Stack[i].V.SetNilValue(); } Top = Stack[newTop]; } else { Utl.ApiCheck(-(index + 1) <= (Top.Index - (CI.FuncIndex + 1)), "invalid new top"); Top = Stack[Top.Index + index + 1]; } }
void ILuaAPI.XMove(ILuaState to, int n) { var toLua = to as LuaState; if ((LuaState)this == toLua) { return; } Utl.ApiCheckNumElems(this, n); Utl.ApiCheck(G == toLua.G, "moving among independent states"); Utl.ApiCheck(toLua.CI.TopIndex - toLua.Top.Index >= n, "not enough elements to move"); int index = Top.Index - n; Top = Stack[index]; for (int i = 0; i < n; ++i) { StkId.inc(ref toLua.Top).V.SetObj(ref Stack[index + i].V); } }
public int GetInfo(string what, LuaDebug ar) { CallInfo ci; StkId func; int pos = 0; if (what[pos] == '>') { ci = null; func = Stack[Top.Index - 1]; Utl.ApiCheck(func.V.TtIsFunction(), "function expected"); pos++; Top = Stack[Top.Index - 1]; } else { ci = BaseCI[ar.ActiveCIIndex]; func = Stack[ci.FuncIndex]; Utl.Assert(Stack[ci.FuncIndex].V.TtIsFunction()); } // var IsClosure( func.Value ) ? func.Value int status = AuxGetInfo(what, ar, func, ci); if (what.Contains("f")) { Top.V.SetObj(ref func.V); IncrTop(); } if (what.Contains("L")) { CollectValidLines(func); } return(status); }
int ILuaAPI.YieldK(int numResults, int context, CSharpFunctionDelegate continueFunc) { CallInfo ci = CI; Utl.ApiCheckNumElems(this, numResults); if (NumNonYieldable > 0) { if (this != G.MainThread) { G_RunError("attempt to yield across metamethod/C-call boundary"); } else { G_RunError("attempt to yield from outside a coroutine"); } } Status = ThreadStatus.LUA_YIELD; ci.ExtraIndex = ci.FuncIndex; // save current `func' if (ci.IsLua) // inside a hook { Utl.ApiCheck(continueFunc == null, "hooks cannot continue after yielding"); } else { ci.ContinueFunc = continueFunc; if (ci.ContinueFunc != null) // is there a continuation { ci.Context = context; } ci.FuncIndex = Top.Index - (numResults + 1); D_Throw(ThreadStatus.LUA_YIELD); } Utl.Assert((ci.CallStatus & CallStatus.CIST_HOOKED) != 0); // must be inside a hook return(0); }
void ILuaAPI.PushCSharpClosure(CSharpFunctionDelegate f, int n) { if (n == 0) { Top.V.SetClCsValue(new LuaCsClosureValue(f)); } else { // 带 UpValue 的 C# function Utl.ApiCheckNumElems(this, n); Utl.ApiCheck(n <= LuaLimits.MAXUPVAL, "upvalue index too large"); LuaCsClosureValue cscl = new LuaCsClosureValue(f, n); int index = Top.Index - n; Top = Stack[index]; for (int i = 0; i < n; ++i) { cscl.Upvals[i].V.SetObj(ref Stack[index + i].V); } Top.V.SetClCsValue(cscl); } ApiIncrTop(); }
private void CheckResults(int numArgs, int numResults) { Utl.ApiCheck(numResults == LuaDef.LUA_MULTRET || CI.TopIndex - Top.Index >= numResults - numArgs, "results from function overflow current stack size"); }