Implemented Or and OrElse.
authorFederico Di Gregorio <fog@initd.org>
Thu, 16 Aug 2007 23:03:15 +0000 (23:03 -0000)
committerFederico Di Gregorio <fog@initd.org>
Thu, 16 Aug 2007 23:03:15 +0000 (23:03 -0000)
svn path=/trunk/mcs/; revision=84246

mcs/class/System.Core/System.Core_test.dll.sources
mcs/class/System.Core/System.Linq.Expressions/BinaryExpression.cs
mcs/class/System.Core/System.Linq.Expressions/ChangeLog
mcs/class/System.Core/System.Linq.Expressions/Expression.cs
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Or.cs [new file with mode: 0644]
mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_OrElse.cs [new file with mode: 0644]

index a98cd3b9db72fe88f067705502635ded867dd19f..f9258d131b1092f97b989a52eef2a09c9181f99b 100644 (file)
@@ -12,4 +12,6 @@ System.Linq.Expressions/ExpressionTest_ExclusiveOr.cs
 System.Linq.Expressions/ExpressionTest_Modulo.cs
 System.Linq.Expressions/ExpressionTest_Multiply.cs
 System.Linq.Expressions/ExpressionTest_MultiplyChecked.cs
+System.Linq.Expressions/ExpressionTest_Or.cs
+System.Linq.Expressions/ExpressionTest_OrElse.cs
 System.Linq.Expressions/ExpressionTest_Utils.cs
index 597eece2cf44bbe656d470707f7e04b0c06d3103..ef1c64f3ff7d6594fdde253a5eaeabc09bcd09e1 100644 (file)
@@ -151,7 +151,7 @@ namespace System.Linq.Expressions
             // See below for ExpressionType.Or.
 
             case ExpressionType.OrElse:
-                builder.AppendFormat ("({0} ^ {1})", left, right);
+                builder.AppendFormat ("({0} || {1})", left, right);
                 break;
 
             case ExpressionType.RightShift:
index c4ff59160ac8c82186d09103f0c1396df6f67ea3..6601ba3f2baaea3dedc93a3fbafb97c1e210bb06 100644 (file)
@@ -1,5 +1,9 @@
 2007-08-17  Federico Di Gregorio <fog@initd.org>
 
+       * Expression.cs: implemented all versions of Or() and OrElse().
+
+       * BinaryExpression.cs: fixed OrElse case in BuildString().
+
        * Expression.cs: implemented all versions of Divide(), Modulo(),
        Multiply(), MultiplyChecked() and tests. Call() works except for
        generic types.
index 78f00f66b37a3f1a41894bba37391d8be18dcd22..acdc08ad4892782dc3d64a66ff51a380eb366aa9 100644 (file)
@@ -344,7 +344,7 @@ namespace System.Linq.Expressions
             if (right == null)
                 throw new ArgumentNullException ("right");
 
-            // Since both the expressions define the same integer or boolean type we don't have
+            // Since both the expressions define the same boolean type we don't have
             // to look for the "op_BitwiseAnd" method.
             if (left.type == right.type && left.type == typeof(bool))
                 return new BinaryExpression(ExpressionType.AndAlso, left, right, left.type);
@@ -830,7 +830,64 @@ namespace System.Linq.Expressions
 
             return new MemberExpression(expression, property, property.PropertyType);
         }
+        
+        #region Or
+        public static BinaryExpression Or (Expression left, Expression right, MethodInfo method)
+        {
+            if (left == null)
+                throw new ArgumentNullException ("left");
+            if (right == null)
+                throw new ArgumentNullException ("right");
+
+            if (method != null)
+                return new BinaryExpression(ExpressionType.Or, left, right, method, method.ReturnType);
+            
+            // Since both the expressions define the same integer or boolean type we don't have
+            // to look for the "op_BitwiseOr" method.
+            if (left.type == right.type && (ExpressionUtil.IsInteger(left.type) || left.type == typeof(bool)))
+                return new BinaryExpression(ExpressionType.Or, left, right, left.type);
+
+            // Else we try for a user-defined operator.
+            return GetUserDefinedBinaryOperatorOrThrow (ExpressionType.Or, "op_BitwiseOr", left, right);
+        
+        }
 
