New tests, update.
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / BinaryExpression.cs
index 115c1268b7426b00c3ecdc4cbee8f89ef2bbb061..569299e8fbdcb2277abe5241e23d55e7e2538735 100644 (file)
@@ -182,12 +182,12 @@ namespace System.Linq.Expressions {
 
                MethodInfo GetFalseOperator ()
                {
-                       return left.Type.GetMethod ("op_False", AllStatic);
+                       return GetFalseOperator (left.Type.GetNotNullableType ());
                }
 
                MethodInfo GetTrueOperator ()
                {
-                       return left.Type.GetMethod ("op_True", AllStatic);
+                       return GetTrueOperator (left.Type.GetNotNullableType ());
                }
 
                void EmitUserDefinedLogicalShortCircuit (EmitContext ec)
@@ -308,10 +308,9 @@ namespace System.Linq.Expressions {
 
                        ig.Emit (OpCodes.Brfalse, load_right);
 
-                       // is it the right way to do it?
-                       ec.EmitReadGlobal (conversion.Compile ());
+                       ec.Emit (conversion);
                        ec.EmitLoad (left);
-                       ig.Emit (OpCodes.Callvirt, conversion.Type.GetMethod ("Invoke"));
+                       ig.Emit (OpCodes.Callvirt, conversion.Type.GetInvokeMethod ());
 
                        ig.Emit (OpCodes.Br, done);
 
@@ -371,10 +370,13 @@ namespace System.Linq.Expressions {
                                ig.Emit (is_unsigned ? OpCodes.Rem_Un : OpCodes.Rem);
                                break;
                        case ExpressionType.RightShift:
-                               ig.Emit (is_unsigned ? OpCodes.Shr_Un : OpCodes.Shr);
-                               break;
                        case ExpressionType.LeftShift:
-                               ig.Emit (OpCodes.Shl);
+                               ig.Emit (OpCodes.Ldc_I4, left.Type == typeof (int) ? 0x1f : 0x3f);
+                               ig.Emit (OpCodes.And);
+                               if (NodeType == ExpressionType.RightShift)
+                                       ig.Emit (is_unsigned ? OpCodes.Shr_Un : OpCodes.Shr);
+                               else
+                                       ig.Emit (OpCodes.Shl);
                                break;
                        case ExpressionType.And:
                                ig.Emit (OpCodes.And);
@@ -649,7 +651,44 @@ namespace System.Linq.Expressions {
 
                void EmitUserDefinedLiftedLogicalShortCircuit (EmitContext ec)
                {
-                       throw new NotImplementedException ();
+                       var ig = ec.ig;
+                       var and = NodeType == ExpressionType.AndAlso;
+
+                       var left_is_null = ig.DefineLabel ();
+                       var ret_left = ig.DefineLabel ();
+                       var ret_null = ig.DefineLabel ();
+                       var done = ig.DefineLabel ();
+
+                       var left = ec.EmitStored (this.left);
+
+                       ec.EmitNullableHasValue (left);
+                       ig.Emit (OpCodes.Brfalse, and ? ret_null : left_is_null);
+
+                       ec.EmitNullableGetValueOrDefault (left);
+                       ec.EmitCall (and ? GetFalseOperator () : GetTrueOperator ());
+                       ig.Emit (OpCodes.Brtrue, ret_left);
+
+                       ig.MarkLabel (left_is_null);
+                       var right = ec.EmitStored (this.right);
+                       ec.EmitNullableHasValue (right);
+                       ig.Emit (OpCodes.Brfalse, ret_null);
+
+                       ec.EmitNullableGetValueOrDefault (left);
+                       ec.EmitNullableGetValueOrDefault (right);
+                       ec.EmitCall (method);
+
+                       ec.EmitNullableNew (Type);
+                       ig.Emit (OpCodes.Br, done);
+
+                       ig.MarkLabel (ret_left);
+                       ec.EmitLoad (left);
+                       ig.Emit (OpCodes.Br, done);
+
+                       ig.MarkLabel (ret_null);
+                       var ret = ig.DeclareLocal (Type);
+                       ec.EmitNullableInitialize (ret);
+
+                       ig.MarkLabel (done);
                }
 
                void EmitUserDefinedOperator (EmitContext ec)
@@ -682,7 +721,7 @@ namespace System.Linq.Expressions {
 
                internal override void Emit (EmitContext ec)
                {
-                       if (method != null){
+                       if (method != null) {
                                EmitUserDefinedOperator (ec);
                                return;
                        }