2006-04-27 Jonathan Chambers <jonathan.chambers@ansys.com>
[mcs.git] / gmcs / cfold.cs
blobaba3ad37c485097ae96c089ed69eba1aa676322f
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 if (left is BoolConstant && right is BoolConstant) {
206 bool lv = ((BoolConstant) left ).Value;
207 bool rv = ((BoolConstant) right).Value;
208 switch (oper) {
209 case Binary.Operator.BitwiseAnd:
210 case Binary.Operator.LogicalAnd:
211 return new BoolConstant (lv && rv, left.Location);
212 case Binary.Operator.BitwiseOr:
213 case Binary.Operator.LogicalOr:
214 return new BoolConstant (lv || rv, left.Location);
215 case Binary.Operator.ExclusiveOr:
216 return new BoolConstant (lv ^ rv, left.Location);
217 default:
218 throw new InternalErrorException ("Invalid operator on booleans: " + oper);
222 Type wrap_as;
223 Constant result = null;
224 switch (oper){
225 case Binary.Operator.BitwiseOr:
226 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
227 if (left == null || right == null)
228 return null;
230 if (left is IntConstant){
231 IntConstant v;
232 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
234 v = new IntConstant (res, left.Location);
235 if (result_type == null)
236 return v;
237 else
238 return new EnumConstant (v, result_type);
239 } else if (left is UIntConstant){
240 UIntConstant v;
241 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
243 v = new UIntConstant (res, left.Location);
244 if (result_type == null)
245 return v;
246 else
247 return new EnumConstant (v, result_type);
248 } else if (left is LongConstant){
249 LongConstant v;
250 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
252 v = new LongConstant (res, left.Location);
253 if (result_type == null)
254 return v;
255 else
256 return new EnumConstant (v, result_type);
257 } else if (left is ULongConstant){
258 ULongConstant v;
259 ulong res = ((ULongConstant)left).Value |
260 ((ULongConstant)right).Value;
262 v = new ULongConstant (res, left.Location);
263 if (result_type == null)
264 return v;
265 else
266 return new EnumConstant (v, result_type);
267 } else if (left is UShortConstant){
268 UShortConstant v;
269 ushort res = (ushort) (((UShortConstant)left).Value |
270 ((UShortConstant)right).Value);
272 v = new UShortConstant (res, left.Location);
273 if (result_type == null)
274 return v;
275 else
276 return new EnumConstant (v, result_type);
277 } else if (left is ShortConstant){
278 ShortConstant v;
279 short res = (short) (((ShortConstant)left).Value |
280 ((ShortConstant)right).Value);
282 v = new ShortConstant (res, left.Location);
283 if (result_type == null)
284 return v;
285 else
286 return new EnumConstant (v, result_type);
288 break;
290 case Binary.Operator.BitwiseAnd:
291 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
292 if (left == null || right == null)
293 return null;
295 if (left is IntConstant){
296 IntConstant v;
297 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
299 v = new IntConstant (res, left.Location);
300 if (result_type == null)
301 return v;
302 else
303 return new EnumConstant (v, result_type);
304 } else if (left is UIntConstant){
305 UIntConstant v;
306 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
308 v = new UIntConstant (res, left.Location);
309 if (result_type == null)
310 return v;
311 else
312 return new EnumConstant (v, result_type);
313 } else if (left is LongConstant){
314 LongConstant v;
315 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
317 v = new LongConstant (res, left.Location);
318 if (result_type == null)
319 return v;
320 else
321 return new EnumConstant (v, result_type);
322 } else if (left is ULongConstant){
323 ULongConstant v;
324 ulong res = ((ULongConstant)left).Value &
325 ((ULongConstant)right).Value;
327 v = new ULongConstant (res, left.Location);
328 if (result_type == null)
329 return v;
330 else
331 return new EnumConstant (v, result_type);
332 } else if (left is UShortConstant){
333 UShortConstant v;
334 ushort res = (ushort) (((UShortConstant)left).Value &
335 ((UShortConstant)right).Value);
337 v = new UShortConstant (res, left.Location);
338 if (result_type == null)
339 return v;
340 else
341 return new EnumConstant (v, result_type);
342 } else if (left is ShortConstant){
343 ShortConstant v;
344 short res = (short) (((ShortConstant)left).Value &
345 ((ShortConstant)right).Value);
347 v = new ShortConstant (res, left.Location);
348 if (result_type == null)
349 return v;
350 else
351 return new EnumConstant (v, result_type);
353 break;
355 case Binary.Operator.ExclusiveOr:
356 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
357 if (left == null || right == null)
358 return null;
360 if (left is IntConstant){
361 IntConstant v;
362 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
364 v = new IntConstant (res, left.Location);
365 if (result_type == null)
366 return v;
367 else
368 return new EnumConstant (v, result_type);
369 } else if (left is UIntConstant){
370 UIntConstant v;
371 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
373 v = new UIntConstant (res, left.Location);
374 if (result_type == null)
375 return v;
376 else
377 return new EnumConstant (v, result_type);
378 } else if (left is LongConstant){
379 LongConstant v;
380 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
382 v = new LongConstant (res, left.Location);
383 if (result_type == null)
384 return v;
385 else
386 return new EnumConstant (v, result_type);
387 } else if (left is ULongConstant){
388 ULongConstant v;
389 ulong res = ((ULongConstant)left).Value ^
390 ((ULongConstant)right).Value;
392 v = new ULongConstant (res, left.Location);
393 if (result_type == null)
394 return v;
395 else
396 return new EnumConstant (v, result_type);
397 } else if (left is UShortConstant){
398 UShortConstant v;
399 ushort res = (ushort) (((UShortConstant)left).Value ^
400 ((UShortConstant)right).Value);
402 v = new UShortConstant (res, left.Location);
403 if (result_type == null)
404 return v;
405 else
406 return new EnumConstant (v, result_type);
407 } else if (left is ShortConstant){
408 ShortConstant v;
409 short res = (short)(((ShortConstant)left).Value ^
410 ((ShortConstant)right).Value);
412 v = new ShortConstant (res, left.Location);
413 if (result_type == null)
414 return v;
415 else
416 return new EnumConstant (v, result_type);
418 break;
420 case Binary.Operator.Addition:
421 bool left_is_string = left is StringConstant;
422 bool right_is_string = right is StringConstant;
425 // If both sides are strings, then concatenate, if
426 // one is a string, and the other is not, then defer
427 // to runtime concatenation
429 wrap_as = null;
430 if (left_is_string || right_is_string){
431 if (left_is_string && right_is_string)
432 return new StringConstant (
433 ((StringConstant) left).Value +
434 ((StringConstant) right).Value, left.Location);
436 return null;
440 // handle "E operator + (E x, U y)"
441 // handle "E operator + (Y y, E x)"
443 // note that E operator + (E x, E y) is invalid
445 if (left is EnumConstant){
446 if (right is EnumConstant){
447 return null;
450 right = right.ToType (((EnumConstant) left).Child.Type, loc);
451 if (right == null)
452 return null;
454 wrap_as = left.Type;
455 } else if (right is EnumConstant){
456 left = left.ToType (((EnumConstant) right).Child.Type, loc);
457 if (left == null)
458 return null;
460 wrap_as = right.Type;
463 result = null;
464 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
465 if (left == null || right == null)
466 return null;
468 try {
469 if (left is DoubleConstant){
470 double res;
472 if (ec.ConstantCheckState)
473 res = checked (((DoubleConstant) left).Value +
474 ((DoubleConstant) right).Value);
475 else
476 res = unchecked (((DoubleConstant) left).Value +
477 ((DoubleConstant) right).Value);
479 result = new DoubleConstant (res, left.Location);
480 } else if (left is FloatConstant){
481 float res;
483 if (ec.ConstantCheckState)
484 res = checked (((FloatConstant) left).Value +
485 ((FloatConstant) right).Value);
486 else
487 res = unchecked (((FloatConstant) left).Value +
488 ((FloatConstant) right).Value);
490 result = new FloatConstant (res, left.Location);
491 } else if (left is ULongConstant){
492 ulong res;
494 if (ec.ConstantCheckState)
495 res = checked (((ULongConstant) left).Value +
496 ((ULongConstant) right).Value);
497 else
498 res = unchecked (((ULongConstant) left).Value +
499 ((ULongConstant) right).Value);
501 result = new ULongConstant (res, left.Location);
502 } else if (left is LongConstant){
503 long res;
505 if (ec.ConstantCheckState)
506 res = checked (((LongConstant) left).Value +
507 ((LongConstant) right).Value);
508 else
509 res = unchecked (((LongConstant) left).Value +
510 ((LongConstant) right).Value);
512 result = new LongConstant (res, left.Location);
513 } else if (left is UIntConstant){
514 uint res;
516 if (ec.ConstantCheckState)
517 res = checked (((UIntConstant) left).Value +
518 ((UIntConstant) right).Value);
519 else
520 res = unchecked (((UIntConstant) left).Value +
521 ((UIntConstant) right).Value);
523 result = new UIntConstant (res, left.Location);
524 } else if (left is IntConstant){
525 int res;
527 if (ec.ConstantCheckState)
528 res = checked (((IntConstant) left).Value +
529 ((IntConstant) right).Value);
530 else
531 res = unchecked (((IntConstant) left).Value +
532 ((IntConstant) right).Value);
534 result = new IntConstant (res, left.Location);
535 } else if (left is DecimalConstant) {
536 decimal res;
538 if (ec.ConstantCheckState)
539 res = checked (((DecimalConstant) left).Value +
540 ((DecimalConstant) right).Value);
541 else
542 res = unchecked (((DecimalConstant) left).Value +
543 ((DecimalConstant) right).Value);
545 result = new DecimalConstant (res, left.Location);
546 } else {
547 throw new Exception ( "Unexepected addition input: " + left);
549 } catch (OverflowException){
550 Error_CompileTimeOverflow (loc);
553 if (wrap_as != null) {
554 try {
555 return result.TryReduce (ec, wrap_as, loc);
557 catch (OverflowException) {
558 return null;
561 else
562 return result;
564 case Binary.Operator.Subtraction:
566 // handle "E operator - (E x, U y)"
567 // handle "E operator - (Y y, E x)"
568 // handle "U operator - (E x, E y)"
570 wrap_as = null;
571 if (left is EnumConstant){
572 if (right is EnumConstant){
573 if (left.Type != right.Type) {
574 Binary.Error_OperatorCannotBeApplied (loc, "-", left.Type, right.Type);
575 return null;
578 wrap_as = TypeManager.EnumToUnderlying (left.Type);
579 right = ((EnumConstant) right).Child.ToType (wrap_as, loc);
580 if (right == null)
581 return null;
583 left = ((EnumConstant) left).Child.ToType (wrap_as, loc);
584 if (left == null)
585 return null;
587 else {
588 right = right.ToType (((EnumConstant) left).Child.Type, loc);
589 if (right == null)
590 return null;
592 wrap_as = left.Type;
594 } else if (right is EnumConstant){
595 left = left.ToType (((EnumConstant) right).Child.Type, loc);
596 if (left == null)
597 return null;
599 wrap_as = right.Type;
602 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
603 if (left == null || right == null)
604 return null;
606 try {
607 if (left is DoubleConstant){
608 double res;
610 if (ec.ConstantCheckState)
611 res = checked (((DoubleConstant) left).Value -
612 ((DoubleConstant) right).Value);
613 else
614 res = unchecked (((DoubleConstant) left).Value -
615 ((DoubleConstant) right).Value);
617 result = new DoubleConstant (res, left.Location);
618 } else if (left is FloatConstant){
619 float res;
621 if (ec.ConstantCheckState)
622 res = checked (((FloatConstant) left).Value -
623 ((FloatConstant) right).Value);
624 else
625 res = unchecked (((FloatConstant) left).Value -
626 ((FloatConstant) right).Value);
628 result = new FloatConstant (res, left.Location);
629 } else if (left is ULongConstant){
630 ulong res;
632 if (ec.ConstantCheckState)
633 res = checked (((ULongConstant) left).Value -
634 ((ULongConstant) right).Value);
635 else
636 res = unchecked (((ULongConstant) left).Value -
637 ((ULongConstant) right).Value);
639 result = new ULongConstant (res, left.Location);
640 } else if (left is LongConstant){
641 long res;
643 if (ec.ConstantCheckState)
644 res = checked (((LongConstant) left).Value -
645 ((LongConstant) right).Value);
646 else
647 res = unchecked (((LongConstant) left).Value -
648 ((LongConstant) right).Value);
650 result = new LongConstant (res, left.Location);
651 } else if (left is UIntConstant){
652 uint res;
654 if (ec.ConstantCheckState)
655 res = checked (((UIntConstant) left).Value -
656 ((UIntConstant) right).Value);
657 else
658 res = unchecked (((UIntConstant) left).Value -
659 ((UIntConstant) right).Value);
661 result = new UIntConstant (res, left.Location);
662 } else if (left is IntConstant){
663 int res;
665 if (ec.ConstantCheckState)
666 res = checked (((IntConstant) left).Value -
667 ((IntConstant) right).Value);
668 else
669 res = unchecked (((IntConstant) left).Value -
670 ((IntConstant) right).Value);
672 result = new IntConstant (res, left.Location);
673 } else if (left is DecimalConstant) {
674 decimal res;
676 if (ec.ConstantCheckState)
677 res = checked (((DecimalConstant) left).Value -
678 ((DecimalConstant) right).Value);
679 else
680 res = unchecked (((DecimalConstant) left).Value -
681 ((DecimalConstant) right).Value);
683 return new DecimalConstant (res, left.Location);
684 } else {
685 throw new Exception ( "Unexepected subtraction input: " + left);
687 } catch (OverflowException){
688 Error_CompileTimeOverflow (loc);
691 if (wrap_as != null) {
692 try {
693 return result.TryReduce (ec, wrap_as, loc);
695 catch (OverflowException) {
696 return null;
700 return result;
702 case Binary.Operator.Multiply:
703 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
704 if (left == null || right == null)
705 return null;
707 try {
708 if (left is DoubleConstant){
709 double res;
711 if (ec.ConstantCheckState)
712 res = checked (((DoubleConstant) left).Value *
713 ((DoubleConstant) right).Value);
714 else
715 res = unchecked (((DoubleConstant) left).Value *
716 ((DoubleConstant) right).Value);
718 return new DoubleConstant (res, left.Location);
719 } else if (left is FloatConstant){
720 float res;
722 if (ec.ConstantCheckState)
723 res = checked (((FloatConstant) left).Value *
724 ((FloatConstant) right).Value);
725 else
726 res = unchecked (((FloatConstant) left).Value *
727 ((FloatConstant) right).Value);
729 return new FloatConstant (res, left.Location);
730 } else if (left is ULongConstant){
731 ulong res;
733 if (ec.ConstantCheckState)
734 res = checked (((ULongConstant) left).Value *
735 ((ULongConstant) right).Value);
736 else
737 res = unchecked (((ULongConstant) left).Value *
738 ((ULongConstant) right).Value);
740 return new ULongConstant (res, left.Location);
741 } else if (left is LongConstant){
742 long res;
744 if (ec.ConstantCheckState)
745 res = checked (((LongConstant) left).Value *
746 ((LongConstant) right).Value);
747 else
748 res = unchecked (((LongConstant) left).Value *
749 ((LongConstant) right).Value);
751 return new LongConstant (res, left.Location);
752 } else if (left is UIntConstant){
753 uint res;
755 if (ec.ConstantCheckState)
756 res = checked (((UIntConstant) left).Value *
757 ((UIntConstant) right).Value);
758 else
759 res = unchecked (((UIntConstant) left).Value *
760 ((UIntConstant) right).Value);
762 return new UIntConstant (res, left.Location);
763 } else if (left is IntConstant){
764 int res;
766 if (ec.ConstantCheckState)
767 res = checked (((IntConstant) left).Value *
768 ((IntConstant) right).Value);
769 else
770 res = unchecked (((IntConstant) left).Value *
771 ((IntConstant) right).Value);
773 return new IntConstant (res, left.Location);
774 } else if (left is DecimalConstant) {
775 decimal res;
777 if (ec.ConstantCheckState)
778 res = checked (((DecimalConstant) left).Value *
779 ((DecimalConstant) right).Value);
780 else
781 res = unchecked (((DecimalConstant) left).Value *
782 ((DecimalConstant) right).Value);
784 return new DecimalConstant (res, left.Location);
785 } else {
786 throw new Exception ( "Unexepected multiply input: " + left);
788 } catch (OverflowException){
789 Error_CompileTimeOverflow (loc);
791 break;
793 case Binary.Operator.Division:
794 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
795 if (left == null || right == null)
796 return null;
798 try {
799 if (left is DoubleConstant){
800 double res;
802 if (ec.ConstantCheckState)
803 res = checked (((DoubleConstant) left).Value /
804 ((DoubleConstant) right).Value);
805 else
806 res = unchecked (((DoubleConstant) left).Value /
807 ((DoubleConstant) right).Value);
809 return new DoubleConstant (res, left.Location);
810 } else if (left is FloatConstant){
811 float res;
813 if (ec.ConstantCheckState)
814 res = checked (((FloatConstant) left).Value /
815 ((FloatConstant) right).Value);
816 else
817 res = unchecked (((FloatConstant) left).Value /
818 ((FloatConstant) right).Value);
820 return new FloatConstant (res, left.Location);
821 } else if (left is ULongConstant){
822 ulong res;
824 if (ec.ConstantCheckState)
825 res = checked (((ULongConstant) left).Value /
826 ((ULongConstant) right).Value);
827 else
828 res = unchecked (((ULongConstant) left).Value /
829 ((ULongConstant) right).Value);
831 return new ULongConstant (res, left.Location);
832 } else if (left is LongConstant){
833 long res;
835 if (ec.ConstantCheckState)
836 res = checked (((LongConstant) left).Value /
837 ((LongConstant) right).Value);
838 else
839 res = unchecked (((LongConstant) left).Value /
840 ((LongConstant) right).Value);
842 return new LongConstant (res, left.Location);
843 } else if (left is UIntConstant){
844 uint res;
846 if (ec.ConstantCheckState)
847 res = checked (((UIntConstant) left).Value /
848 ((UIntConstant) right).Value);
849 else
850 res = unchecked (((UIntConstant) left).Value /
851 ((UIntConstant) right).Value);
853 return new UIntConstant (res, left.Location);
854 } else if (left is IntConstant){
855 int res;
857 if (ec.ConstantCheckState)
858 res = checked (((IntConstant) left).Value /
859 ((IntConstant) right).Value);
860 else
861 res = unchecked (((IntConstant) left).Value /
862 ((IntConstant) right).Value);
864 return new IntConstant (res, left.Location);
865 } else if (left is DecimalConstant) {
866 decimal res;
868 if (ec.ConstantCheckState)
869 res = checked (((DecimalConstant) left).Value /
870 ((DecimalConstant) right).Value);
871 else
872 res = unchecked (((DecimalConstant) left).Value /
873 ((DecimalConstant) right).Value);
875 return new DecimalConstant (res, left.Location);
876 } else {
877 throw new Exception ( "Unexepected division input: " + left);
879 } catch (OverflowException){
880 Error_CompileTimeOverflow (loc);
882 } catch (DivideByZeroException) {
883 Report.Error (020, loc, "Division by constant zero");
886 break;
888 case Binary.Operator.Modulus:
889 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
890 if (left == null || right == null)
891 return null;
893 try {
894 if (left is DoubleConstant){
895 double res;
897 if (ec.ConstantCheckState)
898 res = checked (((DoubleConstant) left).Value %
899 ((DoubleConstant) right).Value);
900 else
901 res = unchecked (((DoubleConstant) left).Value %
902 ((DoubleConstant) right).Value);
904 return new DoubleConstant (res, left.Location);
905 } else if (left is FloatConstant){
906 float res;
908 if (ec.ConstantCheckState)
909 res = checked (((FloatConstant) left).Value %
910 ((FloatConstant) right).Value);
911 else
912 res = unchecked (((FloatConstant) left).Value %
913 ((FloatConstant) right).Value);
915 return new FloatConstant (res, left.Location);
916 } else if (left is ULongConstant){
917 ulong res;
919 if (ec.ConstantCheckState)
920 res = checked (((ULongConstant) left).Value %
921 ((ULongConstant) right).Value);
922 else
923 res = unchecked (((ULongConstant) left).Value %
924 ((ULongConstant) right).Value);
926 return new ULongConstant (res, left.Location);
927 } else if (left is LongConstant){
928 long res;
930 if (ec.ConstantCheckState)
931 res = checked (((LongConstant) left).Value %
932 ((LongConstant) right).Value);
933 else
934 res = unchecked (((LongConstant) left).Value %
935 ((LongConstant) right).Value);
937 return new LongConstant (res, left.Location);
938 } else if (left is UIntConstant){
939 uint res;
941 if (ec.ConstantCheckState)
942 res = checked (((UIntConstant) left).Value %
943 ((UIntConstant) right).Value);
944 else
945 res = unchecked (((UIntConstant) left).Value %
946 ((UIntConstant) right).Value);
948 return new UIntConstant (res, left.Location);
949 } else if (left is IntConstant){
950 int res;
952 if (ec.ConstantCheckState)
953 res = checked (((IntConstant) left).Value %
954 ((IntConstant) right).Value);
955 else
956 res = unchecked (((IntConstant) left).Value %
957 ((IntConstant) right).Value);
959 return new IntConstant (res, left.Location);
960 } else {
961 throw new Exception ( "Unexepected modulus input: " + left);
963 } catch (DivideByZeroException){
964 Report.Error (020, loc, "Division by constant zero");
965 } catch (OverflowException){
966 Error_CompileTimeOverflow (loc);
968 break;
971 // There is no overflow checking on left shift
973 case Binary.Operator.LeftShift:
974 IntConstant ic = right.ToInt (loc);
975 if (ic == null){
976 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
977 return null;
979 int lshift_val = ic.Value;
981 IntConstant lic;
982 if ((lic = left.ConvertToInt ()) != null)
983 return new IntConstant (lic.Value << lshift_val, left.Location);
985 UIntConstant luic;
986 if ((luic = left.ConvertToUInt ()) != null)
987 return new UIntConstant (luic.Value << lshift_val, left.Location);
989 LongConstant llc;
990 if ((llc = left.ConvertToLong ()) != null)
991 return new LongConstant (llc.Value << lshift_val, left.Location);
993 ULongConstant lulc;
994 if ((lulc = left.ConvertToULong ()) != null)
995 return new ULongConstant (lulc.Value << lshift_val, left.Location);
997 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
998 break;
1001 // There is no overflow checking on right shift
1003 case Binary.Operator.RightShift:
1004 IntConstant sic = right.ToInt (loc);
1005 if (sic == null){
1006 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1007 return null;
1009 int rshift_val = sic.Value;
1011 IntConstant ric;
1012 if ((ric = left.ConvertToInt ()) != null)
1013 return new IntConstant (ric.Value >> rshift_val, left.Location);
1015 UIntConstant ruic;
1016 if ((ruic = left.ConvertToUInt ()) != null)
1017 return new UIntConstant (ruic.Value >> rshift_val, left.Location);
1019 LongConstant rlc;
1020 if ((rlc = left.ConvertToLong ()) != null)
1021 return new LongConstant (rlc.Value >> rshift_val, left.Location);
1023 ULongConstant rulc;
1024 if ((rulc = left.ConvertToULong ()) != null)
1025 return new ULongConstant (rulc.Value >> rshift_val, left.Location);
1027 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
1028 break;
1030 case Binary.Operator.Equality:
1031 if (left is BoolConstant && right is BoolConstant){
1032 return new BoolConstant (
1033 ((BoolConstant) left).Value ==
1034 ((BoolConstant) right).Value, left.Location);
1037 if (left is NullLiteral){
1038 if (right is NullLiteral)
1039 return new BoolConstant (true, left.Location);
1040 else if (right is StringConstant)
1041 return new BoolConstant (
1042 ((StringConstant) right).Value == null, left.Location);
1043 } else if (right is NullLiteral){
1044 if (left is NullLiteral)
1045 return new BoolConstant (true, left.Location);
1046 else if (left is StringConstant)
1047 return new BoolConstant (
1048 ((StringConstant) left).Value == null, left.Location);
1050 if (left is StringConstant && right is StringConstant){
1051 return new BoolConstant (
1052 ((StringConstant) left).Value ==
1053 ((StringConstant) right).Value, left.Location);
1057 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1058 if (left == null || right == null)
1059 return null;
1061 bool_res = false;
1062 if (left is DoubleConstant)
1063 bool_res = ((DoubleConstant) left).Value ==
1064 ((DoubleConstant) right).Value;
1065 else if (left is FloatConstant)
1066 bool_res = ((FloatConstant) left).Value ==
1067 ((FloatConstant) right).Value;
1068 else if (left is ULongConstant)
1069 bool_res = ((ULongConstant) left).Value ==
1070 ((ULongConstant) right).Value;
1071 else if (left is LongConstant)
1072 bool_res = ((LongConstant) left).Value ==
1073 ((LongConstant) right).Value;
1074 else if (left is UIntConstant)
1075 bool_res = ((UIntConstant) left).Value ==
1076 ((UIntConstant) right).Value;
1077 else if (left is IntConstant)
1078 bool_res = ((IntConstant) left).Value ==
1079 ((IntConstant) right).Value;
1080 else
1081 return null;
1083 return new BoolConstant (bool_res, left.Location);
1085 case Binary.Operator.Inequality:
1086 if (left is BoolConstant && right is BoolConstant){
1087 return new BoolConstant (
1088 ((BoolConstant) left).Value !=
1089 ((BoolConstant) right).Value, left.Location);
1091 if (left is NullLiteral){
1092 if (right is NullLiteral)
1093 return new BoolConstant (false, left.Location);
1094 else if (right is StringConstant)
1095 return new BoolConstant (
1096 ((StringConstant) right).Value != null, left.Location);
1097 } else if (right is NullLiteral){
1098 if (left is NullLiteral)
1099 return new BoolConstant (false, left.Location);
1100 else if (left is StringConstant)
1101 return new BoolConstant (
1102 ((StringConstant) left).Value != null, left.Location);
1104 if (left is StringConstant && right is StringConstant){
1105 return new BoolConstant (
1106 ((StringConstant) left).Value !=
1107 ((StringConstant) right).Value, left.Location);
1110 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1111 if (left == null || right == null)
1112 return null;
1114 bool_res = false;
1115 if (left is DoubleConstant)
1116 bool_res = ((DoubleConstant) left).Value !=
1117 ((DoubleConstant) right).Value;
1118 else if (left is FloatConstant)
1119 bool_res = ((FloatConstant) left).Value !=
1120 ((FloatConstant) right).Value;
1121 else if (left is ULongConstant)
1122 bool_res = ((ULongConstant) left).Value !=
1123 ((ULongConstant) right).Value;
1124 else if (left is LongConstant)
1125 bool_res = ((LongConstant) left).Value !=
1126 ((LongConstant) right).Value;
1127 else if (left is UIntConstant)
1128 bool_res = ((UIntConstant) left).Value !=
1129 ((UIntConstant) right).Value;
1130 else if (left is IntConstant)
1131 bool_res = ((IntConstant) left).Value !=
1132 ((IntConstant) right).Value;
1133 else
1134 return null;
1136 return new BoolConstant (bool_res, left.Location);
1138 case Binary.Operator.LessThan:
1139 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1140 if (left == null || right == null)
1141 return null;
1143 bool_res = false;
1144 if (left is DoubleConstant)
1145 bool_res = ((DoubleConstant) left).Value <
1146 ((DoubleConstant) right).Value;
1147 else if (left is FloatConstant)
1148 bool_res = ((FloatConstant) left).Value <
1149 ((FloatConstant) right).Value;
1150 else if (left is ULongConstant)
1151 bool_res = ((ULongConstant) left).Value <
1152 ((ULongConstant) right).Value;
1153 else if (left is LongConstant)
1154 bool_res = ((LongConstant) left).Value <
1155 ((LongConstant) right).Value;
1156 else if (left is UIntConstant)
1157 bool_res = ((UIntConstant) left).Value <
1158 ((UIntConstant) right).Value;
1159 else if (left is IntConstant)
1160 bool_res = ((IntConstant) left).Value <
1161 ((IntConstant) right).Value;
1162 else
1163 return null;
1165 return new BoolConstant (bool_res, left.Location);
1167 case Binary.Operator.GreaterThan:
1168 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1169 if (left == null || right == null)
1170 return null;
1172 bool_res = false;
1173 if (left is DoubleConstant)
1174 bool_res = ((DoubleConstant) left).Value >
1175 ((DoubleConstant) right).Value;
1176 else if (left is FloatConstant)
1177 bool_res = ((FloatConstant) left).Value >
1178 ((FloatConstant) right).Value;
1179 else if (left is ULongConstant)
1180 bool_res = ((ULongConstant) left).Value >
1181 ((ULongConstant) right).Value;
1182 else if (left is LongConstant)
1183 bool_res = ((LongConstant) left).Value >
1184 ((LongConstant) right).Value;
1185 else if (left is UIntConstant)
1186 bool_res = ((UIntConstant) left).Value >
1187 ((UIntConstant) right).Value;
1188 else if (left is IntConstant)
1189 bool_res = ((IntConstant) left).Value >
1190 ((IntConstant) right).Value;
1191 else
1192 return null;
1194 return new BoolConstant (bool_res, left.Location);
1196 case Binary.Operator.GreaterThanOrEqual:
1197 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1198 if (left == null || right == null)
1199 return null;
1201 bool_res = false;
1202 if (left is DoubleConstant)
1203 bool_res = ((DoubleConstant) left).Value >=
1204 ((DoubleConstant) right).Value;
1205 else if (left is FloatConstant)
1206 bool_res = ((FloatConstant) left).Value >=
1207 ((FloatConstant) right).Value;
1208 else if (left is ULongConstant)
1209 bool_res = ((ULongConstant) left).Value >=
1210 ((ULongConstant) right).Value;
1211 else if (left is LongConstant)
1212 bool_res = ((LongConstant) left).Value >=
1213 ((LongConstant) right).Value;
1214 else if (left is UIntConstant)
1215 bool_res = ((UIntConstant) left).Value >=
1216 ((UIntConstant) right).Value;
1217 else if (left is IntConstant)
1218 bool_res = ((IntConstant) left).Value >=
1219 ((IntConstant) right).Value;
1220 else
1221 return null;
1223 return new BoolConstant (bool_res, left.Location);
1225 case Binary.Operator.LessThanOrEqual:
1226 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1227 if (left == null || right == null)
1228 return null;
1230 bool_res = false;
1231 if (left is DoubleConstant)
1232 bool_res = ((DoubleConstant) left).Value <=
1233 ((DoubleConstant) right).Value;
1234 else if (left is FloatConstant)
1235 bool_res = ((FloatConstant) left).Value <=
1236 ((FloatConstant) right).Value;
1237 else if (left is ULongConstant)
1238 bool_res = ((ULongConstant) left).Value <=
1239 ((ULongConstant) right).Value;
1240 else if (left is LongConstant)
1241 bool_res = ((LongConstant) left).Value <=
1242 ((LongConstant) right).Value;
1243 else if (left is UIntConstant)
1244 bool_res = ((UIntConstant) left).Value <=
1245 ((UIntConstant) right).Value;
1246 else if (left is IntConstant)
1247 bool_res = ((IntConstant) left).Value <=
1248 ((IntConstant) right).Value;
1249 else
1250 return null;
1252 return new BoolConstant (bool_res, left.Location);
1255 return null;