Skip to content

Commit

Permalink
Merge pull request #116 from SeedV/bugfix_113
Browse files Browse the repository at this point in the history
Handle overflow exceptions for netstandard2.0 in Unity environment
  • Loading branch information
wixette authored Jan 1, 2022
2 parents 2945585 + d9566f5 commit 77accf8
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 28 deletions.
3 changes: 1 addition & 2 deletions csharp/src/SeedLang/Ast/Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ internal static NoneConstantExpression NoneConstant(Range range) {

// The factory method to create a number constant expression.
internal static NumberConstantExpression NumberConstant(double value, Range range) {
// Throws a runtime overflow exception if the constant number is overflowed.
ValueHelper.CheckOverflow(value, range);
Debug.Assert(!double.IsInfinity(value) && !double.IsNaN(value));
return new NumberConstantExpression(value, range);
}

Expand Down
2 changes: 1 addition & 1 deletion csharp/src/SeedLang/Runtime/ValueHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ internal static double StringToNumber(string value) {
internal static void CheckOverflow(double value, Range range = null) {
// TODO: do we need separate NaN as another runtime error?
if (double.IsInfinity(value) || double.IsNaN(value)) {
throw new DiagnosticException(SystemReporters.SeedRuntime, Severity.Error, "", range,
throw new DiagnosticException(SystemReporters.SeedRuntime, Severity.Fatal, "", range,
Message.RuntimeErrorOverflow);
}
}
Expand Down
2 changes: 2 additions & 0 deletions csharp/src/SeedLang/X/BaseParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ internal bool Parse(string source, string module, DiagnosticCollection collectio
return false;
}
try {
// The visitor will throw an overflow runtime exception if any constant number in the source
// code is overflowed.
node = visitor.Visit(program);
return true;
} catch (DiagnosticException e) {
Expand Down
13 changes: 11 additions & 2 deletions csharp/src/SeedLang/X/VisitorHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,17 @@ internal NoneConstantExpression BuildNoneConstant(IToken token) {
// Builds a number constant expresssion.
internal NumberConstantExpression BuildNumberConstant(IToken token) {
TextRange range = HandleConstantOrVariableExpression(token, SyntaxType.Number);
double value = double.Parse(token.Text);
return Expression.NumberConstant(value, range);
try {
// The behavior of double.Parse is different between net6.0 and netstandard2.0 frameworks.
// It returns an infinity double value without throwing any exception on net6.0 framework.
// It throws an OverflowException on netstandard2.0. Handle both cases here.
double value = double.Parse(token.Text);
ValueHelper.CheckOverflow(value, range);
return Expression.NumberConstant(value, range);
} catch (System.OverflowException) {
throw new DiagnosticException(SystemReporters.SeedX, Severity.Fatal, "", range,
Message.RuntimeErrorOverflow);
}
}

// Builds a string constant expresssion.
Expand Down
22 changes: 0 additions & 22 deletions csharp/tests/SeedLang.Tests/Ast/ExecutorErrorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,6 @@ public void TestExecuteOutOfRange() {
Assert.Equal(Message.RuntimeErrorOutOfRange, exception.Diagnostic.MessageId);
}

[Fact]
public void TestExecuteOverflow() {
var exception = Assert.Throws<DiagnosticException>(() =>
Expression.NumberConstant(double.PositiveInfinity, _textRange));
Assert.Equal(Message.RuntimeErrorOverflow, exception.Diagnostic.MessageId);
exception = Assert.Throws<DiagnosticException>(() =>
Expression.NumberConstant(double.NegativeInfinity, _textRange));
Assert.Equal(Message.RuntimeErrorOverflow, exception.Diagnostic.MessageId);
exception = Assert.Throws<DiagnosticException>(() =>
Expression.NumberConstant(double.NaN, _textRange));
Assert.Equal(Message.RuntimeErrorOverflow, exception.Diagnostic.MessageId);

var binary = Expression.Binary(Expression.NumberConstant(7.997e307, _textRange),
BinaryOperator.Add,
Expression.NumberConstant(9.985e307, _textRange),
_textRange);

(var executor, var visualizer) = NewExecutorWithVisualizer();
exception = Assert.Throws<DiagnosticException>(() => executor.Run(binary));
Assert.Equal(Message.RuntimeErrorOverflow, exception.Diagnostic.MessageId);
}

[Fact]
public void TestExecuteNotSubscriptable() {
var one = Expression.NumberConstant(1, _textRange);
Expand Down
10 changes: 9 additions & 1 deletion csharp/tests/SeedLang.Tests/X/SeedPythonErrorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,21 @@ public class SeedPythonErrorTests {

"Keyword [Ln 1, Col 0 - Ln 1, Col 4]," +
"Keyword [Ln 1, Col 6 - Ln 1, Col 9]")]

[InlineData("1e9999",
new string[] {
"RuntimeErrorOverflow",
},

"Number [Ln 1, Col 0 - Ln 1, Col 5]")]
public void TestParseSyntaxError(string input, string[] errorMessages, string expectedTokens) {
Assert.False(_parser.Parse(input, "", _collection, out AstNode node,
out IReadOnlyList<SyntaxToken> tokens));
Assert.Null(node);
Assert.Equal(errorMessages.Length, _collection.Diagnostics.Count);
for (int i = 0; i < errorMessages.Length; ++i) {
Assert.Equal(SystemReporters.SeedX, _collection.Diagnostics[i].Reporter);
Assert.True(_collection.Diagnostics[i].Reporter == SystemReporters.SeedX ||
_collection.Diagnostics[i].Reporter == SystemReporters.SeedRuntime);
Assert.Equal(Severity.Fatal, _collection.Diagnostics[i].Severity);
string diagnostic = _collection.Diagnostics[i].LocalizedMessage.Replace(@"\r\n", @"\n");
Assert.Equal(errorMessages[i], diagnostic);
Expand Down

0 comments on commit 77accf8

Please sign in to comment.