Beispiel #1
0
        private bool CallBinTM( StkId p1, StkId p2, StkId res, TMS tm )
        {
            var tmObj = T_GetTMByObj(ref p1.V, tm);
            if(tmObj.V.TtIsNil())
                tmObj = T_GetTMByObj(ref p2.V, tm);
            if(tmObj.V.TtIsNil())
                return false;

            CallTM( ref tmObj.V, ref p1.V, ref p2.V, res, true );
            return true;
        }
Beispiel #2
0
        private bool CallBinTM( StkId p1, StkId p2, StkId res, TMS tm )
        {
            var tmObj = T_GetTMByObj( p1.Value, tm );
            if( tmObj.IsNil )
                tmObj = T_GetTMByObj( p2.Value, tm );
            if( tmObj.IsNil )
                return false;

            CallTM( tmObj, p1.Value, p2.Value, res, true );
            return true;
        }
Beispiel #3
0
        private bool CallOrderTM( StkId p1, StkId p2, TMS tm, out bool error )
        {
            if( !CallBinTM( p1, p2, Top, tm ) )
            {
                error = true; // no metamethod
                return false;
            }

            error = false;
            return !IsFalse(ref Top.V);
        }
Beispiel #4
0
 private void CallTM( LuaObject f, LuaObject p1, LuaObject p2, StkId p3, bool hasres )
 {
     var func = Top;
     Top.ValueInc = f;	// push function
     Top.ValueInc = p1;	// push 1st argument
     Top.ValueInc = p2;	// push 2nd argument
     if( !hasres ) 		// no result? p3 is 3rd argument
         Top.ValueInc = p3.Value;
     D_Call( func, (hasres ? 1 : 0), CI.IsLua );
     if( hasres )		// if has result, move it ot its place
     {
         var below = Top - 1;
         p3.Value = below.Value;
         Top -= 1;
     }
 }
Beispiel #5
0
 private void CallTM( ref TValue f, ref TValue p1, ref TValue p2, StkId p3, bool hasres )
 {
     var result = p3.Index;
     var func = Top;
     StkId.inc(ref Top).V.SetObj(ref f); 	// push function
     StkId.inc(ref Top).V.SetObj(ref p1);	// push 1st argument
     StkId.inc(ref Top).V.SetObj(ref p2);	// push 2nd argument
     if( !hasres ) 		// no result? p3 is 3rd argument
         StkId.inc(ref Top).V.SetObj(ref p3.V);
     D_CheckStack(0);
     D_Call( func, (hasres ? 1 : 0), CI.IsLua );
     if( hasres )		// if has result, move it ot its place
     {
         Top = Stack[Top.Index - 1];
         Stack[result].V.SetObj(ref Top.V);
     }
 }
Beispiel #6
0
        private void F_Close( StkId level )
        {
            var node = OpenUpval.First;
            while( node != null )
            {
                var upval = node.Value;
                if( upval.V.Index < level.Index )
                    break;

                var next = node.Next;
                OpenUpval.Remove( node );
                node = next;

                upval.Value[0] = upval.V.Value;
                upval.V = new StkId( upval.Value, 0 );
            }
        }
Beispiel #7
0
        private void F_Close( StkId level )
        {
            var node = OpenUpval.First;
            while( node != null )
            {
                var upval = node.Value;
                if( upval.V.Index < level.Index )
                    break;

                var next = node.Next;
                OpenUpval.Remove( node );
                node = next;

                upval.Value.V.SetObj(ref upval.V.V);
                upval.V = upval.Value;
            }
        }
Beispiel #8
0
        private LuaUpvalue F_FindUpval( StkId level )
        {
            #if DEBUG_FIND_UPVALUE
            Debug.Log( "[F_FindUpval] >>>>>>>>>>>>>>>>>>>> level:" + level );
            #endif

            var node = OpenUpval.First;
            LinkedListNode<LuaUpvalue> prev = null;
            while( node != null )
            {
                var upval = node.Value;
            #if DEBUG_FIND_UPVALUE
                Debug.Log("[F_FindUpval] >>>>>>>>>>>>>>>>>>>> upval.V:" + upval.V );
            #endif
                if(upval.V.Index < level.Index)
                    break;

                var next = node.Next;
                if(upval.V == level)
                    return upval;

                prev = node;
                node = next;
            }

            // not found: create a new one
            var ret = new LuaUpvalue();
            ret.V   = level;
            // ret.Prev = G.UpvalHead;
            // ret.Next = G.UpvalHead.Next;
            // ret.Next.Prev = ret;
            // G.UpvalHead.Next = ret;

            if( prev == null )
                OpenUpval.AddFirst( ret );
            else
                OpenUpval.AddAfter( prev, ret );

            #if DEBUG_FIND_UPVALUE
            Debug.Log("[F_FindUpval] >>>>>>>>>>>>>>>>>>>> create new one:" + ret.V );
            #endif

            return ret;
        }
Beispiel #9
0
        static LuaTable()
        {
            TheNilValue = new StkId();
            TheNilValue.V.SetNilValue();
            #if DEBUG_DUMMY_TVALUE_MODIFY
            TheNilValue.V.Lock_ = true;
            #endif

            DummyArrayPart = new StkId[0];

            DummyNode = new HNode();
            DummyNode.Key = TheNilValue;
            DummyNode.Val = TheNilValue;
            DummyNode.Next = null;

            DummyHashPart = new HNode[1];
            DummyHashPart[0] = DummyNode;
            DummyHashPart[0].Index = 0;
        }
Beispiel #10
0
 private void D_Call( StkId func, int nResults, bool allowYield )
 {
     if( ++NumCSharpCalls >= LuaLimits.LUAI_MAXCCALLS )
     {
         if( NumCSharpCalls == LuaLimits.LUAI_MAXCCALLS )
             G_RunError( "CSharp Stack Overflow" );
         else if( NumCSharpCalls >=
                 (LuaLimits.LUAI_MAXCCALLS + (LuaLimits.LUAI_MAXCCALLS>>3))
             )
             D_Throw( ThreadStatus.LUA_ERRERR );
     }
     if( !allowYield )
         NumNonYieldable++;
     if( !D_PreCall( func, nResults ) ) // is a Lua function ?
         V_Execute();
     if( !allowYield )
         NumNonYieldable--;
     NumCSharpCalls--;
 }
