eol
[mcs.git] / mcs / cfold.cs
bloba146e02fc1917f84e4fa85237a594f316e3a2ffd
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 (ResolveContext rc, 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 (rc, ref right, ref left, t);
40 if (t == rtype)
41 return t == ltype || ConvertPromotion (rc, ref left, ref right, t);
44 left = left.ConvertImplicitly (rc, TypeManager.int32_type);
45 right = right.ConvertImplicitly (rc, TypeManager.int32_type);
46 return left != null && right != null;
49 static bool ConvertPromotion (ResolveContext rc, ref Constant prim, ref Constant second, Type type)
51 Constant c = prim.ConvertImplicitly (rc, 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 (rc, type);
60 second = second.ConvertImplicitly (rc, 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 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
147 if (result != null)
148 result = result.Resolve (ec).TryReduce (ec, lt, loc);
149 return result;
152 /// U operator -(E x, E y);
153 ///
154 case Binary.Operator.Subtraction:
155 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
156 if (result != null)
157 result = result.Resolve (ec).TryReduce (ec, ((EnumConstant)left).Child.Type, loc);
158 return result;
161 /// bool operator ==(E x, E y);
162 /// bool operator !=(E x, E y);
163 /// bool operator <(E x, E y);
164 /// bool operator >(E x, E y);
165 /// bool operator <=(E x, E y);
166 /// bool operator >=(E x, E y);
167 ///
168 case Binary.Operator.Equality:
169 case Binary.Operator.Inequality:
170 case Binary.Operator.LessThan:
171 case Binary.Operator.GreaterThan:
172 case Binary.Operator.LessThanOrEqual:
173 case Binary.Operator.GreaterThanOrEqual:
174 return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
176 return null;
179 switch (oper){
180 case Binary.Operator.BitwiseOr:
181 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
182 return null;
184 if (left is IntConstant){
185 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
187 return new IntConstant (res, left.Location);
189 if (left is UIntConstant){
190 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
192 return new UIntConstant (res, left.Location);
194 if (left is LongConstant){
195 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
197 return new LongConstant (res, left.Location);
199 if (left is ULongConstant){
200 ulong res = ((ULongConstant)left).Value |
201 ((ULongConstant)right).Value;
203 return new ULongConstant (res, left.Location);
205 break;
207 case Binary.Operator.BitwiseAnd:
208 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
209 return null;
212 /// int operator &(int x, int y);
213 /// uint operator &(uint x, uint y);
214 /// long operator &(long x, long y);
215 /// ulong operator &(ulong x, ulong y);
217 if (left is IntConstant){
218 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
219 return new IntConstant (res, left.Location);
221 if (left is UIntConstant){
222 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
223 return new UIntConstant (res, left.Location);
225 if (left is LongConstant){
226 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
227 return new LongConstant (res, left.Location);
229 if (left is ULongConstant){
230 ulong res = ((ULongConstant)left).Value &
231 ((ULongConstant)right).Value;
233 return new ULongConstant (res, left.Location);
235 break;
237 case Binary.Operator.ExclusiveOr:
238 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
239 return null;
241 if (left is IntConstant){
242 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
243 return new IntConstant (res, left.Location);
245 if (left is UIntConstant){
246 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
248 return new UIntConstant (res, left.Location);
250 if (left is LongConstant){
251 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
253 return new LongConstant (res, left.Location);
255 if (left is ULongConstant){
256 ulong res = ((ULongConstant)left).Value ^
257 ((ULongConstant)right).Value;
259 return new ULongConstant (res, left.Location);
261 break;
263 case Binary.Operator.Addition:
264 if (lt == TypeManager.null_type)
265 return right;
267 if (rt == TypeManager.null_type)
268 return left;
271 // If both sides are strings, then concatenate, if
272 // one is a string, and the other is not, then defer
273 // to runtime concatenation
275 if (lt == TypeManager.string_type || rt == TypeManager.string_type){
276 if (lt == rt)
277 return new StringConstant ((string)left.GetValue () + (string)right.GetValue (),
278 left.Location);
280 return null;
284 // handle "E operator + (E x, U y)"
285 // handle "E operator + (Y y, E x)"
287 EnumConstant lc = left as EnumConstant;
288 EnumConstant rc = right as EnumConstant;
289 if (lc != null || rc != null){
290 if (lc == null) {
291 lc = rc;
292 lt = lc.Type;
293 right = left;
296 // U has to be implicitly convetible to E.base
297 right = right.ConvertImplicitly (ec, lc.Child.Type);
298 if (right == null)
299 return null;
301 result = BinaryFold (ec, oper, lc.Child, right, loc);
302 if (result == null)
303 return null;
305 result = result.Resolve (ec).TryReduce (ec, lt, loc);
306 if (result == null)
307 return null;
309 return new EnumConstant (result, lt);
312 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
313 return null;
315 try {
316 if (left is DoubleConstant){
317 double res;
319 if (ec.ConstantCheckState)
320 res = checked (((DoubleConstant) left).Value +
321 ((DoubleConstant) right).Value);
322 else
323 res = unchecked (((DoubleConstant) left).Value +
324 ((DoubleConstant) right).Value);
326 return new DoubleConstant (res, left.Location);
328 if (left is FloatConstant){
329 float res;
331 if (ec.ConstantCheckState)
332 res = checked (((FloatConstant) left).Value +
333 ((FloatConstant) right).Value);
334 else
335 res = unchecked (((FloatConstant) left).Value +
336 ((FloatConstant) right).Value);
338 result = new FloatConstant (res, left.Location);
339 } else if (left is ULongConstant){
340 ulong res;
342 if (ec.ConstantCheckState)
343 res = checked (((ULongConstant) left).Value +
344 ((ULongConstant) right).Value);
345 else
346 res = unchecked (((ULongConstant) left).Value +
347 ((ULongConstant) right).Value);
349 result = new ULongConstant (res, left.Location);
350 } else if (left is LongConstant){
351 long res;
353 if (ec.ConstantCheckState)
354 res = checked (((LongConstant) left).Value +
355 ((LongConstant) right).Value);
356 else
357 res = unchecked (((LongConstant) left).Value +
358 ((LongConstant) right).Value);
360 result = new LongConstant (res, left.Location);
361 } else if (left is UIntConstant){
362 uint res;
364 if (ec.ConstantCheckState)
365 res = checked (((UIntConstant) left).Value +
366 ((UIntConstant) right).Value);
367 else
368 res = unchecked (((UIntConstant) left).Value +
369 ((UIntConstant) right).Value);
371 result = new UIntConstant (res, left.Location);
372 } else if (left is IntConstant){
373 int res;
375 if (ec.ConstantCheckState)
376 res = checked (((IntConstant) left).Value +
377 ((IntConstant) right).Value);
378 else
379 res = unchecked (((IntConstant) left).Value +
380 ((IntConstant) right).Value);
382 result = new IntConstant (res, left.Location);
383 } else if (left is DecimalConstant) {
384 decimal res;
386 if (ec.ConstantCheckState)
387 res = checked (((DecimalConstant) left).Value +
388 ((DecimalConstant) right).Value);
389 else
390 res = unchecked (((DecimalConstant) left).Value +
391 ((DecimalConstant) right).Value);
393 result = new DecimalConstant (res, left.Location);
395 } catch (OverflowException){
396 Error_CompileTimeOverflow (ec, loc);
399 return result;
401 case Binary.Operator.Subtraction:
403 // handle "E operator - (E x, U y)"
404 // handle "E operator - (Y y, E x)"
406 lc = left as EnumConstant;
407 rc = right as EnumConstant;
408 if (lc != null || rc != null){
409 if (lc == null) {
410 lc = rc;
411 lt = lc.Type;
412 right = left;
415 // U has to be implicitly convetible to E.base
416 right = right.ConvertImplicitly (ec, lc.Child.Type);
417 if (right == null)
418 return null;
420 result = BinaryFold (ec, oper, lc.Child, right, loc);
421 if (result == null)
422 return null;
424 result = result.Resolve (ec).TryReduce (ec, lt, loc);
425 if (result == null)
426 return null;
428 return new EnumConstant (result, lt);
431 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
432 return null;
434 try {
435 if (left is DoubleConstant){
436 double res;
438 if (ec.ConstantCheckState)
439 res = checked (((DoubleConstant) left).Value -
440 ((DoubleConstant) right).Value);
441 else
442 res = unchecked (((DoubleConstant) left).Value -
443 ((DoubleConstant) right).Value);
445 result = new DoubleConstant (res, left.Location);
446 } else if (left is FloatConstant){
447 float res;
449 if (ec.ConstantCheckState)
450 res = checked (((FloatConstant) left).Value -
451 ((FloatConstant) right).Value);
452 else
453 res = unchecked (((FloatConstant) left).Value -
454 ((FloatConstant) right).Value);
456 result = new FloatConstant (res, left.Location);
457 } else if (left is ULongConstant){
458 ulong res;
460 if (ec.ConstantCheckState)
461 res = checked (((ULongConstant) left).Value -
462 ((ULongConstant) right).Value);
463 else
464 res = unchecked (((ULongConstant) left).Value -
465 ((ULongConstant) right).Value);
467 result = new ULongConstant (res, left.Location);
468 } else if (left is LongConstant){
469 long res;
471 if (ec.ConstantCheckState)
472 res = checked (((LongConstant) left).Value -
473 ((LongConstant) right).Value);
474 else
475 res = unchecked (((LongConstant) left).Value -
476 ((LongConstant) right).Value);
478 result = new LongConstant (res, left.Location);
479 } else if (left is UIntConstant){
480 uint res;
482 if (ec.ConstantCheckState)
483 res = checked (((UIntConstant) left).Value -
484 ((UIntConstant) right).Value);
485 else
486 res = unchecked (((UIntConstant) left).Value -
487 ((UIntConstant) right).Value);
489 result = new UIntConstant (res, left.Location);
490 } else if (left is IntConstant){
491 int res;
493 if (ec.ConstantCheckState)
494 res = checked (((IntConstant) left).Value -
495 ((IntConstant) right).Value);
496 else
497 res = unchecked (((IntConstant) left).Value -
498 ((IntConstant) right).Value);
500 result = new IntConstant (res, left.Location);
501 } else if (left is DecimalConstant) {
502 decimal res;
504 if (ec.ConstantCheckState)
505 res = checked (((DecimalConstant) left).Value -
506 ((DecimalConstant) right).Value);
507 else
508 res = unchecked (((DecimalConstant) left).Value -
509 ((DecimalConstant) right).Value);
511 return new DecimalConstant (res, left.Location);
512 } else {
513 throw new Exception ( "Unexepected subtraction input: " + left);
515 } catch (OverflowException){
516 Error_CompileTimeOverflow (ec, loc);
519 return result;
521 case Binary.Operator.Multiply:
522 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
523 return null;
525 try {
526 if (left is DoubleConstant){
527 double res;
529 if (ec.ConstantCheckState)
530 res = checked (((DoubleConstant) left).Value *
531 ((DoubleConstant) right).Value);
532 else
533 res = unchecked (((DoubleConstant) left).Value *
534 ((DoubleConstant) right).Value);
536 return new DoubleConstant (res, left.Location);
537 } else if (left is FloatConstant){
538 float res;
540 if (ec.ConstantCheckState)
541 res = checked (((FloatConstant) left).Value *
542 ((FloatConstant) right).Value);
543 else
544 res = unchecked (((FloatConstant) left).Value *
545 ((FloatConstant) right).Value);
547 return new FloatConstant (res, left.Location);
548 } else if (left is ULongConstant){
549 ulong res;
551 if (ec.ConstantCheckState)
552 res = checked (((ULongConstant) left).Value *
553 ((ULongConstant) right).Value);
554 else
555 res = unchecked (((ULongConstant) left).Value *
556 ((ULongConstant) right).Value);
558 return new ULongConstant (res, left.Location);
559 } else if (left is LongConstant){
560 long res;
562 if (ec.ConstantCheckState)
563 res = checked (((LongConstant) left).Value *
564 ((LongConstant) right).Value);
565 else
566 res = unchecked (((LongConstant) left).Value *
567 ((LongConstant) right).Value);
569 return new LongConstant (res, left.Location);
570 } else if (left is UIntConstant){
571 uint res;
573 if (ec.ConstantCheckState)
574 res = checked (((UIntConstant) left).Value *
575 ((UIntConstant) right).Value);
576 else
577 res = unchecked (((UIntConstant) left).Value *
578 ((UIntConstant) right).Value);
580 return new UIntConstant (res, left.Location);
581 } else if (left is IntConstant){
582 int res;
584 if (ec.ConstantCheckState)
585 res = checked (((IntConstant) left).Value *
586 ((IntConstant) right).Value);
587 else
588 res = unchecked (((IntConstant) left).Value *
589 ((IntConstant) right).Value);
591 return new IntConstant (res, left.Location);
592 } else if (left is DecimalConstant) {
593 decimal res;
595 if (ec.ConstantCheckState)
596 res = checked (((DecimalConstant) left).Value *
597 ((DecimalConstant) right).Value);
598 else
599 res = unchecked (((DecimalConstant) left).Value *
600 ((DecimalConstant) right).Value);
602 return new DecimalConstant (res, left.Location);
603 } else {
604 throw new Exception ( "Unexepected multiply input: " + left);
606 } catch (OverflowException){
607 Error_CompileTimeOverflow (ec, loc);
609 break;
611 case Binary.Operator.Division:
612 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
613 return null;
615 try {
616 if (left is DoubleConstant){
617 double res;
619 if (ec.ConstantCheckState)
620 res = checked (((DoubleConstant) left).Value /
621 ((DoubleConstant) right).Value);
622 else
623 res = unchecked (((DoubleConstant) left).Value /
624 ((DoubleConstant) right).Value);
626 return new DoubleConstant (res, left.Location);
627 } else if (left is FloatConstant){
628 float res;
630 if (ec.ConstantCheckState)
631 res = checked (((FloatConstant) left).Value /
632 ((FloatConstant) right).Value);
633 else
634 res = unchecked (((FloatConstant) left).Value /
635 ((FloatConstant) right).Value);
637 return new FloatConstant (res, left.Location);
638 } else if (left is ULongConstant){
639 ulong res;
641 if (ec.ConstantCheckState)
642 res = checked (((ULongConstant) left).Value /
643 ((ULongConstant) right).Value);
644 else
645 res = unchecked (((ULongConstant) left).Value /
646 ((ULongConstant) right).Value);
648 return new ULongConstant (res, left.Location);
649 } else if (left is LongConstant){
650 long res;
652 if (ec.ConstantCheckState)
653 res = checked (((LongConstant) left).Value /
654 ((LongConstant) right).Value);
655 else
656 res = unchecked (((LongConstant) left).Value /
657 ((LongConstant) right).Value);
659 return new LongConstant (res, left.Location);
660 } else if (left is UIntConstant){
661 uint res;
663 if (ec.ConstantCheckState)
664 res = checked (((UIntConstant) left).Value /
665 ((UIntConstant) right).Value);
666 else
667 res = unchecked (((UIntConstant) left).Value /
668 ((UIntConstant) right).Value);
670 return new UIntConstant (res, left.Location);
671 } else if (left is IntConstant){
672 int res;
674 if (ec.ConstantCheckState)
675 res = checked (((IntConstant) left).Value /
676 ((IntConstant) right).Value);
677 else
678 res = unchecked (((IntConstant) left).Value /
679 ((IntConstant) right).Value);
681 return new IntConstant (res, left.Location);
682 } else if (left is DecimalConstant) {
683 decimal res;
685 if (ec.ConstantCheckState)
686 res = checked (((DecimalConstant) left).Value /
687 ((DecimalConstant) right).Value);
688 else
689 res = unchecked (((DecimalConstant) left).Value /
690 ((DecimalConstant) right).Value);
692 return new DecimalConstant (res, left.Location);
693 } else {
694 throw new Exception ( "Unexepected division input: " + left);
696 } catch (OverflowException){
697 Error_CompileTimeOverflow (ec, loc);
699 } catch (DivideByZeroException) {
700 ec.Report.Error (20, loc, "Division by constant zero");
703 break;
705 case Binary.Operator.Modulus:
706 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
707 return null;
709 try {
710 if (left is DoubleConstant){
711 double res;
713 if (ec.ConstantCheckState)
714 res = checked (((DoubleConstant) left).Value %
715 ((DoubleConstant) right).Value);
716 else
717 res = unchecked (((DoubleConstant) left).Value %
718 ((DoubleConstant) right).Value);
720 return new DoubleConstant (res, left.Location);
721 } else if (left is FloatConstant){
722 float res;
724 if (ec.ConstantCheckState)
725 res = checked (((FloatConstant) left).Value %
726 ((FloatConstant) right).Value);
727 else
728 res = unchecked (((FloatConstant) left).Value %
729 ((FloatConstant) right).Value);
731 return new FloatConstant (res, left.Location);
732 } else if (left is ULongConstant){
733 ulong res;
735 if (ec.ConstantCheckState)
736 res = checked (((ULongConstant) left).Value %
737 ((ULongConstant) right).Value);
738 else
739 res = unchecked (((ULongConstant) left).Value %
740 ((ULongConstant) right).Value);
742 return new ULongConstant (res, left.Location);
743 } else if (left is LongConstant){
744 long res;
746 if (ec.ConstantCheckState)
747 res = checked (((LongConstant) left).Value %
748 ((LongConstant) right).Value);
749 else
750 res = unchecked (((LongConstant) left).Value %
751 ((LongConstant) right).Value);
753 return new LongConstant (res, left.Location);
754 } else if (left is UIntConstant){
755 uint res;
757 if (ec.ConstantCheckState)
758 res = checked (((UIntConstant) left).Value %
759 ((UIntConstant) right).Value);
760 else
761 res = unchecked (((UIntConstant) left).Value %
762 ((UIntConstant) right).Value);
764 return new UIntConstant (res, left.Location);
765 } else if (left is IntConstant){
766 int res;
768 if (ec.ConstantCheckState)
769 res = checked (((IntConstant) left).Value %
770 ((IntConstant) right).Value);
771 else
772 res = unchecked (((IntConstant) left).Value %
773 ((IntConstant) right).Value);
775 return new IntConstant (res, left.Location);
776 } else {
777 throw new Exception ( "Unexepected modulus input: " + left);
779 } catch (DivideByZeroException){
780 ec.Report.Error (20, loc, "Division by constant zero");
781 } catch (OverflowException){
782 Error_CompileTimeOverflow (ec, loc);
784 break;
787 // There is no overflow checking on left shift
789 case Binary.Operator.LeftShift:
790 IntConstant ic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
791 if (ic == null){
792 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
793 return null;
796 int lshift_val = ic.Value;
797 if (left.Type == TypeManager.uint64_type)
798 return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
799 if (left.Type == TypeManager.int64_type)
800 return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
801 if (left.Type == TypeManager.uint32_type)
802 return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
804 left = left.ConvertImplicitly (ec, TypeManager.int32_type);
805 if (left.Type == TypeManager.int32_type)
806 return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
808 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
809 break;
812 // There is no overflow checking on right shift
814 case Binary.Operator.RightShift:
815 IntConstant sic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
816 if (sic == null){
817 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
818 return null;
820 int rshift_val = sic.Value;
821 if (left.Type == TypeManager.uint64_type)
822 return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
823 if (left.Type == TypeManager.int64_type)
824 return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
825 if (left.Type == TypeManager.uint32_type)
826 return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
828 left = left.ConvertImplicitly (ec, TypeManager.int32_type);
829 if (left.Type == TypeManager.int32_type)
830 return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
832 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
833 break;
835 case Binary.Operator.Equality:
836 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
837 if (left.IsNull || right.IsNull) {
838 return ReducedExpression.Create (
839 new BoolConstant (left.IsNull == right.IsNull, left.Location).Resolve (ec),
840 new Binary (oper, left, right, loc));
843 if (left is StringConstant && right is StringConstant)
844 return new BoolConstant (
845 ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
847 return null;
850 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
851 return null;
853 bool_res = false;
854 if (left is DoubleConstant)
855 bool_res = ((DoubleConstant) left).Value ==
856 ((DoubleConstant) right).Value;
857 else if (left is FloatConstant)
858 bool_res = ((FloatConstant) left).Value ==
859 ((FloatConstant) right).Value;
860 else if (left is ULongConstant)
861 bool_res = ((ULongConstant) left).Value ==
862 ((ULongConstant) right).Value;
863 else if (left is LongConstant)
864 bool_res = ((LongConstant) left).Value ==
865 ((LongConstant) right).Value;
866 else if (left is UIntConstant)
867 bool_res = ((UIntConstant) left).Value ==
868 ((UIntConstant) right).Value;
869 else if (left is IntConstant)
870 bool_res = ((IntConstant) left).Value ==
871 ((IntConstant) right).Value;
872 else
873 return null;
875 return new BoolConstant (bool_res, left.Location);
877 case Binary.Operator.Inequality:
878 if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
879 if (left.IsNull || right.IsNull) {
880 return ReducedExpression.Create (
881 new BoolConstant (left.IsNull != right.IsNull, left.Location).Resolve (ec),
882 new Binary (oper, left, right, loc));
885 if (left is StringConstant && right is StringConstant)
886 return new BoolConstant (
887 ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
889 return null;
892 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
893 return null;
895 bool_res = false;
896 if (left is DoubleConstant)
897 bool_res = ((DoubleConstant) left).Value !=
898 ((DoubleConstant) right).Value;
899 else if (left is FloatConstant)
900 bool_res = ((FloatConstant) left).Value !=
901 ((FloatConstant) right).Value;
902 else if (left is ULongConstant)
903 bool_res = ((ULongConstant) left).Value !=
904 ((ULongConstant) right).Value;
905 else if (left is LongConstant)
906 bool_res = ((LongConstant) left).Value !=
907 ((LongConstant) right).Value;
908 else if (left is UIntConstant)
909 bool_res = ((UIntConstant) left).Value !=
910 ((UIntConstant) right).Value;
911 else if (left is IntConstant)
912 bool_res = ((IntConstant) left).Value !=
913 ((IntConstant) right).Value;
914 else
915 return null;
917 return new BoolConstant (bool_res, left.Location);
919 case Binary.Operator.LessThan:
920 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
921 return null;
923 bool_res = false;
924 if (left is DoubleConstant)
925 bool_res = ((DoubleConstant) left).Value <
926 ((DoubleConstant) right).Value;
927 else if (left is FloatConstant)
928 bool_res = ((FloatConstant) left).Value <
929 ((FloatConstant) right).Value;
930 else if (left is ULongConstant)
931 bool_res = ((ULongConstant) left).Value <
932 ((ULongConstant) right).Value;
933 else if (left is LongConstant)
934 bool_res = ((LongConstant) left).Value <
935 ((LongConstant) right).Value;
936 else if (left is UIntConstant)
937 bool_res = ((UIntConstant) left).Value <
938 ((UIntConstant) right).Value;
939 else if (left is IntConstant)
940 bool_res = ((IntConstant) left).Value <
941 ((IntConstant) right).Value;
942 else
943 return null;
945 return new BoolConstant (bool_res, left.Location);
947 case Binary.Operator.GreaterThan:
948 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
949 return null;
951 bool_res = false;
952 if (left is DoubleConstant)
953 bool_res = ((DoubleConstant) left).Value >
954 ((DoubleConstant) right).Value;
955 else if (left is FloatConstant)
956 bool_res = ((FloatConstant) left).Value >
957 ((FloatConstant) right).Value;
958 else if (left is ULongConstant)
959 bool_res = ((ULongConstant) left).Value >
960 ((ULongConstant) right).Value;
961 else if (left is LongConstant)
962 bool_res = ((LongConstant) left).Value >
963 ((LongConstant) right).Value;
964 else if (left is UIntConstant)
965 bool_res = ((UIntConstant) left).Value >
966 ((UIntConstant) right).Value;
967 else if (left is IntConstant)
968 bool_res = ((IntConstant) left).Value >
969 ((IntConstant) right).Value;
970 else
971 return null;
973 return new BoolConstant (bool_res, left.Location);
975 case Binary.Operator.GreaterThanOrEqual:
976 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
977 return null;
979 bool_res = false;
980 if (left is DoubleConstant)
981 bool_res = ((DoubleConstant) left).Value >=
982 ((DoubleConstant) right).Value;
983 else if (left is FloatConstant)
984 bool_res = ((FloatConstant) left).Value >=
985 ((FloatConstant) right).Value;
986 else if (left is ULongConstant)
987 bool_res = ((ULongConstant) left).Value >=
988 ((ULongConstant) right).Value;
989 else if (left is LongConstant)
990 bool_res = ((LongConstant) left).Value >=
991 ((LongConstant) right).Value;
992 else if (left is UIntConstant)
993 bool_res = ((UIntConstant) left).Value >=
994 ((UIntConstant) right).Value;
995 else if (left is IntConstant)
996 bool_res = ((IntConstant) left).Value >=
997 ((IntConstant) right).Value;
998 else
999 return null;
1001 return new BoolConstant (bool_res, left.Location);
1003 case Binary.Operator.LessThanOrEqual:
1004 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1005 return null;
1007 bool_res = false;
1008 if (left is DoubleConstant)
1009 bool_res = ((DoubleConstant) left).Value <=
1010 ((DoubleConstant) right).Value;
1011 else if (left is FloatConstant)
1012 bool_res = ((FloatConstant) left).Value <=
1013 ((FloatConstant) right).Value;
1014 else if (left is ULongConstant)
1015 bool_res = ((ULongConstant) left).Value <=
1016 ((ULongConstant) right).Value;
1017 else if (left is LongConstant)
1018 bool_res = ((LongConstant) left).Value <=
1019 ((LongConstant) right).Value;
1020 else if (left is UIntConstant)
1021 bool_res = ((UIntConstant) left).Value <=
1022 ((UIntConstant) right).Value;
1023 else if (left is IntConstant)
1024 bool_res = ((IntConstant) left).Value <=
1025 ((IntConstant) right).Value;
1026 else
1027 return null;
1029 return new BoolConstant (bool_res, left.Location);
1032 return null;