Skip to content

Commit

Permalink
nreco#40 non-convertible types support
Browse files Browse the repository at this point in the history
  • Loading branch information
Petr Holubec committed Dec 15, 2021
1 parent b2b3a1a commit d927812
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 43 deletions.
8 changes: 8 additions & 0 deletions src/NReco.LambdaParser.Tests/LambdaParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Numerics;
using System.Text;

using Xunit;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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]
Expand Down
124 changes: 94 additions & 30 deletions src/NReco.LambdaParser/Linq/LambdaParameterWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -302,7 +367,6 @@ internal sealed class LambdaParameterWrapper : IComparable, ILambdaValue {
public static bool operator false(LambdaParameterWrapper x) {
return !x.IsTrue;
}

}

}
31 changes: 18 additions & 13 deletions src/NReco.LambdaParser/NReco.LambdaParser.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ v.1.0.6 changes:
<PackageLicenseUrl>https://raw.githubusercontent.com/nreco/lambdaparser/master/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/nreco/lambdaparser</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.3' ">1.6.0</NetStandardImplicitPackageVersion>
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.3' ">1.6.1</NetStandardImplicitPackageVersion>
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
Expand All @@ -58,6 +58,7 @@ v.1.0.6 changes:
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<LangVersion>9</LangVersion>

</PropertyGroup>

Expand Down Expand Up @@ -96,17 +97,17 @@ v.1.0.6 changes:
<ItemGroup Condition=" '$(TargetFramework)' == 'portable-net45+win8+wpa81+wp8' ">
<Reference Include="System.Core" />
<Reference Include="System" />
<Reference Include="System.Collections"/>
<Reference Include="System.IO"/>
<Reference Include="System.Reflection"/>
<Reference Include="System.Linq"/>
<Reference Include="System.Linq.Expressions"/>
<Reference Include="System.Runtime"/>
<Reference Include="System.Resources.ResourceManager"/>
<Reference Include="System.Reflection.Extensions"/>
<Reference Include="System.Globalization"/>
<Reference Include="System.Runtime.Extensions"/>
<Reference Include="System.Threading"/>
<Reference Include="System.Collections" />
<Reference Include="System.IO" />
<Reference Include="System.Reflection" />
<Reference Include="System.Linq" />
<Reference Include="System.Linq.Expressions" />
<Reference Include="System.Runtime" />
<Reference Include="System.Resources.ResourceManager" />
<Reference Include="System.Reflection.Extensions" />
<Reference Include="System.Globalization" />
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Threading" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'portable-net40+sl5+win8+wpa81+wp8' ">
Expand All @@ -116,7 +117,11 @@ v.1.0.6 changes:
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.1.0" />
<PackageReference Include="System.Reflection.TypeExtensions" Version="4.7.0" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>

<Target Name="_GetRestoreSettingsPerFramework"></Target>
Expand Down

0 comments on commit d927812

Please sign in to comment.