Beispiel #11
0
        private ThreadStatus D_PCall( PFuncDelegate func, object ud,
			StkId oldTop, int errFunc )
        {
            CallInfo oldCI 			= CI;
            bool oldAllowHook 		= AllowHook;
            int oldNumNonYieldable	= NumNonYieldable;
            int oldErrFunc			= ErrFunc;

            ErrFunc = errFunc;
            ThreadStatus status = D_RawRunProtected( func, ud );
            if( status != ThreadStatus.LUA_OK ) // an error occurred?
            {
                F_Close( oldTop );
                SetErrorObj( status, oldTop );
                CI = oldCI;
                AllowHook = oldAllowHook;
                NumNonYieldable = oldNumNonYieldable;
            }
            ErrFunc = oldErrFunc;
            return status;
        }
Beispiel #12
0
        private void V_FinishOp()
        {
            int         ciIndex   = CI.Index;
            int         stackBase = CI.BaseIndex;
            Instruction i         = (CI.SavedPc - 1).Value;     // interrupted instruction
            OpCode      op        = i.GET_OPCODE();

            switch (op)
            {
            case OpCode.OP_ADD:
            case OpCode.OP_SUB:
            case OpCode.OP_MUL:
            case OpCode.OP_DIV:
            case OpCode.OP_MOD:
            case OpCode.OP_POW:
            case OpCode.OP_UNM:
            case OpCode.OP_LEN:
            case OpCode.OP_GETTABUP:
            case OpCode.OP_GETTABLE:
            case OpCode.OP_SELF:
            {
                var tmp = Stack[stackBase + i.GETARG_A()];
                Top = Stack[Top.Index - 1];
                tmp.V.SetObj(ref Stack[Top.Index].V);
                break;
            }

            case OpCode.OP_LE:
            case OpCode.OP_LT:
            case OpCode.OP_EQ:
            {
                bool res = !IsFalse(ref Stack[Top.Index - 1].V);
                Top = Stack[Top.Index - 1];
                // metamethod should not be called when operand is K
                Utl.Assert(!Instruction.ISK(i.GETARG_B()));
                if (op == OpCode.OP_LE &&                         // `<=' using `<' instead?
                    T_GetTMByObj(ref Stack[stackBase + i.GETARG_B()].V, TMS.TM_LE).V.TtIsNil())
                {
                    res = !res;                             // invert result
                }

                var ci = BaseCI[ciIndex];
                Utl.Assert(ci.SavedPc.Value.GET_OPCODE() == OpCode.OP_JMP);
                if ((res ? 1 : 0) != i.GETARG_A())
                {
                    if ((i.GETARG_A() == 0) == res)                 // condition failed?
                    {
                        ci.SavedPc.Index++;                         // skip jump instruction
                    }
                }
                break;
            }

            case OpCode.OP_CONCAT:
            {
                StkId top   = Stack[Top.Index - 1];            // top when `CallBinTM' was called
                int   b     = i.GETARG_B();                    // first element to concatenate
                int   total = top.Index - 1 - (stackBase + b); // yet to concatenate
                var   tmp   = Stack[top.Index - 2];
                tmp.V.SetObj(ref top.V);                       // put TM result in proper position
                if (total > 1)                                 // are there elements to concat?
                {
                    Top = Stack[Top.Index - 1];
                    V_Concat(total);
                }
                // move final result to final position
                var ci   = BaseCI[ciIndex];
                var tmp2 = Stack[ci.BaseIndex + i.GETARG_A()];
                tmp2.V.SetObj(ref Stack[Top.Index - 1].V);
                Top = Stack[ci.TopIndex];
                break;
            }

            case OpCode.OP_TFORCALL:
            {
                var ci = BaseCI[ciIndex];
                Utl.Assert(ci.SavedPc.Value.GET_OPCODE() == OpCode.OP_TFORLOOP);
                Top = Stack[ci.TopIndex];                         // restore top
                break;
            }

            case OpCode.OP_CALL:
            {
                if (i.GETARG_C() - 1 >= 0)                          // numResults >= 0?
                {
                    var ci = BaseCI[ciIndex];
                    Top = Stack[ci.TopIndex];                             // restore top
                }
                break;
            }

            case OpCode.OP_TAILCALL:
            case OpCode.OP_SETTABUP:
            case OpCode.OP_SETTABLE:
                break;

            default:
                Utl.Assert(false);
                break;
            }
        }
Beispiel #13
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;
        }
Beispiel #14
0
        public void Resize(int nasize, int nhsize)
        {
            int oasize = ArrayPart.Length;
            var oldHashPart = HashPart;
            if(nasize > oasize) // array part must grow?
                SetArraryVector(nasize);

            // create new hash part with appropriate size
            SetNodeVector(nhsize);

            // array part must shrink?
            if(nasize < oasize) {
                var oldArrayPart = ArrayPart;
                ArrayPart = DummyArrayPart;
                // re-insert elements from vanishing slice
                for(int i=nasize; i<oasize; ++i) {
                    if(!oldArrayPart[i].V.TtIsNil())
                        { SetInt(i+1, ref oldArrayPart[i].V); }
                }
                // shrink array
                var newArrayPart = new StkId[nasize];
                for(int i=0; i<nasize; ++i) {
                    newArrayPart[i] = oldArrayPart[i];
                }
                ArrayPart = newArrayPart;
            }

            // re-insert elements from hash part
            for(int i=0; i<oldHashPart.Length; ++i) {
                var node = oldHashPart[i];
                if(!node.Val.V.TtIsNil()) {
                    Set(ref node.Key.V, ref node.Val.V);
                }
            }
        }
Beispiel #15
0
 public void SetList(StkId[] list)
 {
     List = list;
 }
Beispiel #16
0
        public LuaUpvalue()
        {
            Value = new StkId();
            Value.V.SetNilValue();

            V = Value;
        }
Beispiel #17
0
        private void MoveTo( StkId fr, int index )
        {
            StkId to;
            if( !Index2Addr( index, out to ) )
                Utl.InvalidIndex();

            to.V.SetObj(ref fr.V);
        }
Beispiel #18
0
        private string AuxUpvalue(StkId addr, int n, out StkId val)
        {
            val = null;

            if(!addr.V.TtIsFunction())
                return null;

            if(addr.V.ClIsLuaClosure()) {
                var f = addr.V.ClLValue();
                var p = f.Proto;
                if(!(1 <= n && n <= p.Upvalues.Count))
                    return null;
                val = f.Upvals[n-1].V;
                var name = p.Upvalues[n-1].Name;
                return (name == null) ? "" : name;
            }
            else if(addr.V.ClIsCsClosure()) {
                var f = addr.V.ClCsValue();
                if(!(1 <= n && n <= f.Upvals.Length))
                    return null;
                val = f.Upvals[n-1];
                return "";
            }
            else return null;
        }
