2008-01-22 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Wed, 23 Jan 2008 01:18:25 +0000 (01:18 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Wed, 23 Jan 2008 01:18:25 +0000 (01:18 -0000)
* BinaryExpression.cs: Unleash the power of cut and paste.

Bring a bunch of operatros from mcs/expression.cs

* Expression.cs: There is no op_LogicalAnd or op_LogicalOr, I just
used those from mcs, that was wrong.   use the proper ones, clean
up the result.

* BinaryExpression.cs: Add method invocations for binary methods.

svn path=/trunk/mcs/; revision=93613

mcs/class/System.Core/System.Linq.Expressions/BinaryExpression.cs
mcs/class/System.Core/System.Linq.Expressions/ChangeLog
mcs/class/System.Core/TODO
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_GreaterThan.cs
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Lambda.cs
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_MakeBinary.cs
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Power.cs

index e880edb7f35460fb8205b49ab4bd52843414bf25..b73b3f44f517804fac62aeb004ab5ad389309882 100644 (file)
@@ -287,6 +287,12 @@ namespace System.Linq.Expressions {
                        case ExpressionType.Coalesce:
                                EmitCoalesce (ec);
                                return;
+
+                       case ExpressionType.Power:
+                               left.Emit (ec);
+                               right.Emit (ec);
+                               ig.Emit (OpCodes.Call, typeof (System.Math).GetMethod ("Pow"));
+                               return;
                        }
                        
                        Label? empty_value = null;
@@ -398,24 +404,64 @@ namespace System.Linq.Expressions {
                                opcode = OpCodes.Xor;
                                break;
 
-                       case ExpressionType.Coalesce:
-                       case ExpressionType.Equal:
                        case ExpressionType.GreaterThan:
+                               if (is_unsigned)
+                                       opcode = OpCodes.Cgt_Un;
+                               else
+                                       opcode = OpCodes.Cgt;
+                               break;
+                               
                        case ExpressionType.GreaterThanOrEqual:
+                               Type le = left.Type;
+                               
+                               if (is_unsigned || (le == typeof (double) || le == typeof (float)))
+                                       ig.Emit (OpCodes.Clt_Un);
+                               else
+                                       ig.Emit (OpCodes.Clt);
+                               
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+                               
                        case ExpressionType.LessThan:
+                               if (is_unsigned)
+                                       opcode = OpCodes.Clt_Un;
+                               else
+                                       opcode = OpCodes.Clt;
+                               break;
+                               
                        case ExpressionType.LessThanOrEqual:
+                               Type lt = left.Type;
+                               
+                               if (is_unsigned || (lt == typeof (double) || lt == typeof (float)))
+                                       ig.Emit (OpCodes.Cgt_Un);
+                               else
+                                       ig.Emit (OpCodes.Cgt);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+                               
+                       case ExpressionType.Equal:
+                               opcode = OpCodes.Ceq;
+                               break;
+                               
                        case ExpressionType.NotEqual:
-                       case ExpressionType.Power:
-                               throw new NotImplementedException (String.Format ("No support for {0} node yet", NodeType));
-
+                               ig.Emit (OpCodes.Ceq);
+                               ig.Emit (OpCodes.Ldc_I4_0);
+                               
+                               opcode = OpCodes.Ceq;
+                               break;
+                               
                        default:
                                throw new Exception (String.Format ("Internal error: BinaryExpression contains non-Binary nodetype {0}", NodeType));
                        }
                        ig.Emit (opcode);
-
+                       
                        if (IsLifted){
                                ig.Emit (OpCodes.Newobj, left.Type.GetConstructors ()[0]);
-
+                               
                                Label skip = ig.DefineLabel ();
                                ig.Emit (OpCodes.Br_S, skip);
                                ig.MarkLabel (empty_value.Value);
index b3fb7dd78abe803b68fd9e62fa7f2e354fbcabf3..a0a537127b251c959dd5f3f6d54cbd48c835ed4d 100644 (file)
@@ -1,5 +1,9 @@
 2008-01-22  Miguel de Icaza  <miguel@novell.com>
 
+       * BinaryExpression.cs: Unleash the power of cut and paste.
+
+       Bring a bunch of operatros from mcs/expression.cs
+
        * Expression.cs: There is no op_LogicalAnd or op_LogicalOr, I just
        used those from mcs, that was wrong.   use the proper ones, clean
        up the result.
index 80302cb64aebbb2cd9241b5fe0495510f08683a0..488febdb95c12609aa66a0992af08cc53cfcb731 100644 (file)
@@ -1,5 +1,9 @@
 Things missing:
 
+       *** Add support for MethodInfos ** and the nullable stuff, I believe
+       we have to pull the values before calling the various
+       MethodINfos in BinaryExpression, need to write test
+
        Coalesce's conversion, what is this used for?
 
        Constant generation of objects, how are those Constants in the first place?
@@ -7,22 +11,19 @@ Things missing:
        Try: 
                    OrElse (Constant (new Boo(), new Boo ()))
 
-Binary missing:
-                       case ExpressionType.Coalesce:
-                       case ExpressionType.Equal:
-                       case ExpressionType.GreaterThan:
-                       case ExpressionType.GreaterThanOrEqual:
-                       case ExpressionType.LessThan:
-                       case ExpressionType.LessThanOrEqual:
-                       case ExpressionType.NotEqual:
-                       case ExpressionType.Power:
-       
 Tests missing:
 
        Must write tests for all the codepaths currently in
        BinaryExpression.Emit (specially the XXXChecked variants as
        those so far have shown most of the problems).
 
+
+       Write tests for stuff using MethodInfos (the various
+       BinaryExpressions using MEthodInfos have been barely tested).   
+
+       Write more tests using nullables, currently we are short on
+       them, and they are not extensively tested.
+
        Missing:
                Add, Subtract, Multiply, Divide, Modulo, <<, >> And, Or, Xor
 
index 0e95597f77542608bcd2cf5e2ff63b220a000928..765688849cb98199a5a54b053818d526505b542d 100644 (file)
@@ -92,6 +92,13 @@ namespace MonoTests.System.Linq.Expressions
                        Expression.GreaterThan (Expression.Constant (true), Expression.Constant (false));
                }
 
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void StringS ()
+               {
+                       Expression.GreaterThan (Expression.Constant (""), Expression.Constant (""));
+               }
+
                [Test]
                public void UserDefinedClass ()
                {
@@ -106,5 +113,24 @@ namespace MonoTests.System.Linq.Expressions
                        Assert.AreEqual ("op_GreaterThan", expr.Method.Name);
                        Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) > value(MonoTests.System.Linq.Expressions.OpClass))", expr.ToString ());
                }
