diff --git a/src/NReco.LambdaParser.Tests/LambdaParserTests.cs b/src/NReco.LambdaParser.Tests/LambdaParserTests.cs index 78e7ea3..defc844 100644 --- a/src/NReco.LambdaParser.Tests/LambdaParserTests.cs +++ b/src/NReco.LambdaParser.Tests/LambdaParserTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections; using System.Diagnostics; +using System.Numerics; using System.Text; using Xunit; @@ -30,6 +31,8 @@ public class LambdaParserTests { varContext["day2"] = new DateTime().AddDays(2); varContext["oneDay"] = new TimeSpan(1,0,0,0); varContext["twoDays"] = new TimeSpan(2,0,0,0); + varContext["complexZero"] = new Complex(); + varContext["complexOne"] = new Complex(1d, 1d); return varContext; } @@ -124,6 +127,11 @@ public class LambdaParserTests { Assert.Equal(new TimeSpan(1,0,0,0), lambdaParser.Eval("twoDays + -oneDay", varContext)); Assert.Equal(new TimeSpan(1,0,0,0).Negate(), lambdaParser.Eval("oneDay - twoDays", varContext)); Assert.Equal(new TimeSpan(1,0,0,0).Negate(), lambdaParser.Eval("-twoDays + oneDay", varContext)); + + Assert.True((bool) lambdaParser.Eval("complexOne != complexZero", varContext)); + Assert.Equal(new Complex(), lambdaParser.Eval("complexOne * complexZero", varContext)); + Assert.Equal(new Complex(-1d, -1d), lambdaParser.Eval("-complexOne", varContext)); + Assert.Equal(Math.Sqrt(2), lambdaParser.Eval("complexOne.Magnitude", varContext)); } [Fact] diff --git a/src/NReco.LambdaParser/Linq/LambdaParameterWrapper.cs b/src/NReco.LambdaParser/Linq/LambdaParameterWrapper.cs index fbe43f9..1296b14 100644 --- a/src/NReco.LambdaParser/Linq/LambdaParameterWrapper.cs +++ b/src/NReco.LambdaParser/Linq/LambdaParameterWrapper.cs @@ -202,9 +202,14 @@ internal sealed class LambdaParameterWrapper : IComparable, ILambdaValue { return new LambdaParameterWrapper(c1ts + c2ts, c1.Cmp); } - var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); - var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); - return new LambdaParameterWrapper(c1decimal + c2decimal, c1.Cmp); + if (c1.Value is IConvertible && c2.Value is IConvertible) + { + var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); + var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); + return new LambdaParameterWrapper(c1decimal + c2decimal, c1.Cmp); + } + + return new LambdaParameterWrapper((dynamic) c1.Value + (dynamic) c2.Value, c1.Cmp); } public static LambdaParameterWrapper operator -(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { @@ -223,9 +228,14 @@ internal sealed class LambdaParameterWrapper : IComparable, ILambdaValue { return new LambdaParameterWrapper(c1DateTime.Add(c2TimeSpan.Negate()), c1.Cmp); } - var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); - var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); - return new LambdaParameterWrapper(c1decimal - c2decimal, c1.Cmp); + if (c1.Value is IConvertible && c2.Value is IConvertible) + { + var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); + var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); + return new LambdaParameterWrapper(c1decimal - c2decimal, c1.Cmp); + } + + return new LambdaParameterWrapper((dynamic) c1.Value - (dynamic) c2.Value, c1.Cmp); } public static LambdaParameterWrapper operator -(LambdaParameterWrapper c1) { @@ -234,65 +244,120 @@ internal sealed class LambdaParameterWrapper : IComparable, ILambdaValue { return new LambdaParameterWrapper(ts.Negate(), c1.Cmp); } - var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); - return new LambdaParameterWrapper(-c1decimal, c1.Cmp); + if (c1.Value is IConvertible) + { + var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); + return new LambdaParameterWrapper(-c1decimal, c1.Cmp); + } + + return new LambdaParameterWrapper(-(dynamic)c1.Value, c1.Cmp); } public static LambdaParameterWrapper operator *(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); - var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); - return new LambdaParameterWrapper(c1decimal * c2decimal, c1.Cmp); + if (c1.Value is IConvertible && c2.Value is IConvertible) + { + var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); + var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); + return new LambdaParameterWrapper(c1decimal * c2decimal, c1.Cmp); + } + + return new LambdaParameterWrapper((dynamic) c1.Value * (dynamic) c2.Value, c1.Cmp); } public static LambdaParameterWrapper operator /(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); - var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); - return new LambdaParameterWrapper(c1decimal / c2decimal, c1.Cmp); + if (c1.Value is IConvertible && c2.Value is IConvertible) + { + var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); + var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); + return new LambdaParameterWrapper(c1decimal / c2decimal, c1.Cmp); + } + + return new LambdaParameterWrapper((dynamic) c1.Value / (dynamic) c2.Value, c1.Cmp); } public static LambdaParameterWrapper operator %(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); - var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); - return new LambdaParameterWrapper(c1decimal % c2decimal, c1.Cmp); + if (c1.Value is IConvertible && c2.Value is IConvertible) + { + var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture); + var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture); + return new LambdaParameterWrapper(c1decimal % c2decimal, c1.Cmp); + } + + return new LambdaParameterWrapper((dynamic) c1.Value % (dynamic) c2.Value, c1.Cmp); } public static bool operator ==(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - return c1.Cmp.Compare(c1.Value, c2.Value)==0; + if(c1.Value == null || c2.Value == null || c1.Value is IComparable or IList || c2.Value is IComparable or IList) + return c1.Cmp.Compare(c1.Value, c2.Value)==0; + + return (dynamic) c1?.Value == (dynamic) c2?.Value; } public static bool operator ==(LambdaParameterWrapper c1, bool c2) { - return c1.Cmp.Compare(c1.Value, c2)==0; + if(c1.Value == null || c1.Value is IComparable or IList) + return c1.Cmp.Compare(c1.Value, c2)==0; + + return (dynamic) c1.Value == c2; + } public static bool operator ==(bool c1, LambdaParameterWrapper c2) { - return c2.Cmp.Compare(c1, c2.Value)==0; + if(c2.Value == null || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c2.Value, c1)==0; + + return (dynamic) c2.Value == c1; } public static bool operator !=(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - return c1.Cmp.Compare(c1.Value, c2.Value)!=0; + if(c1.Value == null || c2.Value == null || c1.Value is IComparable or IList || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c1.Value, c2.Value)!=0; + + return (dynamic) c1.Value != (dynamic) c2.Value; } public static bool operator !=(LambdaParameterWrapper c1, bool c2) { - return c1.Cmp.Compare(c1.Value, c2)!=0; + if(c1.Value == null || c1.Value is IComparable or IList) + return c1.Cmp.Compare(c1.Value, c2)!=0; + + return (dynamic) c1?.Value != c2; } + public static bool operator !=(bool c1, LambdaParameterWrapper c2) { - return c2.Cmp.Compare(c1, c2.Value)!=0; + if(c2.Value == null || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c2.Value, c1)!=0; + + return c1 != (dynamic)c2.Value; } public static bool operator >(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - return c1.Cmp.Compare(c1.Value, c2.Value)>0; + if(c1.Value == null || c2.Value == null || c1.Value is IComparable or IList || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c1.Value, c2.Value)>0; + + return (dynamic) c1.Value > (dynamic) c2.Value; } public static bool operator <(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - return c1.Cmp.Compare(c1.Value, c2.Value) < 0; + if(c1.Value == null || c2.Value == null || c1.Value is IComparable or IList || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c1.Value, c2.Value)<0; + + return (dynamic) c1.Value < (dynamic) c2.Value; } public static bool operator >=(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - return c1.Cmp.Compare(c1.Value, c2.Value)>= 0; + if(c1.Value == null || c2.Value == null || c1.Value is IComparable or IList || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c1.Value, c2.Value)>=0; + + return (dynamic) c1.Value >= (dynamic) c2.Value; } + public static bool operator <=(LambdaParameterWrapper c1, LambdaParameterWrapper c2) { - return c1.Cmp.Compare(c1.Value, c2.Value)<=0; + if(c1.Value == null || c2.Value == null || c1.Value is IComparable or IList || c2.Value is IComparable or IList) + return c2.Cmp.Compare(c1.Value, c2.Value)<=0; + + return (dynamic) c1.Value <= (dynamic) c2.Value; } public static LambdaParameterWrapper operator !(LambdaParameterWrapper c1) { - var c1bool = c1.Cmp.Compare(c1.Value, true)==0; - return new LambdaParameterWrapper( !c1bool, c1.Cmp); + if(c1.Value == null || c1.Value is IComparable or IList) + return new LambdaParameterWrapper(!(c1.Cmp.Compare(c1.Value, true)==0), c1.Cmp); + + return !(dynamic) c1.Value; } public static bool operator true(LambdaParameterWrapper x) { @@ -302,7 +367,6 @@ internal sealed class LambdaParameterWrapper : IComparable, ILambdaValue { public static bool operator false(LambdaParameterWrapper x) { return !x.IsTrue; } - } } diff --git a/src/NReco.LambdaParser/NReco.LambdaParser.csproj b/src/NReco.LambdaParser/NReco.LambdaParser.csproj index 33c1a41..45e90e4 100644 --- a/src/NReco.LambdaParser/NReco.LambdaParser.csproj +++ b/src/NReco.LambdaParser/NReco.LambdaParser.csproj @@ -48,7 +48,7 @@ v.1.0.6 changes: https://raw.githubusercontent.com/nreco/lambdaparser/master/LICENSE https://github.com/nreco/lambdaparser git - 1.6.0 + 1.6.1 false false false @@ -58,6 +58,7 @@ v.1.0.6 changes: false false false + 9 @@ -96,17 +97,17 @@ v.1.0.6 changes: - - - - - - - - - - - + + + + + + + + + + + @@ -116,7 +117,11 @@ v.1.0.6 changes: - + + + + +