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)
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);
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);
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)
internal override void Emit (EmitContext ec)
{
- if (method != null){
+ if (method != null) {
EmitUserDefinedOperator (ec);
return;
}