+
+               [Test]
+               public void TestCompiled ()
+               {
+                       ParameterExpression a = Expression.Parameter(typeof(int), "a");
+                       ParameterExpression b = Expression.Parameter(typeof(int), "b");
+
+                       BinaryExpression p = Expression.GreaterThan (a, b);
+
+                       Expression<Func<int,int,bool>> pexpr = Expression.Lambda<Func<int,int,bool>> (
+                               p, new ParameterExpression [] { a, b });
+                       
+                       Func<int,int,bool> compiled = pexpr.Compile ();
+                       Assert.AreEqual (true, compiled (10, 1), "tc1");
+                       Assert.AreEqual (true, compiled (1, 0), "tc2");
+                       Assert.AreEqual (true, compiled (Int32.MinValue+1, Int32.MinValue), "tc3");
+                       Assert.AreEqual (false, compiled (-1, 0), "tc4");
+                       Assert.AreEqual (false, compiled (0, Int32.MaxValue), "tc5");
+               }
        }
 }
index 5b0faa3884e9dee5c2c3618235bdaefe8db2bef7..ca8619b3b697d5e8b6647aaf8d7f9e04fa564f26 100644 (file)
@@ -81,7 +81,6 @@ namespace MonoTests.System.Linq.Expressions
                public void InvalidArgType ()
                {
                        // invalid argument type
-
                        ParameterExpression p = Expression.Parameter (typeof (string), "AAA");
                        Expression.Lambda (typeof (delegate_object_int), Expression.Constant ("foo"), new ParameterExpression [1] {p});
                }
