diff --git a/README.markdown b/README.markdown index 83f178b..4553cd4 100644 --- a/README.markdown +++ b/README.markdown @@ -34,6 +34,12 @@ You should install [Flee with NuGet](https://www.nuget.org/packages/Flee): Or via the .NET Core command line interface: dotnet add package Flee + +## NuGet Packages + +| Name | NuGet | +| :--- | :--- | +| [Flee](https://www.nuget.org/packages/Flee) | [![Flee](https://img.shields.io/badge/nuget-v1.2.2-blue.svg)](https://www.nuget.org/packages/Flee) ## More information * [Examples](https://github.com/mparlak/Flee/wiki/Examples) to learn how to create and evaluate expressions. diff --git a/nuget/flee.nuspec b/nuget/flee.nuspec index bd67e5b..659051f 100644 --- a/nuget/flee.nuspec +++ b/nuget/flee.nuspec @@ -3,7 +3,7 @@ Flee Flee - 1.0.7 + 1.2.1 Muhammet Parlak Muhammet Parlak https://github.com/mparlak/Flee @@ -14,6 +14,13 @@ Copyright 2017 flee,expression evaluator,Expression Evaluator for c# + 1.2.1 + • Fix for IndexOutOfRange when running complex(?) formulas + • Update Arithmetic.cs + 1.2.0 + • new – digitally sign a strong named assembly + 1.1.0 + • new – added strong name key 1.0.7 • Fixed – Flee fails to parse "if" formula 1.0.6 diff --git a/src/Flee.Net45/ExpressionElements/Base/Binary.cs b/src/Flee.Net45/ExpressionElements/Base/Binary.cs index 125ec2d..e05af55 100644 --- a/src/Flee.Net45/ExpressionElements/Base/Binary.cs +++ b/src/Flee.Net45/ExpressionElements/Base/Binary.cs @@ -92,9 +92,10 @@ protected MethodInfo GetOverloadedBinaryOperator(string name, object operation) } else { + return leftMethod; // Ambiguous call - base.ThrowAmbiguousCallException(leftType, rightType, operation); - return null; + //base.ThrowAmbiguousCallException(leftType, rightType, operation); + //return null; } } diff --git a/src/Flee.Net45/ExpressionElements/Base/ExpressionElement.cs b/src/Flee.Net45/ExpressionElements/Base/ExpressionElement.cs index d0b99e2..1e21c17 100644 --- a/src/Flee.Net45/ExpressionElements/Base/ExpressionElement.cs +++ b/src/Flee.Net45/ExpressionElements/Base/ExpressionElement.cs @@ -36,7 +36,7 @@ protected void ThrowCompileException(string messageKey, CompileExceptionReason r string messageTemplate = FleeResourceManager.Instance.GetCompileErrorString(messageKey); string message = string.Format(messageTemplate, arguments); message = string.Concat(this.Name, ": ", message); - throw new ExpressionCompileException(message, reason); + throw new ExpressionCompileException(message, reason, arguments); } protected void ThrowAmbiguousCallException(Type leftType, Type rightType, object operation) diff --git a/src/Flee.Net45/ExpressionElements/Compare.cs b/src/Flee.Net45/ExpressionElements/Compare.cs index 9033fa5..aa074e5 100644 --- a/src/Flee.Net45/ExpressionElements/Compare.cs +++ b/src/Flee.Net45/ExpressionElements/Compare.cs @@ -24,7 +24,7 @@ public CompareElement() public void Initialize(ExpressionElement leftChild, ExpressionElement rightChild, LogicalCompareOperation op) { MyLeftChild = leftChild; - MyRightChild = (Int32LiteralElement)rightChild; + MyRightChild = rightChild; _myOperation = op; } diff --git a/src/Flee.Net45/ExpressionElements/Conditional.cs b/src/Flee.Net45/ExpressionElements/Conditional.cs index c3ef069..3c73532 100644 --- a/src/Flee.Net45/ExpressionElements/Conditional.cs +++ b/src/Flee.Net45/ExpressionElements/Conditional.cs @@ -22,8 +22,8 @@ public ConditionalElement(ExpressionElement condition, ExpressionElement whenTru _myCondition = condition; _myWhenTrue = whenTrue; _myWhenFalse = whenFalse; - - if ((!object.ReferenceEquals(_myCondition.ResultType, typeof(bool)))) + + if (!ImplicitConverter.EmitImplicitConvert(_myCondition.ResultType, typeof(bool), null)) { base.ThrowCompileException(CompileErrorResourceKeys.FirstArgNotBoolean, CompileExceptionReason.TypeMismatch); } diff --git a/src/Flee.Net45/ExpressionElements/LogicalBitwise/AndOr.cs b/src/Flee.Net45/ExpressionElements/LogicalBitwise/AndOr.cs index 9ae9ceb..9c54485 100644 --- a/src/Flee.Net45/ExpressionElements/LogicalBitwise/AndOr.cs +++ b/src/Flee.Net45/ExpressionElements/LogicalBitwise/AndOr.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Reflection; using System.Reflection.Emit; using Flee.ExpressionElements.Base; using Flee.InternalTypes; @@ -26,6 +27,15 @@ protected override void GetOperation(object operation) protected override System.Type GetResultType(System.Type leftType, System.Type rightType) { + MethodInfo overloadedMethod = this.GetOverloadedAndOrOperator(); + + // Is an overloaded operator defined for our left and right children? + if ((overloadedMethod != null)) + { + // Yes, so use its return type + return overloadedMethod.ReturnType; + } + Type bitwiseOpType = Utility.GetBitwiseOpType(leftType, rightType); if ((bitwiseOpType != null)) { @@ -41,21 +51,52 @@ protected override System.Type GetResultType(System.Type leftType, System.Type r } } + private MethodInfo GetOverloadedAndOrOperator() + { + // Get the name of the operator + string name = GetOverloadedOperatorFunctionName(_myOperation); + return base.GetOverloadedBinaryOperator(name, _myOperation); + } + + private static string GetOverloadedOperatorFunctionName(AndOrOperation op) + { + switch (op) + { + case AndOrOperation.And: + return "BitwiseAnd"; + case AndOrOperation.Or: + return "BitwiseOr"; + default: + Debug.Assert(false, "unknown operator type"); + return null; + } + } + public override void Emit(FleeILGenerator ilg, IServiceProvider services) { - Type resultType = this.ResultType; + MethodInfo overloadedMethod = this.GetOverloadedAndOrOperator(); - if (object.ReferenceEquals(resultType, typeof(bool))) + if ((overloadedMethod != null)) { - this.DoEmitLogical(ilg, services); + // Emit a call to an overloaded operator + this.EmitOverloadedOperatorCall(overloadedMethod, ilg, services); } else { - MyLeftChild.Emit(ilg, services); - ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); - MyRightChild.Emit(ilg, services); - ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); - EmitBitwiseOperation(ilg, _myOperation); + Type resultType = this.ResultType; + + if (object.ReferenceEquals(resultType, typeof(bool))) + { + this.DoEmitLogical(ilg, services); + } + else + { + MyLeftChild.Emit(ilg, services); + ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); + MyRightChild.Emit(ilg, services); + ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); + EmitBitwiseOperation(ilg, _myOperation); + } } } diff --git a/src/Flee.Net45/Flee.Net45.csproj b/src/Flee.Net45/Flee.Net45.csproj index 6716479..5b968e0 100644 --- a/src/Flee.Net45/Flee.Net45.csproj +++ b/src/Flee.Net45/Flee.Net45.csproj @@ -31,7 +31,7 @@ 4 - true + false flee.pfx diff --git a/src/Flee.Net45/InternalTypes/BranchManager.cs b/src/Flee.Net45/InternalTypes/BranchManager.cs index 1e7c87e..c1729d3 100644 --- a/src/Flee.Net45/InternalTypes/BranchManager.cs +++ b/src/Flee.Net45/InternalTypes/BranchManager.cs @@ -108,13 +108,10 @@ public bool IsLongBranch(FleeILGenerator ilg, Label target) if (index > -1 && index < MyBranchInfos.Count) { bi = MyBranchInfos[index]; - return bi.IsLongBranch; } - else - { - return true; // temp fix: not sure why, but MyBranchInfos seems to be missing elements when executing long scripts - } - } + + return bi.IsLongBranch; + } /// /// Add a branch from a location to a target label diff --git a/src/Flee.Net45/InternalTypes/Expression.cs b/src/Flee.Net45/InternalTypes/Expression.cs index 31600a7..9e0cad5 100644 --- a/src/Flee.Net45/InternalTypes/Expression.cs +++ b/src/Flee.Net45/InternalTypes/Expression.cs @@ -157,15 +157,55 @@ private void ValidateOwner(object owner) } } + private T HandleEvaluationException(Func function) + { + try + { + return function.Invoke(); + } + catch (Exception e) + { + if (e.InnerException?.Message != null) + { + throw new ExpressionEvaluationException(e.InnerException.Message); + } + var variables = _myInfo.GetReferencedVariables(); + if (variables.Length != 0) + { + var exception = GetCustomExceptionMessage(variables); + throw new ExpressionEvaluationException(exception); + } + throw new ExpressionEvaluationException(e.Message); + } + } + + private string GetCustomExceptionMessage(string[] variables) + { + var errorMessage = ""; + foreach (var variable in variables) + { + var inputValue = Context.Variables.GetVariableValueInternal(variable); + errorMessage += string.IsNullOrWhiteSpace(inputValue) + ? $"{variable} = empty " + : $"{variable} = {inputValue} " + " "; + } + + var exception = variables.Length == 1 + ? $"failed to run expression {_myExpression} with input {errorMessage}" + : $"failed to run expression {_myExpression} with inputs: {errorMessage}"; + return exception; + } + public object Evaluate() { - return _myEvaluator(_myOwner, _myContext, _myContext.Variables); + return HandleEvaluationException(() => _myEvaluator(_myOwner, _myContext, _myContext.Variables)); } public T EvaluateGeneric() { - return _myEvaluator(_myOwner, _myContext, _myContext.Variables); + return HandleEvaluationException(() => _myEvaluator(_myOwner, _myContext, _myContext.Variables)); } + T IGenericExpression.Evaluate() { return EvaluateGeneric(); diff --git a/src/Flee.Net45/PublicTypes/Exceptions.cs b/src/Flee.Net45/PublicTypes/Exceptions.cs index d45eb8a..b1b5b20 100644 --- a/src/Flee.Net45/PublicTypes/Exceptions.cs +++ b/src/Flee.Net45/PublicTypes/Exceptions.cs @@ -28,8 +28,11 @@ public enum CompileExceptionReason public sealed class ExpressionCompileException : Exception { private readonly CompileExceptionReason _myReason; - internal ExpressionCompileException(string message, CompileExceptionReason reason) : base(message) + public object[] Arguments { get; } + + internal ExpressionCompileException(string message, CompileExceptionReason reason, object[] arguments) : base(message) { + Arguments = arguments; _myReason = reason; } @@ -68,4 +71,16 @@ public override string Message public CompileExceptionReason Reason => _myReason; } + + /// + /// Exception, which occured during expression evaluation. + /// + [Serializable] + public sealed class ExpressionEvaluationException : Exception + { + + public ExpressionEvaluationException(string message) : base(message) + { + } + } } diff --git a/src/Flee.Net45/Resources/CompileErrors.Designer.cs b/src/Flee.Net45/Resources/CompileErrors.Designer.cs index c497a51..20ea61b 100644 --- a/src/Flee.Net45/Resources/CompileErrors.Designer.cs +++ b/src/Flee.Net45/Resources/CompileErrors.Designer.cs @@ -366,18 +366,18 @@ internal static string TypeNotArrayAndHasNoIndexerOfType { return ResourceManager.GetString("TypeNotArrayAndHasNoIndexerOfType", resourceCulture); } } - + /// - /// Looks up a localized string similar to Could find not function '{0}({1})'. + /// Looks up a localized string similar to Could not find function '{0}({1})'. /// internal static string UndefinedFunction { get { return ResourceManager.GetString("UndefinedFunction", resourceCulture); } } - + /// - /// Looks up a localized string similar to Could find not function '{0}({1})' on type '{2}'. + /// Looks up a localized string similar to Could not find function '{0}({1})' on type '{2}'. /// internal static string UndefinedFunctionOnType { get { diff --git a/src/Flee.Net45/Resources/CompileErrors.resx b/src/Flee.Net45/Resources/CompileErrors.resx index dc1320d..73526eb 100644 --- a/src/Flee.Net45/Resources/CompileErrors.resx +++ b/src/Flee.Net45/Resources/CompileErrors.resx @@ -220,10 +220,10 @@ Type '{0}' is not an array and does not have an indexer which accepts '{1}' - Could find not function '{0}({1})' + Could not find function '{0}({1})' - Could find not function '{0}({1})' on type '{2}' + Could not find function '{0}({1})' on type '{2}' Unexpected character: {0} diff --git a/src/Flee.Net45/flee.pfx b/src/Flee.Net45/flee.pfx index 17280da..ce1c5f6 100644 Binary files a/src/Flee.Net45/flee.pfx and b/src/Flee.Net45/flee.pfx differ diff --git a/src/Flee.NetStandard20/ExpressionElements/Arithmetic.cs b/src/Flee.NetStandard20/ExpressionElements/Arithmetic.cs index 4242ec2..2014ab9 100644 --- a/src/Flee.NetStandard20/ExpressionElements/Arithmetic.cs +++ b/src/Flee.NetStandard20/ExpressionElements/Arithmetic.cs @@ -316,7 +316,7 @@ private bool IsOptimizablePower { get { - if (_myOperation != BinaryArithmeticOperation.Power) + if (_myOperation != BinaryArithmeticOperation.Power || !(MyRightChild is Int32LiteralElement)) { return false; } diff --git a/src/Flee.NetStandard20/ExpressionElements/Base/Binary.cs b/src/Flee.NetStandard20/ExpressionElements/Base/Binary.cs index 125ec2d..e05af55 100644 --- a/src/Flee.NetStandard20/ExpressionElements/Base/Binary.cs +++ b/src/Flee.NetStandard20/ExpressionElements/Base/Binary.cs @@ -92,9 +92,10 @@ protected MethodInfo GetOverloadedBinaryOperator(string name, object operation) } else { + return leftMethod; // Ambiguous call - base.ThrowAmbiguousCallException(leftType, rightType, operation); - return null; + //base.ThrowAmbiguousCallException(leftType, rightType, operation); + //return null; } } diff --git a/src/Flee.NetStandard20/ExpressionElements/Base/ExpressionElement.cs b/src/Flee.NetStandard20/ExpressionElements/Base/ExpressionElement.cs index d0b99e2..1e21c17 100644 --- a/src/Flee.NetStandard20/ExpressionElements/Base/ExpressionElement.cs +++ b/src/Flee.NetStandard20/ExpressionElements/Base/ExpressionElement.cs @@ -36,7 +36,7 @@ protected void ThrowCompileException(string messageKey, CompileExceptionReason r string messageTemplate = FleeResourceManager.Instance.GetCompileErrorString(messageKey); string message = string.Format(messageTemplate, arguments); message = string.Concat(this.Name, ": ", message); - throw new ExpressionCompileException(message, reason); + throw new ExpressionCompileException(message, reason, arguments); } protected void ThrowAmbiguousCallException(Type leftType, Type rightType, object operation) diff --git a/src/Flee.NetStandard20/ExpressionElements/Compare.cs b/src/Flee.NetStandard20/ExpressionElements/Compare.cs index 9033fa5..aa074e5 100644 --- a/src/Flee.NetStandard20/ExpressionElements/Compare.cs +++ b/src/Flee.NetStandard20/ExpressionElements/Compare.cs @@ -24,7 +24,7 @@ public CompareElement() public void Initialize(ExpressionElement leftChild, ExpressionElement rightChild, LogicalCompareOperation op) { MyLeftChild = leftChild; - MyRightChild = (Int32LiteralElement)rightChild; + MyRightChild = rightChild; _myOperation = op; } diff --git a/src/Flee.NetStandard20/ExpressionElements/Conditional.cs b/src/Flee.NetStandard20/ExpressionElements/Conditional.cs index c3ef069..4a9e092 100644 --- a/src/Flee.NetStandard20/ExpressionElements/Conditional.cs +++ b/src/Flee.NetStandard20/ExpressionElements/Conditional.cs @@ -23,7 +23,7 @@ public ConditionalElement(ExpressionElement condition, ExpressionElement whenTru _myWhenTrue = whenTrue; _myWhenFalse = whenFalse; - if ((!object.ReferenceEquals(_myCondition.ResultType, typeof(bool)))) + if (!ImplicitConverter.EmitImplicitConvert(_myCondition.ResultType, typeof(bool), null)) { base.ThrowCompileException(CompileErrorResourceKeys.FirstArgNotBoolean, CompileExceptionReason.TypeMismatch); } diff --git a/src/Flee.NetStandard20/ExpressionElements/LogicalBitwise/AndOr.cs b/src/Flee.NetStandard20/ExpressionElements/LogicalBitwise/AndOr.cs index 9ae9ceb..9c54485 100644 --- a/src/Flee.NetStandard20/ExpressionElements/LogicalBitwise/AndOr.cs +++ b/src/Flee.NetStandard20/ExpressionElements/LogicalBitwise/AndOr.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Reflection; using System.Reflection.Emit; using Flee.ExpressionElements.Base; using Flee.InternalTypes; @@ -26,6 +27,15 @@ protected override void GetOperation(object operation) protected override System.Type GetResultType(System.Type leftType, System.Type rightType) { + MethodInfo overloadedMethod = this.GetOverloadedAndOrOperator(); + + // Is an overloaded operator defined for our left and right children? + if ((overloadedMethod != null)) + { + // Yes, so use its return type + return overloadedMethod.ReturnType; + } + Type bitwiseOpType = Utility.GetBitwiseOpType(leftType, rightType); if ((bitwiseOpType != null)) { @@ -41,21 +51,52 @@ protected override System.Type GetResultType(System.Type leftType, System.Type r } } + private MethodInfo GetOverloadedAndOrOperator() + { + // Get the name of the operator + string name = GetOverloadedOperatorFunctionName(_myOperation); + return base.GetOverloadedBinaryOperator(name, _myOperation); + } + + private static string GetOverloadedOperatorFunctionName(AndOrOperation op) + { + switch (op) + { + case AndOrOperation.And: + return "BitwiseAnd"; + case AndOrOperation.Or: + return "BitwiseOr"; + default: + Debug.Assert(false, "unknown operator type"); + return null; + } + } + public override void Emit(FleeILGenerator ilg, IServiceProvider services) { - Type resultType = this.ResultType; + MethodInfo overloadedMethod = this.GetOverloadedAndOrOperator(); - if (object.ReferenceEquals(resultType, typeof(bool))) + if ((overloadedMethod != null)) { - this.DoEmitLogical(ilg, services); + // Emit a call to an overloaded operator + this.EmitOverloadedOperatorCall(overloadedMethod, ilg, services); } else { - MyLeftChild.Emit(ilg, services); - ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); - MyRightChild.Emit(ilg, services); - ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); - EmitBitwiseOperation(ilg, _myOperation); + Type resultType = this.ResultType; + + if (object.ReferenceEquals(resultType, typeof(bool))) + { + this.DoEmitLogical(ilg, services); + } + else + { + MyLeftChild.Emit(ilg, services); + ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); + MyRightChild.Emit(ilg, services); + ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); + EmitBitwiseOperation(ilg, _myOperation); + } } } diff --git a/src/Flee.NetStandard20/Flee.NetStandard20.csproj b/src/Flee.NetStandard20/Flee.NetStandard20.csproj index 365486e..43437d8 100644 --- a/src/Flee.NetStandard20/Flee.NetStandard20.csproj +++ b/src/Flee.NetStandard20/Flee.NetStandard20.csproj @@ -3,7 +3,7 @@ netstandard2.0 Flee - true + false flee.pfx false diff --git a/src/Flee.NetStandard20/InternalTypes/BranchManager.cs b/src/Flee.NetStandard20/InternalTypes/BranchManager.cs index ff8272b..9e1b18c 100644 --- a/src/Flee.NetStandard20/InternalTypes/BranchManager.cs +++ b/src/Flee.NetStandard20/InternalTypes/BranchManager.cs @@ -104,7 +104,10 @@ public bool IsLongBranch(FleeILGenerator ilg, Label target) BranchInfo bi = new BranchInfo(startLoc, target); int index = MyBranchInfos.IndexOf(bi); - bi = MyBranchInfos[index]; + if (index > -1 && index < MyBranchInfos.Count) + { + bi = MyBranchInfos[index]; + } return bi.IsLongBranch; } diff --git a/src/Flee.NetStandard20/InternalTypes/Expression.cs b/src/Flee.NetStandard20/InternalTypes/Expression.cs index 5345f75..63f14c4 100644 --- a/src/Flee.NetStandard20/InternalTypes/Expression.cs +++ b/src/Flee.NetStandard20/InternalTypes/Expression.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel.Design; using System.Diagnostics; +using System.Linq; using System.Reflection.Emit; using System.Reflection; using Flee.ExpressionElements; @@ -154,15 +155,56 @@ private void ValidateOwner(object owner) } } + private T HandleEvaluationException(Func function) + { + try + { + return function.Invoke(); + } + catch (Exception e) + { + if (e.InnerException?.Message != null) + { + throw new ExpressionEvaluationException(e.InnerException.Message); + } + var variables = _myInfo.GetReferencedVariables(); + if (variables.Length != 0) + { + var exception = GetCustomExceptionMessage(variables); + throw new ExpressionEvaluationException(exception); + } + throw new ExpressionEvaluationException(e.Message); + + } + } + + private string GetCustomExceptionMessage(string[] variables) + { + var errorMessage = ""; + foreach (var variable in variables) + { + var inputValue = Context.Variables.GetVariableValueInternal(variable); + errorMessage += string.IsNullOrWhiteSpace(inputValue) + ? $"{variable} = empty " + : $"{variable} = {inputValue} " + " "; + } + + var exception = variables.Length == 1 + ? $"failed to run expression {_myExpression} with input {errorMessage}" + : $"failed to run expression {_myExpression} with inputs: {errorMessage}"; + return exception; + } + public object Evaluate() { - return _myEvaluator(_myOwner, _myContext, _myContext.Variables); + return HandleEvaluationException(() => _myEvaluator(_myOwner, _myContext, _myContext.Variables)); } public T EvaluateGeneric() { - return _myEvaluator(_myOwner, _myContext, _myContext.Variables); + return HandleEvaluationException(() => _myEvaluator(_myOwner, _myContext, _myContext.Variables)); } + T IGenericExpression.Evaluate() { return EvaluateGeneric(); diff --git a/src/Flee.NetStandard20/PublicTypes/Exceptions.cs b/src/Flee.NetStandard20/PublicTypes/Exceptions.cs index d45eb8a..270097e 100644 --- a/src/Flee.NetStandard20/PublicTypes/Exceptions.cs +++ b/src/Flee.NetStandard20/PublicTypes/Exceptions.cs @@ -1,7 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; using Flee.InternalTypes; using Flee.Parsing.grammatica_1._5.alpha2.PerCederberg.Grammatica.Runtime; using Flee.Resources; @@ -28,8 +25,11 @@ public enum CompileExceptionReason public sealed class ExpressionCompileException : Exception { private readonly CompileExceptionReason _myReason; - internal ExpressionCompileException(string message, CompileExceptionReason reason) : base(message) + public object[] Arguments { get; } + + internal ExpressionCompileException(string message, CompileExceptionReason reason, object[] arguments) : base(message) { + Arguments = arguments; _myReason = reason; } @@ -68,4 +68,16 @@ public override string Message public CompileExceptionReason Reason => _myReason; } + + /// + /// Exception, which occured during expression evaluation. + /// + [Serializable] + public sealed class ExpressionEvaluationException : Exception + { + public ExpressionEvaluationException(string message) : base(message) + { + + } + } } diff --git a/src/Flee.NetStandard20/Resources/CompileErrors.Designer.cs b/src/Flee.NetStandard20/Resources/CompileErrors.Designer.cs index c497a51..0ea9fd0 100644 --- a/src/Flee.NetStandard20/Resources/CompileErrors.Designer.cs +++ b/src/Flee.NetStandard20/Resources/CompileErrors.Designer.cs @@ -366,9 +366,9 @@ internal static string TypeNotArrayAndHasNoIndexerOfType { return ResourceManager.GetString("TypeNotArrayAndHasNoIndexerOfType", resourceCulture); } } - + /// - /// Looks up a localized string similar to Could find not function '{0}({1})'. + /// Looks up a localized string similar to Could not find function '{0}({1})'. /// internal static string UndefinedFunction { get { @@ -377,7 +377,7 @@ internal static string UndefinedFunction { } /// - /// Looks up a localized string similar to Could find not function '{0}({1})' on type '{2}'. + /// Looks up a localized string similar to Could not find function '{0}({1})' on type '{2}'. /// internal static string UndefinedFunctionOnType { get { diff --git a/src/Flee.NetStandard20/Resources/CompileErrors.resx b/src/Flee.NetStandard20/Resources/CompileErrors.resx index dc1320d..73526eb 100644 --- a/src/Flee.NetStandard20/Resources/CompileErrors.resx +++ b/src/Flee.NetStandard20/Resources/CompileErrors.resx @@ -220,10 +220,10 @@ Type '{0}' is not an array and does not have an indexer which accepts '{1}' - Could find not function '{0}({1})' + Could not find function '{0}({1})' - Could find not function '{0}({1})' on type '{2}' + Could not find function '{0}({1})' on type '{2}' Unexpected character: {0} diff --git a/src/Flee.NetStandard20/flee.pfx b/src/Flee.NetStandard20/flee.pfx index 6cd87b3..35fe4b0 100644 Binary files a/src/Flee.NetStandard20/flee.pfx and b/src/Flee.NetStandard20/flee.pfx differ diff --git a/test/Flee.Console/Flee.Console.csproj b/test/Flee.Console/Flee.Console.csproj index 7863ed7..3445e9e 100644 --- a/test/Flee.Console/Flee.Console.csproj +++ b/test/Flee.Console/Flee.Console.csproj @@ -6,7 +6,7 @@ - + diff --git a/test/Flee.Test/CalcEngineTests/LongScriptTests.cs b/test/Flee.Test/CalcEngineTests/LongScriptTests.cs index 22d5a0a..f26fc9f 100644 --- a/test/Flee.Test/CalcEngineTests/LongScriptTests.cs +++ b/test/Flee.Test/CalcEngineTests/LongScriptTests.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; using Flee.CalcEngine.PublicTypes; @@ -30,7 +32,8 @@ public LongScriptTests() [Test] public void LongScriptWithManyFunctions() { - var script = System.IO.File.ReadAllText(@"test\Flee.Test\TestScripts\LongScriptWithManyFunctions.js"); + var workingDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var script = File.ReadAllText($"{workingDir}\\TestScripts\\LongScriptWithManyFunctions.js"); var expr = _myEngine.Context.CompileDynamic(script); var result = expr.Evaluate(); @@ -41,7 +44,8 @@ public void LongScriptWithManyFunctions() [Test] public void FailingLongScriptWithManyFunctions() { - var script = System.IO.File.ReadAllText(@"test\Flee.Test\TestScripts\FailingLongScriptWithManyFunctions.js"); + var workingDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var script = File.ReadAllText($"{workingDir}\\TestScripts\\FailingLongScriptWithManyFunctions.js"); var expr = _myEngine.Context.CompileDynamic(script); var result = expr.Evaluate(); diff --git a/test/Flee.Test/ExpressionTests/ExpressionBuildingTest.cs b/test/Flee.Test/ExpressionTests/ExpressionBuildingTest.cs index 0a038b9..2107ffd 100644 --- a/test/Flee.Test/ExpressionTests/ExpressionBuildingTest.cs +++ b/test/Flee.Test/ExpressionTests/ExpressionBuildingTest.cs @@ -77,5 +77,23 @@ public void NullIsNullCheck() Assert.IsTrue((bool)e1.Evaluate()); } + + [TestMethod, ExpectedException(typeof(ExpressionEvaluationException))] + public void RuntimeErrorCheck_DivisionByZero() + { + ExpressionContext context = new ExpressionContext(); + IDynamicExpression e1 = context.CompileDynamic("1 = 1/0"); + e1.Evaluate(); + } + + [TestMethod, ExpectedException(typeof(ExpressionEvaluationException))] + public void RuntimeErrorCheck_ParsingInvalidDate() + { + ExpressionContext context = new ExpressionContext(); + context.Variables.Add("a", "stringObject"); + context.Imports.AddType(typeof(DateTime)); + IDynamicExpression e1 = context.CompileDynamic("Parse(a)"); + e1.Evaluate(); + } } } \ No newline at end of file diff --git a/test/Flee.Test/Flee.Test.csproj b/test/Flee.Test/Flee.Test.csproj index d9682f5..36c066e 100644 --- a/test/Flee.Test/Flee.Test.csproj +++ b/test/Flee.Test/Flee.Test.csproj @@ -39,6 +39,9 @@ 4 + + ..\..\packages\Flee.1.2.1\lib\net45\Flee.Net45.dll + ..\..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll @@ -69,19 +72,17 @@ - - + + Always + + + Always + - - - {658c0ed4-404a-48ec-96ff-d22c3c12ac39} - Flee.Net45 - - diff --git a/test/Flee.Test/packages.config b/test/Flee.Test/packages.config index 512b0a7..e27db3d 100644 --- a/test/Flee.Test/packages.config +++ b/test/Flee.Test/packages.config @@ -1,8 +1,13 @@  - + + + + + + \ No newline at end of file