+ void EmitBoolean (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label left_is_null_label = ig.DefineLabel ();
+ Label right_is_null_label = ig.DefineLabel ();
+ Label is_null_label = ig.DefineLabel ();
+ Label wrap_label = ig.DefineLabel ();
+ Label end_label = ig.DefineLabel ();
+
+ if (left_unwrap != null) {
+ left_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brfalse, left_is_null_label);
+ }
+
+ left.Emit (ec);
+ ig.Emit (OpCodes.Dup);
+ if ((Oper == Binary.Operator.BitwiseOr) || (Oper == Binary.Operator.LogicalOr))
+ ig.Emit (OpCodes.Brtrue, wrap_label);
+ else
+ ig.Emit (OpCodes.Brfalse, wrap_label);
+
+ if (right_unwrap != null) {
+ right_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brfalse, right_is_null_label);
+ }
+
+ if ((Oper == Binary.Operator.LogicalAnd) || (Oper == Binary.Operator.LogicalOr))
+ ig.Emit (OpCodes.Pop);
+
+ right.Emit (ec);
+ if (Oper == Binary.Operator.BitwiseOr)
+ ig.Emit (OpCodes.Or);
+ else if (Oper == Binary.Operator.BitwiseAnd)
+ ig.Emit (OpCodes.And);
+ ig.Emit (OpCodes.Br, wrap_label);
+
+ ig.MarkLabel (left_is_null_label);
+ if (right_unwrap != null) {
+ right_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brfalse, is_null_label);
+ }
+
+ right.Emit (ec);
+ ig.Emit (OpCodes.Dup);
+ if ((Oper == Binary.Operator.BitwiseOr) || (Oper == Binary.Operator.LogicalOr))
+ ig.Emit (OpCodes.Brtrue, wrap_label);
+ else
+ ig.Emit (OpCodes.Brfalse, wrap_label);
+
+ ig.MarkLabel (right_is_null_label);
+ ig.Emit (OpCodes.Pop);
+ ig.MarkLabel (is_null_label);
+ null_value.Emit (ec);
+ ig.Emit (OpCodes.Br, end_label);
+
+ ig.MarkLabel (wrap_label);
+ ig.Emit (OpCodes.Nop);
+ bool_wrap.Emit (ec);
+ ig.Emit (OpCodes.Nop);
+
+ ig.MarkLabel (end_label);
+ }
+
+ void EmitEquality (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label left_not_null_label = ig.DefineLabel ();
+ Label false_label = ig.DefineLabel ();
+ Label true_label = ig.DefineLabel ();
+ Label end_label = ig.DefineLabel ();
+
+ if (left_unwrap != null) {
+ left_unwrap.EmitCheck (ec);
+ if (right is NullLiteral) {
+ if (Oper == Binary.Operator.Equality)
+ ig.Emit (OpCodes.Brfalse, true_label);
+ else
+ ig.Emit (OpCodes.Brfalse, false_label);
+ } else if (right_unwrap != null) {
+ ig.Emit (OpCodes.Dup);
+ ig.Emit (OpCodes.Brtrue, left_not_null_label);
+ right_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Ceq);
+ if (Oper == Binary.Operator.Inequality) {
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Ceq);
+ }
+ ig.Emit (OpCodes.Br, end_label);
+
+ ig.MarkLabel (left_not_null_label);
+ ig.Emit (OpCodes.Pop);
+ } else {
+ if (Oper == Binary.Operator.Equality)
+ ig.Emit (OpCodes.Brfalse, false_label);
+ else
+ ig.Emit (OpCodes.Brfalse, true_label);
+ }
+ }
+
+ if (right_unwrap != null) {
+ right_unwrap.EmitCheck (ec);
+ if (left is NullLiteral) {
+ if (Oper == Binary.Operator.Equality)
+ ig.Emit (OpCodes.Brfalse, true_label);
+ else
+ ig.Emit (OpCodes.Brfalse, false_label);
+ } else {
+ if (Oper == Binary.Operator.Equality)
+ ig.Emit (OpCodes.Brfalse, false_label);
+ else
+ ig.Emit (OpCodes.Brfalse, true_label);
+ }
+ }
+
+ bool left_is_null = left is NullLiteral;
+ bool right_is_null = right is NullLiteral;
+ if (left_is_null || right_is_null) {
+ if (((Oper == Binary.Operator.Equality) && (left_is_null == right_is_null)) ||
+ ((Oper == Binary.Operator.Inequality) && (left_is_null != right_is_null)))
+ ig.Emit (OpCodes.Br, true_label);
+ else
+ ig.Emit (OpCodes.Br, false_label);
+ } else {
+ underlying.Emit (ec);
+ ig.Emit (OpCodes.Br, end_label);
+ }
+
+ ig.MarkLabel (false_label);
+ ig.Emit (OpCodes.Ldc_I4_0);
+ ig.Emit (OpCodes.Br, end_label);
+
+ ig.MarkLabel (true_label);
+ ig.Emit (OpCodes.Ldc_I4_1);
+
+ ig.MarkLabel (end_label);
+ }
+
+ void EmitComparision (EmitContext ec)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label is_null_label = ig.DefineLabel ();
+ Label end_label = ig.DefineLabel ();
+
+ if (left_unwrap != null) {
+ left_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brfalse, is_null_label);
+ }
+
+ if (right_unwrap != null) {
+ right_unwrap.EmitCheck (ec);
+ ig.Emit (OpCodes.Brfalse, is_null_label);
+ }
+
+ underlying.Emit (ec);
+ ig.Emit (OpCodes.Br, end_label);
+
+ ig.MarkLabel (is_null_label);
+ ig.Emit (OpCodes.Ldc_I4_0);
+
+ ig.MarkLabel (end_label);
+ }
+