index 1ab119e1ce9b8eb1401c622a169340fb32938224..df8cfd7d32015dd312996fd57c95d686b2bd6cb5 100644 (file)
@@ -207,5 +207,92 @@ namespace MonoTests.System.Linq.Expressions
                        Assert.AreEqual (100.0/3, CodeGen<double> ((a, b) => Expression.Divide (a, b), 100, 3));
                }
 
+               void CTest<T> (ExpressionType node, bool r, T a, T b)
+               {
+                       ParameterExpression pa = Expression.Parameter(typeof(T), "a");
+                       ParameterExpression pb = Expression.Parameter(typeof(T), "b");
+
+                       BinaryExpression p = Expression.MakeBinary (node, Expression.Constant (a), Expression.Constant(b));
+                       Expression<Func<T,T,bool>> pexpr = Expression.Lambda<Func<T,T,bool>> (
+                               p, new ParameterExpression [] { pa, pb });
+                       
+                       Func<T,T,bool> compiled = pexpr.Compile ();
+                       Assert.AreEqual (r, compiled (a, b), String.Format ("{0} ({1},{2}) == {3}", node, a, b, r));
+               }
+
+               [Test]
+               public void ComparisonTests ()
+               {
+                       ExpressionType t = ExpressionType.Equal;
+               
+                       CTest<byte>   (t, true,   10,  10);
+                       CTest<sbyte>  (t, false,   1,   5);
+                       CTest<sbyte>  (t, true,    1,   1);
+                       CTest<int>    (t, true,    1,   1);
+                       CTest<double> (t, true,  1.0, 1.0);
+                       CTest<string> (t, true,  "",  "");
+                       CTest<string> (t, true,  "Hey",  "Hey");
+                       CTest<string> (t, false,  "Hey",  "There");
+
+                       t = ExpressionType.NotEqual;
+                       
+                       CTest<byte>   (t, false,   10,  10);
+                       CTest<sbyte>  (t, true,   1,   5);
+                       CTest<sbyte>  (t, false,    1,   1);
+                       CTest<int>    (t, false,    1,   1);
+                       CTest<double> (t, false,  1.0, 1.0);
+                       CTest<double> (t, false,  1.0, 1.0);
+                       CTest<string> (t, false,  "",  "");
+                       CTest<string> (t, false,  "Hey",  "Hey");
+                       CTest<string> (t, true,  "Hey",  "There");
+
+                       t = ExpressionType.GreaterThan;
+                       CTest<byte>   (t, true,   5,  1);
+                       CTest<byte>   (t, false,   10,  10);
+                       CTest<sbyte>  (t, false,   1,   5);
+                       CTest<sbyte>  (t, false,    1,   1);
+                       CTest<int>    (t, false,    1,   1);
+                       CTest<uint>   (t, true,     1,   0);
+                       CTest<ulong>  (t, true,     Int64.MaxValue,  0);
+                       CTest<double> (t, false,  1.0, 1.0);
+                       CTest<double> (t, false,  1.0, 1.0);
+
+                       
+                       t = ExpressionType.LessThan;
+                       CTest<byte>   (t, false,   5,  1);
+                       CTest<byte>   (t, false,   10,  10);
+                       CTest<sbyte>  (t, true,   1,   5);
+                       CTest<sbyte>  (t, false,    1,   1);
+                       CTest<int>    (t, false,    1,   1);
+                       CTest<uint>   (t, false,     1,   0);
+                       CTest<ulong>  (t, false,     Int64.MaxValue,  0);
+                       CTest<double> (t, false,  1.0, 1.0);
+                       CTest<double> (t, false,  1.0, 1.0);
+
+                       t = ExpressionType.GreaterThanOrEqual;
+                       CTest<byte>   (t, true,   5,  1);
+                       CTest<byte>   (t, true,   10,  10);
+                       CTest<sbyte>  (t, false,   1,   5);
+                       CTest<sbyte>  (t, true,    1,   1);
+                       CTest<int>    (t, true,    1,   1);
+                       CTest<uint>   (t, true,     1,   0);
+                       CTest<ulong>  (t, true,     Int64.MaxValue,  0);
+                       CTest<double> (t, true,  1.0, 1.0);
+                       CTest<double> (t, true,  1.0, 1.0);
+
+                       
+                       t = ExpressionType.LessThanOrEqual;
+                       CTest<byte>   (t, false,   5,  1);
+                       CTest<byte>   (t, true,   10,  10);
+                       CTest<sbyte>  (t, true,   1,   5);
+                       CTest<sbyte>  (t, true,    1,   1);
+                       CTest<int>    (t, true,    1,   1);
+                       CTest<uint>   (t, false,     1,   0);
+                       CTest<ulong>  (t, false,     Int64.MaxValue,  0);
+                       CTest<double> (t, true,  1.0, 1.0);
+                       CTest<double> (t, true,  1.0, 1.0);
+                       
+               }
+
        }
 }
