SeedV/SeedLang

Single value parsing and evaluating doesn't report RuntimeOverflow

Closed this issue · 3 comments

In both SeedPython and SeedCalc, an expression like a+b reports RuntimeOverflow as expected:

dotnet run --project src/SeedLang.Shell -- -l SeedPython
>>> 2e300 * 2e300
---------- Source ----------
2e300 * 2e300

---------- Run ----------
2e300 * 2e300
: 20211228145042791 Error (SeedLang.Ast) <> [Ln 1, Col 0 - Ln 1, Col 12] 27: RuntimeErrorOverflow

But when parsing and evaluating a single value, SeedLang doesn't report any error:

>>> 1e9999
---------- Source ----------
1e9999

---------- Run ----------
1e9999
Eval result: 0
>>> a = 1e9999
---------- Source ----------
a = 1e9999

---------- Run ----------
>>> a
---------- Source ----------
a

---------- Run ----------
a
Eval result: 0

The issue has been solved in Executor.Run(), but it still exists in Executor.ParseSyntaxTokens().

Background: SeedCalc could result in a number that has to be displayed in scientific notation, e.g., input 800000000*900000000, SeedCalc outputs 7.2000E+017 to the screen. Per the current behavior when a result number is shown on the screen, the user can modify the result by inputting Del and continuing to build a new expression. In this case, the calculator might accept input like 7.2000E+999 and the input will be passed to SeedLang's Executor.ParserSyntaxTokens(), which results in the following exception:

OverflowException: Value was either too large or too small for a Double.
System.Number.ParseDouble (System.String value, System.Globalization.NumberStyles options, System.Globalization.NumberFormatInfo numfmt) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Double.Parse (System.String s, System.Globalization.NumberStyles style, System.Globalization.NumberFormatInfo info) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.Double.Parse (System.String s) (at <695d1cc93cca45069c528c15c9fdd749>:0)
SeedLang.X.VisitorHelper.BuildNumberConstant (Antlr4.Runtime.IToken token) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcVisitor.VisitNumber (SeedLang.X.SeedCalcParser+NumberContext context) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcParser+NumberContext.Accept[TResult] (Antlr4.Runtime.Tree.IParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result].VisitChildren (Antlr4.Runtime.Tree.IRuleNode node) (at <c5557c657b6f4e73b43e492ca53865c9>:0)
SeedLang.X.SeedCalcBaseVisitor`1[Result].VisitAtom_as_factor (SeedLang.X.SeedCalcParser+Atom_as_factorContext context) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcParser+Atom_as_factorContext.Accept[TResult] (Antlr4.Runtime.Tree.IParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result].VisitChildren (Antlr4.Runtime.Tree.IRuleNode node) (at <c5557c657b6f4e73b43e492ca53865c9>:0)
SeedLang.X.SeedCalcBaseVisitor`1[Result].VisitFactor_as_term (SeedLang.X.SeedCalcParser+Factor_as_termContext context) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcParser+Factor_as_termContext.Accept[TResult] (Antlr4.Runtime.Tree.IParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result].VisitChildren (Antlr4.Runtime.Tree.IRuleNode node) (at <c5557c657b6f4e73b43e492ca53865c9>:0)
SeedLang.X.SeedCalcBaseVisitor`1[Result].VisitTerm_as_sum (SeedLang.X.SeedCalcParser+Term_as_sumContext context) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcParser+Term_as_sumContext.Accept[TResult] (Antlr4.Runtime.Tree.IParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result].VisitChildren (Antlr4.Runtime.Tree.IRuleNode node) (at <c5557c657b6f4e73b43e492ca53865c9>:0)
SeedLang.X.SeedCalcBaseVisitor`1[Result].VisitExpression (SeedLang.X.SeedCalcParser+ExpressionContext context) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcParser+ExpressionContext.Accept[TResult] (Antlr4.Runtime.Tree.IParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result].Visit (Antlr4.Runtime.Tree.IParseTree tree) (at <c5557c657b6f4e73b43e492ca53865c9>:0)
SeedLang.X.VisitorHelper.BuildExpressionStatement (Antlr4.Runtime.ParserRuleContext exprContext, Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcVisitor.VisitExpressionStatement (SeedLang.X.SeedCalcParser+ExpressionStatementContext context) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.X.SeedCalcParser+ExpressionStatementContext.Accept[TResult] (Antlr4.Runtime.Tree.IParseTreeVisitor`1[Result] visitor) (at <ba926e67f07147b68068d5633e75d28c>:0)
Antlr4.Runtime.Tree.AbstractParseTreeVisitor`1[Result].Visit (Antlr4.Runtime.Tree.IParseTree tree) (at <c5557c657b6f4e73b43e492ca53865c9>:0)
SeedLang.X.BaseParser.Parse (System.String source, System.String module, SeedLang.Common.DiagnosticCollection collection, SeedLang.Ast.AstNode& node, System.Collections.Generic.IReadOnlyList`1[SeedLang.Common.SyntaxToken]& tokens) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedLang.Runtime.Executor.ParseSyntaxTokens (System.String source, System.String module, SeedLang.Runtime.SeedXLanguage language, SeedLang.Common.DiagnosticCollection collection) (at <ba926e67f07147b68068d5633e75d28c>:0)
SeedCalc.Calculator.ParseExpression (System.String& expression) (at Assets/Src/Scripts/SeedCalc/Calculator.cs:353)

(1) On the SeedCalc side, I think it's not reasonable to enable users to modify a result and continue working on a new expression, especially considering the above case. I will prepare a pr on the SeedCalc side to fix this.

(2) On the SeedLang side, it's still necessary to report RuntimeErrorOverflow when Executor.ParseSyntaxTokens() meets such kind of strings.

@wixette It's caused by difference of dotnet versions. When I run

double.Parse("1e9999")

on dotnet 6.0, it returns a Infinity double value without exceptions. But on Unity environment, it throws a overflow exception. Please refer to https://docs.microsoft.com/en-us/dotnet/api/system.double.parse?view=net-6.0:

OverflowException
.NET Framework and .NET Core 2.2 and earlier versions only: s represents a number that is less than MinValue or greater than MaxValue.

I will think about how to fix it.

Fixed by #116