Ejemplo n.º 1
0
        private int ComputeSizes(ref int[] nums, ref int nasize)
        {
            int a  = 0;
            int na = 0;
            int n  = 0;

            for (int i = 0, tti = 1; tti / 2 < nasize; ++i, tti *= 2)
            {
                if (nums[i] > 0)
                {
                    a += nums[i];
                    if (a > tti / 2)
                    {
                        n  = tti;
                        na = a;
                    }
                }
                if (a == nasize)
                {
                    break;
                }                                          // all elements already conted
            }
            nasize = n;
            Utl.Assert(nasize / 2 <= na && na <= nasize);
            return(na);
        }
Ejemplo n.º 2
0
        private static void F_Load(ref LoadParameter param)
        {
            var L = param.L;

            LuaProto proto;
            var      c = param.LoadInfo.PeekByte();

            if (c == LuaConf.LUA_SIGNATURE[0])
            {
                L.CheckMode(param.Mode, "binary");
                proto = Undump.LoadBinary(L, param.LoadInfo, param.Name);
            }
            else
            {
                L.CheckMode(param.Mode, "text");
                proto = Parser.Parse(L, param.LoadInfo, param.Name);
            }

            var cl = new LuaLClosureValue(proto);

            Utl.Assert(cl.Upvals.Length == cl.Proto.Upvalues.Count);

            L.Top.V.SetClLValue(cl);
            L.IncrTop();
        }
Ejemplo n.º 3
0
        string ILuaAPI.ToString(int index)
        {
            StkId addr;

            if (!Index2Addr(index, out addr))
            {
                return(null);
            }

            if (addr.V.TtIsString())
            {
                return(addr.V.OValue as string);
            }

            if (!V_ToString(ref addr.V))
            {
                return(null);
            }

            if (!Index2Addr(index, out addr))
            {
                return(null);
            }

            Utl.Assert(addr.V.TtIsString());
            return(addr.V.OValue as string);
        }
Ejemplo n.º 4
0
        private int AdjustVarargs(LuaProto p, int actual)
        {
            // 有 `...' 的情况
            // 调用前: func (base)fixed-p1 fixed-p2 var-p1 var-p2 top
            // 调用后: func nil            nil      var-p1 var-p2 (base)fixed-p1 fixed-p2 (reserved...) top
            //
            // 没有 `...' 的情况
            // func (base)fixed-p1 fixed-p2 (reserved...) top

            int NumFixArgs = p.NumParams;

            Utl.Assert(actual >= NumFixArgs, "AdjustVarargs (actual >= NumFixArgs) is false");

            int fixedArg  = Top.Index - actual; // first fixed argument
            int stackBase = Top.Index;          // final position of first argument

            for (int i = stackBase; i < stackBase + NumFixArgs; ++i)
            {
                Stack[i].V.SetObj(ref Stack[fixedArg].V);
                Stack[fixedArg++].V.SetNilValue();
            }

            Top = Stack[stackBase + NumFixArgs];
            return(stackBase);
        }
Ejemplo n.º 5
0
        internal int GetCurrentLine(CallInfo ci)
        {
            Utl.Assert(ci.IsLua);
            LuaLClosureValue cl = Stack[ci.FuncIndex].V.ClLValue();

            return(cl.Proto.GetFuncLine(ci.CurrentPc));
        }
Ejemplo n.º 6
0
        private void DumpConstants(LuaProto proto)
        {
            DumpVector(proto.K, (k) => {
                var t = k.V.Tt;
                DumpByte((byte)t);
                switch (t)
                {
                case (int)LuaType.LUA_TNIL:
                    break;

                case (int)LuaType.LUA_TBOOLEAN:
                    DumpBool(k.V.BValue());
                    break;

                case (int)LuaType.LUA_TNUMBER:
                    DumpBlock(BitConverter.GetBytes(k.V.NValue));
                    break;

                case (int)LuaType.LUA_TSTRING:
                    DumpString(k.V.SValue());
                    break;

                default:
                    Utl.Assert(false);
                    break;
                }
            });

            DumpVector(proto.P, (p) => {
                DumpFunction(p);
            });
        }
Ejemplo n.º 7
0
        private void FuncInfo(LuaDebug ar, StkId func)
        {
            Utl.Assert(func.V.TtIsFunction());
            if (func.V.ClIsLuaClosure())
            {
                var lcl = func.V.ClLValue();
                var p   = lcl.Proto;
                ar.Source          = string.IsNullOrEmpty(p.Source) ? "=?" : p.Source;
                ar.LineDefined     = p.LineDefined;
                ar.LastLineDefined = p.LastLineDefined;
                ar.What            = (ar.LineDefined == 0) ? "main" : "Lua";
            }
            else if (func.V.ClIsCsClosure())
            {
                ar.Source          = "=[C#]";
                ar.LineDefined     = -1;
                ar.LastLineDefined = -1;
                ar.What            = "C#";
            }
            else
            {
                throw new System.NotImplementedException();
            }

            if (ar.Source.Length > LuaDef.LUA_IDSIZE)
            {
                ar.ShortSrc = ar.Source.Substring(0, LuaDef.LUA_IDSIZE);
            }
            else
            {
                ar.ShortSrc = ar.Source;
            }
        }
