From ce637be007589f82aa49d8e51018b64a25562901 Mon Sep 17 00:00:00 2001 From: nekosaur Date: Tue, 19 Aug 2025 09:46:13 +0200 Subject: [PATCH 1/3] fix: addition of null and bubble container --- .../ExpressionEvaluatorTests.cs | 12 +++++++++++- CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs b/CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs index 2f857bd..50fef92 100644 --- a/CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs +++ b/CodingSeb.ExpressionEvaluator.Tests/ExpressionEvaluatorTests.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using Microsoft.CSharp.RuntimeBinder; +using Newtonsoft.Json; using NUnit.Framework; using Shouldly; using System; @@ -1837,6 +1838,15 @@ public void Evaluate_DoubleDoubleQuotesInEscapedStringThrowException() evaluator.Evaluate("@\"Hello \"\" Joe\"").ShouldBe(@"Hello "" Joe"); } + + [Test] + [Category("Bug")] + public void Evaluate_NullAdditionShouldThrowExceptionNotReturnString() + { + var evaluator = new ExpressionEvaluator(); + + Should.Throw(() => evaluator.Evaluate("(null + null) + null")); + } //[Test] //[Category("Bug")] diff --git a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs index dfa1fd9..bcbfbd2 100644 --- a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs +++ b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs @@ -3296,11 +3296,11 @@ void EvaluateFirstPreviousUnaryOp(int j) { list[i] = operatorEvalutationsDict[eOp](left, right); - if (left is BubbleExceptionContainer && right is string) + if (left is BubbleExceptionContainer && right is string or null) { list[i] = left; //Bubble up the causing error } - else if (right is BubbleExceptionContainer && left is string) + else if (right is BubbleExceptionContainer && left is string or null) { list[i] = right; //Bubble up the causing error } From 3858f06a8268018af6dc68850e90dd15fedc9da7 Mon Sep 17 00:00:00 2001 From: CodingSeb Date: Mon, 8 Sep 2025 10:39:52 +0200 Subject: [PATCH 2/3] Refactors expression evaluator operator evaluations Streamlines operator evaluation logic by simplifying lambda expressions and using implicit typing, enhancing code readability. Improves bubbling up of exceptions and null handling during expression evaluation. --- .../ExpressionEvaluator.cs | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs index bcbfbd2..1b291ed 100644 --- a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs +++ b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs @@ -242,56 +242,56 @@ protected enum TryBlockEvaluatedState { new Dictionary>() { - {ExpressionOperator.UnaryPlus, (dynamic _, dynamic right) => +right }, - {ExpressionOperator.UnaryMinus, (dynamic _, dynamic right) => -right }, - {ExpressionOperator.LogicalNegation, (dynamic _, dynamic right) => !right }, - {ExpressionOperator.BitwiseComplement, (dynamic _, dynamic right) => ~right }, - {ExpressionOperator.Cast, (dynamic left, dynamic right) => ChangeType(right, left) }, + {ExpressionOperator.UnaryPlus, (_, right) => +right }, + {ExpressionOperator.UnaryMinus, (_, right) => -right }, + {ExpressionOperator.LogicalNegation, (_, right) => !right }, + {ExpressionOperator.BitwiseComplement, (_, right) => ~right }, + {ExpressionOperator.Cast, (left, right) => ChangeType(right, left) }, }, new Dictionary>() { - {ExpressionOperator.Multiply, (dynamic left, dynamic right) => left * right }, - {ExpressionOperator.Divide, (dynamic left, dynamic right) => left / right }, - {ExpressionOperator.Modulo, (dynamic left, dynamic right) => left % right }, + {ExpressionOperator.Multiply, (left, right) => left * right }, + {ExpressionOperator.Divide, (left, right) => left / right }, + {ExpressionOperator.Modulo, (left, right) => left % right }, }, new Dictionary>() { - {ExpressionOperator.Plus, (dynamic left, dynamic right) => left + right }, - {ExpressionOperator.Minus, (dynamic left, dynamic right) => left - right }, + {ExpressionOperator.Plus, (left, right) => left + right }, + {ExpressionOperator.Minus, (left, right) => left - right }, }, new Dictionary>() { - {ExpressionOperator.ShiftBitsLeft, (dynamic left, dynamic right) => left << right }, - {ExpressionOperator.ShiftBitsRight, (dynamic left, dynamic right) => left >> right }, + {ExpressionOperator.ShiftBitsLeft, (left, right) => left << right }, + {ExpressionOperator.ShiftBitsRight, (left, right) => left >> right }, }, new Dictionary>() { - {ExpressionOperator.Lower, (dynamic left, dynamic right) => left < right }, - {ExpressionOperator.Greater, (dynamic left, dynamic right) => left > right }, - {ExpressionOperator.LowerOrEqual, (dynamic left, dynamic right) => left <= right }, - {ExpressionOperator.GreaterOrEqual, (dynamic left, dynamic right) => left >= right }, - {ExpressionOperator.Is, (dynamic left, dynamic right) => left != null && (((ClassOrEnumType)right).Type).IsAssignableFrom(left.GetType()) }, + {ExpressionOperator.Lower, (left, right) => left < right }, + {ExpressionOperator.Greater, (left, right) => left > right }, + {ExpressionOperator.LowerOrEqual, (left, right) => left <= right }, + {ExpressionOperator.GreaterOrEqual, (left, right) => left >= right }, + {ExpressionOperator.Is, (left, right) => left != null && (((ClassOrEnumType)right).Type).IsAssignableFrom(left.GetType()) }, }, new Dictionary>() { - {ExpressionOperator.Equal, (dynamic left, dynamic right) => left == right }, - {ExpressionOperator.NotEqual, (dynamic left, dynamic right) => left != right }, + {ExpressionOperator.Equal, (left, right) => left == right }, + {ExpressionOperator.NotEqual, (left, right) => left != right }, }, new Dictionary>() { - {ExpressionOperator.LogicalAnd, (dynamic left, dynamic right) => left & right }, + {ExpressionOperator.LogicalAnd, (left, right) => left & right }, }, new Dictionary>() { - {ExpressionOperator.LogicalXor, (dynamic left, dynamic right) => left ^ right }, + {ExpressionOperator.LogicalXor, (left, right) => left ^ right }, }, new Dictionary>() { - {ExpressionOperator.LogicalOr, (dynamic left, dynamic right) => left | right }, + {ExpressionOperator.LogicalOr, (left, right) => left | right }, }, new Dictionary>() { - {ExpressionOperator.ConditionalAnd, (dynamic left, dynamic right) => { + {ExpressionOperator.ConditionalAnd, (left, right) => { if ( left is BubbleExceptionContainer leftExceptionContainer) { leftExceptionContainer.Throw(); @@ -314,7 +314,7 @@ protected enum TryBlockEvaluatedState }, new Dictionary>() { - {ExpressionOperator.ConditionalOr, (dynamic left, dynamic right) => { + {ExpressionOperator.ConditionalOr, (left, right) => { if ( left is BubbleExceptionContainer leftExceptionContainer) { leftExceptionContainer.Throw(); @@ -337,7 +337,7 @@ protected enum TryBlockEvaluatedState }, new Dictionary>() { - {ExpressionOperator.NullCoalescing, (dynamic left, dynamic right) => left ?? right }, + {ExpressionOperator.NullCoalescing, (left, right) => left ?? right }, }, }; @@ -3206,7 +3206,7 @@ protected virtual object ProcessStack(Stack stack) .Select(e => e is NullConditionalNullValue ? null : e) .ToList(); - OperatorsEvaluations.ToList().ForEach((IDictionary> operatorEvalutationsDict) => + OperatorsEvaluations.ToList().ForEach(operatorEvalutationsDict => { for (int i = list.Count - 1; i >= 0; i--) { @@ -3296,11 +3296,11 @@ void EvaluateFirstPreviousUnaryOp(int j) { list[i] = operatorEvalutationsDict[eOp](left, right); - if (left is BubbleExceptionContainer && right is string or null) + if (left is BubbleExceptionContainer && (right == null || right is string)) { list[i] = left; //Bubble up the causing error } - else if (right is BubbleExceptionContainer && left is string or null) + else if (right is BubbleExceptionContainer && (left is string || left is null)) { list[i] = right; //Bubble up the causing error } @@ -3481,7 +3481,7 @@ protected virtual bool GetLambdaExpression(string expression, Stack stac bool inScriptAtDeclaration = inScript; - stack.Push(new InternalDelegate((object[] args) => + stack.Push(new InternalDelegate(args => { var vars = new Dictionary(variables); From 08d47ddee6ef8def7c0a924ef71b1606d0c38dbd Mon Sep 17 00:00:00 2001 From: CodingSeb Date: Mon, 8 Sep 2025 10:43:20 +0200 Subject: [PATCH 3/3] Version 1.4.41.0 --- .../CodingSeb.ExpressionEvaluator.csproj | 10 ++++------ CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj b/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj index 56b2a61..66b6cd9 100644 --- a/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj +++ b/CodingSeb.ExpressionEvaluator/CodingSeb.ExpressionEvaluator.csproj @@ -5,9 +5,9 @@ CodingSeb.ExpressionEvaluator A Simple Math and Pseudo C# Expression Evaluator in One C# File. Can also execute small C# like scripts Copyright © Coding Seb 2017 - 1.4.40.0 - 1.4.40.0 - 1.4.40.0 + 1.4.41.0 + 1.4.41.0 + 1.4.41.0 bin\$(Configuration)\ Coding Seb CodingSeb.ExpressionEvaluator @@ -20,9 +20,7 @@ https://github.com/codingseb/ExpressionEvaluator/blob/master/Icon.png?raw=true Icon.png false - * Make shared cache for types resolution thread safe -* Add ScriptEvaluating and ScriptEvaluated events -* Add unaryOperatorsDictionary to manage custom operators that are both unaries and binaries better + * fix: addition of null and bubble container LICENSE.md https://github.com/codingseb/ExpressionEvaluator true diff --git a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs index 1b291ed..a17720c 100644 --- a/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs +++ b/CodingSeb.ExpressionEvaluator/ExpressionEvaluator.cs @@ -1,6 +1,6 @@ /****************************************************************************************************** Title : ExpressionEvaluator (https://github.com/codingseb/ExpressionEvaluator) - Version : 1.4.40.0 + Version : 1.4.41.0 (if last digit (the forth) is not a zero, the version is an intermediate version and can be unstable) Author : Coding Seb