In ilasm/tests:
[mcs.git] / mcs / cfold.cs
blobfdf1ded3260ba34a5d2e6ba82c1d5b594d7729d0
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, ic.Location);
122 else
123 right = new UIntConstant ((uint) ic.Value, ic.Location);
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){
144 if (left is EnumConstant)
145 left = ((EnumConstant) left).Child;
146 if (right is EnumConstant)
147 right = ((EnumConstant) right).Child;
149 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
150 return;
152 } else {
154 // Force conversions to int32
156 if (!(left is IntConstant))
157 left = left.ToInt (loc);
158 if (!(right is IntConstant))
159 right = right.ToInt (loc);
161 return;
164 static void Error_CompileTimeOverflow (Location loc)
166 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
169 /// <summary>
170 /// Constant expression folder for binary operations.
172 /// Returns null if the expression can not be folded.
173 /// </summary>
174 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
175 Constant left, Constant right, Location loc)
177 if (left is NullCast)
178 return BinaryFold (ec, oper, ((NullCast)left).child, right, loc);
180 if (right is NullCast)
181 return BinaryFold (ec, oper, left, ((NullCast)right).child, loc);
183 Type lt = left.Type;
184 Type rt = right.Type;
185 Type result_type = null;
186 bool bool_res;
189 // Enumerator folding
191 if (rt == lt && left is EnumConstant)
192 result_type = lt;
195 // During an enum evaluation, we need to unwrap enumerations
197 if (ec.InEnumContext){
198 if (left is EnumConstant)
199 left = ((EnumConstant) left).Child;
201 if (right is EnumConstant)
202 right = ((EnumConstant) right).Child;
205 Type wrap_as;
206 Constant result = null;
207 switch (oper){
208 case Binary.Operator.BitwiseOr:
209 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
210 if (left == null || right == null)
211 return null;
213 if (left is IntConstant){
214 IntConstant v;
215 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
217 v = new IntConstant (res, left.Location);
218 if (result_type == null)
219 return v;
220 else
221 return new EnumConstant (v, result_type);
222 } else if (left is UIntConstant){
223 UIntConstant v;
224 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
226 v = new UIntConstant (res, left.Location);
227 if (result_type == null)
228 return v;
229 else
230 return new EnumConstant (v, result_type);
231 } else if (left is LongConstant){
232 LongConstant v;
233 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
235 v = new LongConstant (res, left.Location);
236 if (result_type == null)
237 return v;
238 else
239 return new EnumConstant (v, result_type);
240 } else if (left is ULongConstant){
241 ULongConstant v;
242 ulong res = ((ULongConstant)left).Value |
243 ((ULongConstant)right).Value;
245 v = new ULongConstant (res, left.Location);
246 if (result_type == null)
247 return v;
248 else
249 return new EnumConstant (v, result_type);
250 } else if (left is UShortConstant){
251 UShortConstant v;
252 ushort res = (ushort) (((UShortConstant)left).Value |
253 ((UShortConstant)right).Value);
255 v = new UShortConstant (res, left.Location);
256 if (result_type == null)
257 return v;
258 else
259 return new EnumConstant (v, result_type);
260 } else if (left is ShortConstant){
261 ShortConstant v;
262 short res = (short) (((ShortConstant)left).Value |
263 ((ShortConstant)right).Value);
265 v = new ShortConstant (res, left.Location);
266 if (result_type == null)
267 return v;
268 else
269 return new EnumConstant (v, result_type);
271 break;
273 case Binary.Operator.BitwiseAnd:
274 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
275 if (left == null || right == null)
276 return null;
278 if (left is IntConstant){
279 IntConstant v;
280 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
282 v = new IntConstant (res, left.Location);
283 if (result_type == null)
284 return v;
285 else
286 return new EnumConstant (v, result_type);
287 } else if (left is UIntConstant){
288 UIntConstant v;
289 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
291 v = new UIntConstant (res, left.Location);
292 if (result_type == null)
293 return v;
294 else
295 return new EnumConstant (v, result_type);
296 } else if (left is LongConstant){
297 LongConstant v;
298 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
300 v = new LongConstant (res, left.Location);
301 if (result_type == null)
302 return v;
303 else
304 return new EnumConstant (v, result_type);
305 } else if (left is ULongConstant){
306 ULongConstant v;
307 ulong res = ((ULongConstant)left).Value &
308 ((ULongConstant)right).Value;
310 v = new ULongConstant (res, left.Location);
311 if (result_type == null)
312 return v;
313 else
314 return new EnumConstant (v, result_type);
315 } else if (left is UShortConstant){
316 UShortConstant v;
317 ushort res = (ushort) (((UShortConstant)left).Value &
318 ((UShortConstant)right).Value);
320 v = new UShortConstant (res, left.Location);
321 if (result_type == null)
322 return v;
323 else
324 return new EnumConstant (v, result_type);
325 } else if (left is ShortConstant){
326 ShortConstant v;
327 short res = (short) (((ShortConstant)left).Value &
328 ((ShortConstant)right).Value);
330 v = new ShortConstant (res, left.Location);
331 if (result_type == null)
332 return v;
333 else
334 return new EnumConstant (v, result_type);
336 break;
338 case Binary.Operator.ExclusiveOr:
339 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
340 if (left == null || right == null)
341 return null;
343 if (left is IntConstant){
344 IntConstant v;
345 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
347 v = new IntConstant (res, left.Location);
348 if (result_type == null)
349 return v;
350 else
351 return new EnumConstant (v, result_type);
352 } else if (left is UIntConstant){
353 UIntConstant v;
354 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
356 v = new UIntConstant (res, left.Location);
357 if (result_type == null)
358 return v;
359 else
360 return new EnumConstant (v, result_type);
361 } else if (left is LongConstant){
362 LongConstant v;
363 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
365 v = new LongConstant (res, left.Location);
366 if (result_type == null)
367 return v;
368 else
369 return new EnumConstant (v, result_type);
370 } else if (left is ULongConstant){
371 ULongConstant v;
372 ulong res = ((ULongConstant)left).Value ^
373 ((ULongConstant)right).Value;
375 v = new ULongConstant (res, left.Location);
376 if (result_type == null)
377 return v;
378 else
379 return new EnumConstant (v, result_type);
380 } else if (left is UShortConstant){
381 UShortConstant v;
382 ushort res = (ushort) (((UShortConstant)left).Value ^
383 ((UShortConstant)right).Value);
385 v = new UShortConstant (res, left.Location);
386 if (result_type == null)
387 return v;
388 else
389 return new EnumConstant (v, result_type);
390 } else if (left is ShortConstant){
391 ShortConstant v;
392 short res = (short)(((ShortConstant)left).Value ^
393 ((ShortConstant)right).Value);
395 v = new ShortConstant (res, left.Location);
396 if (result_type == null)
397 return v;
398 else
399 return new EnumConstant (v, result_type);
401 break;
403 case Binary.Operator.Addition:
404 bool left_is_string = left is StringConstant;
405 bool right_is_string = right is StringConstant;
408 // If both sides are strings, then concatenate, if
409 // one is a string, and the other is not, then defer
410 // to runtime concatenation
412 wrap_as = null;
413 if (left_is_string || right_is_string){
414 if (left_is_string && right_is_string)
415 return new StringConstant (
416 ((StringConstant) left).Value +
417 ((StringConstant) right).Value, left.Location);
419 return null;
423 // handle "E operator + (E x, U y)"
424 // handle "E operator + (Y y, E x)"
426 // note that E operator + (E x, E y) is invalid
428 if (left is EnumConstant){
429 if (right is EnumConstant){
430 return null;
433 right = right.ToType (((EnumConstant) left).Child.Type, loc);
434 if (right == null)
435 return null;
437 wrap_as = left.Type;
438 } else if (right is EnumConstant){
439 left = left.ToType (((EnumConstant) right).Child.Type, loc);
440 if (left == null)
441 return null;
443 wrap_as = right.Type;
446 result = null;
447 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
448 if (left == null || right == null)
449 return null;
451 try {
452 if (left is DoubleConstant){
453 double res;
455 if (ec.ConstantCheckState)
456 res = checked (((DoubleConstant) left).Value +
457 ((DoubleConstant) right).Value);
458 else
459 res = unchecked (((DoubleConstant) left).Value +
460 ((DoubleConstant) right).Value);
462 result = new DoubleConstant (res, left.Location);
463 } else if (left is FloatConstant){
464 float res;
466 if (ec.ConstantCheckState)
467 res = checked (((FloatConstant) left).Value +
468 ((FloatConstant) right).Value);
469 else
470 res = unchecked (((FloatConstant) left).Value +
471 ((FloatConstant) right).Value);
473 result = new FloatConstant (res, left.Location);
474 } else if (left is ULongConstant){
475 ulong res;
477 if (ec.ConstantCheckState)
478 res = checked (((ULongConstant) left).Value +
479 ((ULongConstant) right).Value);
480 else
481 res = unchecked (((ULongConstant) left).Value +
482 ((ULongConstant) right).Value);
484 result = new ULongConstant (res, left.Location);
485 } else if (left is LongConstant){
486 long res;
488 if (ec.ConstantCheckState)
489 res = checked (((LongConstant) left).Value +
490 ((LongConstant) right).Value);
491 else
492 res = unchecked (((LongConstant) left).Value +
493 ((LongConstant) right).Value);
495 result = new LongConstant (res, left.Location);
496 } else if (left is UIntConstant){
497 uint res;
499 if (ec.ConstantCheckState)
500 res = checked (((UIntConstant) left).Value +
501 ((UIntConstant) right).Value);
502 else
503 res = unchecked (((UIntConstant) left).Value +
504 ((UIntConstant) right).Value);
506 result = new UIntConstant (res, left.Location);
507 } else if (left is IntConstant){
508 int res;
510 if (ec.ConstantCheckState)
511 res = checked (((IntConstant) left).Value +
512 ((IntConstant) right).Value);
513 else
514 res = unchecked (((IntConstant) left).Value +
515 ((IntConstant) right).Value);
517 result = new IntConstant (res, left.Location);
518 } else if (left is DecimalConstant) {
519 decimal res;
521 if (ec.ConstantCheckState)
522 res = checked (((DecimalConstant) left).Value +
523 ((DecimalConstant) right).Value);
524 else
525 res = unchecked (((DecimalConstant) left).Value +
526 ((DecimalConstant) right).Value);
528 result = new DecimalConstant (res, left.Location);
529 } else {
530 throw new Exception ( "Unexepected addition input: " + left);
532 } catch (OverflowException){
533 Error_CompileTimeOverflow (loc);
536 if (wrap_as != null)
537 return result.TryReduce (ec, wrap_as, loc);
538 else
539 return result;
541 case Binary.Operator.Subtraction:
543 // handle "E operator - (E x, U y)"
544 // handle "E operator - (Y y, E x)"
545 // handle "U operator - (E x, E y)"
547 wrap_as = null;
548 if (left is EnumConstant){
549 if (right is EnumConstant){
550 if (left.Type != right.Type) {
551 Binary.Error_OperatorCannotBeApplied (loc, "-", left.Type, right.Type);
552 return null;
555 wrap_as = TypeManager.EnumToUnderlying (left.Type);
556 right = ((EnumConstant) right).Child.ToType (wrap_as, loc);
557 if (right == null)
558 return null;
560 left = ((EnumConstant) left).Child.ToType (wrap_as, loc);
561 if (left == null)
562 return null;
564 else {
565 right = right.ToType (((EnumConstant) left).Child.Type, loc);
566 if (right == null)
567 return null;
569 wrap_as = left.Type;
571 } else if (right is EnumConstant){
572 left = left.ToType (((EnumConstant) right).Child.Type, loc);
573 if (left == null)
574 return null;
576 wrap_as = right.Type;
579 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
580 if (left == null || right == null)
581 return null;
583 try {
584 if (left is DoubleConstant){
585 double res;
587 if (ec.ConstantCheckState)
588 res = checked (((DoubleConstant) left).Value -
589 ((DoubleConstant) right).Value);
590 else
591 res = unchecked (((DoubleConstant) left).Value -
592 ((DoubleConstant) right).Value);
594 result = new DoubleConstant (res, left.Location);
595 } else if (left is FloatConstant){
596 float res;
598 if (ec.ConstantCheckState)
599 res = checked (((FloatConstant) left).Value -
600 ((FloatConstant) right).Value);
601 else
602 res = unchecked (((FloatConstant) left).Value -
603 ((FloatConstant) right).Value);
605 result = new FloatConstant (res, left.Location);
606 } else if (left is ULongConstant){
607 ulong res;
609 if (ec.ConstantCheckState)
610 res = checked (((ULongConstant) left).Value -
611 ((ULongConstant) right).Value);
612 else
613 res = unchecked (((ULongConstant) left).Value -
614 ((ULongConstant) right).Value);
616 result = new ULongConstant (res, left.Location);
617 } else if (left is LongConstant){
618 long res;
620 if (ec.ConstantCheckState)
621 res = checked (((LongConstant) left).Value -
622 ((LongConstant) right).Value);
623 else
624 res = unchecked (((LongConstant) left).Value -
625 ((LongConstant) right).Value);
627 result = new LongConstant (res, left.Location);
628 } else if (left is UIntConstant){
629 uint res;
631 if (ec.ConstantCheckState)
632 res = checked (((UIntConstant) left).Value -
633 ((UIntConstant) right).Value);
634 else
635 res = unchecked (((UIntConstant) left).Value -
636 ((UIntConstant) right).Value);
638 result = new UIntConstant (res, left.Location);
639 } else if (left is IntConstant){
640 int res;
642 if (ec.ConstantCheckState)
643 res = checked (((IntConstant) left).Value -
644 ((IntConstant) right).Value);
645 else
646 res = unchecked (((IntConstant) left).Value -
647 ((IntConstant) right).Value);
649 result = new IntConstant (res, left.Location);
650 } else if (left is DecimalConstant) {
651 decimal res;
653 if (ec.ConstantCheckState)
654 res = checked (((DecimalConstant) left).Value -
655 ((DecimalConstant) right).Value);
656 else
657 res = unchecked (((DecimalConstant) left).Value -
658 ((DecimalConstant) right).Value);
660 return new DecimalConstant (res, left.Location);
661 } else {
662 throw new Exception ( "Unexepected subtraction input: " + left);
664 } catch (OverflowException){
665 Error_CompileTimeOverflow (loc);
668 if (wrap_as != null)
669 return result.TryReduce (ec, wrap_as, loc);
671 return result;
673 case Binary.Operator.Multiply:
674 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
675 if (left == null || right == null)
676 return null;
678 try {
679 if (left is DoubleConstant){
680 double res;
682 if (ec.ConstantCheckState)
683 res = checked (((DoubleConstant) left).Value *
684 ((DoubleConstant) right).Value);
685 else
686 res = unchecked (((DoubleConstant) left).Value *
687 ((DoubleConstant) right).Value);
689 return new DoubleConstant (res, left.Location);
690 } else if (left is FloatConstant){
691 float res;
693 if (ec.ConstantCheckState)
694 res = checked (((FloatConstant) left).Value *
695 ((FloatConstant) right).Value);
696 else
697 res = unchecked (((FloatConstant) left).Value *
698 ((FloatConstant) right).Value);
700 return new FloatConstant (res, left.Location);
701 } else if (left is ULongConstant){
702 ulong res;
704 if (ec.ConstantCheckState)
705 res = checked (((ULongConstant) left).Value *
706 ((ULongConstant) right).Value);
707 else
708 res = unchecked (((ULongConstant) left).Value *
709 ((ULongConstant) right).Value);
711 return new ULongConstant (res, left.Location);
712 } else if (left is LongConstant){
713 long res;
715 if (ec.ConstantCheckState)
716 res = checked (((LongConstant) left).Value *
717 ((LongConstant) right).Value);
718 else
719 res = unchecked (((LongConstant) left).Value *
720 ((LongConstant) right).Value);
722 return new LongConstant (res, left.Location);
723 } else if (left is UIntConstant){
724 uint res;
726 if (ec.ConstantCheckState)
727 res = checked (((UIntConstant) left).Value *
728 ((UIntConstant) right).Value);
729 else
730 res = unchecked (((UIntConstant) left).Value *
731 ((UIntConstant) right).Value);
733 return new UIntConstant (res, left.Location);
734 } else if (left is IntConstant){
735 int res;
737 if (ec.ConstantCheckState)
738 res = checked (((IntConstant) left).Value *
739 ((IntConstant) right).Value);
740 else
741 res = unchecked (((IntConstant) left).Value *
742 ((IntConstant) right).Value);
744 return new IntConstant (res, left.Location);
745 } else if (left is DecimalConstant) {
746 decimal res;
748 if (ec.ConstantCheckState)
749 res = checked (((DecimalConstant) left).Value *
750 ((DecimalConstant) right).Value);
751 else
752 res = unchecked (((DecimalConstant) left).Value *
753 ((DecimalConstant) right).Value);
755 return new DecimalConstant (res, left.Location);
756 } else {
757 throw new Exception ( "Unexepected multiply input: " + left);
759 } catch (OverflowException){
760 Error_CompileTimeOverflow (loc);
762 break;
764 case Binary.Operator.Division:
765 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
766 if (left == null || right == null)
767 return null;
769 try {
770 if (left is DoubleConstant){
771 double res;
773 if (ec.ConstantCheckState)
774 res = checked (((DoubleConstant) left).Value /
775 ((DoubleConstant) right).Value);
776 else
777 res = unchecked (((DoubleConstant) left).Value /
778 ((DoubleConstant) right).Value);
780 return new DoubleConstant (res, left.Location);
781 } else if (left is FloatConstant){
782 float res;
784 if (ec.ConstantCheckState)
785 res = checked (((FloatConstant) left).Value /
786 ((FloatConstant) right).Value);
787 else
788 res = unchecked (((FloatConstant) left).Value /
789 ((FloatConstant) right).Value);
791 return new FloatConstant (res, left.Location);
792 } else if (left is ULongConstant){
793 ulong res;
795 if (ec.ConstantCheckState)
796 res = checked (((ULongConstant) left).Value /
797 ((ULongConstant) right).Value);
798 else
799 res = unchecked (((ULongConstant) left).Value /
800 ((ULongConstant) right).Value);
802 return new ULongConstant (res, left.Location);
803 } else if (left is LongConstant){
804 long res;
806 if (ec.ConstantCheckState)
807 res = checked (((LongConstant) left).Value /
808 ((LongConstant) right).Value);
809 else
810 res = unchecked (((LongConstant) left).Value /
811 ((LongConstant) right).Value);
813 return new LongConstant (res, left.Location);
814 } else if (left is UIntConstant){
815 uint res;
817 if (ec.ConstantCheckState)
818 res = checked (((UIntConstant) left).Value /
819 ((UIntConstant) right).Value);
820 else
821 res = unchecked (((UIntConstant) left).Value /
822 ((UIntConstant) right).Value);
824 return new UIntConstant (res, left.Location);
825 } else if (left is IntConstant){
826 int res;
828 if (ec.ConstantCheckState)
829 res = checked (((IntConstant) left).Value /
830 ((IntConstant) right).Value);
831 else
832 res = unchecked (((IntConstant) left).Value /
833 ((IntConstant) right).Value);
835 return new IntConstant (res, left.Location);
836 } else if (left is DecimalConstant) {
837 decimal res;
839 if (ec.ConstantCheckState)
840 res = checked (((DecimalConstant) left).Value /
841 ((DecimalConstant) right).Value);
842 else
843 res = unchecked (((DecimalConstant) left).Value /
844 ((DecimalConstant) right).Value);
846 return new DecimalConstant (res, left.Location);
847 } else {
848 throw new Exception ( "Unexepected division input: " + left);
850 } catch (OverflowException){
851 Error_CompileTimeOverflow (loc);
853 } catch (DivideByZeroException) {
854 Report.Error (020, loc, "Division by constant zero");
857 break;
859 case Binary.Operator.Modulus:
860 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
861 if (left == null || right == null)
862 return null;
864 try {
865 if (left is DoubleConstant){
866 double res;
868 if (ec.ConstantCheckState)
869 res = checked (((DoubleConstant) left).Value %
870 ((DoubleConstant) right).Value);
871 else
872 res = unchecked (((DoubleConstant) left).Value %
873 ((DoubleConstant) right).Value);
875 return new DoubleConstant (res, left.Location);
876 } else if (left is FloatConstant){
877 float res;
879 if (ec.ConstantCheckState)
880 res = checked (((FloatConstant) left).Value %
881 ((FloatConstant) right).Value);
882 else
883 res = unchecked (((FloatConstant) left).Value %
884 ((FloatConstant) right).Value);
886 return new FloatConstant (res, left.Location);
887 } else if (left is ULongConstant){
888 ulong res;
890 if (ec.ConstantCheckState)
891 res = checked (((ULongConstant) left).Value %
892 ((ULongConstant) right).Value);
893 else
894 res = unchecked (((ULongConstant) left).Value %
895 ((ULongConstant) right).Value);
897 return new ULongConstant (res, left.Location);
898 } else if (left is LongConstant){
899 long res;
901 if (ec.ConstantCheckState)
902 res = checked (((LongConstant) left).Value %
903 ((LongConstant) right).Value);
904 else
905 res = unchecked (((LongConstant) left).Value %
906 ((LongConstant) right).Value);
908 return new LongConstant (res, left.Location);
909 } else if (left is UIntConstant){
910 uint res;
912 if (ec.ConstantCheckState)
913 res = checked (((UIntConstant) left).Value %
914 ((UIntConstant) right).Value);
915 else
916 res = unchecked (((UIntConstant) left).Value %
917 ((UIntConstant) right).Value);
919 return new UIntConstant (res, left.Location);
920 } else if (left is IntConstant){
921 int res;
923 if (ec.ConstantCheckState)
924 res = checked (((IntConstant) left).Value %
925 ((IntConstant) right).Value);
926 else
927 res = unchecked (((IntConstant) left).Value %
928 ((IntConstant) right).Value);
930 return new IntConstant (res, left.Location);
931 } else {
932 throw new Exception ( "Unexepected modulus input: " + left);
934 } catch (DivideByZeroException){
935 Report.Error (020, loc, "Division by constant zero");
936 } catch (OverflowException){
937 Error_CompileTimeOverflow (loc);
939 break;
942 // There is no overflow checking on left shift
944 case Binary.Operator.LeftShift:
945 IntConstant ic = right.ToInt (loc);
946 if (ic == null){
947 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
948 return null;
950 int lshift_val = ic.Value;
952 IntConstant lic;
953 if ((lic = left.ConvertToInt ()) != null)
954 return new IntConstant (lic.Value << lshift_val, left.Location);
956 UIntConstant luic;
957 if ((luic = left.ConvertToUInt ()) != null)
958 return new UIntConstant (luic.Value << lshift_val, left.Location);
960 LongConstant llc;
961 if ((llc = left.ConvertToLong ()) != null)
962 return new LongConstant (llc.Value << lshift_val, left.Location);
964 ULongConstant lulc;
965 if ((lulc = left.ConvertToULong ()) != null)
966 return new ULongConstant (lulc.Value << lshift_val, left.Location);
968 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
969 break;
972 // There is no overflow checking on right shift
974 case Binary.Operator.RightShift:
975 IntConstant sic = right.ToInt (loc);
976 if (sic == null){
977 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
978 return null;
980 int rshift_val = sic.Value;
982 IntConstant ric;
983 if ((ric = left.ConvertToInt ()) != null)
984 return new IntConstant (ric.Value >> rshift_val, left.Location);
986 UIntConstant ruic;
987 if ((ruic = left.ConvertToUInt ()) != null)
988 return new UIntConstant (ruic.Value >> rshift_val, left.Location);
990 LongConstant rlc;
991 if ((rlc = left.ConvertToLong ()) != null)
992 return new LongConstant (rlc.Value >> rshift_val, left.Location);
994 ULongConstant rulc;
995 if ((rulc = left.ConvertToULong ()) != null)
996 return new ULongConstant (rulc.Value >> rshift_val, left.Location);
998 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
999 break;
1001 case Binary.Operator.LogicalAnd:
1002 if (left is BoolConstant && right is BoolConstant){
1003 return new BoolConstant (
1004 ((BoolConstant) left).Value &&
1005 ((BoolConstant) right).Value, left.Location);
1007 break;
1009 case Binary.Operator.LogicalOr:
1010 if (left is BoolConstant && right is BoolConstant){
1011 return new BoolConstant (
1012 ((BoolConstant) left).Value ||
1013 ((BoolConstant) right).Value, left.Location);
1015 break;
1017 case Binary.Operator.Equality:
1018 if (left is BoolConstant && right is BoolConstant){
1019 return new BoolConstant (
1020 ((BoolConstant) left).Value ==
1021 ((BoolConstant) right).Value, left.Location);
1024 if (left is NullLiteral){
1025 if (right is NullLiteral)
1026 return new BoolConstant (true, left.Location);
1027 else if (right is StringConstant)
1028 return new BoolConstant (
1029 ((StringConstant) right).Value == null, left.Location);
1030 } else if (right is NullLiteral){
1031 if (left is NullLiteral)
1032 return new BoolConstant (true, left.Location);
1033 else if (left is StringConstant)
1034 return new BoolConstant (
1035 ((StringConstant) left).Value == null, left.Location);
1037 if (left is StringConstant && right is StringConstant){
1038 return new BoolConstant (
1039 ((StringConstant) left).Value ==
1040 ((StringConstant) right).Value, left.Location);
1044 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1045 if (left == null || right == null)
1046 return null;
1048 bool_res = false;
1049 if (left is DoubleConstant)
1050 bool_res = ((DoubleConstant) left).Value ==
1051 ((DoubleConstant) right).Value;
1052 else if (left is FloatConstant)
1053 bool_res = ((FloatConstant) left).Value ==
1054 ((FloatConstant) right).Value;
1055 else if (left is ULongConstant)
1056 bool_res = ((ULongConstant) left).Value ==
1057 ((ULongConstant) right).Value;
1058 else if (left is LongConstant)
1059 bool_res = ((LongConstant) left).Value ==
1060 ((LongConstant) right).Value;
1061 else if (left is UIntConstant)
1062 bool_res = ((UIntConstant) left).Value ==
1063 ((UIntConstant) right).Value;
1064 else if (left is IntConstant)
1065 bool_res = ((IntConstant) left).Value ==
1066 ((IntConstant) right).Value;
1067 else
1068 return null;
1070 return new BoolConstant (bool_res, left.Location);
1072 case Binary.Operator.Inequality:
1073 if (left is BoolConstant && right is BoolConstant){
1074 return new BoolConstant (
1075 ((BoolConstant) left).Value !=
1076 ((BoolConstant) right).Value, left.Location);
1078 if (left is NullLiteral){
1079 if (right is NullLiteral)
1080 return new BoolConstant (false, left.Location);
1081 else if (right is StringConstant)
1082 return new BoolConstant (
1083 ((StringConstant) right).Value != null, left.Location);
1084 } else if (right is NullLiteral){
1085 if (left is NullLiteral)
1086 return new BoolConstant (false, left.Location);
1087 else if (left is StringConstant)
1088 return new BoolConstant (
1089 ((StringConstant) left).Value != null, left.Location);
1091 if (left is StringConstant && right is StringConstant){
1092 return new BoolConstant (
1093 ((StringConstant) left).Value !=
1094 ((StringConstant) right).Value, left.Location);
1097 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1098 if (left == null || right == null)
1099 return null;
1101 bool_res = false;
1102 if (left is DoubleConstant)
1103 bool_res = ((DoubleConstant) left).Value !=
1104 ((DoubleConstant) right).Value;
1105 else if (left is FloatConstant)
1106 bool_res = ((FloatConstant) left).Value !=
1107 ((FloatConstant) right).Value;
1108 else if (left is ULongConstant)
1109 bool_res = ((ULongConstant) left).Value !=
1110 ((ULongConstant) right).Value;
1111 else if (left is LongConstant)
1112 bool_res = ((LongConstant) left).Value !=
1113 ((LongConstant) right).Value;
1114 else if (left is UIntConstant)
1115 bool_res = ((UIntConstant) left).Value !=
1116 ((UIntConstant) right).Value;
1117 else if (left is IntConstant)
1118 bool_res = ((IntConstant) left).Value !=
1119 ((IntConstant) right).Value;
1120 else
1121 return null;
1123 return new BoolConstant (bool_res, left.Location);
1125 case Binary.Operator.LessThan:
1126 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1127 if (left == null || right == null)
1128 return null;
1130 bool_res = false;
1131 if (left is DoubleConstant)
1132 bool_res = ((DoubleConstant) left).Value <
1133 ((DoubleConstant) right).Value;
1134 else if (left is FloatConstant)
1135 bool_res = ((FloatConstant) left).Value <
1136 ((FloatConstant) right).Value;
1137 else if (left is ULongConstant)
1138 bool_res = ((ULongConstant) left).Value <
1139 ((ULongConstant) right).Value;
1140 else if (left is LongConstant)
1141 bool_res = ((LongConstant) left).Value <
1142 ((LongConstant) right).Value;
1143 else if (left is UIntConstant)
1144 bool_res = ((UIntConstant) left).Value <
1145 ((UIntConstant) right).Value;
1146 else if (left is IntConstant)
1147 bool_res = ((IntConstant) left).Value <
1148 ((IntConstant) right).Value;
1149 else
1150 return null;
1152 return new BoolConstant (bool_res, left.Location);
1154 case Binary.Operator.GreaterThan:
1155 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1156 if (left == null || right == null)
1157 return null;
1159 bool_res = false;
1160 if (left is DoubleConstant)
1161 bool_res = ((DoubleConstant) left).Value >
1162 ((DoubleConstant) right).Value;
1163 else if (left is FloatConstant)
1164 bool_res = ((FloatConstant) left).Value >
1165 ((FloatConstant) right).Value;
1166 else if (left is ULongConstant)
1167 bool_res = ((ULongConstant) left).Value >
1168 ((ULongConstant) right).Value;
1169 else if (left is LongConstant)
1170 bool_res = ((LongConstant) left).Value >
1171 ((LongConstant) right).Value;
1172 else if (left is UIntConstant)
1173 bool_res = ((UIntConstant) left).Value >
1174 ((UIntConstant) right).Value;
1175 else if (left is IntConstant)
1176 bool_res = ((IntConstant) left).Value >
1177 ((IntConstant) right).Value;
1178 else
1179 return null;
1181 return new BoolConstant (bool_res, left.Location);
1183 case Binary.Operator.GreaterThanOrEqual:
1184 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1185 if (left == null || right == null)
1186 return null;
1188 bool_res = false;
1189 if (left is DoubleConstant)
1190 bool_res = ((DoubleConstant) left).Value >=
1191 ((DoubleConstant) right).Value;
1192 else if (left is FloatConstant)
1193 bool_res = ((FloatConstant) left).Value >=
1194 ((FloatConstant) right).Value;
1195 else if (left is ULongConstant)
1196 bool_res = ((ULongConstant) left).Value >=
1197 ((ULongConstant) right).Value;
1198 else if (left is LongConstant)
1199 bool_res = ((LongConstant) left).Value >=
1200 ((LongConstant) right).Value;
1201 else if (left is UIntConstant)
1202 bool_res = ((UIntConstant) left).Value >=
1203 ((UIntConstant) right).Value;
1204 else if (left is IntConstant)
1205 bool_res = ((IntConstant) left).Value >=
1206 ((IntConstant) right).Value;
1207 else
1208 return null;
1210 return new BoolConstant (bool_res, left.Location);
1212 case Binary.Operator.LessThanOrEqual:
1213 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1214 if (left == null || right == null)
1215 return null;
1217 bool_res = false;
1218 if (left is DoubleConstant)
1219 bool_res = ((DoubleConstant) left).Value <=
1220 ((DoubleConstant) right).Value;
1221 else if (left is FloatConstant)
1222 bool_res = ((FloatConstant) left).Value <=
1223 ((FloatConstant) right).Value;
1224 else if (left is ULongConstant)
1225 bool_res = ((ULongConstant) left).Value <=
1226 ((ULongConstant) right).Value;
1227 else if (left is LongConstant)
1228 bool_res = ((LongConstant) left).Value <=
1229 ((LongConstant) right).Value;
1230 else if (left is UIntConstant)
1231 bool_res = ((UIntConstant) left).Value <=
1232 ((UIntConstant) right).Value;
1233 else if (left is IntConstant)
1234 bool_res = ((IntConstant) left).Value <=
1235 ((IntConstant) right).Value;
1236 else
1237 return null;
1239 return new BoolConstant (bool_res, left.Location);
1242 return null;