Ejemplo n.º 8
0
 private void CollectValidLines(StkId func)
 {
     Utl.Assert(func.V.TtIsFunction());
     if (func.V.ClIsLuaClosure())
     {
         var lcl      = func.V.ClLValue();
         var p        = lcl.Proto;
         var lineinfo = p.LineInfo;
         var t        = new LuaTable(this);
         Top.V.SetHValue(t);
         IncrTop();
         var v = new TValue();
         v.SetBValue(true);
         for (int i = 0; i < lineinfo.Count; ++i)
         {
             t.SetInt(lineinfo[i], ref v);
         }
     }
     else if (func.V.ClIsCsClosure())
     {
         Top.V.SetNilValue();
         IncrTop();
     }
     else
     {
         throw new System.NotImplementedException();
     }
 }
Ejemplo n.º 9
0
 private static void FreeReg(FuncState fs, int reg)
 {
     if (!Instruction.ISK(reg) && reg >= fs.NumActVar)
     {
         fs.FreeReg--;
         Utl.Assert(reg == fs.FreeReg);
     }
 }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
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;
        }
Ejemplo n.º 13
0
        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)));
        }
Ejemplo n.º 14
0
        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);
            }
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
 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);
     }
 }
Ejemplo n.º 17
0
        private int CeilLog2(int x)
        {
            Utl.Assert(x > 0);
            int l = 0;

            x--;
            while (x >= 256)
            {
                l += 8; x >>= 8;
            }
            return(l + Log2_[x]);
        }
Ejemplo n.º 18
0
        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;
        }
Ejemplo n.º 19
0
 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;
     }
 }
Ejemplo n.º 20
0
        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);
            }
        }
Ejemplo n.º 21
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);
        }
Ejemplo n.º 22
0
        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);
        }
Ejemplo n.º 23
0
        private string GetUpvalueName(CallInfo ci, StkId o, out string name)
        {
            var func = Stack[ci.FuncIndex];

            Utl.Assert(func.V.TtIsFunction() && func.V.ClIsLuaClosure());
            var lcl = func.V.ClLValue();

            for (int i = 0; i < lcl.Upvals.Length; ++i)
            {
                if (lcl.Upvals[i].V == o)
                {
                    name = UpvalName(lcl.Proto, i);
                    return("upvalue");
                }
            }
            name = default(string);
            return(null);
        }
Ejemplo n.º 24
0
        private void SetArraryVector(int size)
        {
            Utl.Assert(size >= ArrayPart.Length);

            var newArrayPart = new StkId[size];
            int i            = 0;

            for ( ; i < ArrayPart.Length; ++i)
            {
                newArrayPart[i] = ArrayPart[i];
            }
            for ( ; i < size; ++i)
            {
                newArrayPart[i] = new StkId();
                newArrayPart[i].V.SetNilValue();
            }
            ArrayPart = newArrayPart;
        }
Ejemplo n.º 25
0
        ThreadStatus ILuaAPI.Load(ILoadInfo loadinfo, string name, string mode)
        {
            var param  = new LoadParameter(this, loadinfo, name, mode);
            var status = D_PCall(DG_F_Load, ref param, Top.Index, ErrFunc);

            if (status == ThreadStatus.LUA_OK)
            {
                var below = Stack[Top.Index - 1];
                Utl.Assert(below.V.TtIsFunction() && below.V.ClIsLuaClosure());
                var cl = below.V.ClLValue();
                if (cl.Upvals.Length == 1)
                {
                    var gt = G.Registry.V.HValue().GetInt(LuaDef.LUA_RIDX_GLOBALS);
                    cl.Upvals[0].V.V.SetObj(ref gt.V);
                }
            }

            return(status);
        }
Ejemplo n.º 26
0
        private void D_ReallocStack(int size)
        {
            Utl.Assert(size <= LuaConf.LUAI_MAXSTACK || size == ERRORSTACKSIZE);
            var newStack = new StkId[size];
            int i        = 0;

            for ( ; i < Stack.Length; ++i)
            {
                newStack[i] = Stack[i];
                newStack[i].SetList(newStack);
            }
            for ( ; i < size; ++i)
            {
                newStack[i] = new StkId();
                newStack[i].SetList(newStack);
                newStack[i].SetIndex(i);
                newStack[i].V.SetNilValue();
            }
            Top       = newStack[Top.Index];
            Stack     = newStack;
            StackLast = size - LuaDef.EXTRA_STACK;
        }
Ejemplo n.º 27
0
        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);
        }
Ejemplo n.º 28
0
        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);
        }
Ejemplo n.º 29
0
        public static void SetList(FuncState fs, int t, int nelems, int tostore)
        {
            int c = (nelems - 1) / LuaDef.LFIELDS_PER_FLUSH + 1;
            int b = (tostore == LuaDef.LUA_MULTRET) ? 0 : tostore;

            Utl.Assert(tostore != 0);

            if (c <= Instruction.MAXARG_C)
            {
                CodeABC(fs, OpCode.OP_SETLIST, t, b, c);
            }
            else if (c <= Instruction.MAXARG_Ax)
            {
                CodeABC(fs, OpCode.OP_SETLIST, t, b, 0);
                CodeExtraArg(fs, c);
            }
            else
            {
                fs.Lexer.SyntaxError("constructor too long");
            }

            // free registers with list values
            fs.FreeReg = t + 1;
        }
Ejemplo n.º 30
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);
        }