2010-04-07 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Core / System.Linq.Expressions / BinaryExpression.cs
blob569299e8fbdcb2277abe5241e23d55e7e2538735
1 //
2 // BinaryExpression.cs
3 //
4 // Author:
5 // Jb Evain (jbevain@novell.com)
6 // Miguel de Icaza (miguel@novell.com)
7 //
8 // Contains code from the Mono C# compiler:
9 // Marek Safar (marek.safar@seznam.cz)
10 // Martin Baulig (martin@ximian.com)
11 // Raja Harinath (harinath@gmail.com)
13 // (C) 2001-2003 Ximian, Inc.
14 // (C) 2004-2008 Novell, Inc. (http://www.novell.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System;
37 using System.Reflection;
38 using System.Reflection.Emit;
40 namespace System.Linq.Expressions {
42 public sealed class BinaryExpression : Expression {
44 Expression left;
45 Expression right;
46 LambdaExpression conversion;
47 MethodInfo method;
48 bool lift_to_null, is_lifted;
50 public Expression Left {
51 get { return left; }
54 public Expression Right {
55 get { return right; }
58 public MethodInfo Method {
59 get { return method; }
62 public bool IsLifted {
63 get { return is_lifted; }
66 public bool IsLiftedToNull {
67 get { return lift_to_null; }
70 public LambdaExpression Conversion {
71 get { return conversion; }
74 internal BinaryExpression (ExpressionType node_type, Type type, Expression left, Expression right)
75 : base (node_type, type)
77 this.left = left;
78 this.right = right;
81 internal BinaryExpression (ExpressionType node_type, Type type, Expression left, Expression right, MethodInfo method)
82 : base (node_type, type)
84 this.left = left;
85 this.right = right;
86 this.method = method;
89 internal BinaryExpression (ExpressionType node_type, Type type, Expression left, Expression right, bool lift_to_null,
90 bool is_lifted, MethodInfo method, LambdaExpression conversion) : base (node_type, type)
92 this.left = left;
93 this.right = right;
94 this.method = method;
95 this.conversion = conversion;
96 this.lift_to_null = lift_to_null;
97 this.is_lifted = is_lifted;
100 void EmitArrayAccess (EmitContext ec)
102 left.Emit (ec);
103 right.Emit (ec);
104 ec.ig.Emit (OpCodes.Ldelem, this.Type);
107 void EmitLogicalBinary (EmitContext ec)
109 switch (NodeType) {
110 case ExpressionType.And:
111 case ExpressionType.Or:
112 if (!IsLifted)
113 EmitLogical (ec);
114 else if (Type == typeof (bool?))
115 EmitLiftedLogical (ec);
116 else
117 EmitLiftedArithmeticBinary (ec);
118 break;
119 case ExpressionType.AndAlso:
120 case ExpressionType.OrElse:
121 if (!IsLifted)
122 EmitLogicalShortCircuit (ec);
123 else
124 EmitLiftedLogicalShortCircuit (ec);
125 break;
129 void EmitLogical (EmitContext ec)
131 EmitNonLiftedBinary (ec);
134 void EmitLiftedLogical (EmitContext ec)
136 var ig = ec.ig;
137 var and = NodeType == ExpressionType.And;
138 var left = ec.EmitStored (this.left);
139 var right = ec.EmitStored (this.right);
141 var ret_from_left = ig.DefineLabel ();
142 var ret_from_right = ig.DefineLabel ();
143 var done = ig.DefineLabel ();
145 ec.EmitNullableGetValueOrDefault (left);
146 ig.Emit (OpCodes.Brtrue, ret_from_left);
147 ec.EmitNullableGetValueOrDefault (right);
148 ig.Emit (OpCodes.Brtrue, ret_from_right);
150 ec.EmitNullableHasValue (left);
151 ig.Emit (OpCodes.Brfalse, ret_from_left);
153 ig.MarkLabel (ret_from_right);
154 ec.EmitLoad (and ? left : right);
155 ig.Emit (OpCodes.Br, done);
157 ig.MarkLabel (ret_from_left);
158 ec.EmitLoad (and ? right : left);
160 ig.MarkLabel (done);
163 void EmitLogicalShortCircuit (EmitContext ec)
165 var ig = ec.ig;
166 var and = NodeType == ExpressionType.AndAlso;
167 var ret = ig.DefineLabel ();
168 var done = ig.DefineLabel ();
170 ec.Emit (left);
171 ig.Emit (and ? OpCodes.Brfalse : OpCodes.Brtrue, ret);
173 ec.Emit (right);
175 ig.Emit (OpCodes.Br, done);
177 ig.MarkLabel (ret);
178 ig.Emit (and ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
180 ig.MarkLabel (done);
183 MethodInfo GetFalseOperator ()
185 return GetFalseOperator (left.Type.GetNotNullableType ());
188 MethodInfo GetTrueOperator ()
190 return GetTrueOperator (left.Type.GetNotNullableType ());
193 void EmitUserDefinedLogicalShortCircuit (EmitContext ec)
195 var ig = ec.ig;
196 var and = NodeType == ExpressionType.AndAlso;
198 var done = ig.DefineLabel ();
200 var left = ec.EmitStored (this.left);
202 ec.EmitLoad (left);
203 ig.Emit (OpCodes.Dup);
204 ec.EmitCall (and ? GetFalseOperator () : GetTrueOperator ());
205 ig.Emit (OpCodes.Brtrue, done);
207 ec.Emit (this.right);
208 ec.EmitCall (method);
210 ig.MarkLabel (done);
213 void EmitLiftedLogicalShortCircuit (EmitContext ec)
215 var ig = ec.ig;
216 var and = NodeType == ExpressionType.AndAlso;
217 var left_is_null = ig.DefineLabel ();
218 var ret_from_left = ig.DefineLabel ();
219 var ret_null = ig.DefineLabel ();
220 var ret_new = ig.DefineLabel();
221 var done = ig.DefineLabel();
223 var left = ec.EmitStored (this.left);
225 ec.EmitNullableHasValue (left);
226 ig.Emit (OpCodes.Brfalse, left_is_null);
228 ec.EmitNullableGetValueOrDefault (left);
230 ig.Emit (OpCodes.Ldc_I4_0);
231 ig.Emit (OpCodes.Ceq);
232 ig.Emit (and ? OpCodes.Brtrue : OpCodes.Brfalse, ret_from_left);
234 ig.MarkLabel (left_is_null);
235 var right = ec.EmitStored (this.right);
237 ec.EmitNullableHasValue (right);
238 ig.Emit (OpCodes.Brfalse_S, ret_null);
240 ec.EmitNullableGetValueOrDefault (right);
242 ig.Emit (OpCodes.Ldc_I4_0);
243 ig.Emit (OpCodes.Ceq);
245 ig.Emit (and ? OpCodes.Brtrue : OpCodes.Brfalse, ret_from_left);
247 ec.EmitNullableHasValue (left);
248 ig.Emit (OpCodes.Brfalse, ret_null);
250 ig.Emit (and ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
251 ig.Emit (OpCodes.Br_S, ret_new);
253 ig.MarkLabel (ret_from_left);
254 ig.Emit (and ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
256 ig.MarkLabel (ret_new);
257 ec.EmitNullableNew (Type);
258 ig.Emit (OpCodes.Br, done);
260 ig.MarkLabel (ret_null);
261 var ret = ig.DeclareLocal (Type);
262 ec.EmitNullableInitialize (ret);
264 ig.MarkLabel (done);
267 void EmitCoalesce (EmitContext ec)
269 var ig = ec.ig;
270 var done = ig.DefineLabel ();
271 var load_right = ig.DefineLabel ();
273 var left = ec.EmitStored (this.left);
274 var left_is_nullable = left.LocalType.IsNullable ();
276 if (left_is_nullable)
277 ec.EmitNullableHasValue (left);
278 else
279 ec.EmitLoad (left);
281 ig.Emit (OpCodes.Brfalse, load_right);
283 if (left_is_nullable && !Type.IsNullable ())
284 ec.EmitNullableGetValue (left);
285 else
286 ec.EmitLoad (left);
288 ig.Emit (OpCodes.Br, done);
290 ig.MarkLabel (load_right);
291 ec.Emit (this.right);
293 ig.MarkLabel (done);
296 void EmitConvertedCoalesce (EmitContext ec)
298 var ig = ec.ig;
299 var done = ig.DefineLabel ();
300 var load_right = ig.DefineLabel ();
302 var left = ec.EmitStored (this.left);
304 if (left.LocalType.IsNullable ())
305 ec.EmitNullableHasValue (left);
306 else
307 ec.EmitLoad (left);
309 ig.Emit (OpCodes.Brfalse, load_right);
311 ec.Emit (conversion);
312 ec.EmitLoad (left);
313 ig.Emit (OpCodes.Callvirt, conversion.Type.GetInvokeMethod ());
315 ig.Emit (OpCodes.Br, done);
317 ig.MarkLabel (load_right);
318 ec.Emit (this.right);
320 ig.MarkLabel (done);
323 static bool IsInt32OrInt64 (Type type)
325 return type == typeof (int) || type == typeof (long);
328 static bool IsSingleOrDouble (Type type)
330 return type == typeof (float) || type == typeof (double);
333 void EmitBinaryOperator (EmitContext ec)
335 var ig = ec.ig;
336 bool is_unsigned = IsUnsigned (left.Type);
338 switch (NodeType) {
339 case ExpressionType.Add:
340 ig.Emit (OpCodes.Add);
341 break;
342 case ExpressionType.AddChecked:
343 if (IsInt32OrInt64 (left.Type))
344 ig.Emit (OpCodes.Add_Ovf);
345 else
346 ig.Emit (is_unsigned ? OpCodes.Add_Ovf_Un : OpCodes.Add);
347 break;
348 case ExpressionType.Subtract:
349 ig.Emit (OpCodes.Sub);
350 break;
351 case ExpressionType.SubtractChecked:
352 if (IsInt32OrInt64 (left.Type))
353 ig.Emit (OpCodes.Sub_Ovf);
354 else
355 ig.Emit (is_unsigned ? OpCodes.Sub_Ovf_Un : OpCodes.Sub);
356 break;
357 case ExpressionType.Multiply:
358 ig.Emit (OpCodes.Mul);
359 break;
360 case ExpressionType.MultiplyChecked:
361 if (IsInt32OrInt64 (left.Type))
362 ig.Emit (OpCodes.Mul_Ovf);
363 else
364 ig.Emit (is_unsigned ? OpCodes.Mul_Ovf_Un : OpCodes.Mul);
365 break;
366 case ExpressionType.Divide:
367 ig.Emit (is_unsigned ? OpCodes.Div_Un : OpCodes.Div);
368 break;
369 case ExpressionType.Modulo:
370 ig.Emit (is_unsigned ? OpCodes.Rem_Un : OpCodes.Rem);
371 break;
372 case ExpressionType.RightShift:
373 case ExpressionType.LeftShift:
374 ig.Emit (OpCodes.Ldc_I4, left.Type == typeof (int) ? 0x1f : 0x3f);
375 ig.Emit (OpCodes.And);
376 if (NodeType == ExpressionType.RightShift)
377 ig.Emit (is_unsigned ? OpCodes.Shr_Un : OpCodes.Shr);
378 else
379 ig.Emit (OpCodes.Shl);
380 break;
381 case ExpressionType.And:
382 ig.Emit (OpCodes.And);
383 break;
384 case ExpressionType.Or:
385 ig.Emit (OpCodes.Or);
386 break;
387 case ExpressionType.ExclusiveOr:
388 ig.Emit (OpCodes.Xor);
389 break;
390 case ExpressionType.GreaterThan:
391 ig.Emit (is_unsigned ? OpCodes.Cgt_Un : OpCodes.Cgt);
392 break;
393 case ExpressionType.GreaterThanOrEqual:
394 if (is_unsigned || IsSingleOrDouble (left.Type))
395 ig.Emit (OpCodes.Clt_Un);
396 else
397 ig.Emit (OpCodes.Clt);
399 ig.Emit (OpCodes.Ldc_I4_0);
400 ig.Emit (OpCodes.Ceq);
401 break;
402 case ExpressionType.LessThan:
403 ig.Emit (is_unsigned ? OpCodes.Clt_Un : OpCodes.Clt);
404 break;
405 case ExpressionType.LessThanOrEqual:
406 if (is_unsigned || IsSingleOrDouble (left.Type))
407 ig.Emit (OpCodes.Cgt_Un);
408 else
409 ig.Emit (OpCodes.Cgt);
411 ig.Emit (OpCodes.Ldc_I4_0);
412 ig.Emit (OpCodes.Ceq);
413 break;
414 case ExpressionType.Equal:
415 ig.Emit (OpCodes.Ceq);
416 break;
417 case ExpressionType.NotEqual:
418 ig.Emit (OpCodes.Ceq);
419 ig.Emit (OpCodes.Ldc_I4_0);
420 ig.Emit (OpCodes.Ceq);
421 break;
422 case ExpressionType.Power:
423 ig.Emit (OpCodes.Call, typeof (Math).GetMethod ("Pow"));
424 break;
425 default:
426 throw new InvalidOperationException (
427 string.Format ("Internal error: BinaryExpression contains non-Binary nodetype {0}", NodeType));
431 bool IsLeftLiftedBinary ()
433 return left.Type.IsNullable () && !right.Type.IsNullable ();
436 void EmitLeftLiftedToNullBinary (EmitContext ec)
438 var ig = ec.ig;
440 var ret = ig.DefineLabel ();
441 var done = ig.DefineLabel ();
443 var left = ec.EmitStored (this.left);
445 ec.EmitNullableHasValue (left);
446 ig.Emit (OpCodes.Brfalse, ret);
448 ec.EmitNullableGetValueOrDefault (left);
449 ec.Emit (right);
451 EmitBinaryOperator (ec);
453 ec.EmitNullableNew (Type);
455 ig.Emit (OpCodes.Br, done);
457 ig.MarkLabel (ret);
459 var temp = ig.DeclareLocal (Type);
460 ec.EmitNullableInitialize (temp);
462 ig.MarkLabel (done);
465 void EmitLiftedArithmeticBinary (EmitContext ec)
467 if (IsLeftLiftedBinary ())
468 EmitLeftLiftedToNullBinary (ec);
469 else
470 EmitLiftedToNullBinary (ec);
473 void EmitLiftedToNullBinary (EmitContext ec)
475 var ig = ec.ig;
476 var left = ec.EmitStored (this.left);
477 var right = ec.EmitStored (this.right);
478 var result = ig.DeclareLocal (Type);
480 var has_value = ig.DefineLabel ();
481 var done = ig.DefineLabel ();
483 ec.EmitNullableHasValue (left);
484 ec.EmitNullableHasValue (right);
485 ig.Emit (OpCodes.And);
486 ig.Emit (OpCodes.Brtrue, has_value);
488 ec.EmitNullableInitialize (result);
490 ig.Emit (OpCodes.Br, done);
492 ig.MarkLabel (has_value);
494 ec.EmitNullableGetValueOrDefault (left);
495 ec.EmitNullableGetValueOrDefault (right);
497 EmitBinaryOperator (ec);
499 ec.EmitNullableNew (result.LocalType);
501 ig.MarkLabel (done);
504 void EmitLiftedRelationalBinary (EmitContext ec)
506 var ig = ec.ig;
507 var left = ec.EmitStored (this.left);
508 var right = ec.EmitStored (this.right);
510 var ret = ig.DefineLabel ();
511 var done = ig.DefineLabel ();
513 ec.EmitNullableGetValueOrDefault (left);
514 ec.EmitNullableGetValueOrDefault (right);
516 switch (NodeType) {
517 case ExpressionType.Equal:
518 case ExpressionType.NotEqual:
519 ig.Emit (OpCodes.Bne_Un, ret);
520 break;
521 default:
522 EmitBinaryOperator (ec);
523 ig.Emit (OpCodes.Brfalse, ret);
524 break;
527 ec.EmitNullableHasValue (left);
528 ec.EmitNullableHasValue (right);
530 switch (NodeType) {
531 case ExpressionType.Equal:
532 ig.Emit (OpCodes.Ceq);
533 break;
534 case ExpressionType.NotEqual:
535 ig.Emit (OpCodes.Ceq);
536 ig.Emit (OpCodes.Ldc_I4_0);
537 ig.Emit (OpCodes.Ceq);
538 break;
539 default:
540 ig.Emit (OpCodes.And);
541 break;
544 ig.Emit (OpCodes.Br, done);
546 ig.MarkLabel (ret);
548 ig.Emit (NodeType == ExpressionType.NotEqual ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
550 ig.MarkLabel (done);
553 void EmitArithmeticBinary (EmitContext ec)
555 if (!IsLifted)
556 EmitNonLiftedBinary (ec);
557 else
558 EmitLiftedArithmeticBinary (ec);
561 void EmitNonLiftedBinary (EmitContext ec)
563 ec.Emit (left);
564 ec.Emit (right);
565 EmitBinaryOperator (ec);
568 void EmitRelationalBinary (EmitContext ec)
570 if (!IsLifted)
571 EmitNonLiftedBinary (ec);
572 else if (IsLiftedToNull)
573 EmitLiftedToNullBinary (ec);
574 else
575 EmitLiftedRelationalBinary (ec);
578 void EmitLiftedUserDefinedOperator (EmitContext ec)
580 var ig = ec.ig;
582 var ret_true = ig.DefineLabel ();
583 var ret_false = ig.DefineLabel ();
584 var done = ig.DefineLabel ();
586 var left = ec.EmitStored (this.left);
587 var right = ec.EmitStored (this.right);
589 ec.EmitNullableHasValue (left);
590 ec.EmitNullableHasValue (right);
591 switch (NodeType) {
592 case ExpressionType.Equal:
593 ig.Emit (OpCodes.Bne_Un, ret_false);
594 ec.EmitNullableHasValue (left);
595 ig.Emit (OpCodes.Brfalse, ret_true);
596 break;
597 case ExpressionType.NotEqual:
598 ig.Emit (OpCodes.Bne_Un, ret_true);
599 ec.EmitNullableHasValue (left);
600 ig.Emit (OpCodes.Brfalse, ret_false);
601 break;
602 default:
603 ig.Emit (OpCodes.And);
604 ig.Emit (OpCodes.Brfalse, ret_false);
605 break;
608 ec.EmitNullableGetValueOrDefault (left);
609 ec.EmitNullableGetValueOrDefault (right);
610 ec.EmitCall (method);
611 ig.Emit (OpCodes.Br, done);
613 ig.MarkLabel (ret_true);
614 ig.Emit (OpCodes.Ldc_I4_1);
615 ig.Emit (OpCodes.Br, done);
617 ig.MarkLabel (ret_false);
618 ig.Emit (OpCodes.Ldc_I4_0);
619 ig.Emit (OpCodes.Br, done);
621 ig.MarkLabel (done);
624 void EmitLiftedToNullUserDefinedOperator (EmitContext ec)
626 var ig = ec.ig;
628 var ret = ig.DefineLabel ();
629 var done = ig.DefineLabel ();
631 var left = ec.EmitStored (this.left);
632 var right = ec.EmitStored (this.right);
634 ec.EmitNullableHasValue (left);
635 ec.EmitNullableHasValue (right);
636 ig.Emit (OpCodes.And);
637 ig.Emit (OpCodes.Brfalse, ret);
639 ec.EmitNullableGetValueOrDefault (left);
640 ec.EmitNullableGetValueOrDefault (right);
641 ec.EmitCall (method);
642 ec.EmitNullableNew (Type);
643 ig.Emit (OpCodes.Br, done);
645 ig.MarkLabel (ret);
646 var temp = ig.DeclareLocal (Type);
647 ec.EmitNullableInitialize (temp);
649 ig.MarkLabel (done);
652 void EmitUserDefinedLiftedLogicalShortCircuit (EmitContext ec)
654 var ig = ec.ig;
655 var and = NodeType == ExpressionType.AndAlso;
657 var left_is_null = ig.DefineLabel ();
658 var ret_left = ig.DefineLabel ();
659 var ret_null = ig.DefineLabel ();
660 var done = ig.DefineLabel ();
662 var left = ec.EmitStored (this.left);
664 ec.EmitNullableHasValue (left);
665 ig.Emit (OpCodes.Brfalse, and ? ret_null : left_is_null);
667 ec.EmitNullableGetValueOrDefault (left);
668 ec.EmitCall (and ? GetFalseOperator () : GetTrueOperator ());
669 ig.Emit (OpCodes.Brtrue, ret_left);
671 ig.MarkLabel (left_is_null);
672 var right = ec.EmitStored (this.right);
673 ec.EmitNullableHasValue (right);
674 ig.Emit (OpCodes.Brfalse, ret_null);
676 ec.EmitNullableGetValueOrDefault (left);
677 ec.EmitNullableGetValueOrDefault (right);
678 ec.EmitCall (method);
680 ec.EmitNullableNew (Type);
681 ig.Emit (OpCodes.Br, done);
683 ig.MarkLabel (ret_left);
684 ec.EmitLoad (left);
685 ig.Emit (OpCodes.Br, done);
687 ig.MarkLabel (ret_null);
688 var ret = ig.DeclareLocal (Type);
689 ec.EmitNullableInitialize (ret);
691 ig.MarkLabel (done);
694 void EmitUserDefinedOperator (EmitContext ec)
696 if (!IsLifted) {
697 switch (NodeType) {
698 case ExpressionType.AndAlso:
699 case ExpressionType.OrElse:
700 EmitUserDefinedLogicalShortCircuit (ec);
701 break;
702 default:
703 left.Emit (ec);
704 right.Emit (ec);
705 ec.EmitCall (method);
706 break;
708 } else if (IsLiftedToNull) {
709 switch (NodeType) {
710 case ExpressionType.AndAlso:
711 case ExpressionType.OrElse:
712 EmitUserDefinedLiftedLogicalShortCircuit (ec);
713 break;
714 default:
715 EmitLiftedToNullUserDefinedOperator (ec);
716 break;
718 } else
719 EmitLiftedUserDefinedOperator (ec);
722 internal override void Emit (EmitContext ec)
724 if (method != null) {
725 EmitUserDefinedOperator (ec);
726 return;
729 switch (NodeType){
730 case ExpressionType.ArrayIndex:
731 EmitArrayAccess (ec);
732 return;
733 case ExpressionType.Coalesce:
734 if (conversion != null)
735 EmitConvertedCoalesce (ec);
736 else
737 EmitCoalesce (ec);
738 return;
739 case ExpressionType.Power:
740 case ExpressionType.Add:
741 case ExpressionType.AddChecked:
742 case ExpressionType.Divide:
743 case ExpressionType.ExclusiveOr:
744 case ExpressionType.LeftShift:
745 case ExpressionType.Modulo:
746 case ExpressionType.Multiply:
747 case ExpressionType.MultiplyChecked:
748 case ExpressionType.RightShift:
749 case ExpressionType.Subtract:
750 case ExpressionType.SubtractChecked:
751 EmitArithmeticBinary (ec);
752 return;
753 case ExpressionType.Equal:
754 case ExpressionType.GreaterThan:
755 case ExpressionType.GreaterThanOrEqual:
756 case ExpressionType.LessThan:
757 case ExpressionType.LessThanOrEqual:
758 case ExpressionType.NotEqual:
759 EmitRelationalBinary (ec);
760 return;
761 case ExpressionType.And:
762 case ExpressionType.Or:
763 case ExpressionType.AndAlso:
764 case ExpressionType.OrElse:
765 EmitLogicalBinary (ec);
766 return;
767 default:
768 throw new NotSupportedException (this.NodeType.ToString ());