merge 99630:99762
[mono.git] / mcs / tests / gtest-etree-01.cs
index 5292a002b7fd77a4c1da6d3d16241b97b8caeeb8..c19d638895709fe6fbc2951d98216ad36a82a388 100644 (file)
@@ -40,6 +40,10 @@ public struct MyType<T>
 }
 */
 
+
+// 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;
@@ -69,16 +73,31 @@ public struct MyType
                return a.value != a;
        }
 
-       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);
@@ -128,11 +147,16 @@ public struct MyType
        {
                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 ()
        {
@@ -140,6 +164,22 @@ public struct MyType
        }
 }
 
+
+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
@@ -152,8 +192,16 @@ class Tester
 
        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)
@@ -180,7 +228,7 @@ class Tester
                Expression<Func<MyType, MyType, MyType>> e3 = (MyType a, MyType b) => a + b;
                AssertNodeType (e3, ExpressionType.Add);
                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)));
@@ -189,11 +237,10 @@ class Tester
                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)));               
-*/
+               Assert (-1, e6.Compile ().Invoke (-31, new MyType (30)));
        }
 
        void AddCheckedTest ()
@@ -212,6 +259,28 @@ class Tester
                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 ()
        {
@@ -265,15 +334,18 @@ class Tester
        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 ()
@@ -334,6 +406,9 @@ class Tester
                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 ()
@@ -378,6 +453,33 @@ class Tester
                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 ());
+       }
 
        void ConvertTest ()
        {
@@ -399,6 +501,19 @@ class Tester
 
                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;
        }
 
        void ConvertCheckedTest ()
@@ -441,6 +556,15 @@ class Tester
                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 ()
@@ -464,8 +588,31 @@ class Tester
                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 ()
@@ -486,15 +633,15 @@ class Tester
 
        void ExclusiveOrTest ()
        {
-               Expression<Func<int, int, int>> e = (int a, int b) => a ^ b;
+               Expression<Func<int, short, int>> e = (int a, short b) => a ^ b;
                AssertNodeType (e, ExpressionType.ExclusiveOr);
                Assert (34, e.Compile ().Invoke (60, 30));
-/* FIXME: missing conversion
+
                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)));
@@ -503,6 +650,11 @@ class Tester
                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 ()
@@ -510,7 +662,7 @@ class Tester
                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));
@@ -525,7 +677,16 @@ class Tester
                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 ()
@@ -541,16 +702,212 @@ class Tester
 
                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)));
-/*
-               Expression<Func<MyType?, MyType?, bool>> e4 = (MyType? a, MyType? b) => a >= null;
+               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];
@@ -569,7 +926,7 @@ class Tester
                AssertNodeType (e3, ExpressionType.NewArrayInit);
                Assert (new char [] { 'a' }, e3.Compile ().Invoke () [0]);
        }
-       
+
        void NotTest ()
        {
                Expression<Func<bool, bool>> e = (bool a) => !a;
@@ -594,7 +951,7 @@ class Tester
                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;
@@ -616,7 +973,30 @@ class Tester
                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 ()
        {
@@ -659,8 +1039,17 @@ class Tester
                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;
@@ -672,7 +1061,7 @@ class Tester
                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;
@@ -681,13 +1070,13 @@ class Tester
 
                Expression<Func<object[], object[]>> e2 = (object[] a) => a;
                AssertNodeType (e2, ExpressionType.Parameter);
-               Assert (new object[0], e2.Compile ().Invoke (new object[0]));
+               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;
@@ -718,7 +1107,64 @@ class Tester
                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));
+               }
+       }
 
        //
        // Test helpers
@@ -747,6 +1193,7 @@ class Tester
        {
                Tester e = new Tester ();
                e.AddTest ();
+               e.AddStringTest ();
                e.AndNullableTest ();
                e.AddCheckedTest ();
                e.AndTest ();
@@ -756,6 +1203,7 @@ class Tester
                e.CallTest ();
                e.CoalesceTest ();
                e.ConditionTest ();
+               e.ConstantTest ();
                e.ConvertTest ();
                e.ConvertCheckedTest ();
                e.DivideTest ();
@@ -764,6 +1212,13 @@ class Tester
                e.ExclusiveOrTest ();
                e.GreaterThanTest ();
                e.GreaterThanOrEqualTest ();
+               e.LeftShiftTest ();
+               e.LessThanTest ();
+               e.LessThanOrEqualTest ();
+
+               e.ModuloTest ();        
+               e.MultiplyTest ();
+               e.MultiplyCheckedTest ();
                e.NewArrayInitTest ();
                e.NotTest ();
                e.NotNullableTest ();
@@ -774,6 +1229,8 @@ class Tester
                e.ParameterTest ();
                e.QuoteTest ();
                e.RightShiftTest ();
+               e.SubtractTest ();
+               e.SubtractCheckedTest ();
 
                return 0;
        }