index 6a37c5dbd6b417402b614c04c5a2f8181602cc7d..790cc447472de2afce4b93a413033cf94ec8c5c5 100644 (file)
@@ -69,45 +69,24 @@ namespace MonoTests.System.Linq.Expressions
                [Test]
                public void ArgTypesFloat_OK ()
                {
-                       Expression.Power (Expression.Constant (1.0), Expression.Constant (2.0));
-               }
-
-#if false
-               [Test]
-               [ExpectedException (typeof (InvalidOperationException))]
-               public void NoOperatorClass ()
-               {
-                       Expression.Subtract (Expression.Constant (new NoOpClass ()), Expression.Constant (new NoOpClass ()));
-               }
-       
-               [Test]
-               public void Nullable ()
-               {
-                       int? a = 1;
-                       int? b = 2;
+                       BinaryExpression p = Expression.Power (Expression.Constant (1.0), Expression.Constant (2.0));
 
-                       BinaryExpression expr = Expression.Subtract (Expression.Constant (a), Expression.Constant (b));
-                       Assert.AreEqual (ExpressionType.Subtract, expr.NodeType, "Subtract#05");
-                       Assert.AreEqual (typeof (int), expr.Type, "Subtract#06");
-                       Assert.IsNull (expr.Method, "Subtract#07");
-                       Assert.AreEqual ("(1 - 2)", expr.ToString(), "Subtract#08");
+                       Assert.AreEqual (ExpressionType.Power, p.NodeType, "Power#01");
+                       Assert.AreEqual (typeof (double), p.Type, "Add#02");
                }
 
                [Test]
-               public void UserDefinedClass ()
+               public void TestCompile ()
                {
-                       // We can use the simplest version of GetMethod because we already know only one
-                       // exists in the very simple class we're using for the tests.
-                       MethodInfo mi = typeof (OpClass).GetMethod ("op_Subtraction");
-
-                       BinaryExpression expr = Expression.Subtract (Expression.Constant (new OpClass ()), Expression.Constant (new OpClass ()));
-                       Assert.AreEqual (ExpressionType.Subtract, expr.NodeType, "Subtract#09");
-                       Assert.AreEqual (typeof (OpClass), expr.Type, "Subtract#10");
-                       Assert.AreEqual (mi, expr.Method, "Subtract#11");
-                       Assert.AreEqual ("op_Subtraction", expr.Method.Name, "Subtract#12");
-                       Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) - value(MonoTests.System.Linq.Expressions.OpClass))",
-                               expr.ToString(), "Subtract#13");
+                       ParameterExpression a = Expression.Parameter(typeof(double), "a");
+                       ParameterExpression b = Expression.Parameter(typeof(double), "b");
+                       BinaryExpression p = Expression.Power (a, b);
+                       
+                       Expression<Func<double,double,double>> pexpr = Expression.Lambda<Func<double,double,double>> (p, new ParameterExpression [] { a, b });
+                       Func<double,double,double> compiled = pexpr.Compile ();
+                       Assert.AreEqual (1, compiled (1, 10));
+                       Assert.AreEqual (16, compiled (2, 4));
                }
-#endif
+
        }
 }