+        public static BinaryExpression Or (Expression left, Expression right)
+        {
+            return Or (left, right, null);
+        }
+        #endregion
+        
+        #region OrElse
+        public static BinaryExpression OrElse (Expression left, Expression right, MethodInfo method)
+        {
+            if (left == null)
+                throw new ArgumentNullException ("left");
+            if (right == null)
+                throw new ArgumentNullException ("right");
+
+            // Since both the expressions define the same boolean type we don't have
+            // to look for the "op_BitwiseOr" method.
+            if (left.type == right.type && left.type == typeof(bool))
+                return new BinaryExpression(ExpressionType.OrElse, left, right, left.type);
+
+            // Else we must validate the method to make sure it has companion "true" and "false" operators.
+            if (method == null)
+                method = GetUserDefinedBinaryOperator (left.type, right.type, "op_BitwiseOr");
+            if (method == null)
+                throw new InvalidOperationException(String.Format(
+                    "The binary operator OrElse is not defined for the types '{0}' and '{1}'.", left.type, right.type));
+            ValidateUserDefinedConditionalLogicOperator(ExpressionType.OrElse, left.type, right.type, method);
+            
+            return new BinaryExpression(ExpressionType.OrElse, left, right, method, method.ReturnType);
+        }
+        
+        public static BinaryExpression OrElse (Expression left, Expression right)
+        {
+            return OrElse(left, right, null);
+        }
+        #endregion
+        
         public static UnaryExpression Quote(Expression expression)
         {
             if (expression == null)
diff --git a/mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Or.cs b/mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_Or.cs
new file mode 100644 (file)
index 0000000..24468cf
--- /dev/null
@@ -0,0 +1,104 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+//
+// Authors:
+//        Federico Di Gregorio <fog@initd.org>
+
+using System;
+using System.Reflection;
+using System.Linq;
+using System.Linq.Expressions;
+using NUnit.Framework;
+
+namespace MonoTests.System.Linq.Expressions
+{    
+    [TestFixture]
+    public class ExpressionTest_Or
+    {
+        [Test]
+        [ExpectedException (typeof (ArgumentNullException))]
+        public void Arg1Null ()
+        {
+            Expression.Or (null, Expression.Constant (1));
+        }
+
+        [Test]
+        [ExpectedException (typeof (ArgumentNullException))]
+        public void Arg2Null ()
+        {
+            Expression.Or (Expression.Constant (1), null);
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void NoOperatorClass ()
+        {
+            Expression.Or (Expression.Constant (new NoOpClass ()), Expression.Constant (new NoOpClass ()));
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void ArgTypesDifferent ()
+        {
+            Expression.Or (Expression.Constant (1), Expression.Constant (true));
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void Double ()
+        {
+            Expression.Or (Expression.Constant (1.0), Expression.Constant (2.0));
+        }
+
+        [Test]
+        public void Integer ()
+        {
+            BinaryExpression expr = Expression.Or (Expression.Constant (1), Expression.Constant (2));
+            Assert.AreEqual (ExpressionType.Or, expr.NodeType, "Or#01");
+            Assert.AreEqual (typeof (int), expr.Type, "Or#02");
+            Assert.IsNull (expr.Method, "Or#03");
+            Assert.AreEqual ("(1 | 2)", expr.ToString(), "Or#04");
+        }
+
+        [Test]
+        public void Boolean ()
+        {
+            BinaryExpression expr = Expression.Or (Expression.Constant (true), Expression.Constant (false));
+            Assert.AreEqual (ExpressionType.Or, expr.NodeType, "Or#05");
+            Assert.AreEqual (typeof (bool), expr.Type, "Or#06");
+            Assert.IsNull (expr.Method, "Or#07");
+            Assert.AreEqual ("(True Or False)", expr.ToString(), "Or#08");
+        }
+
+        [Test]
+        public void UserDefinedClass ()
+        {
+            // 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_BitwiseOr");
+            
+            BinaryExpression expr = Expression.Or (Expression.Constant (new OpClass ()), Expression.Constant (new OpClass ()));
+            Assert.AreEqual (ExpressionType.Or, expr.NodeType, "Or#09");
+            Assert.AreEqual (typeof (OpClass), expr.Type, "Or#10");
+            Assert.AreEqual (mi, expr.Method, "Or#11");
+            Assert.AreEqual ("op_BitwiseOr", expr.Method.Name, "Or#12");
+            Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) | value(MonoTests.System.Linq.Expressions.OpClass))",
+                expr.ToString(), "Or#13");
+        }
+    }
+}
diff --git a/mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_OrElse.cs b/mcs/class/System.Core/Test/System.Linq.Expressions/ExpressionTest_OrElse.cs
new file mode 100644 (file)
index 0000000..3313d72
--- /dev/null
@@ -0,0 +1,101 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+//
+// Authors:
+//        Federico Di Gregorio <fog@initd.org>
+
+using System;
+using System.Reflection;
+using System.Linq;
+using System.Linq.Expressions;
+using NUnit.Framework;
+
+namespace MonoTests.System.Linq.Expressions
+{    
+    [TestFixture]
+    public class ExpressionTest_OrElse
+    {
+        [Test]
+        [ExpectedException (typeof (ArgumentNullException))]
+        public void Arg1Null ()
+        {
+            Expression.OrElse (null, Expression.Constant (1));
+        }
+
+        [Test]
+        [ExpectedException (typeof (ArgumentNullException))]
+        public void Arg2Null ()
+        {
+            Expression.OrElse (Expression.Constant (1), null);
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void NoOperatorClass ()
+        {
+            Expression.OrElse (Expression.Constant (new NoOpClass ()), Expression.Constant (new NoOpClass ()));
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void Double ()
+        {
+            Expression.OrElse (Expression.Constant (1.0), Expression.Constant (2.0));
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void Integer ()
+        {
+            Expression.OrElse (Expression.Constant (1), Expression.Constant (2));
+        }
+
+        [Test]
+        [ExpectedException (typeof (InvalidOperationException))]
+        public void MismatchedTypes ()
+        {
+            Expression.OrElse (Expression.Constant (new OpClass ()), Expression.Constant (true));
+        }
+
+        [Test]
+        public void Boolean ()
+        {
+            BinaryExpression expr = Expression.OrElse (Expression.Constant (true), Expression.Constant (false));
+            Assert.AreEqual (ExpressionType.OrElse, expr.NodeType, "OrElse#01");
+            Assert.AreEqual (typeof (bool), expr.Type, "OrElse#02");
+            Assert.IsNull (expr.Method, "OrElse#03");
+            Assert.AreEqual ("(True || False)", expr.ToString(), "OrElse#04");
+        }
+
+        [Test]
+        public void UserDefinedClass ()
+        {
+            // 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_BitwiseOr");
+
+            BinaryExpression expr = Expression.OrElse (Expression.Constant (new OpClass ()), Expression.Constant (new OpClass ()));
+            Assert.AreEqual (ExpressionType.OrElse, expr.NodeType, "OrElse#05");
+            Assert.AreEqual (typeof (OpClass), expr.Type, "OrElse#06");
+            Assert.AreEqual (mi, expr.Method, "OrElse#07");
+            Assert.AreEqual ("op_BitwiseOr", expr.Method.Name, "OrElse#08");
+            Assert.AreEqual ("(value(MonoTests.System.Linq.Expressions.OpClass) || value(MonoTests.System.Linq.Expressions.OpClass))",
+                expr.ToString(), "OrElse#09");
+        }
+    }
+}