Beispiel #19
0
 private void G_ConcatError(StkId p1, StkId p2)
 {
     // TODO
     throw new NotImplementedException();
 }
Beispiel #20
0
        private int AuxGetInfo(string what, LuaDebug ar, StkId func, CallInfo ci)
        {
            int status = 1;

            for (int i = 0; i < what.Length; ++i)
            {
                char c = what[i];
                switch (c)
                {
                case 'S':
                {
                    FuncInfo(ar, func);
                    break;
                }

                case 'l':
                {
                    ar.CurrentLine = (ci != null && ci.IsLua) ? GetCurrentLine(ci) : -1;
                    break;
                }

                case 'u':
                {
                    Utl.Assert(func.V.TtIsFunction());
                    if (func.V.ClIsLuaClosure())
                    {
                        var lcl = func.V.ClLValue();
                        ar.NumUps    = lcl.Upvals.Length;
                        ar.IsVarArg  = lcl.Proto.IsVarArg;
                        ar.NumParams = lcl.Proto.NumParams;
                    }
                    else if (func.V.ClIsCsClosure())
                    {
                        var ccl = func.V.ClCsValue();
                        ar.NumUps    = ccl.Upvals.Length;
                        ar.IsVarArg  = true;
                        ar.NumParams = 0;
                    }
                    else
                    {
                        throw new System.NotImplementedException();
                    }
                    break;
                }

                case 't':
                {
                    ar.IsTailCall = (ci != null)
                                                        ? ((ci.CallStatus & CallStatus.CIST_TAIL) != 0)
                                                        : false;
                    break;
                }

                case 'n':
                {
                    var prevCI = BaseCI[ci.Index - 1];
                    if (ci != null &&
                        ((ci.CallStatus & CallStatus.CIST_TAIL) == 0) &&
                        prevCI.IsLua)
                    {
                        ar.NameWhat = GetFuncName(prevCI, out ar.Name);
                    }
                    else
                    {
                        ar.NameWhat = null;
                    }
                    if (ar.NameWhat == null)
                    {
                        ar.NameWhat = "";                                 // not found
                        ar.Name     = null;
                    }
                    break;
                }

                case 'L':
                case 'f':                         // handled by GetInfo
                    break;

                default: status = 0;                         // invalid option
                    break;
                }
            }
            return(status);
        }
Beispiel #21
0
 private void IncrTop()
 {
     StkId.inc(ref Top);
     D_CheckStack(0);
 }
Beispiel #22
0
 static LuaState()
 {
     TheNilValue = new StkId();
     TheNilValue.V.SetNilValue();
 }
