Browse Source

Fix: vm (arithmetic operations on strings representing numbers)

AnnulusGames 1 year ago
parent
commit
324cb2327f

+ 39 - 0
src/Lua/Runtime/LuaValueRuntimeExtensions.cs

@@ -1,10 +1,49 @@
 using System.Buffers;
 using System.Buffers;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
+using Lua.Internal;
 
 
 namespace Lua.Runtime;
 namespace Lua.Runtime;
 
 
 internal static class LuaRuntimeExtensions
 internal static class LuaRuntimeExtensions
 {
 {
+    public static bool TryGetNumber(this LuaValue value, out double result)
+    {
+        if (value.TryRead(out result)) return true;
+
+        if (value.TryRead<string>(out var str))
+        {
+            var span = str.AsSpan().Trim();
+
+            var sign = 1;
+            if (span.Length > 0 && span[0] == '-')
+            {
+                sign = -1;
+                span = span[1..];
+            }
+
+            if (span.Length > 2 && span[0] is '0' && span[1] is 'x' or 'X')
+            {
+                // TODO: optimize
+                try
+                {
+                    result = HexConverter.ToDouble(span) * sign;
+                    return true;
+                }
+                catch (FormatException)
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                return double.TryParse(str, out result);
+            }
+        }
+
+        result = default;
+        return false;
+    }
+
     public static bool TryGetMetamethod(this LuaValue value, LuaState state, string methodName, out LuaValue result)
     public static bool TryGetMetamethod(this LuaValue value, LuaState state, string methodName, out LuaValue result)
     {
     {
         result = default;
         result = default;

+ 7 - 7
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -121,7 +121,7 @@ public static partial class LuaVirtualMachine
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
 
 
-                        if (vb.TryRead<double>(out var valueB) && vc.TryRead<double>(out var valueC))
+                        if (vb.TryGetNumber(out var valueB) && vc.TryGetNumber(out var valueC))
                         {
                         {
                             stack.UnsafeGet(RA) = valueB + valueC;
                             stack.UnsafeGet(RA) = valueB + valueC;
                         }
                         }
@@ -160,7 +160,7 @@ public static partial class LuaVirtualMachine
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
 
 
-                        if (vb.TryRead<double>(out var valueB) && vc.TryRead<double>(out var valueC))
+                        if (vb.TryGetNumber(out var valueB) && vc.TryGetNumber(out var valueC))
                         {
                         {
                             stack.UnsafeGet(RA) = valueB - valueC;
                             stack.UnsafeGet(RA) = valueB - valueC;
                         }
                         }
@@ -199,7 +199,7 @@ public static partial class LuaVirtualMachine
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
 
 
-                        if (vb.TryRead<double>(out var valueB) && vc.TryRead<double>(out var valueC))
+                        if (vb.TryGetNumber(out var valueB) && vc.TryGetNumber(out var valueC))
                         {
                         {
                             stack.UnsafeGet(RA) = valueB * valueC;
                             stack.UnsafeGet(RA) = valueB * valueC;
                         }
                         }
@@ -238,7 +238,7 @@ public static partial class LuaVirtualMachine
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
 
 
-                        if (vb.TryRead<double>(out var valueB) && vc.TryRead<double>(out var valueC))
+                        if (vb.TryGetNumber(out var valueB) && vc.TryGetNumber(out var valueC))
                         {
                         {
                             stack.UnsafeGet(RA) = valueB / valueC;
                             stack.UnsafeGet(RA) = valueB / valueC;
                         }
                         }
@@ -277,7 +277,7 @@ public static partial class LuaVirtualMachine
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
 
 
-                        if (vb.TryRead<double>(out var valueB) && vc.TryRead<double>(out var valueC))
+                        if (vb.TryGetNumber(out var valueB) && vc.TryGetNumber(out var valueC))
                         {
                         {
                             stack.UnsafeGet(RA) = valueB % valueC;
                             stack.UnsafeGet(RA) = valueB % valueC;
                         }
                         }
@@ -316,7 +316,7 @@ public static partial class LuaVirtualMachine
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vb = RK(stack, chunk, instruction.B, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
                         var vc = RK(stack, chunk, instruction.C, frame.Base);
 
 
-                        if (vb.TryRead<double>(out var valueB) && vc.TryRead<double>(out var valueC))
+                        if (vb.TryGetNumber(out var valueB) && vc.TryGetNumber(out var valueC))
                         {
                         {
                             stack.UnsafeGet(RA) = Math.Pow(valueB, valueC);
                             stack.UnsafeGet(RA) = Math.Pow(valueB, valueC);
                         }
                         }
@@ -354,7 +354,7 @@ public static partial class LuaVirtualMachine
 
 
                         var vb = stack.UnsafeGet(RB);
                         var vb = stack.UnsafeGet(RB);
 
 
-                        if (vb.TryRead<double>(out var valueB))
+                        if (vb.TryGetNumber(out var valueB))
                         {
                         {
                             stack.UnsafeGet(RA) = -valueB;
                             stack.UnsafeGet(RA) = -valueB;
                         }
                         }