diff --git a/ExpressionEvaluator/Parser/ExpressionHelper.cs b/ExpressionEvaluator/Parser/ExpressionHelper.cs
index 6b0194a..1b7d4df 100644
--- a/ExpressionEvaluator/Parser/ExpressionHelper.cs
+++ b/ExpressionEvaluator/Parser/ExpressionHelper.cs
@@ -1061,11 +1061,8 @@ public static Expression BinaryOperator(Expression le, Expression re, Expression
re = TypeConversion.EnumConversion(ref re);
le = TypeConversion.EnumConversion(ref le);
- var ret = re.Type;
- var let = le.Type;
-
- TypeConversion.ImplicitConversion(ref le, ret);
- TypeConversion.ImplicitConversion(ref re, let);
+
+ TypeConversion.ImplicitConversion(ref le, ref re);
//TypeConversion.BinaryNumericPromotion(expressionType, ref le, ref re);
//le = TypeConversion.DynamicConversion(re, le);
return GetBinaryOperator(le, re, expressionType);
diff --git a/ExpressionEvaluator/Parser/TypeConversion.cs b/ExpressionEvaluator/Parser/TypeConversion.cs
index 3e48e44..f636d02 100644
--- a/ExpressionEvaluator/Parser/TypeConversion.cs
+++ b/ExpressionEvaluator/Parser/TypeConversion.cs
@@ -137,7 +137,7 @@ internal static void Convert(ref Expression le, ref Expression re)
if (Instance._typePrecedence[le.Type] < Instance._typePrecedence[re.Type]) le = Expression.Convert(le, re.Type);
}
}
-
+
///
/// Performs implicit conversion on an expression against a specified type
///
@@ -263,7 +263,7 @@ public static Expression EnumConversion(ref Expression src)
public static bool ImplicitConversion(ref Expression src, Type destType)
{
return src.Type != destType && (
- (destType.IsNumericType() && src.Type.IsNumericType() && ImplicitNumericConversion(ref src, destType)) ||
+ ImplicitNumericConversion(ref src, destType) ||
NullableConverion(ref src, destType) ||
NullLiteralConverion(ref src, destType) ||
ReferenceConversion(ref src, destType) ||
@@ -273,6 +273,41 @@ public static bool ImplicitConversion(ref Expression src, Type destType)
);
}
+ public static void ImplicitConversion(ref Expression le, ref Expression re)
+ {
+ if (le.Type != re.Type)
+ {
+ var leType = le.Type.GetNotNullable();
+ var reType = re.Type.GetNotNullable();
+ Type maxCommonType = null;
+ if (leType == reType) //the only difference is the nullable
+ {
+ maxCommonType = typeof(Nullable<>).MakeGenericType(leType);
+ }
+ else if (Instance._typePrecedence.ContainsKey(leType) && Instance._typePrecedence.ContainsKey(reType))
+ {
+ maxCommonType = Instance._typePrecedence[leType] < Instance._typePrecedence[reType] ? reType : leType;
+ if (le.Type.IsNullable() || re.Type.IsNullable())
+ maxCommonType = typeof(Nullable<>).MakeGenericType(maxCommonType);
+ }
+ if (maxCommonType != null)
+ {
+ ImplicitConversion(ref le, maxCommonType);
+ ImplicitConversion(ref re, maxCommonType);
+ return;
+ }
+ if (le.Type.IsNullable() || re.Type.IsNullable())
+ {
+ if (!le.Type.IsNullable())
+ ImplicitConversion(ref le, typeof(Nullable<>).MakeGenericType(le.Type));
+ if (!re.Type.IsNullable())
+ ImplicitConversion(ref re, typeof(Nullable<>).MakeGenericType(re.Type));
+ }
+ ImplicitConversion(ref le, re.Type);
+ ImplicitConversion(ref re, le.Type);
+ }
+ }
+
// 6.1.9 Implicit constant expression conversions
public static bool ImplicitConstantConversion(ref Expression src, Type destType)
{
@@ -283,12 +318,12 @@ public static bool ImplicitConstantConversion(ref Expression src, Type destType)
if (src.Type == typeof(int))
{
var value = (int)((ConstantExpression)src).Value;
- if (destType == typeof (sbyte))
+ if (destType == typeof(sbyte))
{
if (value >= SByte.MinValue && value <= SByte.MinValue)
{
src = Expression.Convert(src, typeof(sbyte));
- return true;
+ return true;
}
}
if (destType == typeof(byte))
@@ -296,7 +331,7 @@ public static bool ImplicitConstantConversion(ref Expression src, Type destType)
if (value >= Byte.MinValue && value <= Byte.MaxValue)
{
src = Expression.Convert(src, typeof(byte));
- return true;
+ return true;
}
}
if (destType == typeof(short))
@@ -304,7 +339,7 @@ public static bool ImplicitConstantConversion(ref Expression src, Type destType)
if (value >= Int16.MinValue && value <= Int16.MaxValue)
{
src = Expression.Convert(src, typeof(short));
- return true;
+ return true;
}
}
if (destType == typeof(ushort))
@@ -312,7 +347,7 @@ public static bool ImplicitConstantConversion(ref Expression src, Type destType)
if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
{
src = Expression.Convert(src, typeof(ushort));
- return true;
+ return true;
}
}
if (destType == typeof(uint))
@@ -320,7 +355,7 @@ public static bool ImplicitConstantConversion(ref Expression src, Type destType)
if (value >= UInt32.MinValue && value <= UInt32.MaxValue)
{
src = Expression.Convert(src, typeof(uint));
- return true;
+ return true;
}
}
if (destType == typeof(ulong))
@@ -390,9 +425,9 @@ public static bool DynamicConversion(ref Expression src, Type destType)
public static bool ImplicitNumericConversion(ref Expression src, Type target)
{
List allowed;
- if (ImplicitNumericConversions.TryGetValue(src.Type, out allowed))
+ if (ImplicitNumericConversions.TryGetValue(src.Type.GetNotNullable(), out allowed))
{
- if (allowed.Contains(target))
+ if (allowed.Contains(target.GetNotNullable()))
{
src = Expression.Convert(src, target);
return true;
@@ -413,7 +448,8 @@ public static bool ImplicitNumericConversion(ref Expression src, Type target)
{typeof (short), 4},
{typeof (long), 5},
{typeof (float), 6},
- {typeof (double), 7}
+ {typeof (double), 7},
+ {typeof (decimal), 8}
};
ImplicitNumericConversions.Add(typeof(sbyte), new List() { typeof(short), typeof(int), typeof(long), typeof(float), typeof(double), typeof(decimal) });
@@ -426,6 +462,8 @@ public static bool ImplicitNumericConversion(ref Expression src, Type target)
ImplicitNumericConversions.Add(typeof(ulong), new List() { typeof(float), typeof(double), typeof(decimal) });
ImplicitNumericConversions.Add(typeof(char), new List() { typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal) });
ImplicitNumericConversions.Add(typeof(float), new List() { typeof(double) });
+ ImplicitNumericConversions.Add(typeof(double), new List() { typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(decimal) });
+ ImplicitNumericConversions.Add(typeof(decimal), new List() { typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double) });
}
}
}
\ No newline at end of file
diff --git a/ExpressionEvaluator/Parser/TypeExtensions.cs b/ExpressionEvaluator/Parser/TypeExtensions.cs
index c76859d..3161420 100644
--- a/ExpressionEvaluator/Parser/TypeExtensions.cs
+++ b/ExpressionEvaluator/Parser/TypeExtensions.cs
@@ -28,6 +28,11 @@ public static bool IsNumericType(this Type type)
return NumericTypes.Contains(type);
}
+ public static Type GetNotNullable(this Type type)
+ {
+ return Nullable.GetUnderlyingType(type) ?? type;
+ }
+
public static bool IsDynamicOrObject(this Type type)
{
return type.GetInterfaces().Contains(typeof(IDynamicMetaObjectProvider)) ||