Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1205,20 +1205,20 @@ private void ExecTblInitN(Instruction i)
tbl.Table.Set(key, val.ToScalar());
}

DynValue lastBurnedValueInIndexSet;
private int ExecIndexSet(Instruction i, int instructionPtr)
{
int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here

// stack: vals.. - base - index
bool isNameIndex = i.OpCode == OpCode.IndexSetN;
bool isMultiIndex = (i.OpCode == OpCode.IndexSetL);
bool isMultiIndex = i.OpCode == OpCode.IndexSetL;

DynValue originalIdx = i.Value ?? m_ValueStack.Pop();
DynValue idx = originalIdx.ToScalar();
DynValue obj = m_ValueStack.Pop().ToScalar();
var value = GetStoreValue(i);
DynValue h = null;

DynValue value = GetStoreValue(i);
DynValue newIndexMetaMethod;

while (nestedMetaOps > 0)
{
Expand All @@ -1235,9 +1235,9 @@ private int ExecIndexSet(Instruction i, int instructionPtr)
}
}

h = GetMetamethodRaw(obj, "__newindex");
newIndexMetaMethod = GetMetamethodRaw(obj, "__newindex");

if (h == null || h.IsNil())
if (newIndexMetaMethod == null || newIndexMetaMethod.IsNil())
{
if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index a table. userdata expected");

Expand All @@ -1258,27 +1258,38 @@ private int ExecIndexSet(Instruction i, int instructionPtr)
}
else
{
h = GetMetamethodRaw(obj, "__newindex");
newIndexMetaMethod = GetMetamethodRaw(obj, "__newindex");

if (h == null || h.IsNil())
if (newIndexMetaMethod == null || newIndexMetaMethod.IsNil())
throw ScriptRuntimeException.IndexType(obj);
}

if (h.Type == DataType.Function || h.Type == DataType.ClrFunction)
if (newIndexMetaMethod.Type == DataType.Function || newIndexMetaMethod.Type == DataType.ClrFunction)
{
if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index through metamethods. userdata expected");
m_ValueStack.Pop(); // burn extra value ?

m_ValueStack.Push(h);
// Burn extra value
DynValue burnedValue = m_ValueStack.Pop();
if (burnedValue.Type != DataType.Void)
{
lastBurnedValueInIndexSet = burnedValue;
}
// Restore burned value
if (value.Type == DataType.Void && lastBurnedValueInIndexSet != null)
{
value = lastBurnedValueInIndexSet;
lastBurnedValueInIndexSet = null;
}

m_ValueStack.Push(newIndexMetaMethod);
m_ValueStack.Push(obj);
m_ValueStack.Push(idx);
m_ValueStack.Push(value);
return Internal_ExecCall(3, instructionPtr);
}
else
{
obj = h;
h = null;
obj = newIndexMetaMethod;
}
}
throw ScriptRuntimeException.LoopInNewIndex();
Expand All @@ -1290,14 +1301,13 @@ private int ExecIndex(Instruction i, int instructionPtr)

// stack: base - index
bool isNameIndex = i.OpCode == OpCode.IndexN;

bool isMultiIndex = (i.OpCode == OpCode.IndexL);
bool isMultiIndex = i.OpCode == OpCode.IndexL;

DynValue originalIdx = i.Value ?? m_ValueStack.Pop();
DynValue idx = originalIdx.ToScalar();
DynValue obj = m_ValueStack.Pop().ToScalar();

DynValue h = null;
DynValue indexMetaMethod;


while (nestedMetaOps > 0)
Expand All @@ -1317,9 +1327,9 @@ private int ExecIndex(Instruction i, int instructionPtr)
}
}

h = GetMetamethodRaw(obj, "__index");
indexMetaMethod = GetMetamethodRaw(obj, "__index");

if (h == null || h.IsNil())
if (indexMetaMethod == null || indexMetaMethod.IsNil())
{
if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index a table. userdata expected");

Expand All @@ -1343,33 +1353,27 @@ private int ExecIndex(Instruction i, int instructionPtr)
}
else
{
h = GetMetamethodRaw(obj, "__index");
indexMetaMethod = GetMetamethodRaw(obj, "__index");

if (h == null || h.IsNil())
if (indexMetaMethod == null || indexMetaMethod.IsNil())
throw ScriptRuntimeException.IndexType(obj);
}

if (h.Type == DataType.Function || h.Type == DataType.ClrFunction)
if (indexMetaMethod.Type == DataType.Function || indexMetaMethod.Type == DataType.ClrFunction)
{
if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index through metamethods. userdata expected");
m_ValueStack.Push(h);
m_ValueStack.Push(indexMetaMethod);
m_ValueStack.Push(obj);
m_ValueStack.Push(idx);
return Internal_ExecCall(2, instructionPtr);
}
else
{
obj = h;
h = null;
obj = indexMetaMethod;
}
}

throw ScriptRuntimeException.LoopInIndex();
}





}
}