void ILuaAPI.Concat(int n) { Utl.ApiCheckNumElems(this, n); if (n >= 2) { V_Concat(n); } else if (n == 0) { Top.V.SetSValue(""); ApiIncrTop(); } }
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]; }
// 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.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]; }
ThreadStatus ILuaAPI.Resume(ILuaState from, int numArgs) { LuaState fromState = from as LuaState; NumCSharpCalls = (fromState != null) ? fromState.NumCSharpCalls + 1 : 1; NumNonYieldable = 0; // allow yields Utl.ApiCheckNumElems(this, (Status == ThreadStatus.LUA_OK) ? numArgs + 1 : numArgs); var resumeParam = new ResumeParam(); resumeParam.L = this; resumeParam.firstArg = Top.Index - numArgs; ThreadStatus status = D_RawRunProtected(DG_Resume, ref resumeParam); if (status == ThreadStatus.LUA_RESUME_ERROR) // error calling `lua_resume'? { status = ThreadStatus.LUA_ERRRUN; } else // yield or regular error { while (status != ThreadStatus.LUA_OK && status != ThreadStatus.LUA_YIELD) // error? { if (Recover(status)) // recover point? { var unrollParam = new UnrollParam(); unrollParam.L = this; status = D_RawRunProtected(DG_Unroll, ref unrollParam); } else // unrecoverable error { Status = status; // mark thread as `dead' SetErrorObj(status, Top); CI.TopIndex = Top.Index; break; } } Utl.Assert(status == Status); } NumNonYieldable = 1; // do not allow yields NumCSharpCalls--; Utl.Assert(NumCSharpCalls == ((fromState != null) ? fromState.NumCSharpCalls : 0)); return(status); }
DumpStatus ILuaAPI.Dump(LuaWriter writeFunc) { Utl.ApiCheckNumElems(this, 1); var below = Stack[Top.Index - 1]; if (!below.V.TtIsFunction() || !below.V.ClIsLuaClosure()) { return(DumpStatus.ERROR); } var o = below.V.ClLValue(); if (o == null) { return(DumpStatus.ERROR); } return(DumpState.Dump(o.Proto, writeFunc, false)); }
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); } }
string ILuaAPI.SetUpvalue(int funcIndex, int n) { StkId addr; if (!Index2Addr(funcIndex, out addr)) { return(null); } Utl.ApiCheckNumElems(this, 1); StkId val; var name = AuxUpvalue(addr, n, out val); if (name == null) { return(null); } Top = Stack[Top.Index - 1]; val.V.SetObj(ref Top.V); return(name); }
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); }
private void FinishCSharpCall() { CallInfo ci = CI; Utl.Assert(ci.ContinueFunc != null); // must have a continuation Utl.Assert(NumNonYieldable == 0); // finish `CallK' AdjustResults(ci.NumResults); // call continuation function if ((ci.CallStatus & CallStatus.CIST_STAT) == 0) // no call status? { ci.Status = ThreadStatus.LUA_YIELD; // `default' status } Utl.Assert(ci.Status != ThreadStatus.LUA_OK); ci.CallStatus = (ci.CallStatus & ~(CallStatus.CIST_YPCALL | CallStatus.CIST_STAT)) | CallStatus.CIST_YIELDED; int n = ci.ContinueFunc(this); // call Utl.ApiCheckNumElems(this, n); // finish `D_PreCall' D_PosCall(Top.Index - n); }
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(); }
int ILuaAPI.Error() { Utl.ApiCheckNumElems(this, 1); G_ErrorMsg(); return(0); }
void ILuaAPI.Replace(int index) { Utl.ApiCheckNumElems(this, 1); MoveTo(Stack[Top.Index - 1], index); Top = Stack[Top.Index - 1]; }
public int Error() { Utl.ApiCheckNumElems(this, 1); G_ErrorMsg(); return(0); }