Beispiel #23
0
        private void V_Execute()
        {
            ExecuteEnvironment env;
            CallInfo           ci = CI;

newframe:
            Utl.Assert(ci == CI);
            var cl = Stack[ci.FuncIndex].V.ClLValue();

            env.Stack = Stack;
            env.K     = cl.Proto.K;
            env.Base  = ci.BaseIndex;

#if DEBUG_NEW_FRAME
            ULDebug.Log("#### NEW FRAME #########################################################################");
            ULDebug.Log("## cl:" + cl);
            ULDebug.Log("## Base:" + env.Base);
            ULDebug.Log("########################################################################################");
#endif

            while (true)
            {
                Instruction i = ci.SavedPc.ValueInc;
                env.I = i;

#if DEBUG_SRC_INFO
                int    line = 0;
                string src  = "";
                if (ci.IsLua)
                {
                    line = GetCurrentLine(ci);
                    src  = GetCurrentLuaFunc(ci).Proto.Source;
                }
#endif

                StkId ra = env.RA;

#if DEBUG_DUMP_INS_STACK
#if DEBUG_DUMP_INS_STACK_EX
                DumpStack(env.Base, i.ToString());
#else
                DumpStack(env.Base);
#endif
#endif

#if DEBUG_INSTRUCTION
                ULDebug.Log(System.DateTime.Now + " [VM] ======================================================================== Instruction: " + i
#if DEBUG_INSTRUCTION_WITH_STACK
                            + "\n" + DumpStackToString(env.Base.Index)
#endif
                            );
#endif

#if DEBUG_RECORD_INS
                InstructionHistory.Enqueue(i);
                if (InstructionHistory.Count > 100)
                {
                    InstructionHistory.Dequeue();
                }
#endif

                switch (i.GET_OPCODE())
                {
                case OpCode.OP_MOVE:
                {
                    var rb = env.RB;

#if DEBUG_OP_MOVE
                    ULDebug.Log("[VM] ==== OP_MOVE rb:" + rb);
                    ULDebug.Log("[VM] ==== OP_MOVE ra:" + ra);
#endif

                    ra.V.SetObj(ref rb.V);
                    break;
                }

                case OpCode.OP_LOADK:
                {
                    var rb = env.K[i.GETARG_Bx()];
                    ra.V.SetObj(ref rb.V);
                    break;
                }

                case OpCode.OP_LOADKX:
                {
                    Utl.Assert(ci.SavedPc.Value.GET_OPCODE() == OpCode.OP_EXTRAARG);
                    var rb = env.K[ci.SavedPc.ValueInc.GETARG_Ax()];
                    ra.V.SetObj(ref rb.V);
                    break;
                }

                case OpCode.OP_LOADBOOL:
                {
                    ra.V.SetBValue(i.GETARG_B() != 0);
                    if (i.GETARG_C() != 0)
                    {
                        ci.SavedPc.Index += 1;                                 // skip next instruction (if C)
                    }
                    break;
                }

                case OpCode.OP_LOADNIL:
                {
                    int b     = i.GETARG_B();
                    int index = ra.Index;
                    do
                    {
                        Stack[index++].V.SetNilValue();
                    } while (b-- > 0);
                    break;
                }

                case OpCode.OP_GETUPVAL:
                {
                    int b = i.GETARG_B();
                    ra.V.SetObj(ref cl.Upvals[b].V.V);

#if DEBUG_OP_GETUPVAL
                    // for( var j=0; j<cl.Upvals.Length; ++j)
                    // {
                    //  ULDebug.Log("[VM] ==== GETUPVAL upval:" + cl.Upvals[j] );
                    // }
                    ULDebug.Log("[VM] ==== GETUPVAL b:" + b);
                    ULDebug.Log("[VM] ==== GETUPVAL ra:" + ra);
#endif
                    break;
                }

                case OpCode.OP_GETTABUP:
                {
                    int b   = i.GETARG_B();
                    var key = env.RKC;
                    V_GetTable(cl.Upvals[b].V, key, ra);
#if DEBUG_OP_GETTABUP
                    ULDebug.Log("[VM] ==== OP_GETTABUP key:" + key);
                    ULDebug.Log("[VM] ==== OP_GETTABUP val:" + ra);
#endif
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_GETTABLE:
                {
                    var tbl = env.RB;
                    var key = env.RKC;
                    var val = ra;
                    V_GetTable(tbl, key, val);
#if DEBUG_OP_GETTABLE
                    ULDebug.Log("[VM] ==== OP_GETTABLE key:" + key.ToString());
                    ULDebug.Log("[VM] ==== OP_GETTABLE val:" + val.ToString());
#endif
                    break;
                }

                case OpCode.OP_SETTABUP:
                {
                    int a = i.GETARG_A();

                    var key = env.RKB;
                    var val = env.RKC;
                    V_SetTable(cl.Upvals[a].V, key, val);
#if DEBUG_OP_SETTABUP
                    ULDebug.Log("[VM] ==== OP_SETTABUP key:" + key.Value);
                    ULDebug.Log("[VM] ==== OP_SETTABUP val:" + val.Value);
#endif
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_SETUPVAL:
                {
                    int b  = i.GETARG_B();
                    var uv = cl.Upvals[b];
                    uv.V.V.SetObj(ref ra.V);
#if DEBUG_OP_SETUPVAL
                    ULDebug.Log("[VM] ==== SETUPVAL b:" + b);
                    ULDebug.Log("[VM] ==== SETUPVAL ra:" + ra);
#endif
                    break;
                }

                case OpCode.OP_SETTABLE:
                {
                    var key = env.RKB;
                    var val = env.RKC;
#if DEBUG_OP_SETTABLE
                    ULDebug.Log("[VM] ==== OP_SETTABLE key:" + key.ToString());
                    ULDebug.Log("[VM] ==== OP_SETTABLE val:" + val.ToString());
#endif
                    V_SetTable(ra, key, val);
                    break;
                }

                case OpCode.OP_NEWTABLE:
                {
                    int b   = i.GETARG_B();
                    int c   = i.GETARG_C();
                    var tbl = new LuaTable(this);
                    ra.V.SetHValue(tbl);
                    if (b > 0 || c > 0)
                    {
                        tbl.Resize(b, c);
                    }
                    break;
                }

                case OpCode.OP_SELF:
                {
                    // OP_SELF put function referenced by a table on ra
                    // and the table on ra+1
                    //
                    // RB:  table
                    // RKC: key
                    var ra1 = Stack[ra.Index + 1];
                    var rb  = env.RB;
                    ra1.V.SetObj(ref rb.V);
                    V_GetTable(rb, env.RKC, ra);
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_ADD:
                {
                    var rkb = env.RKB;
                    var rkc = env.RKC;
                    if (rkb.V.TtIsNumber() && rkc.V.TtIsNumber())
                    {
                        ra.V.SetNValue(rkb.V.NValue + rkc.V.NValue);
                    }
                    else
                    {
                        V_Arith(ra, rkb, rkc, TMS.TM_ADD);
                    }

                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_SUB:
                {
                    var rkb = env.RKB;
                    var rkc = env.RKC;
                    if (rkb.V.TtIsNumber() && rkc.V.TtIsNumber())
                    {
                        ra.V.SetNValue(rkb.V.NValue - rkc.V.NValue);
                    }
                    else
                    {
                        V_Arith(ra, rkb, rkc, TMS.TM_SUB);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_MUL:
                {
                    var rkb = env.RKB;
                    var rkc = env.RKC;
                    if (rkb.V.TtIsNumber() && rkc.V.TtIsNumber())
                    {
                        ra.V.SetNValue(rkb.V.NValue * rkc.V.NValue);
                    }
                    else
                    {
                        V_Arith(ra, rkb, rkc, TMS.TM_MUL);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_DIV:
                {
                    var rkb = env.RKB;
                    var rkc = env.RKC;
                    if (rkb.V.TtIsNumber() && rkc.V.TtIsNumber())
                    {
                        ra.V.SetNValue(rkb.V.NValue / rkc.V.NValue);
                    }
                    else
                    {
                        V_Arith(ra, rkb, rkc, TMS.TM_DIV);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_MOD:
                {
                    var rkb = env.RKB;
                    var rkc = env.RKC;
                    if (rkb.V.TtIsNumber() && rkc.V.TtIsNumber())
                    {
                        ra.V.SetNValue(rkb.V.NValue % rkc.V.NValue);
                    }
                    else
                    {
                        V_Arith(ra, rkb, rkc, TMS.TM_MOD);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_POW:
                {
                    var rkb = env.RKB;
                    var rkc = env.RKC;
                    if (rkb.V.TtIsNumber() && rkc.V.TtIsNumber())
                    {
                        ra.V.SetNValue(Math.Pow(rkb.V.NValue, rkc.V.NValue));
                    }
                    else
                    {
                        V_Arith(ra, rkb, rkc, TMS.TM_POW);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_UNM:
                {
                    var rb = env.RB;
                    if (rb.V.TtIsNumber())
                    {
                        ra.V.SetNValue(-rb.V.NValue);
                    }
                    else
                    {
                        V_Arith(ra, rb, rb, TMS.TM_UNM);
                        env.Base = ci.BaseIndex;
                    }
                    break;
                }

                case OpCode.OP_NOT:
                {
                    var rb = env.RB;
                    ra.V.SetBValue(IsFalse(ref rb.V));
                    break;
                }

                case OpCode.OP_LEN:
                {
                    V_ObjLen(ra, env.RB);
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_CONCAT:
                {
                    int b = i.GETARG_B();
                    int c = i.GETARG_C();
                    Top = Stack[env.Base + c + 1];
                    V_Concat(c - b + 1);
                    env.Base = ci.BaseIndex;

                    ra = env.RA;                             // 'V_Concat' may invoke TMs and move the stack
                    StkId rb = env.RB;
                    ra.V.SetObj(ref rb.V);

                    Top = Stack[ci.TopIndex];                             // restore top
                    break;
                }

                case OpCode.OP_JMP:
                {
                    V_DoJump(ci, i, 0);
                    break;
                }

                case OpCode.OP_EQ:
                {
                    var lhs      = env.RKB;
                    var rhs      = env.RKC;
                    var expectEq = i.GETARG_A() != 0;
#if DEBUG_OP_EQ
                    ULDebug.Log("[VM] ==== OP_EQ lhs:" + lhs);
                    ULDebug.Log("[VM] ==== OP_EQ rhs:" + rhs);
                    ULDebug.Log("[VM] ==== OP_EQ expectEq:" + expectEq);
                    ULDebug.Log("[VM] ==== OP_EQ (lhs.V == rhs.V):" + (lhs.V == rhs.V));
#endif
                    if ((lhs.V == rhs.V) != expectEq)
                    {
                        ci.SavedPc.Index += 1;                                 // skip next jump instruction
                    }
                    else
                    {
                        V_DoNextJump(ci);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_LT:
                {
                    var expectCmpResult = i.GETARG_A() != 0;
                    if (V_LessThan(env.RKB, env.RKC) != expectCmpResult)
                    {
                        ci.SavedPc.Index += 1;
                    }
                    else
                    {
                        V_DoNextJump(ci);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_LE:
                {
                    var expectCmpResult = i.GETARG_A() != 0;
                    if (V_LessEqual(env.RKB, env.RKC) != expectCmpResult)
                    {
                        ci.SavedPc.Index += 1;
                    }
                    else
                    {
                        V_DoNextJump(ci);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_TEST:
                {
                    if ((i.GETARG_C() != 0) ?
                        IsFalse(ref ra.V) : !IsFalse(ref ra.V))
                    {
                        ci.SavedPc.Index += 1;
                    }
                    else
                    {
                        V_DoNextJump(ci);
                    }

                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_TESTSET:
                {
                    var rb = env.RB;
                    if ((i.GETARG_C() != 0) ?
                        IsFalse(ref rb.V) : !IsFalse(ref rb.V))
                    {
                        ci.SavedPc.Index += 1;
                    }
                    else
                    {
                        ra.V.SetObj(ref rb.V);
                        V_DoNextJump(ci);
                    }
                    env.Base = ci.BaseIndex;
                    break;
                }

                case OpCode.OP_CALL:
                {
                    int b        = i.GETARG_B();
                    int nresults = i.GETARG_C() - 1;
                    if (b != 0)
                    {
                        Top = Stack[ra.Index + b];
                    }                                                             // else previous instruction set top
                    if (D_PreCall(ra, nresults))                                  // C# function?
                    {
                        if (nresults >= 0)
                        {
                            Top = Stack[ci.TopIndex];
                        }
                        env.Base = ci.BaseIndex;
                    }
                    else                               // Lua function
                    {
                        ci             = CI;
                        ci.CallStatus |= CallStatus.CIST_REENTRY;
                        goto newframe;
                    }
                    break;
                }

                case OpCode.OP_TAILCALL:
                {
                    int b = i.GETARG_B();
                    if (b != 0)
                    {
                        Top = Stack[ra.Index + b];
                    }                                                                           // else previous instruction set top

                    Utl.Assert(i.GETARG_C() - 1 == LuaDef.LUA_MULTRET);

                    var called = D_PreCall(ra, LuaDef.LUA_MULTRET);

                    // C# function ?
                    if (called)
                    {
                        env.Base = ci.BaseIndex;
                    }

                    // LuaFunciton
                    else
                    {
                        var   nci   = CI;                                             // called frame
                        var   oci   = BaseCI[CI.Index - 1];                           // caller frame
                        StkId nfunc = Stack[nci.FuncIndex];                           // called function
                        StkId ofunc = Stack[oci.FuncIndex];                           // caller function
                        var   ncl   = nfunc.V.ClLValue();
                        var   ocl   = ofunc.V.ClLValue();

                        // last stack slot filled by 'precall'
                        int lim = nci.BaseIndex + ncl.Proto.NumParams;

                        if (cl.Proto.P.Count > 0)
                        {
                            F_Close(Stack[env.Base]);
                        }

                        // move new frame into old one
                        var nindex = nfunc.Index;
                        var oindex = ofunc.Index;
                        while (nindex < lim)
                        {
                            Stack[oindex++].V.SetObj(ref Stack[nindex++].V);
                        }

                        oci.BaseIndex   = ofunc.Index + (nci.BaseIndex - nfunc.Index);
                        oci.TopIndex    = ofunc.Index + (Top.Index - nfunc.Index);
                        Top             = Stack[oci.TopIndex];
                        oci.SavedPc     = nci.SavedPc;
                        oci.CallStatus |= CallStatus.CIST_TAIL;
                        ci              = CI = oci;

                        ocl = ofunc.V.ClLValue();
                        Utl.Assert(Top.Index == oci.BaseIndex + ocl.Proto.MaxStackSize);

                        goto newframe;
                    }

                    break;
                }

                case OpCode.OP_RETURN:
                {
                    int b = i.GETARG_B();
                    if (b != 0)
                    {
                        Top = Stack[ra.Index + b - 1];
                    }
                    if (cl.Proto.P.Count > 0)
                    {
                        F_Close(Stack[env.Base]);
                    }
                    b = D_PosCall(ra.Index);
                    if ((ci.CallStatus & CallStatus.CIST_REENTRY) == 0)
                    {
                        return;
                    }
                    else
                    {
                        ci = CI;
                        if (b != 0)
                        {
                            Top = Stack[ci.TopIndex];
                        }
                        goto newframe;
                    }
                }

                case OpCode.OP_FORLOOP:
                {
                    var ra1 = Stack[ra.Index + 1];
                    var ra2 = Stack[ra.Index + 2];
                    var ra3 = Stack[ra.Index + 3];

                    var step  = ra2.V.NValue;
                    var idx   = ra.V.NValue + step;                                     // increment index
                    var limit = ra1.V.NValue;

                    if ((0 < step) ? idx <= limit
                                                                           : limit <= idx)
                    {
                        ci.SavedPc.Index += i.GETARG_sBx();                 // jump back
                        ra.V.SetNValue(idx);                                // updateinternal index...
                        ra3.V.SetNValue(idx);                               // ... and external index
                    }

                    break;
                }

                case OpCode.OP_FORPREP:
                {
                    var init  = new TValue();
                    var limit = new TValue();
                    var step  = new TValue();

                    var ra1 = Stack[ra.Index + 1];
                    var ra2 = Stack[ra.Index + 2];

                    // WHY: why limit is not used ?

                    if (!V_ToNumber(ra, ref init))
                    {
                        G_RunError("'for' initial value must be a number");
                    }
                    if (!V_ToNumber(ra1, ref limit))
                    {
                        G_RunError("'for' limit must be a number");
                    }
                    if (!V_ToNumber(ra2, ref step))
                    {
                        G_RunError("'for' step must be a number");
                    }

                    ra.V.SetNValue(init.NValue - step.NValue);
                    ci.SavedPc.Index += i.GETARG_sBx();

                    break;
                }

                case OpCode.OP_TFORCALL:
                {
                    int rai = ra.Index;
                    int cbi = ra.Index + 3;
                    Stack[cbi + 2].V.SetObj(ref Stack[rai + 2].V);
                    Stack[cbi + 1].V.SetObj(ref Stack[rai + 1].V);
                    Stack[cbi].V.SetObj(ref Stack[rai].V);

                    StkId callBase = Stack[cbi];
                    Top = Stack[cbi + 3];                           // func. +2 args (state and index)

                    D_Call(callBase, i.GETARG_C(), true);

                    env.Base = ci.BaseIndex;

                    Top   = Stack[ci.TopIndex];
                    i     = ci.SavedPc.ValueInc;                                // go to next instruction
                    env.I = i;
                    ra    = env.RA;

                    DumpStack(env.Base);
#if DEBUG_INSTRUCTION
                    ULDebug.Log("[VM] ============================================================ OP_TFORCALL Instruction: " + i);
#endif

                    Utl.Assert(i.GET_OPCODE() == OpCode.OP_TFORLOOP);
                    goto l_tforloop;
                }

                case OpCode.OP_TFORLOOP:
l_tforloop:
                    {
                        StkId ra1 = Stack[ra.Index + 1];
                        if (!ra1.V.TtIsNil())                           // continue loop?
                        {
                            ra.V.SetObj(ref ra1.V);
                            ci.SavedPc += i.GETARG_sBx();
                        }
                        break;
                    }

                // sets the values for a range of array elements in a table(RA)
                // RA -> table
                // RB -> number of elements to set
                // C  -> encodes the block number of the table to be initialized
                // the values used to initialize the table are located in
                //   R(A+1), R(A+2) ...
                case OpCode.OP_SETLIST:
                {
                    int n = i.GETARG_B();
                    int c = i.GETARG_C();
                    if (n == 0)
                    {
                        n = (Top.Index - ra.Index) - 1;
                    }
                    if (c == 0)
                    {
                        Utl.Assert(ci.SavedPc.Value.GET_OPCODE() == OpCode.OP_EXTRAARG);
                        c = ci.SavedPc.ValueInc.GETARG_Ax();
                    }

                    var tbl = ra.V.HValue();
                    Utl.Assert(tbl != null);

                    int last = ((c - 1) * LuaDef.LFIELDS_PER_FLUSH) + n;
                    int rai  = ra.Index;
                    for (; n > 0; --n)
                    {
                        tbl.SetInt(last--, ref Stack[rai + n].V);
                    }
#if DEBUG_OP_SETLIST
                    ULDebug.Log("[VM] ==== OP_SETLIST ci.Top:" + ci.Top.Index);
                    ULDebug.Log("[VM] ==== OP_SETLIST Top:" + Top.Index);
#endif
                    Top = Stack[ci.TopIndex];                             // correct top (in case of previous open call)
                    break;
                }

                case OpCode.OP_CLOSURE:
                {
                    LuaProto p = cl.Proto.P[i.GETARG_Bx()];
                    V_PushClosure(p, cl.Upvals, env.Base, ra);
#if DEBUG_OP_CLOSURE
                    ULDebug.Log("OP_CLOSURE:" + ra.Value);
                    var racl = ra.Value as LuaLClosure;
                    if (racl != null)
                    {
                        for (int ii = 0; ii < racl.Upvals.Count; ++ii)
                        {
                            ULDebug.Log(ii + " ) " + racl.Upvals[ii]);
                        }
                    }
#endif
                    break;
                }

                /// <summary>
                /// VARARG implements the vararg operator `...' in expressions.
                /// VARARG copies B-1 parameters into a number of registers
                /// starting from R(A), padding with nils if there aren't enough values.
                /// If B is 0, VARARG copies as many values as it can based on
                /// the number of parameters passed.
                /// If a fixed number of values is required, B is a value greater than 1.
                /// If any number of values is required, B is 0.
                /// </summary>
                case OpCode.OP_VARARG:
                {
                    int b = i.GETARG_B() - 1;
                    int n = (env.Base - ci.FuncIndex) - cl.Proto.NumParams - 1;
                    if (b < 0)                              // B == 0?
                    {
                        b = n;
                        D_CheckStack(n);
                        ra  = env.RA;                                // previous call may change the stack
                        Top = Stack[ra.Index + n];
                    }

                    var p = ra.Index;
                    var q = env.Base - n;
                    for (int j = 0; j < b; ++j)
                    {
                        if (j < n)
                        {
                            Stack[p++].V.SetObj(ref Stack[q++].V);
                        }
                        else
                        {
                            Stack[p++].V.SetNilValue();
                        }
                    }
                    break;
                }

                case OpCode.OP_EXTRAARG:
                {
                    Utl.Assert(false);
                    V_NotImplemented(i);
                    break;
                }

                default:
                    V_NotImplemented(i);
                    break;
                }
            }
        }
Beispiel #24
0
        private bool V_EqualObject(ref TValue t1, ref TValue t2, bool rawEq)
        {
            Utl.Assert(t1.Tt == t2.Tt);
            StkId tm = null;

            switch (t1.Tt)
            {
            case (int)LuaType.LUA_TNIL:
                return(true);

            case (int)LuaType.LUA_TNUMBER:
                return(t1.NValue == t2.NValue);

            case (int)LuaType.LUA_TUINT64:
                return(t1.UInt64Value == t2.UInt64Value);

            case (int)LuaType.LUA_TBOOLEAN:
                return(t1.BValue() == t2.BValue());

            case (int)LuaType.LUA_TSTRING:
                return(t1.SValue() == t2.SValue());

            case (int)LuaType.LUA_TUSERDATA:
            {
                var ud1 = t1.RawUValue();
                var ud2 = t2.RawUValue();
                if (ud1.Value == ud2.Value)
                {
                    return(true);
                }
                if (rawEq)
                {
                    return(false);
                }
                tm = GetEqualTM(ud1.MetaTable, ud2.MetaTable, TMS.TM_EQ);
                break;
            }

            case (int)LuaType.LUA_TTABLE:
            {
                var tbl1 = t1.HValue();
                var tbl2 = t2.HValue();
                if (System.Object.ReferenceEquals(tbl1, tbl2))
                {
                    return(true);
                }
                if (rawEq)
                {
                    return(false);
                }
                tm = GetEqualTM(tbl1.MetaTable, tbl2.MetaTable, TMS.TM_EQ);
                break;
            }

            default:
                return(t1.OValue == t2.OValue);
            }
            if (tm == null)              // no TM?
            {
                return(false);
            }
            CallTM(ref tm.V, ref t1, ref t2, Top, true);              // call TM
            return(!IsFalse(ref Top.V));
        }
Beispiel #25
0
 private void G_ConcatError(StkId p1, StkId p2)
 {
     // TODO
 }
Beispiel #26
0
        private string GetObjName(LuaProto proto, int lastpc, int reg,
                                  out string name)
        {
            name = F_GetLocalName(proto, reg + 1, lastpc);
            if (name != null)              // is a local?
            {
                return("local");
            }

            // else try symbolic execution
            int pc = FindSetReg(proto, lastpc, reg);

            if (pc != -1)
            {
                Instruction ins = proto.Code[pc];
                OpCode      op  = ins.GET_OPCODE();
                switch (op)
                {
                case OpCode.OP_MOVE: {
                    int b = ins.GETARG_B();                             // move from `b' to `a'
                    if (b < ins.GETARG_A())
                    {
                        return(GetObjName(proto, pc, b, out name));
                    }
                    break;
                }

                case OpCode.OP_GETTABUP:
                case OpCode.OP_GETTABLE: {
                    int    k  = ins.GETARG_C();
                    int    t  = ins.GETARG_B();
                    string vn = (op == OpCode.OP_GETTABLE)
                                                        ? F_GetLocalName(proto, t + 1, pc)
                                                        : UpvalName(proto, t);
                    KName(proto, pc, k, out name);
                    return((vn == LuaDef.LUA_ENV) ? "global" : "field");
                }

                case OpCode.OP_GETUPVAL: {
                    name = UpvalName(proto, ins.GETARG_B());
                    return("upvalue");
                }

                case OpCode.OP_LOADK:
                case OpCode.OP_LOADKX: {
                    int b = (op == OpCode.OP_LOADK)
                                                        ? ins.GETARG_Bx()
                                                        : proto.Code[pc + 1].GETARG_Ax();
                    StkId val = proto.K[b];
                    if (val.V.TtIsString())
                    {
                        name = val.V.SValue();
                        return("constant");
                    }
                    break;
                }

                case OpCode.OP_SELF: {
                    int k = ins.GETARG_C();                             // key index
                    KName(proto, pc, k, out name);
                    return("method");
                }

                default: break;                         // go through to return null
                }
            }

            return(null);            // could not find reasonable name
        }
Beispiel #27
0
 private bool IsInStack(CallInfo ci, StkId o)
 {
     // TODO
     return(false);
 }
Beispiel #28
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;
            }
        }
Beispiel #29
0
        private void LoadConstants( LuaProto proto )
        {
            var n = LoadInt();
            #if DEBUG_UNDUMP
            ULDebug.Log( "Load Constants:" + n );
            #endif
            proto.K.Clear();
            for( int i=0; i<n; ++i )
            {
                int t = (int)LoadByte();
            #if DEBUG_UNDUMP
                ULDebug.Log( "Constant Type:" + t );
            #endif
                var v = new StkId();
                switch( t )
                {
                    case (int)LuaType.LUA_TNIL:
                        v.V.SetNilValue();
                        proto.K.Add( v );
                        break;

                    case (int)LuaType.LUA_TBOOLEAN:
                        v.V.SetBValue(LoadBoolean());
                        proto.K.Add( v );
                        break;

                    case (int)LuaType.LUA_TNUMBER:
                        v.V.SetNValue(LoadNumber());
                        proto.K.Add( v );
                        break;

                    case (int)LuaType.LUA_TSTRING:
            #if DEBUG_UNDUMP
                        ULDebug.Log( "LuaType.LUA_TSTRING" );
            #endif
                        v.V.SetSValue(LoadString());
                        proto.K.Add( v );
                        break;

                    default:
                        throw new UndumpException(
                            "LoadConstants unknown type: " + t );
                }
            }

            n = LoadInt();
            #if DEBUG_UNDUMP
            ULDebug.Log( "Load Functions:" + n );
            #endif
            proto.P.Clear();
            for( int i=0; i<n; ++i )
            {
                proto.P.Add( LoadFunction() );
            }
        }
Beispiel #30
0
 public LuaCsClosureValue( CSharpFunctionDelegate f, int numUpvalues )
 {
     F = f;
     Upvals = new StkId[numUpvalues];
     for(int i=0; i<numUpvalues; ++i) {
         var newItem = new StkId();
         Upvals[i] = newItem;
         newItem.SetList(Upvals);
         newItem.SetIndex(i);
     }
 }
Beispiel #31
0
		private void V_SetTable(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 oldval = tbl.Get(ref key.V);
					if(!oldval.V.TtIsNil()) {
						tbl.Set(ref key.V, ref val.V);
						return;
					}

					// check meta method
					tmObj = FastTM(tbl.MetaTable, TMS.TM_NEWINDEX);
					if( tmObj == null ) {
						tbl.Set(ref key.V, ref val.V);
						return;
					}

					// else will try the tag method
				}
				else {
					tmObj = T_GetTMByObj(ref t.V, TMS.TM_NEWINDEX);
					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, false );
					return;
				}

				t = tmObj;
			}
			G_RunError( "loop in settable" );
		}
Beispiel #32
0
 public static StkId inc(ref StkId val)
 {
     var ret = val;
     val = val.List[val.Index+1];
     return ret;
 }
Beispiel #33
0
		private void V_PushClosure( LuaProto p, LuaUpvalue[] encup, int stackBase, StkId ra )
		{
			var ncl = new LuaLClosureValue( p );
			ra.V.SetClLValue(ncl);
			for( int i=0; i<p.Upvalues.Count; ++i )
			{
				// ULDebug.Log( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ V_PushClosure i:" + i );
				// ULDebug.Log( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ V_PushClosure InStack:" + p.Upvalues[i].InStack );
				// ULDebug.Log( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ V_PushClosure Index:" + p.Upvalues[i].Index );

				if( p.Upvalues[i].InStack ) // upvalue refers to local variable
					ncl.Upvals[i] = F_FindUpval(
						Stack[stackBase + p.Upvalues[i].Index] );
				else	// get upvalue from enclosing function
					ncl.Upvals[i] = encup[ p.Upvalues[i].Index ];
			}
		}
Beispiel #34
0
        public bool Next(StkId key, StkId val)
        {
            // find original element
            int i = FindIndex(key);

            // try first array part
            for(i++; i<ArrayPart.Length; ++i) {
                if(!ArrayPart[i].V.TtIsNil()) {
                    key.V.SetNValue(i+1);
                    val.V.SetObj(ref ArrayPart[i].V);
                    return true;
                }
            }

            // then hash part
            for(i-=ArrayPart.Length; i<HashPart.Length; ++i) {
                if(!HashPart[i].Val.V.TtIsNil()) {
                    key.V.SetObj(ref HashPart[i].Key.V);
                    val.V.SetObj(ref HashPart[i].Val.V);
                    return true;
                }
            }
            return false;
        }
Beispiel #35
0
		private void V_ObjLen( StkId ra, StkId rb )
		{
			StkId tmObj = null;

			var rbt = rb.V.HValue();
			if( rbt != null )
			{
				tmObj = FastTM( rbt.MetaTable, TMS.TM_LEN );
				if( tmObj != null )
					goto calltm;
				ra.V.SetNValue(rbt.Length);
				return;
			}

			var rbs = rb.V.SValue();
			if( rbs != null )
			{
				ra.V.SetNValue(rbs.Length);
				return;
			}

			tmObj = T_GetTMByObj(ref rb.V, TMS.TM_LEN);
			if(tmObj.V.TtIsNil())
				G_TypeError( rb, "get length of" );

calltm:
			CallTM( ref tmObj.V, ref rb.V, ref rb.V, ra, true );
		}
Beispiel #36
0
        /*
        ** returns the index of a `key' for table traversals. First goes all
        ** elements in the array part, then elements in the hash part. The
        ** beginning of a traversal is signaled by -1.
        */
        private int FindIndex(StkId key)
        {
            if(key.V.TtIsNil())
                { return -1; }

            // is `key' inside array part?
            int i = ArrayIndex(ref key.V);
            if(0 < i && i <= ArrayPart.Length)
                { return i-1; }

            var n = GetHashNode(ref key.V);
            // check whether `key' is somewhere in the chain
            for(;;) {
                if(L.V_RawEqualObj(ref n.Key.V, ref key.V))
                    { return ArrayPart.Length + n.Index; }
                n = n.Next;

                // key not found
                if(n == null) { L.G_RunError("invalid key to 'next'"); }
            }
        }
Beispiel #37
0
		private bool V_ToNumber( StkId obj, ref TValue n )
		{
			if( obj.V.TtIsNumber() ) {
				n.SetNValue( obj.V.NValue );
				return true;
			}
			if( obj.V.TtIsString() ) {
				double val;
				if( O_Str2Decimal(obj.V.SValue(), out val) ) {
					n.SetNValue( val );
					return true;
				}
			}

			return false;
		}
Beispiel #38
0
		private bool V_LessThan( StkId lhs, StkId rhs )
		{
			// compare number
			if(lhs.V.TtIsNumber() && rhs.V.TtIsNumber()) {
				return lhs.V.NValue < rhs.V.NValue;
			}

			// compare string
			if(lhs.V.TtIsString() && rhs.V.TtIsString()) {
				return string.Compare(lhs.V.SValue(), rhs.V.SValue()) < 0;
			}

			bool error;
			var res = CallOrderTM( lhs, rhs, TMS.TM_LT, out error );
			if( error )
			{
				G_OrderError( lhs, rhs );
				return false;
			}
			return res;
		}
Beispiel #39
0
        /// <summary>
        /// return true if function has been executed
        /// </summary>
        private bool D_PreCall(StkId func, int nResults)
        {
            // prepare for Lua call

#if DEBUG_D_PRE_CALL
            ULDebug.Log("============================ D_PreCall func:" + func);
#endif

            int funcIndex = func.Index;
            if (!func.V.TtIsFunction())
            {
                // not a function
                // retry with `function' tag method
                func = tryFuncTM(func);

                // now it must be a function
                return(D_PreCall(func, nResults));
            }

            if (func.V.ClIsLuaClosure())
            {
                var cl = func.V.ClLValue();
                Utl.Assert(cl != null);
                var p = cl.Proto;

                D_CheckStack(p.MaxStackSize + p.NumParams);
                func = Stack[funcIndex];

                // 补全参数
                int n = (Top.Index - func.Index) - 1;
                for ( ; n < p.NumParams; ++n)
                {
                    StkId.inc(ref Top).V.SetNilValue();
                }

                int stackBase = (!p.IsVarArg) ? (func.Index + 1) : AdjustVarargs(p, n);

                CI            = ExtendCI();
                CI.NumResults = nResults;
                CI.FuncIndex  = func.Index;
                CI.BaseIndex  = stackBase;
                CI.TopIndex   = stackBase + p.MaxStackSize;
                Utl.Assert(CI.TopIndex <= StackLast);
                CI.SavedPc    = new InstructionPtr(p.Code, 0);
                CI.CallStatus = CallStatus.CIST_LUA;

                Top = Stack[CI.TopIndex];

                return(false);
            }

            if (func.V.ClIsCsClosure())
            {
                var cscl = func.V.ClCsValue();
                Utl.Assert(cscl != null);

                D_CheckStack(LuaDef.LUA_MINSTACK);
                func = Stack[funcIndex];

                CI            = ExtendCI();
                CI.NumResults = nResults;
                CI.FuncIndex  = func.Index;
                CI.TopIndex   = Top.Index + LuaDef.LUA_MINSTACK;
                CI.CallStatus = CallStatus.CIST_NONE;

                // do the actual call
                int n = cscl.F(this);

                // poscall
                D_PosCall(Top.Index - n);

                return(true);
            }

            throw new System.NotImplementedException();
        }
Beispiel #40
0
		public static int AddK( FuncState fs, ref TValue key, ref TValue v )
		{
			int idx;
			if( fs.H.TryGetValue( key, out idx ) )
				return idx;

			idx = fs.Proto.K.Count;
			fs.H.Add( key, idx );

			var newItem = new StkId();
			newItem.V.SetObj(ref v);
			fs.Proto.K.Add(newItem);
			// Debug.Log("--------- ADD K ------- " + fs.Proto.K.Count + " line:" + fs.Lexer.LineNumber + " key:" + key);
			return idx;
		}
Beispiel #41
0
		private bool V_LessEqual( StkId lhs, StkId rhs )
		{
			// compare number
			if(lhs.V.TtIsNumber() && rhs.V.TtIsNumber()) {
				return lhs.V.NValue <= rhs.V.NValue;
			}

			// compare string
			if(lhs.V.TtIsString() && rhs.V.TtIsString()) {
				return string.Compare(lhs.V.SValue(), rhs.V.SValue()) <= 0;
			}

			// first try `le'
			bool error;
			var res = CallOrderTM( lhs, rhs, TMS.TM_LE, out error );
			if( !error )
				return res;

			// else try `lt'
			res = CallOrderTM( rhs, lhs, TMS.TM_LT, out error );
			if( !error )
				return res;

			G_OrderError( lhs, rhs );
			return false;
		}