Exception throwing when required, and fixes for unit tests
This commit is contained in:
@@ -201,12 +201,6 @@ namespace Upsilon.Binder
|
|||||||
{
|
{
|
||||||
var variableExpression =(BoundVariableExpression) expression;
|
var variableExpression =(BoundVariableExpression) expression;
|
||||||
var function = (FunctionVariableSymbol)variableExpression.Variable.VariableSymbol;
|
var function = (FunctionVariableSymbol)variableExpression.Variable.VariableSymbol;
|
||||||
if (function.Parameters.Length != parameters.Count)
|
|
||||||
{
|
|
||||||
_diagnostics.LogError($"Invalid number of parameters for function '{function.Name}'. " +
|
|
||||||
$"Expected '{function.Parameters.Length}', got '{parameters.Count}'", e.Span);
|
|
||||||
return new BoundLiteralExpression(new ScriptNull(), e.Span);
|
|
||||||
}
|
|
||||||
if (!function.IsBound)
|
if (!function.IsBound)
|
||||||
{
|
{
|
||||||
Scope = new BoundScope(Scope);
|
Scope = new BoundScope(Scope);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Upsilon.BaseTypes;
|
using Upsilon.BaseTypes;
|
||||||
|
using Upsilon.Exceptions;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Parser;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
@@ -9,10 +10,12 @@ namespace Upsilon
|
|||||||
{
|
{
|
||||||
public SourceText ScriptString { get; }
|
public SourceText ScriptString { get; }
|
||||||
public readonly List<DiagnosticsMessage> Messages = new List<DiagnosticsMessage>();
|
public readonly List<DiagnosticsMessage> Messages = new List<DiagnosticsMessage>();
|
||||||
|
public bool ThrowsOnError { get; }
|
||||||
|
|
||||||
public Diagnostics(SourceText scriptString)
|
public Diagnostics(SourceText scriptString, bool throwsOnError)
|
||||||
{
|
{
|
||||||
ScriptString = scriptString;
|
ScriptString = scriptString;
|
||||||
|
ThrowsOnError = throwsOnError;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Log(DiagnosticLevel level, string message, TextSpan location)
|
public void Log(DiagnosticLevel level, string message, TextSpan location)
|
||||||
@@ -22,6 +25,12 @@ namespace Upsilon
|
|||||||
|
|
||||||
public void LogError(string message, TextSpan location)
|
public void LogError(string message, TextSpan location)
|
||||||
{
|
{
|
||||||
|
if (ThrowsOnError)
|
||||||
|
{
|
||||||
|
var linePos = ScriptString.GetLinePosition(location.Start);
|
||||||
|
var line = ScriptString.GetLine(linePos.Line);
|
||||||
|
throw new ParseException(message, linePos.Line, linePos.Pos, line);
|
||||||
|
}
|
||||||
Log(DiagnosticLevel.Error, message, location);
|
Log(DiagnosticLevel.Error, message, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Upsilon.Evaluator
|
|||||||
Options = options;
|
Options = options;
|
||||||
_scriptString = scriptString;
|
_scriptString = scriptString;
|
||||||
ScriptString = new SourceText(scriptString);
|
ScriptString = new SourceText(scriptString);
|
||||||
Diagnostics = new Diagnostics(ScriptString);
|
Diagnostics = new Diagnostics(ScriptString, options.ThrowExceptionOnError);
|
||||||
|
|
||||||
var staticBoundScope = options.OverrideStaticBoundScope ?? StaticScope.BoundScope;
|
var staticBoundScope = options.OverrideStaticBoundScope ?? StaticScope.BoundScope;
|
||||||
var boundScope = BoundScope.WithReadOnlyScope(staticBoundScope);
|
var boundScope = BoundScope.WithReadOnlyScope(staticBoundScope);
|
||||||
@@ -38,10 +38,10 @@ namespace Upsilon.Evaluator
|
|||||||
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, Scope);
|
Evaluator = Evaluator.CreateWithSetScope(Diagnostics, Scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Script(string scriptString, Binder.Binder binder, Evaluator evaluator)
|
private Script(string scriptString, Binder.Binder binder, Evaluator evaluator, ScriptOptions options)
|
||||||
{
|
{
|
||||||
ScriptString = new SourceText(scriptString);
|
ScriptString = new SourceText(scriptString);
|
||||||
Diagnostics = new Diagnostics(ScriptString);
|
Diagnostics = new Diagnostics(ScriptString, Options.ThrowExceptionOnError);
|
||||||
Binder = new Binder.Binder(Diagnostics, binder.Scope.Variables);
|
Binder = new Binder.Binder(Diagnostics, binder.Scope.Variables);
|
||||||
Evaluator = new Evaluator( Diagnostics, evaluator.Scope.Variables);
|
Evaluator = new Evaluator( Diagnostics, evaluator.Scope.Variables);
|
||||||
Scope = Evaluator.Scope;
|
Scope = Evaluator.Scope;
|
||||||
@@ -50,7 +50,7 @@ namespace Upsilon.Evaluator
|
|||||||
|
|
||||||
internal static Script ContinueWith(Script previousScript, string scriptString)
|
internal static Script ContinueWith(Script previousScript, string scriptString)
|
||||||
{
|
{
|
||||||
var s = new Script(scriptString, previousScript.Binder, previousScript.Evaluator);
|
var s = new Script(scriptString, previousScript.Binder, previousScript.Evaluator, previousScript.Options);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
Upsilon/Exceptions/ParseException.cs
Normal file
28
Upsilon/Exceptions/ParseException.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Upsilon.Text;
|
||||||
|
|
||||||
|
namespace Upsilon.Exceptions
|
||||||
|
{
|
||||||
|
public class ParseException : Exception
|
||||||
|
{
|
||||||
|
public string ErrorMessage { get; }
|
||||||
|
public int Line { get; }
|
||||||
|
public int Character { get; }
|
||||||
|
public string ErrorLine { get; }
|
||||||
|
|
||||||
|
public ParseException(string errorMessage, int line, int character, string errorLine)
|
||||||
|
{
|
||||||
|
ErrorMessage = errorMessage;
|
||||||
|
Line = line;
|
||||||
|
Character = character;
|
||||||
|
ErrorLine = errorLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"{ErrorMessage} at ({Line}, {Character})\n{ErrorLine}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message => ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,13 +44,13 @@ namespace Upsilon
|
|||||||
|
|
||||||
public static T EvaluateFunction<T>(string input, string function, object[] parameters = null, ScriptOptions options = null)
|
public static T EvaluateFunction<T>(string input, string function, object[] parameters = null, ScriptOptions options = null)
|
||||||
{
|
{
|
||||||
var script = ParseInput(input, options);
|
var script = ParseInputAndEvaluate(input, options);
|
||||||
return script.EvaluateFunction<T>(function, parameters);
|
return script.EvaluateFunction<T>(function, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object EvaluateFunction(string input, string function, object[] parameters = null, ScriptOptions options = null)
|
public static object EvaluateFunction(string input, string function, object[] parameters = null, ScriptOptions options = null)
|
||||||
{
|
{
|
||||||
var script = ParseInput(input, options);
|
var script = ParseInputAndEvaluate(input, options);
|
||||||
return script.EvaluateFunction(function, parameters);
|
return script.EvaluateFunction(function, parameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ namespace Upsilon.Parser
|
|||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
EndToken = endToken;
|
EndToken = endToken;
|
||||||
Span = new TextSpan(IfToken.Span.Start, EndToken.Span.End - IfToken.Span.Start);
|
var end = Block.Span.End;
|
||||||
|
if (EndToken != null) end = EndToken.Span.End;
|
||||||
|
Span = new TextSpan(IfToken.Span.Start, end - IfToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
||||||
@@ -27,7 +29,7 @@ namespace Upsilon.Parser
|
|||||||
ThenToken = thenToken;
|
ThenToken = thenToken;
|
||||||
Block = block;
|
Block = block;
|
||||||
ElseStatement = elseStatement;
|
ElseStatement = elseStatement;
|
||||||
Span = new TextSpan(IfToken.Span.Start, EndToken.Span.End - IfToken.Span.Start);
|
Span = new TextSpan(IfToken.Span.Start, ElseStatement.Span.End - IfToken.Span.Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
public IfStatementSyntax(SyntaxToken ifToken, ExpressionStatementSyntax condition, SyntaxToken thenToken,
|
||||||
|
|||||||
@@ -85,6 +85,12 @@ namespace Upsilon.Text
|
|||||||
return _text.Length;
|
return _text.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetLine(int linePosition)
|
||||||
|
{
|
||||||
|
var line = _lines[linePosition];
|
||||||
|
return GetSpan(line.Start, line.LineLength);
|
||||||
|
}
|
||||||
|
|
||||||
public SourceTextLine GetLineInfo(int lineIndex)
|
public SourceTextLine GetLineInfo(int lineIndex)
|
||||||
{
|
{
|
||||||
return _lines[lineIndex];
|
return _lines[lineIndex];
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Upsilon;
|
using Upsilon;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
using Upsilon.Exceptions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace UpsilonTests.GeneralTests
|
namespace UpsilonTests.GeneralTests
|
||||||
@@ -50,8 +51,7 @@ function testFunc (var1)
|
|||||||
end
|
end
|
||||||
testFunc(100)
|
testFunc(100)
|
||||||
";
|
";
|
||||||
var script = Executor.ParseInputAndEvaluate(input, Options);
|
Assert.Throws<ParseException>(() => Executor.ParseInputAndEvaluate(input, Options));
|
||||||
Assert.True(script.HasVariable("testFunc"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Upsilon;
|
using Upsilon;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
using Upsilon.Exceptions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace UpsilonTests.GeneralTests
|
namespace UpsilonTests.GeneralTests
|
||||||
@@ -49,7 +50,7 @@ table = {
|
|||||||
}
|
}
|
||||||
return table[""test""]
|
return table[""test""]
|
||||||
";
|
";
|
||||||
Executor.EvaluateScript<long>(input, Options);
|
Assert.Throws<ParseException>(() => Executor.EvaluateScript<long>(input, Options));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function getValue(arr)
|
|||||||
return arr[""here""]
|
return arr[""here""]
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
var evaluated = Executor.EvaluateScript<long>(input, Options);
|
var evaluated = Executor.EvaluateFunction<long>(input, "getValue", new[] {arr}, Options);
|
||||||
Assert.Equal(1683, evaluated);
|
Assert.Equal(1683, evaluated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ function getValue(arr)
|
|||||||
return arr[3]
|
return arr[3]
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
var evaluated = Executor.EvaluateScript<long>(input, Options);
|
var evaluated = Executor.EvaluateFunction<long>(input, "getValue", new []{arr}, Options);
|
||||||
Assert.Equal(56, evaluated);
|
Assert.Equal(56, evaluated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ function getValue(arr)
|
|||||||
return arr[2]
|
return arr[2]
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
var evaluated = Executor.EvaluateScript<long>(input, Options);
|
var evaluated = Executor.EvaluateFunction<long>(input, "getValue", new []{arr}, Options);
|
||||||
Assert.Equal(30, evaluated);
|
Assert.Equal(30, evaluated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System;
|
|||||||
using Upsilon;
|
using Upsilon;
|
||||||
using Upsilon.BaseTypes.UserData;
|
using Upsilon.BaseTypes.UserData;
|
||||||
using Upsilon.Evaluator;
|
using Upsilon.Evaluator;
|
||||||
|
using Upsilon.Exceptions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Local
|
// ReSharper disable UnusedMember.Local
|
||||||
@@ -68,7 +69,7 @@ function test(o)
|
|||||||
o.FieldStringSet = ""Test""
|
o.FieldStringSet = ""Test""
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
var result = Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options);
|
Executor.EvaluateFunction(input, "test", new[] {obj}, Options);
|
||||||
Assert.Equal("Test", obj.FieldStringSet);
|
Assert.Equal("Test", obj.FieldStringSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ function test(o)
|
|||||||
o.testMethod()
|
o.testMethod()
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options);
|
Executor.EvaluateFunction(input, "test", new[] {obj}, Options);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -106,7 +107,7 @@ function test(o)
|
|||||||
return o._privateTestField
|
return o._privateTestField
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options);
|
Assert.Throws<ParseException>(() => Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -118,7 +119,7 @@ function test(o)
|
|||||||
o.GetOnly = true
|
o.GetOnly = true
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options);
|
Assert.Throws<ParseException>(() => Executor.EvaluateFunction(input, "test", new[] {obj}, Options));
|
||||||
Assert.False(obj.GetOnly);
|
Assert.False(obj.GetOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +132,7 @@ function test(o)
|
|||||||
o.PrivateSet = true
|
o.PrivateSet = true
|
||||||
end
|
end
|
||||||
";
|
";
|
||||||
Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options);
|
Assert.Throws<ParseException>(() => Executor.EvaluateFunction<string>(input, "test", new[] {obj}, Options));
|
||||||
Assert.False(obj.PrivateSet);
|
Assert.False(obj.PrivateSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace UpsilonTests.StandardLibraryTests
|
|||||||
public void AssertTest()
|
public void AssertTest()
|
||||||
{
|
{
|
||||||
Executor.EvaluateScript("assert(true)", Options);
|
Executor.EvaluateScript("assert(true)", Options);
|
||||||
Assert.Throws<Exception>(() => Executor.EvaluateScript("assert(true)", Options));
|
Assert.Throws<Exception>(() => Executor.EvaluateScript("assert(false)", Options));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ namespace Ycicle
|
|||||||
{
|
{
|
||||||
Console.WriteLine("Upsilon REPL");
|
Console.WriteLine("Upsilon REPL");
|
||||||
Script script = null;
|
Script script = null;
|
||||||
var (evaluationScope, boundScope) = StaticScope.CreateStandardLibrary();
|
var options = new ScriptOptions()
|
||||||
|
{
|
||||||
|
ThrowExceptionOnError = false
|
||||||
|
};
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -21,7 +24,7 @@ namespace Ycicle
|
|||||||
var input = Console.ReadLine();
|
var input = Console.ReadLine();
|
||||||
if (input == "exit") return;
|
if (input == "exit") return;
|
||||||
script = script == null
|
script = script == null
|
||||||
? Executor.ParseInput(input)
|
? Executor.ParseInput(input, options)
|
||||||
: Executor.ContinueWith(script, input);
|
: Executor.ContinueWith(script, input);
|
||||||
|
|
||||||
if (script.Diagnostics.Messages.Count > 0)
|
if (script.Diagnostics.Messages.Count > 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user