Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#40 non-convertible types support #41

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ Dictionary<string,object> getContext() {
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 void Eval() {
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 @@ public LambdaParameterWrapper InvokeIndexer(object obj, object[] args) {
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 @@ public LambdaParameterWrapper InvokeIndexer(object obj, object[] args) {
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 @@ public LambdaParameterWrapper InvokeIndexer(object obj, object[] args) {
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 @@ public static bool operator true(LambdaParameterWrapper x) {
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