2009-11-02 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / cfold.cs
blob7091a1fba7da652c9b23d3421f59db3f10c0d0e6
1 //
2 // cfold.cs: Constant Folding
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2008, Novell, Inc.
10 //
11 using System;
13 namespace Mono.CSharp {
15 public class ConstantFold {
17 public static readonly Type[] binary_promotions = new Type[] {
18 TypeManager.decimal_type, TypeManager.double_type, TypeManager.float_type,
19 TypeManager.uint64_type, TypeManager.int64_type, TypeManager.uint32_type };
22 // Performs the numeric promotions on the left and right expresions
23 // and deposits the results on `lc' and `rc'.
25 // On success, the types of `lc' and `rc' on output will always match,
26 // and the pair will be one of:
28 // TODO: BinaryFold should be called as an optimization step only,
29 // error checking here is weak
30 //
31 static bool DoBinaryNumericPromotions (ref Constant left, ref Constant right)
33 Type ltype = left.Type;
34 Type rtype = right.Type;
36 foreach (Type t in binary_promotions) {
37 if (t == ltype)
38 return t == rtype || ConvertPromotion (ref right, ref left, t);
40 if (t == rtype)
41 return t == ltype || ConvertPromotion (ref left, ref right, t);
44 left = left.ConvertImplicitly (TypeManager.int32_type);
45 right = right.ConvertImplicitly (TypeManager.int32_type);
46 return left != null && right != null;
49 static bool ConvertPromotion (ref Constant prim, ref Constant second, Type type)
51 Constant c = prim.ConvertImplicitly (type);
52 if (c != null) {
53 prim = c;
54 return true;
57 if (type == TypeManager.uint32_type) {
58 type = TypeManager.int64_type;
59 prim = prim.ConvertImplicitly (type);
60 second = second.ConvertImplicitly (type);
61 return prim != null && second != null;
64 return false;
67 internal static void Error_CompileTimeOverflow (ResolveContext rc, Location loc)
69 rc.Report.Error (220, loc, "The operation overflows at compile time in checked mode");
72 /// <summary>
73 /// Constant expression folder for binary operations.
74 ///
75 /// Returns null if the expression can not be folded.
76 /// </summary>
77 static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper,
78 Constant left, Constant right, Location loc)
80 Constant result = null;
82 if (left is EmptyConstantCast)
83 return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
85 if (left is SideEffectConstant) {
86 result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc);
87 if (result == null)
88 return null;
89 return new SideEffectConstant (result, left, loc);
92 if (right is EmptyConstantCast)
93 return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
95 if (right is SideEffectConstant) {
96 result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc);
97 if (result == null)
98 return null;
99 return new SideEffectConstant (result, right, loc);
102 Type lt = left.Type;
103 Type rt = right.Type;
104 bool bool_res;
106 if (lt == TypeManager.bool_type && lt == rt) {
107 bool lv = (bool) left.GetValue ();
108 bool rv = (bool) right.GetValue ();
109 switch (oper) {
110 case Binary.Operator.BitwiseAnd:
111 case Binary.Operator.LogicalAnd:
112 return new BoolConstant (lv && rv, left.Location);
113 case Binary.Operator.BitwiseOr:
114 case Binary.Operator.LogicalOr:
115 return new BoolConstant (lv || rv, left.Location);
116 case Binary.Operator.ExclusiveOr:
117 return new BoolConstant (lv ^ rv, left.Location);
118 case Binary.Operator.Equality:
119 return new BoolConstant (lv == rv, left.Location);
120 case Binary.Operator.Inequality:
121 return new BoolConstant (lv != rv, left.Location);
123 return null;
127 // During an enum evaluation, none of the rules are valid
128 // Not sure whether it is bug in csc or in documentation
130 if (ec.HasSet (ResolveContext.Options.EnumScope)){
131 if (left is EnumConstant)
132 left = ((EnumConstant) left).Child;
134 if (right is EnumConstant)
135 right = ((EnumConstant) right).Child;
136 } else if (left is EnumConstant && rt == lt) {
137 switch (oper){
139 /// E operator |(E x, E y);
140 /// E operator &(E x, E y);
141 /// E operator ^(E x, E y);
142 ///
143 case Binary.Operator.BitwiseOr:
144 case Binary.Operator.BitwiseAnd:
145 case Binary.Operator.ExclusiveOr:
146 return BinaryFold (ec, oper, ((EnumConstant)left).Child,
147 ((EnumConstant)right).Child, loc).TryReduce (ec, lt, loc);
150 /// U operator -(E x, E y);
151 ///
152 case Binary.Operator.Subtraction:
153 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
154 return result.TryReduce (ec, ((EnumConstant)left).Child.Type, loc);
157 /// bool operator ==(E x, E y);
158 /// bool operator !=(E x, E y);
159 /// bool operator <(E x, E y);
160 /// bool operator >(E x, E y);
161 /// bool operator <=(E x, E y);
162 /// bool operator >=(E x, E y);
163 ///
164 case Binary.Operator.Equality:
165 case Binary.Operator.Inequality:
166 case Binary.Operator.LessThan:
167 case Binary.Operator.GreaterThan:
168 case Binary.Operator.LessThanOrEqual:
169 case Binary.Operator.GreaterThanOrEqual:
170 return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
172 return null;
175 switch (oper){
176 case Binary.Operator.BitwiseOr:
177 if (!DoBinaryNumericPromotions (ref left, ref right))
178 return null;
180 if (left is IntConstant){
181 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
183 return new IntConstant (res, left.Location);
185 if (left is UIntConstant){
186 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
188 return new UIntConstant (res, left.Location);
190 if (left is LongConstant){
191 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
193 return new LongConstant (res, left.Location);
195 if (left is ULongConstant){
196 ulong res = ((ULongConstant)left).Value |
197 ((ULongConstant)right).Value;
199 return new ULongConstant (res, left.Location);
201 break;
203 case Binary.Operator.BitwiseAnd:
204 if (!DoBinaryNumericPromotions (ref left, ref right))
205 return null;
208 /// int operator &(int x, int y);
209 /// uint operator &(uint x, uint y);
210 /// long operator &(long x, long y);
211 /// ulong operator &(ulong x, ulong y);
213 if (left is IntConstant){
214 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
215 return new IntConstant (res, left.Location);
217 if (left is UIntConstant){
218 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
219 return new UIntConstant (res, left.Location);
221 if (left is LongConstant){
222 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
223 return new LongConstant (res, left.Location);
225 if (left is ULongConstant){
226 ulong res = ((ULongConstant)left).Value &
227 ((ULongConstant)right).Value;
229 return new ULongConstant (res, left.Location);
231 break;
233 case Binary.Operator.ExclusiveOr:
234 if (!DoBinaryNumericPromotions (ref left, ref right))
235 return null;
237 if (left is IntConstant){
238 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
239 return new IntConstant (res, left.Location);
241 if (left is UIntConstant){
242 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
244 return new UIntConstant (res, left.Location);
246 if (left is LongConstant){
247 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
249 return new LongConstant (res, left.Location);
251 if (left is ULongConstant){
252 ulong res = ((ULongConstant)left).Value ^
253 ((ULongConstant)right).Value;
255 return new ULongConstant (res, left.Location);
257 break;
259 case Binary.Operator.Addition:
260 if (lt == TypeManager.null_type)
261 return right;
263 if (rt == TypeManager.null_type)
264 return left;
267 // If both sides are strings, then concatenate, if
268 // one is a string, and the other is not, then defer
269 // to runtime concatenation
271 if (lt == TypeManager.string_type || rt == TypeManager.string_type){
272 if (lt == rt)
273 return new StringConstant ((string)left.GetValue () + (string)right.GetValue (),
274 left.Location);
276 return null;
280 // handle "E operator + (E x, U y)"
281 // handle "E operator + (Y y, E x)"
283 EnumConstant lc = left as EnumConstant;
284 EnumConstant rc = right as EnumConstant;
285 if (lc != null || rc != null){
286 if (lc == null) {
287 lc = rc;
288 lt = lc.Type;
289 right = left;
292 // U has to be implicitly convetible to E.base
293 right = right.ConvertImplicitly (lc.Child.Type);
294 if (right == null)
295 return null;
297 result = BinaryFold (ec, oper, lc.Child, right, loc);
298 if (result == null)
299 return null;
301 result = result.TryReduce (ec, lt, loc);
302 if (result == null)
303 return null;
305 return new EnumConstant (result, lt);
308 if (!DoBinaryNumericPromotions (ref left, ref right))
309 return null;
311 try {
312 if (left is DoubleConstant){
313 double res;
315 if (ec.ConstantCheckState)
316 res = checked (((DoubleConstant) left).Value +
317 ((DoubleConstant) right).Value);
318 else
319 res = unchecked (((DoubleConstant) left).Value +
320 ((DoubleConstant) right).Value);
322 return new DoubleConstant (res, left.Location);
324 if (left is FloatConstant){
325 float res;
327 if (ec.ConstantCheckState)
328 res = checked (((FloatConstant) left).Value +
329 ((FloatConstant) right).Value);
330 else
331 res = unchecked (((FloatConstant) left).Value +
332 ((FloatConstant) right).Value);
334 result = new FloatConstant (res, left.Location);
335 } else if (left is ULongConstant){
336 ulong res;
338 if (ec.ConstantCheckState)
339 res = checked (((ULongConstant) left).Value +
340 ((ULongConstant) right).Value);
341 else
342 res = unchecked (((ULongConstant) left).Value +
343 ((ULongConstant) right).Value);
345 result = new ULongConstant (res, left.Location);
346 } else if (left is LongConstant){
347 long res;
349 if (ec.ConstantCheckState)
350 res = checked (((LongConstant) left).Value +
351 ((LongConstant) right).Value);
352 else
353 res = unchecked (((LongConstant) left).Value +
354 ((LongConstant) right).Value);
356 result = new LongConstant (res, left.Location);
357 } else if (left is UIntConstant){
358 uint res;
360 if (ec.ConstantCheckState)
361 res = checked (((UIntConstant) left).Value +
362 ((UIntConstant) right).Value);
363 else
364 res = unchecked (((UIntConstant) left).Value +
365 ((UIntConstant) right).Value);
367 result = new UIntConstant (res, left.Location);
368 } else if (left is IntConstant){
369 int res;
371 if (ec.ConstantCheckState)
372 res = checked (((IntConstant) left).Value +
373 ((IntConstant) right).Value);
374 else
375 res = unchecked (((IntConstant) left).Value +
376 ((IntConstant) right).Value);
378 result = new IntConstant (res, left.Location);
379 } else if (left is DecimalConstant) {
380 decimal res;
382 if (ec.ConstantCheckState)
383 res = checked (((DecimalConstant) left).Value +
384 ((DecimalConstant) right).Value);
385 else
386 res = unchecked (((DecimalConstant) left).Value +
387 ((DecimalConstant) right).Value);
389 result = new DecimalConstant (res, left.Location);
391 } catch (OverflowException){
392 Error_CompileTimeOverflow (ec, loc);
395 return result;
397 case Binary.Operator.Subtraction:
399 // handle "E operator - (E x, U y)"
400 // handle "E operator - (Y y, E x)"
402 lc = left as EnumConstant;
403 rc = right as EnumConstant;
404 if (lc != null || rc != null){
405 if (lc == null) {
406 lc = rc;
407 lt = lc.Type;
408 right = left;
411 // U has to be implicitly convetible to E.base
412 right = right.ConvertImplicitly (lc.Child.Type);
413 if (right == null)
414 return null;
416 result = BinaryFold (ec, oper, lc.Child, right, loc);
417 if (result == null)
418 return null;
420 result = result.TryReduce (ec, lt, loc);
421 if (result == null)
422 return null;
424 return new EnumConstant (result, lt);
427 if (!DoBinaryNumericPromotions (ref left, ref right))
428 return null;
430 try {
431 if (left is DoubleConstant){
432 double res;
434 if (ec.ConstantCheckState)
435 res = checked (((DoubleConstant) left).Value -
436 ((DoubleConstant) right).Value);
437 else
438 res = unchecked (((DoubleConstant) left).Value -
439 ((DoubleConstant) right).Value);
441 result = new DoubleConstant (res, left.Location);
442 } else if (left is FloatConstant){
443 float res;
445 if (ec.ConstantCheckState)
446 res = checked (((FloatConstant) left).Value -
447 ((FloatConstant) right).Value);
448 else
449 res = unchecked (((FloatConstant) left).Value -
450 ((FloatConstant) right).Value);
452 result = new FloatConstant (res, left.Location);
453 } else if (left is ULongConstant){
454 ulong res;
456 if (ec.ConstantCheckState)
457 res = checked (((ULongConstant) left).Value -
458 ((ULongConstant) right).Value);
459 else
460 res = unchecked (((ULongConstant) left).Value -
461 ((ULongConstant) right).Value);
463 result = new ULongConstant (res, left.Location);
464 } else if (left is LongConstant){
465 long res;
467 if (ec.ConstantCheckState)
468 res = checked (((LongConstant) left).Value -
469 ((LongConstant) right).Value);
470 else
471 res = unchecked (((LongConstant) left).Value -
472 ((LongConstant) right).Value);
474 result = new LongConstant (res, left.Location);
475 } else if (left is UIntConstant){
476 uint res;
478 if (ec.ConstantCheckState)
479 res = checked (((UIntConstant) left).Value -
480 ((UIntConstant) right).Value);
481 else
482 res = unchecked (((UIntConstant) left).Value -
483 ((UIntConstant) right).Value);
485 result = new UIntConstant (res, left.Location);
486 } else if (left is IntConstant){
487 int res;
489 if (ec.ConstantCheckState)
490 res = checked (((IntConstant) left).Value -
491 ((IntConstant) right).Value);
492 else
493 res = unchecked (((IntConstant) left).Value -
494 ((IntConstant) right).Value);
496 result = new IntConstant (res, left.Location);
497 } else if (left is DecimalConstant) {
498 decimal res;
500 if (ec.ConstantCheckState)
501 res = checked (((DecimalConstant) left).Value -
502 ((DecimalConstant) right).Value);
503 else
504 res = unchecked (((DecimalConstant) left).Value -
505 ((DecimalConstant) right).Value);
507 return new DecimalConstant (res, left.Location);
508 } else {
509 throw new Exception ( "Unexepected subtraction input: " + left);
511 } catch (OverflowException){
512 Error_CompileTimeOverflow (ec, loc);
515 return result;
517 case Binary.Operator.Multiply:
518 if (!DoBinaryNumericPromotions (ref left, ref right))
519 return null;
521 try {
522 if (left is DoubleConstant){
523 double res;
525 if (ec.ConstantCheckState)
526 res = checked (((DoubleConstant) left).Value *
527 ((DoubleConstant) right).Value);
528 else
529 res = unchecked (((DoubleConstant) left).Value *
530 ((DoubleConstant) right).Value);
532 return new DoubleConstant (res, left.Location);
533 } else if (left is FloatConstant){
534 float res;
536 if (ec.ConstantCheckState)
537 res = checked (((FloatConstant) left).Value *
538 ((FloatConstant) right).Value);
539 else
540 res = unchecked (((FloatConstant) left).Value *
541 ((FloatConstant) right).Value);
543 return new FloatConstant (res, left.Location);
544 } else if (left is ULongConstant){
545 ulong res;
547 if (ec.ConstantCheckState)
548 res = checked (((ULongConstant) left).Value *
549 ((ULongConstant) right).Value);
550 else
551 res = unchecked (((ULongConstant) left).Value *
552 ((ULongConstant) right).Value);
554 return new ULongConstant (res, left.Location);
555 } else if (left is LongConstant){
556 long res;
558 if (ec.ConstantCheckState)
559 res = checked (((LongConstant) left).Value *
560 ((LongConstant) right).Value);
561 else
562 res = unchecked (((LongConstant) left).Value *
563 ((LongConstant) right).Value);
565 return new LongConstant (res, left.Location);
566 } else if (left is UIntConstant){
567 uint res;
569 if (ec.ConstantCheckState)
570 res = checked (((UIntConstant) left).Value *
571 ((UIntConstant) right).Value);
572 else
573 res = unchecked (((UIntConstant) left).Value *
574 ((UIntConstant) right).Value);
576 return new UIntConstant (res, left.Location);
577 } else if (left is IntConstant){
578 int res;
580 if (ec.ConstantCheckState)
581 res = checked (((IntConstant) left).Value *
582 ((IntConstant) right).Value);
583 else
584 res = unchecked (((IntConstant) left).Value *
585 ((IntConstant) right).Value);
587 return new IntConstant (res, left.Location);
588 } else if (left is DecimalConstant) {
589 decimal res;
591 if (ec.ConstantCheckState)
592 res = checked (((DecimalConstant) left).Value *
593 ((DecimalConstant) right).Value);
594 else
595 res = unchecked (((DecimalConstant) left).Value *
596 ((DecimalConstant) right).Value);
598 return new DecimalConstant (res, left.Location);
599 } else {
600 throw new Exception ( "Unexepected multiply input: " + left);
602 } catch (OverflowException){
603 Error_CompileTimeOverflow (ec, loc);
605 break;
607 case Binary.Operator.Division:
608 if (!DoBinaryNumericPromotions (ref left, ref right))
609 return null;
611 try {
612 if (left is DoubleConstant){
613 double res;
615 if (ec.ConstantCheckState)
616 res = checked (((DoubleConstant) left).Value /
617 ((DoubleConstant) right).Value);
618 else
619 res = unchecked (((DoubleConstant) left).Value /
620 ((DoubleConstant) right).Value);
622 return new DoubleConstant (res, left.Location);
623 } else if (left is FloatConstant){
624 float res;
626 if (ec.ConstantCheckState)
627 res = checked (((FloatConstant) left).Value /
628 ((FloatConstant) right).Value);
629 else
630 res = unchecked (((FloatConstant) left).Value /
631 ((FloatConstant) right).Value);
633 return new FloatConstant (res, left.Location);
634 } else if (left is ULongConstant){
635 ulong res;
637 if (ec.ConstantCheckState)
638 res = checked (((ULongConstant) left).Value /
639 ((ULongConstant) right).Value);
640 else
641 res = unchecked (((ULongConstant) left).Value /
642 ((ULongConstant) right).Value);
644 return new ULongConstant (res, left.Location);
645 } else if (left is LongConstant){
646 long res;
648 if (ec.ConstantCheckState)
649 res = checked (((LongConstant) left).Value /
650 ((LongConstant) right).Value);
651 else
652 res = unchecked (((LongConstant) left).Value /
653 ((LongConstant) right).Value);
655 return new LongConstant (res, left.Location);
656 } else if (left is UIntConstant){
657 uint res;
659 if (ec.ConstantCheckState)
660 res = checked (((UIntConstant) left).Value /
661 ((UIntConstant) right).Value);
662 else
663 res = unchecked (((UIntConstant) left).Value /
664 ((UIntConstant) right).Value);
666 return new UIntConstant (res, left.Location);
667 } else if (left is IntConstant){
668 int res;
670 if (ec.ConstantCheckState)
671 res = checked (((IntConstant) left).Value /
672 ((IntConstant) right).Value);
673 else
674 res = unchecked (((IntConstant) left).Value /
675 ((IntConstant) right).Value);
677 return new IntConstant (res, left.Location);
678 } else if (left is DecimalConstant) {
679 decimal res;
681 if (ec.ConstantCheckState)
682 res = checked (((DecimalConstant) left).Value /
683 ((DecimalConstant) right).Value);
684 else
685 res = unchecked (((DecimalConstant) left).Value /
686 ((DecimalConstant) right).Value);
688 return new DecimalConstant (res, left.Location);
689 } else {
690 throw new Exception ( "Unexepected division input: " + left);
692 } catch (OverflowException){
693 Error_CompileTimeOverflow (ec, loc);
695 } catch (DivideByZeroException) {
696 ec.Report.Error (20, loc, "Division by constant zero");
699 break;
701 case Binary.Operator.Modulus:
702 if (!DoBinaryNumericPromotions (ref left, ref right))
703 return null;
705 try {
706 if (left is DoubleConstant){
707 double res;
709 if (ec.ConstantCheckState)
710 res = checked (((DoubleConstant) left).Value %
711 ((DoubleConstant) right).Value);
712 else
713 res = unchecked (((DoubleConstant) left).Value %
714 ((DoubleConstant) right).Value);
716 return new DoubleConstant (res, left.Location);
717 } else if (left is FloatConstant){
718 float res;
720 if (ec.ConstantCheckState)
721 res = checked (((FloatConstant) left).Value %
722 ((FloatConstant) right).Value);
723 else
724 res = unchecked (((FloatConstant) left).Value %
725 ((FloatConstant) right).Value);
727 return new FloatConstant (res, left.Location);
728 } else if (left is ULongConstant){
729 ulong res;
731 if (ec.ConstantCheckState)
732 res = checked (((ULongConstant) left).Value %
733 ((ULongConstant) right).Value);
734 else
735 res = unchecked (((ULongConstant) left).Value %
736 ((ULongConstant) right).Value);
738 return new ULongConstant (res, left.Location);
739 } else if (left is LongConstant){
740 long res;
742 if (ec.ConstantCheckState)
743 res = checked (((LongConstant) left).Value %
744 ((LongConstant) right).Value);
745 else
746 res = unchecked (((LongConstant) left).Value %
747 ((LongConstant) right).Value);
749 return new LongConstant (res, left.Location);
750 } else if (left is UIntConstant){
751 uint res;
753 if (ec.ConstantCheckState)
754 res = checked (((UIntConstant) left).Value %
755 ((UIntConstant) right).Value);
756 else
757 res = unchecked (((UIntConstant) left).Value %
758 ((UIntConstant) right).Value);
760 return new UIntConstant (res, left.Location);
761 } else if (left is IntConstant){
762 int res;
764 if (ec.ConstantCheckState)
765 res = checked (((IntConstant) left).Value %
766 ((IntConstant) right).Value);
767 else
768 res = unchecked (((IntConstant) left).Value %
769 ((IntConstant) right).Value);
771 return new IntConstant (res, left.Location);
772 } else {
773 throw new Exception ( "Unexepected modulus input: " + left);
775 } catch (DivideByZeroException){
776 ec.Report.Error (20, loc, "Division by constant zero");
777 } catch (OverflowException){
778 Error_CompileTimeOverflow (ec, loc);
780 break;
783 // There is no overflow checking on left shift
785 case Binary.Operator.LeftShift:
786 IntConstant ic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
787 if (ic == null){
788 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
789 return null;
792 int lshift_val = ic.Value;
793 if (left.Type == TypeManager.uint64_type)
794 return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
795 if (left.Type == TypeManager.int64_type)
796 return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
797 if (left.Type == TypeManager.uint32_type)
798 return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
800 left = left.ConvertImplicitly (TypeManager.int32_type);
801 if (left.Type == TypeManager.int32_type)
802 return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
804 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
805 break;
808 // There is no overflow checking on right shift
810 case Binary.Operator.RightShift:
811 IntConstant sic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
812 if (sic == null){
813 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
814 return null;
816 int rshift_val = sic.Value;
817 if (left.Type == TypeManager.uint64_type)
818 return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
819 if (left.Type == TypeManager.int64_type)
820 return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
821 if (left.Type == TypeManager.uint32_type)
822 return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
824 left = left.ConvertImplicitly (TypeManager.int32_type);
825 if (left.Type == TypeManager.int32_type)
826 return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
828 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
829 break;
831 case Binary.Operator.Equality:
832 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
833 if (left.IsNull || right.IsNull) {
834 return ReducedExpression.Create (
835 new BoolConstant (left.IsNull == right.IsNull, left.Location),
836 new Binary (oper, left, right));
839 if (left is StringConstant && right is StringConstant)
840 return new BoolConstant (
841 ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
843 return null;
846 if (!DoBinaryNumericPromotions (ref left, ref right))
847 return null;
849 bool_res = false;
850 if (left is DoubleConstant)
851 bool_res = ((DoubleConstant) left).Value ==
852 ((DoubleConstant) right).Value;
853 else if (left is FloatConstant)
854 bool_res = ((FloatConstant) left).Value ==
855 ((FloatConstant) right).Value;
856 else if (left is ULongConstant)
857 bool_res = ((ULongConstant) left).Value ==
858 ((ULongConstant) right).Value;
859 else if (left is LongConstant)
860 bool_res = ((LongConstant) left).Value ==
861 ((LongConstant) right).Value;
862 else if (left is UIntConstant)
863 bool_res = ((UIntConstant) left).Value ==
864 ((UIntConstant) right).Value;
865 else if (left is IntConstant)
866 bool_res = ((IntConstant) left).Value ==
867 ((IntConstant) right).Value;
868 else
869 return null;
871 return new BoolConstant (bool_res, left.Location);
873 case Binary.Operator.Inequality:
874 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
875 if (left.IsNull || right.IsNull) {
876 return ReducedExpression.Create (
877 new BoolConstant (left.IsNull != right.IsNull, left.Location),
878 new Binary (oper, left, right));
881 if (left is StringConstant && right is StringConstant)
882 return new BoolConstant (
883 ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
885 return null;
888 if (!DoBinaryNumericPromotions (ref left, ref right))
889 return null;
891 bool_res = false;
892 if (left is DoubleConstant)
893 bool_res = ((DoubleConstant) left).Value !=
894 ((DoubleConstant) right).Value;
895 else if (left is FloatConstant)
896 bool_res = ((FloatConstant) left).Value !=
897 ((FloatConstant) right).Value;
898 else if (left is ULongConstant)
899 bool_res = ((ULongConstant) left).Value !=
900 ((ULongConstant) right).Value;
901 else if (left is LongConstant)
902 bool_res = ((LongConstant) left).Value !=
903 ((LongConstant) right).Value;
904 else if (left is UIntConstant)
905 bool_res = ((UIntConstant) left).Value !=
906 ((UIntConstant) right).Value;
907 else if (left is IntConstant)
908 bool_res = ((IntConstant) left).Value !=
909 ((IntConstant) right).Value;
910 else
911 return null;
913 return new BoolConstant (bool_res, left.Location);
915 case Binary.Operator.LessThan:
916 if (!DoBinaryNumericPromotions (ref left, ref right))
917 return null;
919 bool_res = false;
920 if (left is DoubleConstant)
921 bool_res = ((DoubleConstant) left).Value <
922 ((DoubleConstant) right).Value;
923 else if (left is FloatConstant)
924 bool_res = ((FloatConstant) left).Value <
925 ((FloatConstant) right).Value;
926 else if (left is ULongConstant)
927 bool_res = ((ULongConstant) left).Value <
928 ((ULongConstant) right).Value;
929 else if (left is LongConstant)
930 bool_res = ((LongConstant) left).Value <
931 ((LongConstant) right).Value;
932 else if (left is UIntConstant)
933 bool_res = ((UIntConstant) left).Value <
934 ((UIntConstant) right).Value;
935 else if (left is IntConstant)
936 bool_res = ((IntConstant) left).Value <
937 ((IntConstant) right).Value;
938 else
939 return null;
941 return new BoolConstant (bool_res, left.Location);
943 case Binary.Operator.GreaterThan:
944 if (!DoBinaryNumericPromotions (ref left, ref right))
945 return null;
947 bool_res = false;
948 if (left is DoubleConstant)
949 bool_res = ((DoubleConstant) left).Value >
950 ((DoubleConstant) right).Value;
951 else if (left is FloatConstant)
952 bool_res = ((FloatConstant) left).Value >
953 ((FloatConstant) right).Value;
954 else if (left is ULongConstant)
955 bool_res = ((ULongConstant) left).Value >
956 ((ULongConstant) right).Value;
957 else if (left is LongConstant)
958 bool_res = ((LongConstant) left).Value >
959 ((LongConstant) right).Value;
960 else if (left is UIntConstant)
961 bool_res = ((UIntConstant) left).Value >
962 ((UIntConstant) right).Value;
963 else if (left is IntConstant)
964 bool_res = ((IntConstant) left).Value >
965 ((IntConstant) right).Value;
966 else
967 return null;
969 return new BoolConstant (bool_res, left.Location);
971 case Binary.Operator.GreaterThanOrEqual:
972 if (!DoBinaryNumericPromotions (ref left, ref right))
973 return null;
975 bool_res = false;
976 if (left is DoubleConstant)
977 bool_res = ((DoubleConstant) left).Value >=
978 ((DoubleConstant) right).Value;
979 else if (left is FloatConstant)
980 bool_res = ((FloatConstant) left).Value >=
981 ((FloatConstant) right).Value;
982 else if (left is ULongConstant)
983 bool_res = ((ULongConstant) left).Value >=
984 ((ULongConstant) right).Value;
985 else if (left is LongConstant)
986 bool_res = ((LongConstant) left).Value >=
987 ((LongConstant) right).Value;
988 else if (left is UIntConstant)
989 bool_res = ((UIntConstant) left).Value >=
990 ((UIntConstant) right).Value;
991 else if (left is IntConstant)
992 bool_res = ((IntConstant) left).Value >=
993 ((IntConstant) right).Value;
994 else
995 return null;
997 return new BoolConstant (bool_res, left.Location);
999 case Binary.Operator.LessThanOrEqual:
1000 if (!DoBinaryNumericPromotions (ref left, ref right))
1001 return null;
1003 bool_res = false;
1004 if (left is DoubleConstant)
1005 bool_res = ((DoubleConstant) left).Value <=
1006 ((DoubleConstant) right).Value;
1007 else if (left is FloatConstant)
1008 bool_res = ((FloatConstant) left).Value <=
1009 ((FloatConstant) right).Value;
1010 else if (left is ULongConstant)
1011 bool_res = ((ULongConstant) left).Value <=
1012 ((ULongConstant) right).Value;
1013 else if (left is LongConstant)
1014 bool_res = ((LongConstant) left).Value <=
1015 ((LongConstant) right).Value;
1016 else if (left is UIntConstant)
1017 bool_res = ((UIntConstant) left).Value <=
1018 ((UIntConstant) right).Value;
1019 else if (left is IntConstant)
1020 bool_res = ((IntConstant) left).Value <=
1021 ((IntConstant) right).Value;
1022 else
1023 return null;
1025 return new BoolConstant (bool_res, left.Location);
1028 return null;