AnnulusGames / Lua-CSharp

High performance Lua interpreter implemented in C# for .NET and Unity
MIT License
190 stars 9 forks source link

Fix for floating number not able to be parsed (Godot) #47

Closed Flo12344 closed 1 month ago

Flo12344 commented 1 month ago

Hello, I started using Lua-CSharp in Godot for my game to implement modding and map making scripts. While testing my script I realized that in Godot when using floating number the parser would make the script crash and while searching the error I come up with this little change, which fixes the crashes.

Small exemple of a script in my test scene : https://github.com/user-attachments/assets/34f8c20b-d729-450d-b18f-685081274d3a

(Hope it can be useful ^^)

Flo12344 commented 1 month ago

If you are interested I could also add the Godot C# setup to the Readme

AnnulusGames commented 1 month ago

ToString() incurs an allocation to create a new string. Use the overload that accepts ReadOnlySpan<char>.

AnnulusGames commented 1 month ago

Also, the video alone is not sufficient to determine the exact cause of the error. Please provide the error message, stack trace and C# and Lua source code.

Flo12344 commented 1 month ago

Error message :

E 0:00:02:0148   void System.Number.ThrowFormatException<TChar>(System.ReadOnlySpan`1[TChar]): System.FormatException: The input string '1.0' was not in a correct format.
  <C++ Error>    System.FormatException
  <C++ Source>   :0 @ void System.Number.ThrowFormatException<TChar>(System.ReadOnlySpan`1[TChar])
  <Stack Trace>  :0 @ void System.Number.ThrowFormatException<TChar>(System.ReadOnlySpan`1[TChar])
                 :0 @ double System.Double.Parse(System.ReadOnlySpan`1[System.Char], System.Globalization.NumberStyles, System.IFormatProvider)
                 :0 @ double Lua.CodeAnalysis.Syntax.Parser.ConvertTextToNumber(System.ReadOnlySpan`1[System.Char])
                 :0 @ bool Lua.CodeAnalysis.Syntax.Parser.TryParseExpression(Lua.CodeAnalysis.Syntax.SyntaxTokenEnumerator&, Lua.CodeAnalysis.Syntax.OperatorPrecedence, Lua.CodeAnalysis.Syntax.Nodes.ExpressionNode&)
                 :0 @ Lua.CodeAnalysis.Syntax.Nodes.ExpressionNode[] Lua.CodeAnalysis.Syntax.Parser.ParseExpressionList(Lua.CodeAnalysis.Syntax.SyntaxTokenEnumerator&)
                 :0 @ Lua.CodeAnalysis.Syntax.Nodes.ReturnStatementNode Lua.CodeAnalysis.Syntax.Parser.ParseReturnStatement(Lua.CodeAnalysis.Syntax.SyntaxTokenEnumerator&)
                 :0 @ Lua.CodeAnalysis.Syntax.Nodes.StatementNode Lua.CodeAnalysis.Syntax.Parser.ParseStatement(Lua.CodeAnalysis.Syntax.SyntaxTokenEnumerator&)
                 :0 @ Lua.CodeAnalysis.Syntax.LuaSyntaxTree Lua.CodeAnalysis.Syntax.Parser.Parse()
                 :0 @ Lua.CodeAnalysis.Syntax.LuaSyntaxTree Lua.CodeAnalysis.Syntax.LuaSyntaxTree.Parse(string, string)
                 :0 @ System.Threading.Tasks.ValueTask`1[System.Int32] Lua.LuaStateExtensions.DoStringAsync(Lua.LuaState, string, System.Memory`1[Lua.LuaValue], string, System.Threading.CancellationToken)
                 :0 @ void Lua.LuaStateExtensions+<DoStringAsync>d__1.MoveNext()
                 :0 @ void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                 :0 @ void System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)
                 :0 @ void System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task, System.Threading.Tasks.ConfigureAwaitOptions)
                 :0 @ TResult System.Threading.Tasks.ValueTask`1.get_Result()
                 LuaErrorShowcase.cs:13 @ void LuaErrorShowcase+<_Ready>d__0.MoveNext()
                 :0 @ void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                 :0 @ void System.Threading.Tasks.Task+<>c.<ThrowAsync>b__128_0(object)
                 GodotSynchronizationContext.cs:51 @ void Godot.GodotSynchronizationContext.ExecutePendingContinuations()
                 GodotTaskScheduler.cs:76 @ void Godot.GodotTaskScheduler.Activate()
                 ScriptManagerBridge.cs:84 @ void Godot.Bridge.ScriptManagerBridge.FrameCallback()

Code :

using Godot;
using System;
using Lua;

public partial class LuaErrorShowcase : Node
{
    public override async void _Ready()
    {
        // Create a LuaState
        var state = LuaState.Create();

        // Execute a Lua script string with DoStringAsync
        var results = await state.DoStringAsync("return 1.0 + 1");

        // 2
        Console.WriteLine(results[0]);
    }
}
Akeit0 commented 1 month ago

It seems to be a problem about decimal separator. I think double.Parse(text,NumberStyles.Float, CultureInfo.InvariantCulture) is most appropriate.

Flo12344 commented 1 month ago

@Akeit0 that's it my bad, I'm not used to use those function in c#

Akeit0 commented 1 month ago

Same problems can be seen in these. https://github.com/AnnulusGames/Lua-CSharp/blob/b3b7d8d976733929d0f8726b46cb688a4ceb7215/src/Lua/LuaValue.cs#L123 https://github.com/AnnulusGames/Lua-CSharp/blob/b3b7d8d976733929d0f8726b46cb688a4ceb7215/src/Lua/Standard/BasicLibrary.cs#L448

AnnulusGames commented 1 month ago

Merged the PR. Thanks!