}
}
-/*
+/* TODO: Add tests for every numeric expression where a type has only 1 implicit
+ numeric conversion
public struct MyType<T>
{
T value;
}
*/
+
+// TODO: Create a clone which uses +(MyType, int) pattern and an implicit conversion
+// is required to do the user-conversion
+
public struct MyType
{
int value;
{
this.value = value;
}
+
+ public override int GetHashCode ()
+ {
+ throw new NotImplementedException ();
+ }
public static implicit operator int (MyType o)
{
return a.value != a;
}
- //public static implicit operator MyType (int i)
- //{
- // return new MyType (i);
- //}
-
- public static MyType operator +(MyType a, MyType b)
+ public static MyType operator + (MyType a, MyType b)
{
return new MyType (a.value + b.value);
}
+ public static MyType operator - (MyType a, MyType b)
+ {
+ return new MyType (a.value - b.value);
+ }
+
+ public static MyType operator / (MyType a, MyType b)
+ {
+ return new MyType (a.value / b.value);
+ }
+
+ public static MyType operator * (MyType a, MyType b)
+ {
+ return new MyType (a.value * b.value);
+ }
+
+ public static MyType operator % (MyType a, MyType b)
+ {
+ return new MyType (a.value % b.value);
+ }
+
public static MyType operator &(MyType a, MyType b)
{
return new MyType (a.value & b.value);
return new MyType (a.value | b.value);
}
+ public static MyType operator ^ (MyType a, MyType b)
+ {
+ return new MyType (a.value ^ b.value);
+ }
+
+ public static bool operator == (MyType a, MyType b)
+ {
+ return a.value == b.value;
+ }
+
+ public static bool operator != (MyType a, MyType b)
+ {
+ return a.value != b.value;
+ }
+
+ public static bool operator > (MyType a, MyType b)
+ {
+ return a.value > b.value;
+ }
+
+ public static bool operator < (MyType a, MyType b)
+ {
+ return a.value < b.value;
+ }
+
+ public static bool operator >= (MyType a, MyType b)
+ {
+ return a.value >= b.value;
+ }
+
+ public static bool operator <= (MyType a, MyType b)
+ {
+ return a.value <= b.value;
+ }
+
+ public static bool operator ! (MyType a)
+ {
+ return a.value > 0;
+ }
+
+ public static int operator >> (MyType a, int b)
+ {
+ return a.value >> b;
+ }
+
+ public static int operator << (MyType a, int b)
+ {
+ return a.value << b;
+ }
+
public override string ToString ()
{
return value.ToString ();
}
}
+
+class MyTypeExplicit
+{
+ int value;
+
+ public MyTypeExplicit (int value)
+ {
+ this.value = value;
+ }
+
+ public static explicit operator int (MyTypeExplicit m)
+ {
+ return m.value;
+ }
+}
+
+// TODO: Add more nullable tests, follow AddTest pattern.
+
class Tester
{
static void AssertNodeType (LambdaExpression e, ExpressionType et)
static void Assert<T> (T expected, T value)
{
- if (!EqualityComparer<T>.Default.Equals (expected, value))
- throw new ApplicationException (expected + " != " + value);
+ Assert (expected, value, null);
+ }
+
+ static void Assert<T> (T expected, T value, string name)
+ {
+ if (!EqualityComparer<T>.Default.Equals (expected, value)) {
+ if (!string.IsNullOrEmpty (name))
+ name += ": ";
+ throw new ApplicationException (name + expected + " != " + value);
+ }
}
static void Assert<T> (T [] expected, T [] value)
Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a + b;
AssertNodeType (e3, ExpressionType.Add);
-// FIXME: type inference
-// Assert (10, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
+ Assert (10, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
+
+ Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a + b;
+ AssertNodeType (e4, ExpressionType.Add);
+ Assert (new MyType (10), e4.Compile ().Invoke (new MyType (-20), new MyType (30)));
+ Assert (null, e4.Compile ().Invoke (null, new MyType (30)));
+
+ Expression<Func<int, MyType, int>> e5 = (int a, MyType b) => a + b;
+ AssertNodeType (e5, ExpressionType.Add);
+ Assert (31, e5.Compile ().Invoke (1, new MyType (30)));
+
+ Expression<Func<int, MyType?, int?>> e6 = (int a, MyType? b) => a + b;
+ AssertNodeType (e6, ExpressionType.Add);
+ Assert (-1, e6.Compile ().Invoke (-31, new MyType (30)));
}
void AddCheckedTest ()
Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a + b;
AssertNodeType (e3, ExpressionType.Add);
-// FIXME: type inference
-// Assert (10, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
+ Assert (10, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
}
}
+
+ void AddStringTest ()
+ {
+ Expression<Func<string, string>> e6 = (a) => 1 + a;
+ AssertNodeType (e6, ExpressionType.Add);
+ Assert ("1to", e6.Compile ().Invoke ("to"));
+
+ Expression<Func<object, string, string>> e7 = (object a, string b) => a + b;
+ AssertNodeType (e7, ExpressionType.Add);
+ Assert ("testme", e7.Compile ().Invoke ("test", "me"));
+ Assert ("test", e7.Compile ().Invoke ("test", null));
+ Assert ("", e7.Compile ().Invoke (null, null));
+
+ Expression<Func<string, int, string>> e8 = (a, b) => a + " " + "-" + "> " + b;
+ AssertNodeType (e8, ExpressionType.Add);
+ Assert ("test -> 2", e8.Compile ().Invoke ("test", 2));
+
+ Expression<Func<string, ushort?, string>> e9 = (a, b) => a + b;
+ AssertNodeType (e9, ExpressionType.Add);
+ Assert ("test2", e9.Compile ().Invoke ("test", 2));
+ Assert ("test", e9.Compile ().Invoke ("test", null));
+ }
void AndTest ()
{
void AndAlsoTest ()
{
Expression<Func<bool, bool, bool>> e = (bool a, bool b) => a && b;
-
AssertNodeType (e, ExpressionType.AndAlso);
Assert (false, e.Compile ().Invoke (true, false));
Expression<Func<MyType, MyType, MyType>> e2 = (MyType a, MyType b) => a && b;
-
AssertNodeType (e2, ExpressionType.AndAlso);
Assert (new MyType (64), e2.Compile ().Invoke (new MyType (64), new MyType (64)));
Assert (new MyType (0), e2.Compile ().Invoke (new MyType (32), new MyType (64)));
+
+ Expression<Func<bool, bool>> e3 = (bool a) => a && true;
+ AssertNodeType (e3, ExpressionType.AndAlso);
+ Assert (false, e3.Compile ().Invoke (false));
+ Assert (true, e3.Compile ().Invoke (true));
}
void ArrayIndexTest ()
void ArrayLengthTest ()
{
- int o = new int [0].Length;
-
Expression<Func<double [], int>> e = (double [] a) => a.Length;
AssertNodeType (e, ExpressionType.ArrayLength);
Assert (0, e.Compile ().Invoke (new double [0]));
Expression<Func<int, int>> e5 = (int a) => GenericMethod (a);
AssertNodeType (e5, ExpressionType.Call);
Assert (5, e5.Compile ().Invoke (5));
+
+ Expression<Action> e6 = () => Console.WriteLine ("call test");
+ AssertNodeType (e6, ExpressionType.Call);
}
void CoalesceTest ()
Assert (3, r4.Invoke (new InverseLogicalOperator (true), 3, 4));
Assert (4, r4.Invoke (new InverseLogicalOperator (false), 3, 4));
}
+
+ void ConstantTest ()
+ {
+ Expression<Func<int>> e1 = () => default (int);
+ AssertNodeType (e1, ExpressionType.Constant);
+ Assert (0, e1.Compile ().Invoke ());
+
+ Expression<Func<int?>> e2 = () => default (int?);
+ AssertNodeType (e2, ExpressionType.Constant);
+ Assert (null, e2.Compile ().Invoke ());
+
+ Expression<Func<Tester>> e3 = () => default (Tester);
+ AssertNodeType (e3, ExpressionType.Constant);
+ Assert (null, e3.Compile ().Invoke ());
+
+ Expression<Func<object>> e4 = () => null;
+ AssertNodeType (e4, ExpressionType.Constant);
+ Assert (null, e4.Compile ().Invoke ());
+
+ Expression<Func<int>> e5 = () => 8 / 4;
+ AssertNodeType (e5, ExpressionType.Constant);
+ Assert (2, e5.Compile ().Invoke ());
+
+ Expression<Func<int>> e6 = () => 0xFFFFFF >> 0x40;
+ AssertNodeType (e6, ExpressionType.Constant);
+ Assert (0xFFFFFF, e6.Compile ().Invoke ());
+ }
- public void ConvertTest ()
+ void ConvertTest ()
{
Expression<Func<int, byte>> e = (int a) => ((byte) a);
AssertNodeType (e, ExpressionType.Convert);
Expression<Func<MyType, int>> e4 = (MyType a) => (a);
AssertNodeType (e4, ExpressionType.Convert);
Assert (-9, e4.Compile ().Invoke (new MyType (-9)));
+
+ Expression<Func<MyType, MyType, bool?>> e5 = (MyType a, MyType b) => a == b;
+ AssertNodeType (e5, ExpressionType.Convert);
+
+ Expression<Func<MyType?, MyType?, bool?>> e6 = (MyType? a, MyType? b) => a == b;
+ AssertNodeType (e6, ExpressionType.Convert);
+ Assert (false, e6.Compile ().Invoke (null, new MyType (-20)));
+ Assert (true, e6.Compile ().Invoke (null, null));
+ Assert (true, e6.Compile ().Invoke (new MyType (120), new MyType (120)));
+
+ // TODO: redundant return conversion
+ // Expression<Func<MyTypeExplicit, int?>> e6 = x => (int?)x;
+
+ // TODO: redundant convert
+ // TODO: pass null value
+ // Expression<Func<int?, object>> ex = x => (object)x;
}
- public void ConvertCheckedTest ()
+ void ConvertCheckedTest ()
{
Expression<Func<int, byte>> e = (int a) => checked((byte) a);
AssertNodeType (e, ExpressionType.ConvertChecked);
}
}
+ void DivideTest ()
+ {
+ Expression<Func<int, int, int>> e = (int a, int b) => a / b;
+ AssertNodeType (e, ExpressionType.Divide);
+ Assert (2, e.Compile ().Invoke (60, 30));
+
+ Expression<Func<double?, double?, double?>> e2 = (a, b) => a / b;
+ AssertNodeType (e2, ExpressionType.Divide);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+ Assert (1.5, e2.Compile ().Invoke (3, 2));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a / b;
+ AssertNodeType (e3, ExpressionType.Divide);
+ Assert (1, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a / b;
+ AssertNodeType (e4, ExpressionType.Divide);
+ Assert (null, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (new MyType (-6), e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
+
+ Expression<Func<int, MyType, int>> e5 = (int a, MyType b) => a / b;
+ AssertNodeType (e5, ExpressionType.Divide);
+ Assert (50, e5.Compile ().Invoke (100, new MyType (2)));
+
+ Expression<Func<int, MyType?, int?>> e6 = (int a, MyType? b) => a / b;
+ AssertNodeType (e6, ExpressionType.Divide);
+ Assert (50, e6.Compile ().Invoke (100, new MyType (2)));
+ Assert (null, e6.Compile ().Invoke (20, null));
+ }
+
+ void EqualTest ()
+ {
+ Expression<Func<int, int, bool>> e = (int a, int b) => a == b;
+ AssertNodeType (e, ExpressionType.Equal);
+ Assert (false, e.Compile ().Invoke (60, 30));
+ Assert (true, e.Compile ().Invoke (-1, -1));
+
+ Expression<Func<double?, double?, bool>> e2 = (a, b) => a == b;
+ AssertNodeType (e2, ExpressionType.Equal);
+ Assert (true, e2.Compile ().Invoke (3, 3));
+ Assert (false, e2.Compile ().Invoke (3, 2));
+
+ Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a == b;
+ AssertNodeType (e3, ExpressionType.Equal);
+ Assert (true, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a == b;
+ AssertNodeType (e4, ExpressionType.Equal);
+ Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (true, e4.Compile ().Invoke (null, null));
+ Assert (true, e4.Compile ().Invoke (new MyType (120), new MyType (120)));
+
+ Expression<Func<bool?, bool?, bool>> e5 = (bool? a, bool? b) => a == b;
+ AssertNodeType (e5, ExpressionType.Equal);
+ Assert (false, e5.Compile ().Invoke (true, null));
+ Assert (true, e5.Compile ().Invoke (null, null));
+ Assert (true, e5.Compile ().Invoke (false, false));
+
+ Expression<Func<bool, bool>> e6 = (bool a) => a == null;
+ AssertNodeType (e6, ExpressionType.Equal);
+ Assert (false, e6.Compile ().Invoke (true));
+ Assert (false, e6.Compile ().Invoke (false));
+
+ Expression<Func<string, string, bool>> e7 = (string a, string b) => a == b;
+ AssertNodeType (e7, ExpressionType.Equal);
+ Assert (true, e7.Compile ().Invoke (null, null));
+ Assert (false, e7.Compile ().Invoke ("a", "A"));
+ Assert (true, e7.Compile ().Invoke ("a", "a"));
+
+ Expression<Func<object, bool>> e8 = (object a) => null == a;
+ AssertNodeType (e8, ExpressionType.Equal);
+ Assert (true, e8.Compile ().Invoke (null));
+ Assert (false, e8.Compile ().Invoke ("a"));
+ Assert (false, e8.Compile ().Invoke (this));
+ }
+
+ delegate void EmptyDelegate ();
+
+ void EqualTestDelegate ()
+ {
+ Expression<Func<Delegate, Delegate, bool>> e1 = (a, b) => a == b;
+ AssertNodeType (e1, ExpressionType.Equal);
+ Assert (true, e1.Compile ().Invoke (null, null));
+
+ EmptyDelegate ed = delegate () {};
+
+ Expression<Func<EmptyDelegate, EmptyDelegate, bool>> e2 = (a, b) => a == b;
+ AssertNodeType (e2, ExpressionType.Equal);
+ Assert (false, e2.Compile ().Invoke (delegate () {}, null));
+ Assert (false, e2.Compile ().Invoke (delegate () {}, delegate {}));
+ Assert (false, e2.Compile ().Invoke (ed, delegate {}));
+ Assert (true, e2.Compile ().Invoke (ed, ed));
+ }
+
+ void ExclusiveOrTest ()
+ {
+ Expression<Func<int, short, int>> e = (int a, short b) => a ^ b;
+ AssertNodeType (e, ExpressionType.ExclusiveOr);
+ Assert (34, e.Compile ().Invoke (60, 30));
+
+ Expression<Func<byte?, byte?, int?>> e2 = (a, b) => a ^ b;
+ AssertNodeType (e2, ExpressionType.ExclusiveOr);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+ Assert (1, e2.Compile ().Invoke (3, 2));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a ^ b;
+ AssertNodeType (e3, ExpressionType.ExclusiveOr);
+ Assert (0, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a ^ b;
+ AssertNodeType (e4, ExpressionType.ExclusiveOr);
+ Assert (null, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (new MyType (-108), e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
+
+ Expression<Func<MyType?, byte, int?>> e5 = (MyType? a, byte b) => a ^ b;
+ AssertNodeType (e5, ExpressionType.ExclusiveOr);
+ Assert (null, e5.Compile ().Invoke (null, 64));
+ Assert (96, e5.Compile ().Invoke (new MyType (64), 32));
+ }
+
+ void GreaterThanTest ()
+ {
+ Expression<Func<int, int, bool>> e = (int a, int b) => a > b;
+ AssertNodeType (e, ExpressionType.GreaterThan);
+ Assert (true, e.Compile ().Invoke (60, 30));
+
+ Expression<Func<uint?, byte?, bool>> e2 = (a, b) => a > b;
+ AssertNodeType (e2, ExpressionType.GreaterThan);
+ Assert (false, e2.Compile ().Invoke (null, 3));
+ Assert (false, e2.Compile ().Invoke (2, 2));
+
+ Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a > b;
+ AssertNodeType (e3, ExpressionType.GreaterThan);
+ Assert (false, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a > b;
+ AssertNodeType (e4, ExpressionType.GreaterThan);
+ Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (false, e4.Compile ().Invoke (null, null));
+ Assert (true, e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
+
+ Expression<Func<MyType?, sbyte, bool>> e5 = (MyType? a, sbyte b) => a > b;
+ AssertNodeType (e5, ExpressionType.GreaterThan);
+ Assert (false, e5.Compile ().Invoke (null, 33));
+ Assert (false, e5.Compile ().Invoke (null, 0));
+ Assert (true, e5.Compile ().Invoke (new MyType (120), 3));
+
+ Expression<Func<ushort, bool>> e6 = (ushort a) => a > null;
+ AssertNodeType (e6, ExpressionType.GreaterThan);
+ Assert (false, e6.Compile ().Invoke (60));
+ }
+
+ void GreaterThanOrEqualTest ()
+ {
+ Expression<Func<int, int, bool>> e = (int a, int b) => a >= b;
+ AssertNodeType (e, ExpressionType.GreaterThanOrEqual);
+ Assert (true, e.Compile ().Invoke (60, 30));
+
+ Expression<Func<byte?, byte?, bool>> e2 = (a, b) => a >= b;
+ AssertNodeType (e2, ExpressionType.GreaterThanOrEqual);
+ Assert (false, e2.Compile ().Invoke (null, 3));
+ Assert (true, e2.Compile ().Invoke (2, 2));
+
+ Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a >= b;
+ AssertNodeType (e3, ExpressionType.GreaterThanOrEqual);
+ Assert (true, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)), "D1");
+
+ Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a >= b;
+ AssertNodeType (e4, ExpressionType.GreaterThanOrEqual);
+ Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (false, e4.Compile ().Invoke (null, null));
+ Assert (true, e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
+
+ Expression<Func<MyType?, sbyte, bool>> e5 = (MyType? a, sbyte b) => a >= b;
+ AssertNodeType (e5, ExpressionType.GreaterThanOrEqual);
+ Assert (false, e5.Compile ().Invoke (null, 33));
+ Assert (false, e5.Compile ().Invoke (null, 0));
+ Assert (true, e5.Compile ().Invoke (new MyType (120), 3));
+
+ Expression<Func<ushort, bool>> e6 = (ushort a) => a >= null;
+ AssertNodeType (e6, ExpressionType.GreaterThanOrEqual);
+ Assert (false, e6.Compile ().Invoke (60));
+ }
+
+ void LeftShiftTest ()
+ {
+ Expression<Func<ulong, short, ulong>> e = (ulong a, short b) => a << b;
+ AssertNodeType (e, ExpressionType.LeftShift);
+ Assert ((ulong) 0x7F000, e.Compile ().Invoke (0xFE, 11));
+ Assert ((ulong) 0xFFFFFFFE00000000, e.Compile ().Invoke (0xFFFFFFFF, 0xA01));
+
+ Expression<Func<MyType, MyType, int>> e2 = (MyType a, MyType b) => a << b;
+ AssertNodeType (e2, ExpressionType.LeftShift);
+ var c2 = e2.Compile ();
+ Assert (1024, c2 (new MyType (256), new MyType (2)));
+
+ Expression<Func<long?, sbyte, long?>> e3 = (long? a, sbyte b) => a << b;
+ AssertNodeType (e3, ExpressionType.LeftShift);
+ Assert (null, e3.Compile ().Invoke (null, 11));
+ Assert (2048, e3.Compile ().Invoke (1024, 1));
+
+ Expression<Func<MyType?, MyType?, int?>> e4 = (MyType? a, MyType? b) => a << b;
+ AssertNodeType (e4, ExpressionType.LeftShift);
+ var c4 = e4.Compile ();
+ Assert (null, c4 (new MyType (8), null));
+ Assert (null, c4 (null, new MyType (8)));
+ Assert (1024, c4 (new MyType (256), new MyType (2)));
+
+ Expression<Func<ushort, int?>> e5 = (ushort a) => a << null;
+ AssertNodeType (e5, ExpressionType.LeftShift);
+ Assert (null, e5.Compile ().Invoke (30));
+ }
+
+ void LessThanTest ()
+ {
+ Expression<Func<int, int, bool>> e = (int a, int b) => a < b;
+ AssertNodeType (e, ExpressionType.LessThan);
+ Assert (false, e.Compile ().Invoke (60, 30));
+
+ Expression<Func<uint?, byte?, bool>> e2 = (a, b) => a < b;
+ AssertNodeType (e2, ExpressionType.LessThan);
+ Assert (false, e2.Compile ().Invoke (null, 3));
+ Assert (false, e2.Compile ().Invoke (2, 2));
+
+ Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a < b;
+ AssertNodeType (e3, ExpressionType.LessThan);
+ Assert (false, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a < b;
+ AssertNodeType (e4, ExpressionType.LessThan);
+ Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (false, e4.Compile ().Invoke (null, null));
+ Assert (false, e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
+
+ Expression<Func<MyType?, sbyte, bool>> e5 = (MyType? a, sbyte b) => a < b;
+ AssertNodeType (e5, ExpressionType.LessThan);
+ Assert (false, e5.Compile ().Invoke (null, 33));
+ Assert (false, e5.Compile ().Invoke (null, 0));
+ Assert (false, e5.Compile ().Invoke (new MyType (120), 3));
+
+ Expression<Func<ushort, bool>> e6 = (ushort a) => a < null;
+ AssertNodeType (e6, ExpressionType.LessThan);
+ Assert (false, e6.Compile ().Invoke (60));
+ }
+
+ void LessThanOrEqualTest ()
+ {
+ Expression<Func<int, int, bool>> e = (int a, int b) => a <= b;
+ AssertNodeType (e, ExpressionType.LessThanOrEqual);
+ Assert (false, e.Compile ().Invoke (60, 30));
+
+ Expression<Func<byte?, byte?, bool>> e2 = (a, b) => a <= b;
+ AssertNodeType (e2, ExpressionType.LessThanOrEqual);
+ Assert (false, e2.Compile ().Invoke (null, 3));
+ Assert (true, e2.Compile ().Invoke (2, 2));
+
+ Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a <= b;
+ AssertNodeType (e3, ExpressionType.LessThanOrEqual);
+ Assert (true, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a <= b;
+ AssertNodeType (e4, ExpressionType.LessThanOrEqual);
+ Assert (false, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (false, e4.Compile ().Invoke (null, null));
+ Assert (false, e4.Compile ().Invoke (new MyType (120), new MyType (-20)));
+
+ Expression<Func<MyType?, sbyte, bool>> e5 = (MyType? a, sbyte b) => a <= b;
+ AssertNodeType (e5, ExpressionType.LessThanOrEqual);
+ Assert (false, e5.Compile ().Invoke (null, 33));
+ Assert (false, e5.Compile ().Invoke (null, 0));
+ Assert (false, e5.Compile ().Invoke (new MyType (120), 3));
+
+ Expression<Func<ushort, bool>> e6 = (ushort a) => a <= null;
+ AssertNodeType (e6, ExpressionType.LessThanOrEqual);
+ Assert (false, e6.Compile ().Invoke (60));
+ }
+
+ void ModuloTest ()
+ {
+ Expression<Func<int, int, int>> e = (int a, int b) => a % b;
+ AssertNodeType (e, ExpressionType.Modulo);
+ Assert (29, e.Compile ().Invoke (60, 31));
+
+ Expression<Func<double?, double?, double?>> e2 = (a, b) => a % b;
+ AssertNodeType (e2, ExpressionType.Modulo);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+ Assert (1.1, e2.Compile ().Invoke (3.1, 2));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a % b;
+ AssertNodeType (e3, ExpressionType.Modulo);
+ Assert (0, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a % b;
+ AssertNodeType (e4, ExpressionType.Modulo);
+ Assert (null, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (new MyType (12), e4.Compile ().Invoke (new MyType (12), new MyType (-20)));
+
+ Expression<Func<int, MyType, int>> e5 = (int a, MyType b) => a % b;
+ AssertNodeType (e5, ExpressionType.Modulo);
+ Assert (1, e5.Compile ().Invoke (99, new MyType (2)));
+
+ Expression<Func<int, MyType?, int?>> e6 = (int a, MyType? b) => a % b;
+ AssertNodeType (e6, ExpressionType.Modulo);
+ Assert (100, e6.Compile ().Invoke (100, new MyType (200)));
+ Assert (null, e6.Compile ().Invoke (20, null));
+
+ Expression<Func<ushort, int?>> e7 = (ushort a) => a % null;
+ AssertNodeType (e7, ExpressionType.Modulo);
+ Assert (null, e7.Compile ().Invoke (60));
+ }
+
+ void MultiplyTest ()
+ {
+ Expression<Func<int, int, int>> e = (int a, int b) => a * b;
+ AssertNodeType (e, ExpressionType.Multiply);
+ Assert (1860, e.Compile ().Invoke (60, 31));
+ Assert (2147483617, e.Compile ().Invoke (int.MaxValue, 31));
+
+ Expression<Func<double?, double?, double?>> e2 = (a, b) => a * b;
+ AssertNodeType (e2, ExpressionType.Multiply);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+ Assert (6.2, e2.Compile ().Invoke (3.1, 2));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a * b;
+ AssertNodeType (e3, ExpressionType.Multiply);
+ Assert (400, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a * b;
+ AssertNodeType (e4, ExpressionType.Multiply);
+ Assert (null, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (new MyType (-240), e4.Compile ().Invoke (new MyType (12), new MyType (-20)));
+
+ Expression<Func<int, MyType, int>> e5 = (int a, MyType b) => a * b;
+ AssertNodeType (e5, ExpressionType.Multiply);
+ Assert (198, e5.Compile ().Invoke (99, new MyType (2)));
+
+ Expression<Func<int, MyType?, int?>> e6 = (int a, MyType? b) => a * b;
+ AssertNodeType (e6, ExpressionType.Multiply);
+ Assert (0, e6.Compile ().Invoke (int.MinValue, new MyType (200)));
+ Assert (null, e6.Compile ().Invoke (20, null));
+
+ Expression<Func<ushort, int?>> e7 = (ushort a) => a * null;
+ AssertNodeType (e7, ExpressionType.Multiply);
+ Assert (null, e7.Compile ().Invoke (60));
+ }
+
+ void MultiplyCheckedTest ()
+ {
+ checked {
+ Expression<Func<int, int, int>> e = (int a, int b) => a * b;
+ AssertNodeType (e, ExpressionType.MultiplyChecked);
+ try {
+ e.Compile ().Invoke (int.MaxValue, 309);
+ throw new ApplicationException ("MultiplyCheckedTest #1");
+ } catch (OverflowException) { }
+
+ Expression<Func<byte?, byte?, int?>> e2 = (a, b) => a * b;
+ AssertNodeType (e2, ExpressionType.MultiplyChecked);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+ Assert (14025, e2.Compile ().Invoke (byte.MaxValue, 55));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a * b;
+ AssertNodeType (e3, ExpressionType.Multiply);
+ Assert (-600, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
+
+ Expression<Func<double, double, double>> e4 = (a, b) => a * b;
+ AssertNodeType (e4, ExpressionType.Multiply);
+ Assert (double.PositiveInfinity, e4.Compile ().Invoke (double.MaxValue, int.MaxValue));
+ }
+ }
+
void NewArrayInitTest ()
{
Expression<Func<int []>> e = () => new int [0];
Assert (new char [] { 'a' }, e3.Compile ().Invoke () [0]);
}
+ void NotTest ()
+ {
+ Expression<Func<bool, bool>> e = (bool a) => !a;
+ AssertNodeType (e, ExpressionType.Not);
+ Assert (false, e.Compile ().Invoke (true));
+
+ Expression<Func<MyType, bool>> e2 = (MyType a) => !a;
+ AssertNodeType (e2, ExpressionType.Not);
+ Assert (true, e2.Compile ().Invoke (new MyType (1)));
+ Assert (false, e2.Compile ().Invoke (new MyType (-1)));
+ }
+
+ void NotNullableTest ()
+ {
+ Expression<Func<bool?, bool?>> e = (bool? a) => !a;
+ AssertNodeType (e, ExpressionType.Not);
+ Assert (false, e.Compile ().Invoke (true));
+ Assert (null, e.Compile ().Invoke (null));
+
+ Expression<Func<MyType?, bool?>> e2 = (MyType? a) => !a;
+ AssertNodeType (e2, ExpressionType.Not);
+ Assert (true, e2.Compile ().Invoke (new MyType (1)));
+ Assert (null, e2.Compile ().Invoke (null));
+ }
+
+ void NotEqualTest ()
+ {
+ Expression<Func<int, int, bool>> e = (int a, int b) => a != b;
+ AssertNodeType (e, ExpressionType.NotEqual);
+ Assert (true, e.Compile ().Invoke (60, 30));
+ Assert (false, e.Compile ().Invoke (-1, -1));
+
+ Expression<Func<sbyte?, sbyte?, bool>> e2 = (a, b) => a != b;
+ AssertNodeType (e2, ExpressionType.NotEqual);
+ Assert (false, e2.Compile ().Invoke (3, 3));
+ Assert (true, e2.Compile ().Invoke (3, 2));
+
+ Expression<Func<MyType, MyType, bool>> e3 = (MyType a, MyType b) => a != b;
+ AssertNodeType (e3, ExpressionType.NotEqual);
+ Assert (false, e3.Compile ().Invoke (new MyType (-20), new MyType (-20)));
+
+ Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a != b;
+ AssertNodeType (e4, ExpressionType.NotEqual);
+ Assert (true, e4.Compile ().Invoke (null, new MyType (-20)));
+ Assert (false, e4.Compile ().Invoke (null, null));
+ Assert (false, e4.Compile ().Invoke (new MyType (120), new MyType (120)));
+
+ Expression<Func<bool?, bool?, bool>> e5 = (bool? a, bool? b) => a != b;
+ AssertNodeType (e5, ExpressionType.NotEqual);
+ Assert (true, e5.Compile ().Invoke (true, null));
+ Assert (false, e5.Compile ().Invoke (null, null));
+ Assert (false, e5.Compile ().Invoke (false, false));
+
+ Expression<Func<bool, bool>> e6 = (bool a) => a != null;
+ AssertNodeType (e6, ExpressionType.NotEqual);
+ Assert (true, e6.Compile ().Invoke (true));
+ Assert (true, e6.Compile ().Invoke (false));
+
+ Expression<Func<string, string, bool>> e7 = (string a, string b) => a != b;
+ AssertNodeType (e7, ExpressionType.NotEqual);
+ Assert (false, e7.Compile ().Invoke (null, null));
+ Assert (true, e7.Compile ().Invoke ("a", "A"));
+ Assert (false, e7.Compile ().Invoke ("a", "a"));
+
+ Expression<Func<object, bool>> e8 = (object a) => null != a;
+ AssertNodeType (e8, ExpressionType.NotEqual);
+ Assert (false, e8.Compile ().Invoke (null));
+ Assert (true, e8.Compile ().Invoke ("a"));
+ Assert (true, e8.Compile ().Invoke (this));
+ }
+
void OrTest ()
{
Expression<Func<bool, bool, bool>> e = (bool a, bool b) => a | b;
var c2 = e2.Compile ();
Assert (new MyType (3), c2 (new MyType (1), new MyType (2)));
Assert (null, c2 (new MyType (1), null));
+
+ /* BUG: This does not work with csc either, because nullable conversions on top of user conversion is required
+
+ Expression<Func<MyType?, uint, long?>> e3 = (MyType? a, uint b) => a | b;
+ AssertNodeType (e3, ExpressionType.Or);
+ var c3 = e3.Compile ();
+ Assert (9, c3 (new MyType (1), 8));
+ Assert (null, c3 (null, 4));
+ */
+ }
+
+ void OrElseTest ()
+ {
+ Expression<Func<bool, bool, bool>> e = (bool a, bool b) => a || b;
+ AssertNodeType (e, ExpressionType.OrElse);
+ Assert (true, e.Compile ().Invoke (true, false));
+
+ Expression<Func<MyType, MyType, MyType>> e2 = (MyType a, MyType b) => a || b;
+ AssertNodeType (e2, ExpressionType.OrElse);
+ Assert (new MyType (64), e2.Compile ().Invoke (new MyType (64), new MyType (64)));
+ Assert (new MyType (32), e2.Compile ().Invoke (new MyType (32), new MyType (64)));
+ }
+
+ void ParameterTest ()
+ {
+ Expression<Func<string, string>> e = (string a) => a;
+ AssertNodeType (e, ExpressionType.Parameter);
+ Assert ("t", e.Compile ().Invoke ("t"));
+
+ Expression<Func<object[], object[]>> e2 = (object[] a) => a;
+ AssertNodeType (e2, ExpressionType.Parameter);
+ Assert (new object [0], e2.Compile ().Invoke (new object [0]));
+
+ Expression<Func<IntPtr, IntPtr>> e3 = a => a;
+ AssertNodeType (e3, ExpressionType.Parameter);
+ Assert (IntPtr.Zero, e3.Compile ().Invoke (IntPtr.Zero));
+ }
+
+ void QuoteTest ()
+ {
+ Expression<Func<Expression<Func<int>>>> e = () => () => 2;
+ AssertNodeType (e, ExpressionType.Quote);
+ Assert (2, e.Compile ().Invoke ().Compile ().Invoke ());
+ }
+
+ void RightShiftTest ()
+ {
+ Expression<Func<ulong, short, ulong>> e = (ulong a, short b) => a >> b;
+ AssertNodeType (e, ExpressionType.RightShift);
+ Assert ((ulong)0x1FD940L, e.Compile ().Invoke (0xFECA0000, 11));
+ Assert ((ulong)0, e.Compile ().Invoke (0xFFFFFFFF, 0xA01));
+
+ Expression<Func<MyType, MyType, int>> e2 = (MyType a, MyType b) => a >> b;
+ AssertNodeType (e2, ExpressionType.RightShift);
+ var c2 = e2.Compile ();
+ Assert (64, c2 (new MyType (256), new MyType (2)));
+
+ Expression<Func<long?, sbyte, long?>> e3 = (long? a, sbyte b) => a >> b;
+ AssertNodeType (e3, ExpressionType.RightShift);
+ Assert (null, e3.Compile ().Invoke (null, 11));
+ Assert (512, e3.Compile ().Invoke (1024, 1));
+
+ Expression<Func<MyType?, MyType?, int?>> e4 = (MyType? a, MyType? b) => a >> b;
+ AssertNodeType (e4, ExpressionType.RightShift);
+ var c4 = e4.Compile ();
+ Assert (null, c4 (new MyType (8), null));
+ Assert (null, c4 (null, new MyType (8)));
+ Assert (64, c4 (new MyType (256), new MyType (2)));
+ }
+
+ void SubtractTest ()
+ {
+ Expression<Func<int, int, int>> e = (int a, int b) => a - b;
+ AssertNodeType (e, ExpressionType.Subtract);
+ Assert (-10, e.Compile ().Invoke (20, 30));
+
+ Expression<Func<int?, int?, int?>> e2 = (a, b) => a - b;
+ AssertNodeType (e2, ExpressionType.Subtract);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a - b;
+ AssertNodeType (e3, ExpressionType.Subtract);
+ Assert (-50, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
+
+ Expression<Func<MyType?, MyType?, MyType?>> e4 = (MyType? a, MyType? b) => a - b;
+ AssertNodeType (e4, ExpressionType.Subtract);
+ Assert (new MyType (-50), e4.Compile ().Invoke (new MyType (-20), new MyType (30)));
+ Assert (null, e4.Compile ().Invoke (null, new MyType (30)));
+
+ Expression<Func<int, MyType, int>> e5 = (int a, MyType b) => a - b;
+ AssertNodeType (e5, ExpressionType.Subtract);
+ Assert (-29, e5.Compile ().Invoke (1, new MyType (30)));
+
+ Expression<Func<int, MyType?, int?>> e6 = (int a, MyType? b) => a - b;
+ AssertNodeType (e6, ExpressionType.Subtract);
+ Assert (-61, e6.Compile ().Invoke (-31, new MyType (30)));
+
+ Expression<Func<ushort, int?>> e7 = (ushort a) => null - a;
+ AssertNodeType (e7, ExpressionType.Subtract);
+ Assert (null, e7.Compile ().Invoke (690));
+ }
+
+ void SubtractCheckedTest ()
+ {
+ checked {
+ Expression<Func<long, long, long>> e = (long a, long b) => a - b;
+ AssertNodeType (e, ExpressionType.SubtractChecked);
+ try {
+ e.Compile ().Invoke (long.MinValue, 309);
+ throw new ApplicationException ("SubtractCheckedTest #1");
+ } catch (OverflowException) { }
+
+ Expression<Func<byte?, byte?, int?>> e2 = (a, b) => a - b;
+ AssertNodeType (e2, ExpressionType.SubtractChecked);
+ Assert (null, e2.Compile ().Invoke (null, 3));
+ Assert (-55, e2.Compile ().Invoke (byte.MinValue, 55));
+
+ Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a - b;
+ AssertNodeType (e3, ExpressionType.Subtract);
+ Assert (-50, e3.Compile ().Invoke (new MyType (-20), new MyType (30)));
+
+ Expression<Func<double, double, double>> e4 = (a, b) => a - b;
+ AssertNodeType (e4, ExpressionType.Subtract);
+ Assert (double.PositiveInfinity, e4.Compile ().Invoke (double.MinValue, double.NegativeInfinity));
+ }
}
//
{
Tester e = new Tester ();
e.AddTest ();
+ e.AddStringTest ();
e.AndNullableTest ();
e.AddCheckedTest ();
e.AndTest ();
e.CallTest ();
e.CoalesceTest ();
e.ConditionTest ();
+ e.ConstantTest ();
e.ConvertTest ();
e.ConvertCheckedTest ();
+ e.DivideTest ();
+ e.EqualTest ();
+ e.EqualTestDelegate ();
+ e.ExclusiveOrTest ();
+ e.GreaterThanTest ();
+ e.GreaterThanOrEqualTest ();
+ e.LeftShiftTest ();
+ e.LessThanTest ();
+ e.LessThanOrEqualTest ();
+
+ e.ModuloTest ();
+ e.MultiplyTest ();
+ e.MultiplyCheckedTest ();
e.NewArrayInitTest ();
+ e.NotTest ();
+ e.NotNullableTest ();
+ e.NotEqualTest ();
e.OrTest ();
e.OrNullableTest ();
+ e.OrElseTest ();
+ e.ParameterTest ();
+ e.QuoteTest ();
+ e.RightShiftTest ();
+ e.SubtractTest ();
+ e.SubtractCheckedTest ();
return 0;
}