In ilasm/codegen:
[mcs.git] / bmcs / cfold.cs
blob346d981594eb804d70ff2e2973198ae38b501164
1 //
2 // cfold.cs: Constant Folding
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2002, 2003 Ximian, Inc.
8 //
10 using System;
12 namespace Mono.CSharp {
14 public class ConstantFold {
17 // Performs the numeric promotions on the left and right expresions
18 // and desposits the results on `lc' and `rc'.
20 // On success, the types of `lc' and `rc' on output will always match,
21 // and the pair will be one of:
23 // (double, double)
24 // (float, float)
25 // (ulong, ulong)
26 // (long, long)
27 // (uint, uint)
28 // (int, int)
29 // (short, short) (Happens with enumerations with underlying short type)
30 // (ushort, ushort) (Happens with enumerations with underlying short type)
32 static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
33 ref Constant left, ref Constant right,
34 Location loc)
36 if (left is DoubleConstant || right is DoubleConstant){
38 // If either side is a double, convert the other to a double
40 if (!(left is DoubleConstant))
41 left = left.ToDouble (loc);
43 if (!(right is DoubleConstant))
44 right = right.ToDouble (loc);
45 return;
46 } else if (left is FloatConstant || right is FloatConstant) {
48 // If either side is a float, convert the other to a float
50 if (!(left is FloatConstant))
51 left = left.ToFloat (loc);
53 if (!(right is FloatConstant))
54 right = right.ToFloat (loc);
55 ; return;
56 } else if (left is ULongConstant || right is ULongConstant){
58 // If either operand is of type ulong, the other operand is
59 // converted to type ulong. or an error ocurrs if the other
60 // operand is of type sbyte, short, int or long
62 #if WRONG
63 Constant match, other;
64 #endif
66 if (left is ULongConstant){
67 #if WRONG
68 other = right;
69 match = left;
70 #endif
71 if (!(right is ULongConstant))
72 right = right.ToULong (loc);
73 } else {
74 #if WRONG
75 other = left;
76 match = right;
77 #endif
78 left = left.ToULong (loc);
81 #if WRONG
82 if (other is SByteConstant || other is ShortConstant ||
83 other is IntConstant || other is LongConstant){
84 Binary.Error_OperatorAmbiguous
85 (loc, oper, other.Type, match.Type);
86 left = null;
87 right = null;
89 #endif
90 return;
91 } else if (left is LongConstant || right is LongConstant){
93 // If either operand is of type long, the other operand is converted
94 // to type long.
96 if (!(left is LongConstant))
97 left = left.ToLong (loc);
98 else if (!(right is LongConstant))
99 right = right.ToLong (loc);
100 return;
101 } else if (left is UIntConstant || right is UIntConstant){
103 // If either operand is of type uint, and the other
104 // operand is of type sbyte, short or int, the operands are
105 // converted to type long.
107 Constant other;
108 if (left is UIntConstant)
109 other = right;
110 else
111 other = left;
113 // Nothing to do.
114 if (other is UIntConstant)
115 return;
117 IntConstant ic = other as IntConstant;
118 if (ic != null){
119 if (ic.Value >= 0){
120 if (left == other)
121 left = new UIntConstant ((uint) ic.Value);
122 else
123 right = new UIntConstant ((uint) ic.Value);
124 return;
128 if (other is SByteConstant || other is ShortConstant || ic != null){
129 left = left.ToLong (loc);
130 right = right.ToLong (loc);
131 } else {
132 left = left.ToUInt (loc);
133 right = left.ToUInt (loc);
136 return;
137 } else if (left is DecimalConstant || right is DecimalConstant) {
138 if (!(left is DecimalConstant))
139 left = left.ToDecimal (loc);
140 else if (!(right is DecimalConstant))
141 right = right.ToDecimal (loc);
142 return;
143 } else if (left is EnumConstant || right is EnumConstant){
145 // If either operand is an enum constant, the other one must
146 // be implicitly convertable to that enum's underlying type.
148 EnumConstant match;
149 Constant other;
150 if (left is EnumConstant){
151 other = right;
152 match = (EnumConstant) left;
153 } else {
154 other = left;
155 match = (EnumConstant) right;
158 bool need_check = (other is EnumConstant) ||
159 ((oper != Binary.Operator.Addition) &&
160 (oper != Binary.Operator.Subtraction));
162 if (need_check &&
163 !Convert.WideningConversionExists (ec, match, other.Type)) {
164 Convert.Error_CannotWideningConversion (loc, match.Type, other.Type);
165 left = null;
166 right = null;
167 return;
170 if (left is EnumConstant)
171 left = ((EnumConstant) left).Child;
172 if (right is EnumConstant)
173 right = ((EnumConstant) right).Child;
175 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
176 return;
178 } else {
180 // Force conversions to int32
182 if (!(left is IntConstant))
183 left = left.ToInt (loc);
184 if (!(right is IntConstant))
185 right = right.ToInt (loc);
187 return;
190 static void Error_CompileTimeOverflow (Location loc)
192 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
195 /// <summary>
196 /// Constant expression folder for binary operations.
198 /// Returns null if the expression can not be folded.
199 /// </summary>
200 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
201 Constant left, Constant right, Location loc)
203 Type lt = left.Type;
204 Type rt = right.Type;
205 Type result_type = null;
206 bool bool_res;
209 // Enumerator folding
211 if (rt == lt && left is EnumConstant)
212 result_type = lt;
215 // During an enum evaluation, we need to unwrap enumerations
217 if (ec.InEnumContext){
218 if (left is EnumConstant)
219 left = ((EnumConstant) left).Child;
221 if (right is EnumConstant)
222 right = ((EnumConstant) right).Child;
225 Type wrap_as;
226 Constant result = null;
227 switch (oper){
228 case Binary.Operator.BitwiseOr:
229 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
230 if (left == null || right == null)
231 return null;
233 if (left is IntConstant){
234 IntConstant v;
235 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
237 v = new IntConstant (res);
238 if (result_type == null)
239 return v;
240 else
241 return new EnumConstant (v, result_type);
242 } else if (left is UIntConstant){
243 UIntConstant v;
244 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
246 v = new UIntConstant (res);
247 if (result_type == null)
248 return v;
249 else
250 return new EnumConstant (v, result_type);
251 } else if (left is LongConstant){
252 LongConstant v;
253 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
255 v = new LongConstant (res);
256 if (result_type == null)
257 return v;
258 else
259 return new EnumConstant (v, result_type);
260 } else if (left is ULongConstant){
261 ULongConstant v;
262 ulong res = ((ULongConstant)left).Value |
263 ((ULongConstant)right).Value;
265 v = new ULongConstant (res);
266 if (result_type == null)
267 return v;
268 else
269 return new EnumConstant (v, result_type);
270 } else if (left is UShortConstant){
271 UShortConstant v;
272 ushort res = (ushort) (((UShortConstant)left).Value |
273 ((UShortConstant)right).Value);
275 v = new UShortConstant (res);
276 if (result_type == null)
277 return v;
278 else
279 return new EnumConstant (v, result_type);
280 } else if (left is ShortConstant){
281 ShortConstant v;
282 short res = (short) (((ShortConstant)left).Value |
283 ((ShortConstant)right).Value);
285 v = new ShortConstant (res);
286 if (result_type == null)
287 return v;
288 else
289 return new EnumConstant (v, result_type);
291 break;
293 case Binary.Operator.BitwiseAnd:
294 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
295 if (left == null || right == null)
296 return null;
298 if (left is IntConstant){
299 IntConstant v;
300 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
302 v = new IntConstant (res);
303 if (result_type == null)
304 return v;
305 else
306 return new EnumConstant (v, result_type);
307 } else if (left is UIntConstant){
308 UIntConstant v;
309 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
311 v = new UIntConstant (res);
312 if (result_type == null)
313 return v;
314 else
315 return new EnumConstant (v, result_type);
316 } else if (left is LongConstant){
317 LongConstant v;
318 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
320 v = new LongConstant (res);
321 if (result_type == null)
322 return v;
323 else
324 return new EnumConstant (v, result_type);
325 } else if (left is ULongConstant){
326 ULongConstant v;
327 ulong res = ((ULongConstant)left).Value &
328 ((ULongConstant)right).Value;
330 v = new ULongConstant (res);
331 if (result_type == null)
332 return v;
333 else
334 return new EnumConstant (v, result_type);
335 } else if (left is UShortConstant){
336 UShortConstant v;
337 ushort res = (ushort) (((UShortConstant)left).Value &
338 ((UShortConstant)right).Value);
340 v = new UShortConstant (res);
341 if (result_type == null)
342 return v;
343 else
344 return new EnumConstant (v, result_type);
345 } else if (left is ShortConstant){
346 ShortConstant v;
347 short res = (short) (((ShortConstant)left).Value &
348 ((ShortConstant)right).Value);
350 v = new ShortConstant (res);
351 if (result_type == null)
352 return v;
353 else
354 return new EnumConstant (v, result_type);
356 break;
358 case Binary.Operator.ExclusiveOr:
359 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
360 if (left == null || right == null)
361 return null;
363 if (left is IntConstant){
364 IntConstant v;
365 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
367 v = new IntConstant (res);
368 if (result_type == null)
369 return v;
370 else
371 return new EnumConstant (v, result_type);
372 } else if (left is UIntConstant){
373 UIntConstant v;
374 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
376 v = new UIntConstant (res);
377 if (result_type == null)
378 return v;
379 else
380 return new EnumConstant (v, result_type);
381 } else if (left is LongConstant){
382 LongConstant v;
383 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
385 v = new LongConstant (res);
386 if (result_type == null)
387 return v;
388 else
389 return new EnumConstant (v, result_type);
390 } else if (left is ULongConstant){
391 ULongConstant v;
392 ulong res = ((ULongConstant)left).Value ^
393 ((ULongConstant)right).Value;
395 v = new ULongConstant (res);
396 if (result_type == null)
397 return v;
398 else
399 return new EnumConstant (v, result_type);
400 } else if (left is UShortConstant){
401 UShortConstant v;
402 ushort res = (ushort) (((UShortConstant)left).Value ^
403 ((UShortConstant)right).Value);
405 v = new UShortConstant (res);
406 if (result_type == null)
407 return v;
408 else
409 return new EnumConstant (v, result_type);
410 } else if (left is ShortConstant){
411 ShortConstant v;
412 short res = (short)(((ShortConstant)left).Value ^
413 ((ShortConstant)right).Value);
415 v = new ShortConstant (res);
416 if (result_type == null)
417 return v;
418 else
419 return new EnumConstant (v, result_type);
421 break;
423 case Binary.Operator.Addition:
424 bool left_is_string = left is StringConstant;
425 bool right_is_string = right is StringConstant;
428 // If both sides are strings, then concatenate, if
429 // one is a string, and the other is not, then defer
430 // to runtime concatenation
432 wrap_as = null;
433 if (left_is_string || right_is_string){
434 if (left_is_string && right_is_string)
435 return new StringConstant (
436 ((StringConstant) left).Value +
437 ((StringConstant) right).Value);
439 return null;
443 // handle "E operator + (E x, U y)"
444 // handle "E operator + (Y y, E x)"
446 // note that E operator + (E x, E y) is invalid
448 if (left is EnumConstant){
449 if (right is EnumConstant){
450 return null;
452 if (((EnumConstant) left).Child.Type != right.Type)
453 return null;
455 wrap_as = left.Type;
456 } else if (right is EnumConstant){
457 if (((EnumConstant) right).Child.Type != left.Type)
458 return null;
459 wrap_as = right.Type;
462 result = null;
463 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
464 if (left == null || right == null)
465 return null;
467 try {
468 if (left is DoubleConstant){
469 double res;
471 if (ec.ConstantCheckState)
472 res = checked (((DoubleConstant) left).Value +
473 ((DoubleConstant) right).Value);
474 else
475 res = unchecked (((DoubleConstant) left).Value +
476 ((DoubleConstant) right).Value);
478 result = new DoubleConstant (res);
479 } else if (left is FloatConstant){
480 float res;
482 if (ec.ConstantCheckState)
483 res = checked (((FloatConstant) left).Value +
484 ((FloatConstant) right).Value);
485 else
486 res = unchecked (((FloatConstant) left).Value +
487 ((FloatConstant) right).Value);
489 result = new FloatConstant (res);
490 } else if (left is ULongConstant){
491 ulong res;
493 if (ec.ConstantCheckState)
494 res = checked (((ULongConstant) left).Value +
495 ((ULongConstant) right).Value);
496 else
497 res = unchecked (((ULongConstant) left).Value +
498 ((ULongConstant) right).Value);
500 result = new ULongConstant (res);
501 } else if (left is LongConstant){
502 long res;
504 if (ec.ConstantCheckState)
505 res = checked (((LongConstant) left).Value +
506 ((LongConstant) right).Value);
507 else
508 res = unchecked (((LongConstant) left).Value +
509 ((LongConstant) right).Value);
511 result = new LongConstant (res);
512 } else if (left is UIntConstant){
513 uint res;
515 if (ec.ConstantCheckState)
516 res = checked (((UIntConstant) left).Value +
517 ((UIntConstant) right).Value);
518 else
519 res = unchecked (((UIntConstant) left).Value +
520 ((UIntConstant) right).Value);
522 result = new UIntConstant (res);
523 } else if (left is IntConstant){
524 int res;
526 if (ec.ConstantCheckState)
527 res = checked (((IntConstant) left).Value +
528 ((IntConstant) right).Value);
529 else
530 res = unchecked (((IntConstant) left).Value +
531 ((IntConstant) right).Value);
533 result = new IntConstant (res);
534 } else if (left is DecimalConstant) {
535 decimal res;
537 if (ec.ConstantCheckState)
538 res = checked (((DecimalConstant) left).Value +
539 ((DecimalConstant) right).Value);
540 else
541 res = unchecked (((DecimalConstant) left).Value +
542 ((DecimalConstant) right).Value);
544 result = new DecimalConstant (res);
545 } else {
546 throw new Exception ( "Unexepected addition input: " + left);
548 } catch (OverflowException){
549 Error_CompileTimeOverflow (loc);
552 if (wrap_as != null)
553 return new EnumConstant (result, wrap_as);
554 else
555 return result;
557 case Binary.Operator.Subtraction:
559 // handle "E operator - (E x, U y)"
560 // handle "E operator - (Y y, E x)"
561 // handle "U operator - (E x, E y)"
563 wrap_as = null;
564 if (left is EnumConstant){
565 if (right is EnumConstant){
566 if (left.Type == right.Type)
567 wrap_as = TypeManager.EnumToUnderlying (left.Type);
568 else
569 return null;
571 if (((EnumConstant) left).Child.Type != right.Type)
572 return null;
574 wrap_as = left.Type;
575 } else if (right is EnumConstant){
576 if (((EnumConstant) right).Child.Type != left.Type)
577 return null;
578 wrap_as = right.Type;
581 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
582 if (left == null || right == null)
583 return null;
585 try {
586 if (left is DoubleConstant){
587 double res;
589 if (ec.ConstantCheckState)
590 res = checked (((DoubleConstant) left).Value -
591 ((DoubleConstant) right).Value);
592 else
593 res = unchecked (((DoubleConstant) left).Value -
594 ((DoubleConstant) right).Value);
596 result = new DoubleConstant (res);
597 } else if (left is FloatConstant){
598 float res;
600 if (ec.ConstantCheckState)
601 res = checked (((FloatConstant) left).Value -
602 ((FloatConstant) right).Value);
603 else
604 res = unchecked (((FloatConstant) left).Value -
605 ((FloatConstant) right).Value);
607 result = new FloatConstant (res);
608 } else if (left is ULongConstant){
609 ulong res;
611 if (ec.ConstantCheckState)
612 res = checked (((ULongConstant) left).Value -
613 ((ULongConstant) right).Value);
614 else
615 res = unchecked (((ULongConstant) left).Value -
616 ((ULongConstant) right).Value);
618 result = new ULongConstant (res);
619 } else if (left is LongConstant){
620 long res;
622 if (ec.ConstantCheckState)
623 res = checked (((LongConstant) left).Value -
624 ((LongConstant) right).Value);
625 else
626 res = unchecked (((LongConstant) left).Value -
627 ((LongConstant) right).Value);
629 result = new LongConstant (res);
630 } else if (left is UIntConstant){
631 uint res;
633 if (ec.ConstantCheckState)
634 res = checked (((UIntConstant) left).Value -
635 ((UIntConstant) right).Value);
636 else
637 res = unchecked (((UIntConstant) left).Value -
638 ((UIntConstant) right).Value);
640 result = new UIntConstant (res);
641 } else if (left is IntConstant){
642 int res;
644 if (ec.ConstantCheckState)
645 res = checked (((IntConstant) left).Value -
646 ((IntConstant) right).Value);
647 else
648 res = unchecked (((IntConstant) left).Value -
649 ((IntConstant) right).Value);
651 result = new IntConstant (res);
652 } else if (left is DecimalConstant) {
653 decimal res;
655 if (ec.ConstantCheckState)
656 res = checked (((DecimalConstant) left).Value -
657 ((DecimalConstant) right).Value);
658 else
659 res = unchecked (((DecimalConstant) left).Value -
660 ((DecimalConstant) right).Value);
662 return new DecimalConstant (res);
663 } else {
664 throw new Exception ( "Unexepected subtraction input: " + left);
666 } catch (OverflowException){
667 Error_CompileTimeOverflow (loc);
669 if (wrap_as != null)
670 return new EnumConstant (result, wrap_as);
671 else
672 return result;
674 case Binary.Operator.Multiply:
675 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
676 if (left == null || right == null)
677 return null;
679 try {
680 if (left is DoubleConstant){
681 double res;
683 if (ec.ConstantCheckState)
684 res = checked (((DoubleConstant) left).Value *
685 ((DoubleConstant) right).Value);
686 else
687 res = unchecked (((DoubleConstant) left).Value *
688 ((DoubleConstant) right).Value);
690 return new DoubleConstant (res);
691 } else if (left is FloatConstant){
692 float res;
694 if (ec.ConstantCheckState)
695 res = checked (((FloatConstant) left).Value *
696 ((FloatConstant) right).Value);
697 else
698 res = unchecked (((FloatConstant) left).Value *
699 ((FloatConstant) right).Value);
701 return new FloatConstant (res);
702 } else if (left is ULongConstant){
703 ulong res;
705 if (ec.ConstantCheckState)
706 res = checked (((ULongConstant) left).Value *
707 ((ULongConstant) right).Value);
708 else
709 res = unchecked (((ULongConstant) left).Value *
710 ((ULongConstant) right).Value);
712 return new ULongConstant (res);
713 } else if (left is LongConstant){
714 long res;
716 if (ec.ConstantCheckState)
717 res = checked (((LongConstant) left).Value *
718 ((LongConstant) right).Value);
719 else
720 res = unchecked (((LongConstant) left).Value *
721 ((LongConstant) right).Value);
723 return new LongConstant (res);
724 } else if (left is UIntConstant){
725 uint res;
727 if (ec.ConstantCheckState)
728 res = checked (((UIntConstant) left).Value *
729 ((UIntConstant) right).Value);
730 else
731 res = unchecked (((UIntConstant) left).Value *
732 ((UIntConstant) right).Value);
734 return new UIntConstant (res);
735 } else if (left is IntConstant){
736 int res;
738 if (ec.ConstantCheckState)
739 res = checked (((IntConstant) left).Value *
740 ((IntConstant) right).Value);
741 else
742 res = unchecked (((IntConstant) left).Value *
743 ((IntConstant) right).Value);
745 return new IntConstant (res);
746 } else if (left is DecimalConstant) {
747 decimal res;
749 if (ec.ConstantCheckState)
750 res = checked (((DecimalConstant) left).Value *
751 ((DecimalConstant) right).Value);
752 else
753 res = unchecked (((DecimalConstant) left).Value *
754 ((DecimalConstant) right).Value);
756 return new DecimalConstant (res);
757 } else {
758 throw new Exception ( "Unexepected multiply input: " + left);
760 } catch (OverflowException){
761 Error_CompileTimeOverflow (loc);
763 break;
765 case Binary.Operator.Division:
766 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
767 if (left == null || right == null)
768 return null;
770 try {
771 if (left is DoubleConstant){
772 double res;
774 if (ec.ConstantCheckState)
775 res = checked (((DoubleConstant) left).Value /
776 ((DoubleConstant) right).Value);
777 else
778 res = unchecked (((DoubleConstant) left).Value /
779 ((DoubleConstant) right).Value);
781 return new DoubleConstant (res);
782 } else if (left is FloatConstant){
783 float res;
785 if (ec.ConstantCheckState)
786 res = checked (((FloatConstant) left).Value /
787 ((FloatConstant) right).Value);
788 else
789 res = unchecked (((FloatConstant) left).Value /
790 ((FloatConstant) right).Value);
792 return new FloatConstant (res);
793 } else if (left is ULongConstant){
794 ulong res;
796 if (ec.ConstantCheckState)
797 res = checked (((ULongConstant) left).Value /
798 ((ULongConstant) right).Value);
799 else
800 res = unchecked (((ULongConstant) left).Value /
801 ((ULongConstant) right).Value);
803 return new ULongConstant (res);
804 } else if (left is LongConstant){
805 long res;
807 if (ec.ConstantCheckState)
808 res = checked (((LongConstant) left).Value /
809 ((LongConstant) right).Value);
810 else
811 res = unchecked (((LongConstant) left).Value /
812 ((LongConstant) right).Value);
814 return new LongConstant (res);
815 } else if (left is UIntConstant){
816 uint res;
818 if (ec.ConstantCheckState)
819 res = checked (((UIntConstant) left).Value /
820 ((UIntConstant) right).Value);
821 else
822 res = unchecked (((UIntConstant) left).Value /
823 ((UIntConstant) right).Value);
825 return new UIntConstant (res);
826 } else if (left is IntConstant){
827 int res;
829 if (ec.ConstantCheckState)
830 res = checked (((IntConstant) left).Value /
831 ((IntConstant) right).Value);
832 else
833 res = unchecked (((IntConstant) left).Value /
834 ((IntConstant) right).Value);
836 return new IntConstant (res);
837 } else if (left is DecimalConstant) {
838 decimal res;
840 if (ec.ConstantCheckState)
841 res = checked (((DecimalConstant) left).Value /
842 ((DecimalConstant) right).Value);
843 else
844 res = unchecked (((DecimalConstant) left).Value /
845 ((DecimalConstant) right).Value);
847 return new DecimalConstant (res);
848 } else {
849 throw new Exception ( "Unexepected division input: " + left);
851 } catch (OverflowException){
852 Error_CompileTimeOverflow (loc);
854 } catch (DivideByZeroException) {
855 Report.Error (020, loc, "Division by constant zero");
858 break;
860 case Binary.Operator.Modulus:
861 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
862 if (left == null || right == null)
863 return null;
865 try {
866 if (left is DoubleConstant){
867 double res;
869 if (ec.ConstantCheckState)
870 res = checked (((DoubleConstant) left).Value %
871 ((DoubleConstant) right).Value);
872 else
873 res = unchecked (((DoubleConstant) left).Value %
874 ((DoubleConstant) right).Value);
876 return new DoubleConstant (res);
877 } else if (left is FloatConstant){
878 float res;
880 if (ec.ConstantCheckState)
881 res = checked (((FloatConstant) left).Value %
882 ((FloatConstant) right).Value);
883 else
884 res = unchecked (((FloatConstant) left).Value %
885 ((FloatConstant) right).Value);
887 return new FloatConstant (res);
888 } else if (left is ULongConstant){
889 ulong res;
891 if (ec.ConstantCheckState)
892 res = checked (((ULongConstant) left).Value %
893 ((ULongConstant) right).Value);
894 else
895 res = unchecked (((ULongConstant) left).Value %
896 ((ULongConstant) right).Value);
898 return new ULongConstant (res);
899 } else if (left is LongConstant){
900 long res;
902 if (ec.ConstantCheckState)
903 res = checked (((LongConstant) left).Value %
904 ((LongConstant) right).Value);
905 else
906 res = unchecked (((LongConstant) left).Value %
907 ((LongConstant) right).Value);
909 return new LongConstant (res);
910 } else if (left is UIntConstant){
911 uint res;
913 if (ec.ConstantCheckState)
914 res = checked (((UIntConstant) left).Value %
915 ((UIntConstant) right).Value);
916 else
917 res = unchecked (((UIntConstant) left).Value %
918 ((UIntConstant) right).Value);
920 return new UIntConstant (res);
921 } else if (left is IntConstant){
922 int res;
924 if (ec.ConstantCheckState)
925 res = checked (((IntConstant) left).Value %
926 ((IntConstant) right).Value);
927 else
928 res = unchecked (((IntConstant) left).Value %
929 ((IntConstant) right).Value);
931 return new IntConstant (res);
932 } else {
933 throw new Exception ( "Unexepected modulus input: " + left);
935 } catch (DivideByZeroException){
936 Report.Error (020, loc, "Division by constant zero");
937 } catch (OverflowException){
938 Error_CompileTimeOverflow (loc);
940 break;
943 // There is no overflow checking on left shift
945 case Binary.Operator.LeftShift:
946 IntConstant ic = right.ToInt (loc);
947 if (ic == null){
948 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
949 return null;
951 int lshift_val = ic.Value;
953 IntConstant lic;
954 if ((lic = left.ConvertToInt ()) != null)
955 return new IntConstant (lic.Value << lshift_val);
957 UIntConstant luic;
958 if ((luic = left.ConvertToUInt ()) != null)
959 return new UIntConstant (luic.Value << lshift_val);
961 LongConstant llc;
962 if ((llc = left.ConvertToLong ()) != null)
963 return new LongConstant (llc.Value << lshift_val);
965 ULongConstant lulc;
966 if ((lulc = left.ConvertToULong ()) != null)
967 return new ULongConstant (lulc.Value << lshift_val);
969 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
970 break;
973 // There is no overflow checking on right shift
975 case Binary.Operator.RightShift:
976 IntConstant sic = right.ToInt (loc);
977 if (sic == null){
978 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
979 return null;
981 int rshift_val = sic.Value;
983 IntConstant ric;
984 if ((ric = left.ConvertToInt ()) != null)
985 return new IntConstant (ric.Value >> rshift_val);
987 UIntConstant ruic;
988 if ((ruic = left.ConvertToUInt ()) != null)
989 return new UIntConstant (ruic.Value >> rshift_val);
991 LongConstant rlc;
992 if ((rlc = left.ConvertToLong ()) != null)
993 return new LongConstant (rlc.Value >> rshift_val);
995 ULongConstant rulc;
996 if ((rulc = left.ConvertToULong ()) != null)
997 return new ULongConstant (rulc.Value >> rshift_val);
999 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1000 break;
1002 case Binary.Operator.LogicalAndAlso:
1003 if (left is BoolConstant && right is BoolConstant){
1004 return new BoolConstant (
1005 ((BoolConstant) left).Value &&
1006 ((BoolConstant) right).Value);
1008 break;
1010 case Binary.Operator.LogicalOrElse:
1011 if (left is BoolConstant && right is BoolConstant){
1012 return new BoolConstant (
1013 ((BoolConstant) left).Value ||
1014 ((BoolConstant) right).Value);
1016 break;
1018 case Binary.Operator.Equality:
1019 if (left is BoolConstant && right is BoolConstant){
1020 return new BoolConstant (
1021 ((BoolConstant) left).Value ==
1022 ((BoolConstant) right).Value);
1025 if (left is NullLiteral){
1026 if (right is NullLiteral)
1027 return new BoolConstant (true);
1028 else if (right is StringConstant)
1029 return new BoolConstant (
1030 ((StringConstant) right).Value == null);
1031 } else if (right is NullLiteral){
1032 if (left is NullLiteral)
1033 return new BoolConstant (true);
1034 else if (left is StringConstant)
1035 return new BoolConstant (
1036 ((StringConstant) left).Value == null);
1038 if (left is StringConstant && right is StringConstant){
1039 return new BoolConstant (
1040 ((StringConstant) left).Value ==
1041 ((StringConstant) right).Value);
1045 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1046 if (left == null || right == null)
1047 return null;
1049 bool_res = false;
1050 if (left is DoubleConstant)
1051 bool_res = ((DoubleConstant) left).Value ==
1052 ((DoubleConstant) right).Value;
1053 else if (left is FloatConstant)
1054 bool_res = ((FloatConstant) left).Value ==
1055 ((FloatConstant) right).Value;
1056 else if (left is ULongConstant)
1057 bool_res = ((ULongConstant) left).Value ==
1058 ((ULongConstant) right).Value;
1059 else if (left is LongConstant)
1060 bool_res = ((LongConstant) left).Value ==
1061 ((LongConstant) right).Value;
1062 else if (left is UIntConstant)
1063 bool_res = ((UIntConstant) left).Value ==
1064 ((UIntConstant) right).Value;
1065 else if (left is IntConstant)
1066 bool_res = ((IntConstant) left).Value ==
1067 ((IntConstant) right).Value;
1068 else
1069 return null;
1071 return new BoolConstant (bool_res);
1073 case Binary.Operator.Inequality:
1074 if (left is BoolConstant && right is BoolConstant){
1075 return new BoolConstant (
1076 ((BoolConstant) left).Value !=
1077 ((BoolConstant) right).Value);
1079 if (left is NullLiteral){
1080 if (right is NullLiteral)
1081 return new BoolConstant (false);
1082 else if (right is StringConstant)
1083 return new BoolConstant (
1084 ((StringConstant) right).Value != null);
1085 } else if (right is NullLiteral){
1086 if (left is NullLiteral)
1087 return new BoolConstant (false);
1088 else if (left is StringConstant)
1089 return new BoolConstant (
1090 ((StringConstant) left).Value != null);
1092 if (left is StringConstant && right is StringConstant){
1093 return new BoolConstant (
1094 ((StringConstant) left).Value !=
1095 ((StringConstant) right).Value);
1098 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1099 if (left == null || right == null)
1100 return null;
1102 bool_res = false;
1103 if (left is DoubleConstant)
1104 bool_res = ((DoubleConstant) left).Value !=
1105 ((DoubleConstant) right).Value;
1106 else if (left is FloatConstant)
1107 bool_res = ((FloatConstant) left).Value !=
1108 ((FloatConstant) right).Value;
1109 else if (left is ULongConstant)
1110 bool_res = ((ULongConstant) left).Value !=
1111 ((ULongConstant) right).Value;
1112 else if (left is LongConstant)
1113 bool_res = ((LongConstant) left).Value !=
1114 ((LongConstant) right).Value;
1115 else if (left is UIntConstant)
1116 bool_res = ((UIntConstant) left).Value !=
1117 ((UIntConstant) right).Value;
1118 else if (left is IntConstant)
1119 bool_res = ((IntConstant) left).Value !=
1120 ((IntConstant) right).Value;
1121 else
1122 return null;
1124 return new BoolConstant (bool_res);
1126 case Binary.Operator.LessThan:
1127 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1128 if (left == null || right == null)
1129 return null;
1131 bool_res = false;
1132 if (left is DoubleConstant)
1133 bool_res = ((DoubleConstant) left).Value <
1134 ((DoubleConstant) right).Value;
1135 else if (left is FloatConstant)
1136 bool_res = ((FloatConstant) left).Value <
1137 ((FloatConstant) right).Value;
1138 else if (left is ULongConstant)
1139 bool_res = ((ULongConstant) left).Value <
1140 ((ULongConstant) right).Value;
1141 else if (left is LongConstant)
1142 bool_res = ((LongConstant) left).Value <
1143 ((LongConstant) right).Value;
1144 else if (left is UIntConstant)
1145 bool_res = ((UIntConstant) left).Value <
1146 ((UIntConstant) right).Value;
1147 else if (left is IntConstant)
1148 bool_res = ((IntConstant) left).Value <
1149 ((IntConstant) right).Value;
1150 else
1151 return null;
1153 return new BoolConstant (bool_res);
1155 case Binary.Operator.GreaterThan:
1156 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1157 if (left == null || right == null)
1158 return null;
1160 bool_res = false;
1161 if (left is DoubleConstant)
1162 bool_res = ((DoubleConstant) left).Value >
1163 ((DoubleConstant) right).Value;
1164 else if (left is FloatConstant)
1165 bool_res = ((FloatConstant) left).Value >
1166 ((FloatConstant) right).Value;
1167 else if (left is ULongConstant)
1168 bool_res = ((ULongConstant) left).Value >
1169 ((ULongConstant) right).Value;
1170 else if (left is LongConstant)
1171 bool_res = ((LongConstant) left).Value >
1172 ((LongConstant) right).Value;
1173 else if (left is UIntConstant)
1174 bool_res = ((UIntConstant) left).Value >
1175 ((UIntConstant) right).Value;
1176 else if (left is IntConstant)
1177 bool_res = ((IntConstant) left).Value >
1178 ((IntConstant) right).Value;
1179 else
1180 return null;
1182 return new BoolConstant (bool_res);
1184 case Binary.Operator.GreaterThanOrEqual:
1185 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1186 if (left == null || right == null)
1187 return null;
1189 bool_res = false;
1190 if (left is DoubleConstant)
1191 bool_res = ((DoubleConstant) left).Value >=
1192 ((DoubleConstant) right).Value;
1193 else if (left is FloatConstant)
1194 bool_res = ((FloatConstant) left).Value >=
1195 ((FloatConstant) right).Value;
1196 else if (left is ULongConstant)
1197 bool_res = ((ULongConstant) left).Value >=
1198 ((ULongConstant) right).Value;
1199 else if (left is LongConstant)
1200 bool_res = ((LongConstant) left).Value >=
1201 ((LongConstant) right).Value;
1202 else if (left is UIntConstant)
1203 bool_res = ((UIntConstant) left).Value >=
1204 ((UIntConstant) right).Value;
1205 else if (left is IntConstant)
1206 bool_res = ((IntConstant) left).Value >=
1207 ((IntConstant) right).Value;
1208 else
1209 return null;
1211 return new BoolConstant (bool_res);
1213 case Binary.Operator.LessThanOrEqual:
1214 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1215 if (left == null || right == null)
1216 return null;
1218 bool_res = false;
1219 if (left is DoubleConstant)
1220 bool_res = ((DoubleConstant) left).Value <=
1221 ((DoubleConstant) right).Value;
1222 else if (left is FloatConstant)
1223 bool_res = ((FloatConstant) left).Value <=
1224 ((FloatConstant) right).Value;
1225 else if (left is ULongConstant)
1226 bool_res = ((ULongConstant) left).Value <=
1227 ((ULongConstant) right).Value;
1228 else if (left is LongConstant)
1229 bool_res = ((LongConstant) left).Value <=
1230 ((LongConstant) right).Value;
1231 else if (left is UIntConstant)
1232 bool_res = ((UIntConstant) left).Value <=
1233 ((UIntConstant) right).Value;
1234 else if (left is IntConstant)
1235 bool_res = ((IntConstant) left).Value <=
1236 ((IntConstant) right).Value;
1237 else
1238 return null;
1240 return new BoolConstant (bool_res);
1243 return null;