|
|
@@ -74,109 +74,147 @@ public static class LuaThreadAccessAccessExtensions
|
|
|
return new LuaReturnValuesReader(stack, stack.Count - argumentCount);
|
|
|
}
|
|
|
|
|
|
+ public static async ValueTask<LuaValue> Add(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (x.TryReadDouble(out var numX) && y.TryReadDouble(out var numY))
|
|
|
+ {
|
|
|
+ return numX + numY;
|
|
|
+ }
|
|
|
|
|
|
- public static async ValueTask<LuaValue> Arithmetic(this LuaThreadAccess access, LuaValue x, LuaValue y, OpCode opCode, CancellationToken cancellationToken = default)
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Add, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static async ValueTask<LuaValue> Sub(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
- [MethodImpl(MethodImplOptions.NoInlining)]
|
|
|
- static double Mod(double a, double b)
|
|
|
+ if (x.TryReadDouble(out var numX) && y.TryReadDouble(out var numY))
|
|
|
{
|
|
|
- var mod = a % b;
|
|
|
- if ((b > 0 && mod < 0) || (b < 0 && mod > 0))
|
|
|
- {
|
|
|
- mod += b;
|
|
|
- }
|
|
|
+ return numX - numY;
|
|
|
+ }
|
|
|
+
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Sub, cancellationToken);
|
|
|
+ }
|
|
|
|
|
|
- return mod;
|
|
|
+ public static async ValueTask<LuaValue> Mul(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (x.TryReadDouble(out var numX) && y.TryReadDouble(out var numY))
|
|
|
+ {
|
|
|
+ return numX * numY;
|
|
|
}
|
|
|
|
|
|
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
- static double ArithmeticOperation(OpCode code, double a, double b)
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Mul, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static async ValueTask<LuaValue> Div(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (x.TryReadDouble(out var numX) && y.TryReadDouble(out var numY))
|
|
|
{
|
|
|
- return code switch
|
|
|
- {
|
|
|
- OpCode.Add => a + b,
|
|
|
- OpCode.Sub => a - b,
|
|
|
- OpCode.Mul => a * b,
|
|
|
- OpCode.Div => a / b,
|
|
|
- OpCode.Mod => Mod(a, b),
|
|
|
- OpCode.Pow => Math.Pow(a, b),
|
|
|
- _ => throw new InvalidOperationException($"Unsupported arithmetic operation: {code}"),
|
|
|
- };
|
|
|
+ return numX / numY;
|
|
|
}
|
|
|
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Div, cancellationToken);
|
|
|
+ }
|
|
|
|
|
|
+ public static async ValueTask<LuaValue> Mod(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
if (x.TryReadDouble(out var numX) && y.TryReadDouble(out var numY))
|
|
|
{
|
|
|
- return ArithmeticOperation(opCode, numX, numY);
|
|
|
+ return LuaVirtualMachine.Mod(numX, numY);
|
|
|
}
|
|
|
|
|
|
access.ThrowIfInvalid();
|
|
|
- return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, opCode, cancellationToken);
|
|
|
+ return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Mod, cancellationToken);
|
|
|
}
|
|
|
|
|
|
- public static async ValueTask<LuaValue> Unary(this LuaThreadAccess access, LuaValue value, OpCode opCode, CancellationToken cancellationToken = default)
|
|
|
+ public static async ValueTask<LuaValue> Pow(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
- if (opCode == OpCode.Unm)
|
|
|
+ if (x.TryReadDouble(out var numX) && y.TryReadDouble(out var numY))
|
|
|
{
|
|
|
- if (value.TryReadDouble(out var numB))
|
|
|
- {
|
|
|
- return -numB;
|
|
|
- }
|
|
|
+ return Math.Pow(numX, numY);
|
|
|
}
|
|
|
- else if (opCode == OpCode.Len)
|
|
|
+
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteBinaryOperationMetaMethod(access.Thread, x, y, OpCode.Pow, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static async ValueTask<LuaValue> Unm(this LuaThreadAccess access, LuaValue value, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (value.TryReadDouble(out var numB))
|
|
|
{
|
|
|
- if (value.TryReadString(out var str))
|
|
|
- {
|
|
|
- return str.Length;
|
|
|
- }
|
|
|
+ return -numB;
|
|
|
+ }
|
|
|
|
|
|
- if (value.TryReadTable(out var table))
|
|
|
- {
|
|
|
- return table.ArrayLength;
|
|
|
- }
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.Thread, value, OpCode.Unm, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static async ValueTask<LuaValue> Len(this LuaThreadAccess access, LuaValue value, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (value.TryReadString(out var str))
|
|
|
+ {
|
|
|
+ return str.Length;
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ if (value.TryReadTable(out var table))
|
|
|
{
|
|
|
- throw new InvalidOperationException($"Unsupported unary operation: {opCode}");
|
|
|
+ return table.ArrayLength;
|
|
|
}
|
|
|
|
|
|
access.ThrowIfInvalid();
|
|
|
- return await LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.Thread, value, opCode, cancellationToken);
|
|
|
+ return await LuaVirtualMachine.ExecuteUnaryOperationMetaMethod(access.Thread, value, OpCode.Len, cancellationToken);
|
|
|
}
|
|
|
|
|
|
|
|
|
- public static async ValueTask<bool> Compare(this LuaThreadAccess access, LuaValue x, LuaValue y, OpCode opCode, CancellationToken cancellationToken = default)
|
|
|
+ public static async ValueTask<bool> LessThan(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
- if (opCode is not (OpCode.Eq or OpCode.Lt or OpCode.Le))
|
|
|
+ if (x.TryReadNumber(out var numX) && y.TryReadNumber(out var numY))
|
|
|
{
|
|
|
- throw new InvalidOperationException($"Unsupported compare operation: {opCode}");
|
|
|
+ return numX < numY;
|
|
|
}
|
|
|
|
|
|
- if (opCode == OpCode.Eq)
|
|
|
+ if (x.TryReadString(out var strX) && y.TryReadString(out var strY))
|
|
|
{
|
|
|
- if (x == y)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
+ var c = StringComparer.Ordinal.Compare(strX, strY);
|
|
|
+ return c < 0;
|
|
|
}
|
|
|
- else
|
|
|
+
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, OpCode.Lt, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static async ValueTask<bool> LessThanOrEquals(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (x.TryReadNumber(out var numX) && y.TryReadNumber(out var numY))
|
|
|
{
|
|
|
- if (x.TryReadNumber(out var numX) && y.TryReadNumber(out var numY))
|
|
|
- {
|
|
|
- return opCode == OpCode.Lt ? numX < numY : numX <= numY;
|
|
|
- }
|
|
|
+ return numX <= numY;
|
|
|
+ }
|
|
|
|
|
|
- if (x.TryReadString(out var strX) && y.TryReadString(out var strY))
|
|
|
- {
|
|
|
- var c = StringComparer.Ordinal.Compare(strX, strY);
|
|
|
- return opCode == OpCode.Lt ? c < 0 : c <= 0;
|
|
|
- }
|
|
|
+ if (x.TryReadString(out var strX) && y.TryReadString(out var strY))
|
|
|
+ {
|
|
|
+ var c = StringComparer.Ordinal.Compare(strX, strY);
|
|
|
+ return c <= 0;
|
|
|
}
|
|
|
|
|
|
access.ThrowIfInvalid();
|
|
|
- return await LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, opCode, cancellationToken);
|
|
|
+ return await LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, OpCode.Le, cancellationToken);
|
|
|
}
|
|
|
|
|
|
+ public static async ValueTask<bool> Equals(this LuaThreadAccess access, LuaValue x, LuaValue y, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ if (x == y)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ access.ThrowIfInvalid();
|
|
|
+ return await LuaVirtualMachine.ExecuteCompareOperationMetaMethod(access.Thread, x, y, OpCode.Eq, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
public static async ValueTask<LuaValue> GetTable(this LuaThreadAccess access, LuaValue table, LuaValue key, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
if (table.TryReadTable(out var luaTable))
|