private int ExecIndex(Instruction i, int instructionPtr) { int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here // stack: base - index DynValue idx = i.Value ?? m_ValueStack.Pop().ToScalar(); DynValue obj = m_ValueStack.Pop().ToScalar(); DynValue h = null; while (nestedMetaOps > 0) { --nestedMetaOps; if (obj.Type == DataType.Table) { var v = obj.Table.Get(idx); if (!v.IsNil()) { m_ValueStack.Push(v.AsReadOnly()); return(instructionPtr); } h = GetMetamethod(obj, "__index"); if (h == null || h.IsNil()) { m_ValueStack.Push(DynValue.Nil); return(instructionPtr); } } else if (obj.Type == DataType.UserData) { UserData ud = obj.UserData; var v = ud.Descriptor.Index(this.GetScript(), ud.Object, idx); if (v == null) { throw ScriptRuntimeException.UserDataMissingField(ud.Descriptor.Name, idx.String); } m_ValueStack.Push(v.AsReadOnly()); return(instructionPtr); } else { h = GetMetamethod(obj, "__index"); if (h == null || h.IsNil()) { throw ScriptRuntimeException.IndexType(obj); } } if (h.Type == DataType.Function || h.Type == DataType.ClrFunction) { m_ValueStack.Push(h); m_ValueStack.Push(obj); m_ValueStack.Push(idx); return(Internal_ExecCall(2, instructionPtr)); } else { obj = h; h = null; } } throw ScriptRuntimeException.LoopInIndex(); }