|
|
@@ -37,34 +37,40 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
m_ValueStack.Push(i.Value);
|
|
|
break;
|
|
|
case OpCode.Add:
|
|
|
- ExecAdd(i);
|
|
|
+ instructionPtr = ExecAdd(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Concat:
|
|
|
- ExecConcat(i);
|
|
|
+ instructionPtr = ExecConcat(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Neg:
|
|
|
- ExecNeg(i);
|
|
|
+ instructionPtr = ExecNeg(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Sub:
|
|
|
- ExecSub(i);
|
|
|
+ instructionPtr = ExecSub(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Mul:
|
|
|
- ExecMul(i);
|
|
|
+ instructionPtr = ExecMul(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Div:
|
|
|
- ExecDiv(i);
|
|
|
+ instructionPtr = ExecDiv(i, instructionPtr);
|
|
|
+ break;
|
|
|
+ case OpCode.Mod:
|
|
|
+ instructionPtr = ExecMod(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Power:
|
|
|
- ExecPower(i);
|
|
|
+ instructionPtr = ExecPower(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Eq:
|
|
|
- ExecEq(i);
|
|
|
+ instructionPtr = ExecEq(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.LessEq:
|
|
|
- ExecLessEq(i);
|
|
|
+ instructionPtr = ExecLessEq(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Less:
|
|
|
- ExecLess(i);
|
|
|
+ instructionPtr = ExecLess(i, instructionPtr);
|
|
|
+ break;
|
|
|
+ case OpCode.Len:
|
|
|
+ instructionPtr = ExecLen(i, instructionPtr);
|
|
|
break;
|
|
|
case OpCode.Call:
|
|
|
instructionPtr = Internal_ExecCall(i.NumVal, instructionPtr);
|
|
|
@@ -103,7 +109,7 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
instructionPtr = i.NumVal;
|
|
|
break;
|
|
|
case OpCode.MkTuple:
|
|
|
- m_ValueStack.Push(RValue.FromPotentiallyNestedTuple(StackTopToArrayReverse(i.NumVal, true)));
|
|
|
+ ExecMkTuple(i);
|
|
|
break;
|
|
|
case OpCode.Enter:
|
|
|
NilifyBlockData(i.Block);
|
|
|
@@ -118,6 +124,9 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
case OpCode.BeginFn:
|
|
|
ExecBeginFn(i);
|
|
|
break;
|
|
|
+ case OpCode.ToBool:
|
|
|
+ m_ValueStack.Push(m_ValueStack.Pop().AsBoolean());
|
|
|
+ break;
|
|
|
case OpCode.Args:
|
|
|
ExecArgs(i);
|
|
|
break;
|
|
|
@@ -130,7 +139,7 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
ExecIncr(i);
|
|
|
break;
|
|
|
case OpCode.ToNum:
|
|
|
- m_ValueStack.Push(m_ValueStack.Pop().AsNumber());
|
|
|
+ ExecToNum(i);
|
|
|
break;
|
|
|
case OpCode.SymStorN:
|
|
|
ExecSymStorN(i);
|
|
|
@@ -153,9 +162,6 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
case OpCode.NewTable:
|
|
|
m_ValueStack.Push(new RValue(new Table()));
|
|
|
break;
|
|
|
- case OpCode.Len:
|
|
|
- ExecLen(i);
|
|
|
- break;
|
|
|
case OpCode.IterPrep:
|
|
|
ExecIterPrep(i);
|
|
|
break;
|
|
|
@@ -183,8 +189,35 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
|
|
|
}
|
|
|
|
|
|
+ private void ExecMkTuple(Instruction i)
|
|
|
+ {
|
|
|
+ //RValue[] t = new RValue[i.NumVal];
|
|
|
+ //for(int ii = i.NumVal - 1; ii >= 0; ii--)
|
|
|
+ //{
|
|
|
+ // if (ii == i.NumVal - 1)
|
|
|
+ // {
|
|
|
+ // t[ii] = m_ValueStack.Pop();
|
|
|
+ // }
|
|
|
+ // else
|
|
|
+ // {
|
|
|
+ // t[ii] = m_ValueStack.Pop().ToSimplestValue();
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+
|
|
|
|
|
|
+ var explist = StackTopToArrayReverse(i.NumVal, true);
|
|
|
+ var v = RValue.FromPotentiallyNestedTuple(explist);
|
|
|
+ m_ValueStack.Push(v);
|
|
|
+ }
|
|
|
|
|
|
+ private void ExecToNum(Instruction i)
|
|
|
+ {
|
|
|
+ double? v = m_ValueStack.Pop().AsNumber();
|
|
|
+ if (v.HasValue)
|
|
|
+ m_ValueStack.Push(new RValue(v.Value));
|
|
|
+ else
|
|
|
+ throw new ScriptRuntimeException(null, "Can't convert value to number");
|
|
|
+ }
|
|
|
|
|
|
|
|
|
private void ExecIterUpd(Instruction i)
|
|
|
@@ -348,6 +381,7 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
private int Internal_ExecCall(int argsCount, int instructionPtr)
|
|
|
{
|
|
|
RValue fn = m_ValueStack.Peek(argsCount);
|
|
|
@@ -374,7 +408,26 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- throw new NotImplementedException("Meta");
|
|
|
+ if (fn.Meta != null)
|
|
|
+ {
|
|
|
+ var m = fn.Meta.Table.RawGet("__call");
|
|
|
+
|
|
|
+ if (m != null && m.Type != DataType.Nil)
|
|
|
+ {
|
|
|
+ RValue[] tmp = new RValue[argsCount + 1];
|
|
|
+ for (int i = 0; i < argsCount + 1; i++)
|
|
|
+ tmp[i] = m_ValueStack.Pop();
|
|
|
+
|
|
|
+ m_ValueStack.Push(m);
|
|
|
+
|
|
|
+ for (int i = argsCount; i >= 0; i--)
|
|
|
+ m_ValueStack.Push(tmp[i]);
|
|
|
+
|
|
|
+ return Internal_ExecCall(argsCount + 1, instructionPtr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new NotImplementedException("Can't call non function");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -440,239 +493,409 @@ namespace MoonSharp.Interpreter.Execution.VM
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- private void ExecLen(Instruction i)
|
|
|
+ private void Internal_Assign(LRef l, RValue r)
|
|
|
{
|
|
|
- RValue r = m_ValueStack.Pop();
|
|
|
+ if (l.i_Type == LRefType.Index)
|
|
|
+ {
|
|
|
+ l.i_TableRefObject.Table[l.i_TableRefIndex] = r;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ this.AssignGenericSymbol(l, r.ToSimplestValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (r.Type == DataType.Table)
|
|
|
- m_ValueStack.Push(new RValue(r.Table.Length));
|
|
|
- else if (r.Type == DataType.String)
|
|
|
- m_ValueStack.Push(new RValue(r.String.Length));
|
|
|
+ private void Internal_Assign(RValue l, RValue r)
|
|
|
+ {
|
|
|
+ if (l.Type == DataType.Symbol)
|
|
|
+ {
|
|
|
+ Internal_Assign(l.Symbol, r);
|
|
|
+ }
|
|
|
else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ {
|
|
|
+ throw new NotImplementedException("How should we manage this ?");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void ExecAdd(Instruction i)
|
|
|
+ private void ExecIndexGet(Instruction i, bool methodCall)
|
|
|
{
|
|
|
- RValue r = m_ValueStack.Pop();
|
|
|
- RValue l = m_ValueStack.Pop();
|
|
|
+ RValue indexValue = m_ValueStack.Pop();
|
|
|
+ RValue baseValue = m_ValueStack.Pop();
|
|
|
|
|
|
- if (r.Type == DataType.Number && l.Type == DataType.Number)
|
|
|
- m_ValueStack.Push(new RValue(l.Number + r.Number));
|
|
|
+ if (baseValue.Type != DataType.Table)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException("META! : Can't index non-table yet");
|
|
|
+ }
|
|
|
else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ {
|
|
|
+ RValue v = baseValue.Table[indexValue];
|
|
|
+ m_ValueStack.Push(v.AsReadOnly());
|
|
|
+ }
|
|
|
+
|
|
|
+ if (methodCall)
|
|
|
+ m_ValueStack.Push(baseValue);
|
|
|
}
|
|
|
|
|
|
- private void ExecConcat(Instruction i)
|
|
|
+ private void ExecIndexRef(Instruction i, bool keepOnStack)
|
|
|
{
|
|
|
- RValue r = m_ValueStack.Pop();
|
|
|
- RValue l = m_ValueStack.Pop();
|
|
|
+ RValue indexValue = m_ValueStack.Pop();
|
|
|
+ RValue baseValue = keepOnStack ? m_ValueStack.Peek() : m_ValueStack.Pop();
|
|
|
|
|
|
- if ((r.Type == DataType.String || r.Type == DataType.Number) && (l.Type == DataType.String || l.Type == DataType.Number))
|
|
|
- m_ValueStack.Push(new RValue(l.AsString() + r.AsString()));
|
|
|
+ if (baseValue.Type != DataType.Table)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException("META! : Can't index non-table yet");
|
|
|
+ }
|
|
|
else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ {
|
|
|
+ LRef s = LRef.ObjIndex(baseValue, indexValue);
|
|
|
+ m_ValueStack.Push(new RValue(s));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void ExecSub(Instruction i)
|
|
|
+ private void ExecStore(Instruction i)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (r.Type == DataType.Number && l.Type == DataType.Number)
|
|
|
- m_ValueStack.Push(new RValue(l.Number - r.Number));
|
|
|
- else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ Internal_Assign(l, r);
|
|
|
}
|
|
|
|
|
|
- private void ExecNeg(Instruction i)
|
|
|
+
|
|
|
+ private void ExecSymStorN(Instruction i)
|
|
|
{
|
|
|
- RValue r = m_ValueStack.Pop();
|
|
|
+ this.AssignGenericSymbol(i.Symbol, m_ValueStack.Peek());
|
|
|
+ }
|
|
|
|
|
|
- if (r.Type == DataType.Number)
|
|
|
- m_ValueStack.Push(new RValue(-r.Number));
|
|
|
- else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+
|
|
|
+ private void ExecAssign(Instruction i)
|
|
|
+ {
|
|
|
+ Slice<RValue> rvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2, i.NumVal2, false);
|
|
|
+ Slice<RValue> lvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2 - i.NumVal, i.NumVal, false);
|
|
|
+
|
|
|
+ Internal_MultiAssign(lvalues, rvalues);
|
|
|
+
|
|
|
+ m_ValueStack.CropAtCount(m_ValueStack.Count - i.NumVal - i.NumVal2);
|
|
|
}
|
|
|
- private void ExecPower(Instruction i)
|
|
|
+
|
|
|
+ private void Internal_MultiAssign(Slice<RValue> lValues, Slice<RValue> rValues)
|
|
|
{
|
|
|
- RValue r = m_ValueStack.Pop();
|
|
|
- RValue l = m_ValueStack.Pop();
|
|
|
+ int li = 0;
|
|
|
+ int rValues_Count = rValues.Count;
|
|
|
+ int lValues_Count = lValues.Count;
|
|
|
|
|
|
- if (r.Type == DataType.Number && l.Type == DataType.Number)
|
|
|
- m_ValueStack.Push(new RValue(Math.Pow(l.Number, r.Number)));
|
|
|
- else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ for (int ri = 0; ri < rValues_Count && li < lValues_Count; ri++, li++)
|
|
|
+ {
|
|
|
+ RValue vv = rValues[ri];
|
|
|
+
|
|
|
+ if ((ri != rValues_Count - 1) || (vv.Type != DataType.Tuple))
|
|
|
+ {
|
|
|
+ Internal_Assign(lValues[li], vv.ToSingleValue());
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ for (int rri = 0, len = vv.Tuple.Length; rri < len && li < lValues_Count; rri++, li++)
|
|
|
+ {
|
|
|
+ Internal_Assign(lValues[li], vv.Tuple[rri].ToSingleValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void ExecMul(Instruction i)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private int ExecAdd(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (r.Type == DataType.Number && l.Type == DataType.Number)
|
|
|
- m_ValueStack.Push(new RValue(l.Number * r.Number));
|
|
|
- else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+ double? ln = l.AsNumber();
|
|
|
+
|
|
|
+ if (ln.HasValue && rn.HasValue)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(ln.Value + rn.Value));
|
|
|
+ return instructionPtr;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__add", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void ExecEq(Instruction i)
|
|
|
+ private int ExecSub(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- m_ValueStack.Push(new RValue(r.Equals(l)));
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+ double? ln = l.AsNumber();
|
|
|
+
|
|
|
+ if (ln.HasValue && rn.HasValue)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(ln.Value - rn.Value));
|
|
|
+ return instructionPtr;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__sub", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void ExecLess(Instruction i)
|
|
|
+
|
|
|
+ private int ExecMul(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (r.Type == DataType.Number && r.Type == DataType.Number)
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+ double? ln = l.AsNumber();
|
|
|
+
|
|
|
+ if (ln.HasValue && rn.HasValue)
|
|
|
{
|
|
|
- m_ValueStack.Push(new RValue(l.Number < r.Number));
|
|
|
+ m_ValueStack.Push(new RValue(ln.Value * rn.Value));
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- throw new NotImplementedException("Comparison between non numbers!");
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mul", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- private void ExecLessEq(Instruction i)
|
|
|
+ }
|
|
|
+
|
|
|
+ private int ExecMod(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (r.Type == DataType.Number && r.Type == DataType.Number)
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+ double? ln = l.AsNumber();
|
|
|
+
|
|
|
+ if (ln.HasValue && rn.HasValue)
|
|
|
{
|
|
|
- m_ValueStack.Push(new RValue(l.Number <= r.Number));
|
|
|
+ m_ValueStack.Push(new RValue(Math.IEEERemainder(ln.Value, rn.Value)));
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- throw new NotImplementedException("Comparison between non numbers!");
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__div", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void ExecDiv(Instruction i)
|
|
|
+ private int ExecDiv(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (r.Type == DataType.Number && l.Type == DataType.Number)
|
|
|
- m_ValueStack.Push(new RValue(l.Number / r.Number));
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+ double? ln = l.AsNumber();
|
|
|
+
|
|
|
+ if (ln.HasValue && rn.HasValue)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(ln.Value / rn.Value));
|
|
|
+ return instructionPtr;
|
|
|
+ }
|
|
|
else
|
|
|
- throw new NotImplementedException("Meta operators");
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__div", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
|
|
|
+ }
|
|
|
}
|
|
|
+ private int ExecPower(Instruction i, int instructionPtr)
|
|
|
+ {
|
|
|
+ RValue r = m_ValueStack.Pop();
|
|
|
+ RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+ double? ln = l.AsNumber();
|
|
|
|
|
|
- private void Internal_Assign(LRef l, RValue r)
|
|
|
- {
|
|
|
- if (l.i_Type == LRefType.Index)
|
|
|
+ if (ln.HasValue && rn.HasValue)
|
|
|
{
|
|
|
- l.i_TableRefObject.Table[l.i_TableRefIndex] = r;
|
|
|
+ m_ValueStack.Push(new RValue(Math.Pow(ln.Value, rn.Value)));
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- this.AssignGenericSymbol(l, r.ToSimplestValue());
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__pow", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non numbers");
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- private void Internal_Assign(RValue l, RValue r)
|
|
|
+
|
|
|
+ private int ExecNeg(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
- if (l.Type == DataType.Symbol)
|
|
|
+ RValue r = m_ValueStack.Pop();
|
|
|
+ double? rn = r.AsNumber();
|
|
|
+
|
|
|
+ if (rn.HasValue)
|
|
|
{
|
|
|
- Internal_Assign(l.Symbol, r);
|
|
|
+ m_ValueStack.Push(new RValue(-rn.Value));
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
+
|
|
|
+ if (r.Type == DataType.Number)
|
|
|
+ m_ValueStack.Push(new RValue(-r.Number));
|
|
|
else
|
|
|
{
|
|
|
- throw new NotImplementedException("How should we manage this ?");
|
|
|
+ int ip = Internal_InvokeUnaryMetaMethod(r, "__unm", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Arithmetic on non number");
|
|
|
}
|
|
|
+
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
|
|
|
- private void ExecIndexGet(Instruction i, bool methodCall)
|
|
|
+
|
|
|
+ private int ExecEq(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
- RValue indexValue = m_ValueStack.Pop();
|
|
|
- RValue baseValue = m_ValueStack.Pop();
|
|
|
+ RValue r = m_ValueStack.Pop();
|
|
|
+ RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (baseValue.Type != DataType.Table)
|
|
|
+ if (object.ReferenceEquals(r, l))
|
|
|
{
|
|
|
- throw new NotImplementedException("META! : Can't index non-table yet");
|
|
|
+ m_ValueStack.Push(new RValue(true));
|
|
|
+ }
|
|
|
+ else if (r.Type != l.Type)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(false));
|
|
|
+ }
|
|
|
+ else if ((l.Type == DataType.Table || l.Type == DataType.UserData) && (l.Meta != null) && (l.Meta == r.Meta))
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__eq", instructionPtr);
|
|
|
+ if (ip < 0)
|
|
|
+ m_ValueStack.Push(new RValue(r.Equals(l)));
|
|
|
+ else
|
|
|
+ return ip;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- RValue v = baseValue.Table[indexValue];
|
|
|
- m_ValueStack.Push(v.AsReadOnly());
|
|
|
+ m_ValueStack.Push(new RValue(r.Equals(l)));
|
|
|
}
|
|
|
|
|
|
- if (methodCall)
|
|
|
- m_ValueStack.Push(baseValue);
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
|
|
|
- private void ExecIndexRef(Instruction i, bool keepOnStack)
|
|
|
+ private int ExecLess(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
- RValue indexValue = m_ValueStack.Pop();
|
|
|
- RValue baseValue = keepOnStack ? m_ValueStack.Peek() : m_ValueStack.Pop();
|
|
|
+ RValue r = m_ValueStack.Pop();
|
|
|
+ RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- if (baseValue.Type != DataType.Table)
|
|
|
+ if (l.Type == DataType.Number && r.Type == DataType.Number)
|
|
|
{
|
|
|
- throw new NotImplementedException("META! : Can't index non-table yet");
|
|
|
+ m_ValueStack.Push(new RValue(l.Number < r.Number));
|
|
|
+ }
|
|
|
+ else if (l.Type == DataType.String && r.Type == DataType.String)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(l.String.CompareTo(r.String) < 0));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- LRef s = LRef.ObjIndex(baseValue, indexValue);
|
|
|
- m_ValueStack.Push(new RValue(s));
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__lt", instructionPtr);
|
|
|
+ if (ip < 0)
|
|
|
+ throw new ScriptRuntimeException(null, "Can't compare on non number non string");
|
|
|
+ else
|
|
|
+ return ip;
|
|
|
}
|
|
|
+
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
|
|
|
- private void ExecStore(Instruction i)
|
|
|
+ private int ExecLessEq(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
RValue r = m_ValueStack.Pop();
|
|
|
RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- Internal_Assign(l, r);
|
|
|
- }
|
|
|
+ if (l.Type == DataType.Number && r.Type == DataType.Number)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(l.Number <= r.Number));
|
|
|
+ }
|
|
|
+ else if (l.Type == DataType.String && r.Type == DataType.String)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(l.String.CompareTo(r.String) <= 0));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__le", instructionPtr);
|
|
|
+ if (ip < 0)
|
|
|
+ {
|
|
|
+ ip = Internal_InvokeBinaryMetaMethod(r, l, "__lt", instructionPtr);
|
|
|
|
|
|
+ if (ip < 0)
|
|
|
+ throw new ScriptRuntimeException(null, "Can't compare on non number non string");
|
|
|
+ else
|
|
|
+ return ip;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return ip;
|
|
|
+ }
|
|
|
|
|
|
- private void ExecSymStorN(Instruction i)
|
|
|
- {
|
|
|
- this.AssignGenericSymbol(i.Symbol, m_ValueStack.Peek());
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- private void ExecAssign(Instruction i)
|
|
|
+ private int ExecLen(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
- Slice<RValue> rvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2, i.NumVal2, false);
|
|
|
- Slice<RValue> lvalues = new Slice<RValue>(m_ValueStack, m_ValueStack.Count - i.NumVal2 - i.NumVal, i.NumVal, false);
|
|
|
+ RValue r = m_ValueStack.Pop();
|
|
|
|
|
|
- Internal_MultiAssign(lvalues, rvalues);
|
|
|
+ if (r.Type == DataType.String)
|
|
|
+ m_ValueStack.Push(new RValue(r.String.Length));
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeUnaryMetaMethod(r, "__len", instructionPtr);
|
|
|
+ if (ip >= 0)
|
|
|
+ return ip;
|
|
|
+ else if (r.Type == DataType.Table)
|
|
|
+ m_ValueStack.Push(new RValue(r.Table.Length));
|
|
|
+ else
|
|
|
+ throw new ScriptRuntimeException(null, "Arithmetic on non number");
|
|
|
+ }
|
|
|
|
|
|
- m_ValueStack.CropAtCount(m_ValueStack.Count - i.NumVal - i.NumVal2);
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
|
|
|
- private void Internal_MultiAssign(Slice<RValue> lValues, Slice<RValue> rValues)
|
|
|
+ private int ExecConcat(Instruction i, int instructionPtr)
|
|
|
{
|
|
|
- int li = 0;
|
|
|
- int rValues_Count = rValues.Count;
|
|
|
- int lValues_Count = lValues.Count;
|
|
|
+ RValue r = m_ValueStack.Pop();
|
|
|
+ RValue l = m_ValueStack.Pop();
|
|
|
|
|
|
- for (int ri = 0; ri < rValues_Count && li < lValues_Count; ri++, li++)
|
|
|
- {
|
|
|
- RValue vv = rValues[ri];
|
|
|
+ string rs = r.AsSimpleString();
|
|
|
+ string ls = l.AsSimpleString();
|
|
|
|
|
|
- if ((ri != rValues_Count - 1) || (vv.Type != DataType.Tuple))
|
|
|
- {
|
|
|
- Internal_Assign(lValues[li], vv.ToSingleValue());
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- for (int rri = 0, len = vv.Tuple.Length; rri < len && li < lValues_Count; rri++, li++)
|
|
|
- {
|
|
|
- Internal_Assign(lValues[li], vv.Tuple[rri].ToSingleValue());
|
|
|
- }
|
|
|
- }
|
|
|
+ if (rs != null && ls != null)
|
|
|
+ {
|
|
|
+ m_ValueStack.Push(new RValue(ls + rs));
|
|
|
+ return instructionPtr;
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int ip = Internal_InvokeBinaryMetaMethod(l, r, "__concat", instructionPtr);
|
|
|
+ if (ip >= 0) return ip;
|
|
|
+ else throw new ScriptRuntimeException(null, "Concatenation on non strings");
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
}
|