(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / mcs / cfold.cs
blob12999eccdd858e3627f29b560e25e400fd17dcd2
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 EnumConstant || right is EnumConstant){
139 // If either operand is an enum constant, the other one must
140 // be implicitly convertable to that enum's underlying type.
142 EnumConstant match;
143 Constant other;
144 if (left is EnumConstant){
145 other = right;
146 match = (EnumConstant) left;
147 } else {
148 other = left;
149 match = (EnumConstant) right;
152 bool need_check = (other is EnumConstant) ||
153 ((oper != Binary.Operator.Addition) &&
154 (oper != Binary.Operator.Subtraction));
156 if (need_check &&
157 !Convert.ImplicitConversionExists (ec, match, other.Type)) {
158 Convert.Error_CannotImplicitConversion (loc, match.Type, other.Type);
159 left = null;
160 right = null;
161 return;
164 if (left is EnumConstant)
165 left = ((EnumConstant) left).Child;
166 if (right is EnumConstant)
167 right = ((EnumConstant) right).Child;
168 return;
170 } else {
172 // Force conversions to int32
174 if (!(left is IntConstant))
175 left = left.ToInt (loc);
176 if (!(right is IntConstant))
177 right = right.ToInt (loc);
179 return;
182 static void Error_CompileTimeOverflow (Location loc)
184 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
187 /// <summary>
188 /// Constant expression folder for binary operations.
190 /// Returns null if the expression can not be folded.
191 /// </summary>
192 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
193 Constant left, Constant right, Location loc)
195 Type lt = left.Type;
196 Type rt = right.Type;
197 Type result_type = null;
198 bool bool_res;
201 // Enumerator folding
203 if (rt == lt && left is EnumConstant)
204 result_type = lt;
207 // During an enum evaluation, we need to unwrap enumerations
209 if (ec.InEnumContext){
210 if (left is EnumConstant)
211 left = ((EnumConstant) left).Child;
213 if (right is EnumConstant)
214 right = ((EnumConstant) right).Child;
217 Type wrap_as;
218 Constant result = null;
219 switch (oper){
220 case Binary.Operator.BitwiseOr:
221 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
222 if (left == null || right == null)
223 return null;
225 if (left is IntConstant){
226 IntConstant v;
227 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
229 v = new IntConstant (res);
230 if (result_type == null)
231 return v;
232 else
233 return new EnumConstant (v, result_type);
234 } else if (left is UIntConstant){
235 UIntConstant v;
236 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
238 v = new UIntConstant (res);
239 if (result_type == null)
240 return v;
241 else
242 return new EnumConstant (v, result_type);
243 } else if (left is LongConstant){
244 LongConstant v;
245 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
247 v = new LongConstant (res);
248 if (result_type == null)
249 return v;
250 else
251 return new EnumConstant (v, result_type);
252 } else if (left is ULongConstant){
253 ULongConstant v;
254 ulong res = ((ULongConstant)left).Value |
255 ((ULongConstant)right).Value;
257 v = new ULongConstant (res);
258 if (result_type == null)
259 return v;
260 else
261 return new EnumConstant (v, result_type);
262 } else if (left is UShortConstant){
263 UShortConstant v;
264 ushort res = (ushort) (((UShortConstant)left).Value |
265 ((UShortConstant)right).Value);
267 v = new UShortConstant (res);
268 if (result_type == null)
269 return v;
270 else
271 return new EnumConstant (v, result_type);
272 } else if (left is ShortConstant){
273 ShortConstant v;
274 short res = (short) (((ShortConstant)left).Value |
275 ((ShortConstant)right).Value);
277 v = new ShortConstant (res);
278 if (result_type == null)
279 return v;
280 else
281 return new EnumConstant (v, result_type);
283 break;
285 case Binary.Operator.BitwiseAnd:
286 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
287 if (left == null || right == null)
288 return null;
290 if (left is IntConstant){
291 IntConstant v;
292 int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
294 v = new IntConstant (res);
295 if (result_type == null)
296 return v;
297 else
298 return new EnumConstant (v, result_type);
299 } else if (left is UIntConstant){
300 UIntConstant v;
301 uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
303 v = new UIntConstant (res);
304 if (result_type == null)
305 return v;
306 else
307 return new EnumConstant (v, result_type);
308 } else if (left is LongConstant){
309 LongConstant v;
310 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
312 v = new LongConstant (res);
313 if (result_type == null)
314 return v;
315 else
316 return new EnumConstant (v, result_type);
317 } else if (left is ULongConstant){
318 ULongConstant v;
319 ulong res = ((ULongConstant)left).Value &
320 ((ULongConstant)right).Value;
322 v = new ULongConstant (res);
323 if (result_type == null)
324 return v;
325 else
326 return new EnumConstant (v, result_type);
327 } else if (left is UShortConstant){
328 UShortConstant v;
329 ushort res = (ushort) (((UShortConstant)left).Value &
330 ((UShortConstant)right).Value);
332 v = new UShortConstant (res);
333 if (result_type == null)
334 return v;
335 else
336 return new EnumConstant (v, result_type);
337 } else if (left is ShortConstant){
338 ShortConstant v;
339 short res = (short) (((ShortConstant)left).Value &
340 ((ShortConstant)right).Value);
342 v = new ShortConstant (res);
343 if (result_type == null)
344 return v;
345 else
346 return new EnumConstant (v, result_type);
348 break;
350 case Binary.Operator.ExclusiveOr:
351 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
352 if (left == null || right == null)
353 return null;
355 if (left is IntConstant){
356 IntConstant v;
357 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
359 v = new IntConstant (res);
360 if (result_type == null)
361 return v;
362 else
363 return new EnumConstant (v, result_type);
364 } else if (left is UIntConstant){
365 UIntConstant v;
366 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
368 v = new UIntConstant (res);
369 if (result_type == null)
370 return v;
371 else
372 return new EnumConstant (v, result_type);
373 } else if (left is LongConstant){
374 LongConstant v;
375 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
377 v = new LongConstant (res);
378 if (result_type == null)
379 return v;
380 else
381 return new EnumConstant (v, result_type);
382 } else if (left is ULongConstant){
383 ULongConstant v;
384 ulong res = ((ULongConstant)left).Value ^
385 ((ULongConstant)right).Value;
387 v = new ULongConstant (res);
388 if (result_type == null)
389 return v;
390 else
391 return new EnumConstant (v, result_type);
392 } else if (left is UShortConstant){
393 UShortConstant v;
394 ushort res = (ushort) (((UShortConstant)left).Value ^
395 ((UShortConstant)right).Value);
397 v = new UShortConstant (res);
398 if (result_type == null)
399 return v;
400 else
401 return new EnumConstant (v, result_type);
402 } else if (left is ShortConstant){
403 ShortConstant v;
404 short res = (short)(((ShortConstant)left).Value ^
405 ((ShortConstant)right).Value);
407 v = new ShortConstant (res);
408 if (result_type == null)
409 return v;
410 else
411 return new EnumConstant (v, result_type);
413 break;
415 case Binary.Operator.Addition:
416 bool left_is_string = left is StringConstant;
417 bool right_is_string = right is StringConstant;
420 // If both sides are strings, then concatenate, if
421 // one is a string, and the other is not, then defer
422 // to runtime concatenation
424 wrap_as = null;
425 if (left_is_string || right_is_string){
426 if (left_is_string && right_is_string)
427 return new StringConstant (
428 ((StringConstant) left).Value +
429 ((StringConstant) right).Value);
431 return null;
435 // handle "E operator + (E x, U y)"
436 // handle "E operator + (Y y, E x)"
438 // note that E operator + (E x, E y) is invalid
440 if (left is EnumConstant){
441 if (right is EnumConstant){
442 return null;
444 if (((EnumConstant) left).Child.Type != right.Type)
445 return null;
447 wrap_as = left.Type;
448 } else if (right is EnumConstant){
449 if (((EnumConstant) right).Child.Type != left.Type)
450 return null;
451 wrap_as = right.Type;
454 result = null;
455 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
456 if (left == null || right == null)
457 return null;
459 try {
460 if (left is DoubleConstant){
461 double res;
463 if (ec.ConstantCheckState)
464 res = checked (((DoubleConstant) left).Value +
465 ((DoubleConstant) right).Value);
466 else
467 res = unchecked (((DoubleConstant) left).Value +
468 ((DoubleConstant) right).Value);
470 result = new DoubleConstant (res);
471 } else if (left is FloatConstant){
472 float res;
474 if (ec.ConstantCheckState)
475 res = checked (((FloatConstant) left).Value +
476 ((FloatConstant) right).Value);
477 else
478 res = unchecked (((FloatConstant) left).Value +
479 ((FloatConstant) right).Value);
481 result = new FloatConstant (res);
482 } else if (left is ULongConstant){
483 ulong res;
485 if (ec.ConstantCheckState)
486 res = checked (((ULongConstant) left).Value +
487 ((ULongConstant) right).Value);
488 else
489 res = unchecked (((ULongConstant) left).Value +
490 ((ULongConstant) right).Value);
492 result = new ULongConstant (res);
493 } else if (left is LongConstant){
494 long res;
496 if (ec.ConstantCheckState)
497 res = checked (((LongConstant) left).Value +
498 ((LongConstant) right).Value);
499 else
500 res = unchecked (((LongConstant) left).Value +
501 ((LongConstant) right).Value);
503 result = new LongConstant (res);
504 } else if (left is UIntConstant){
505 uint res;
507 if (ec.ConstantCheckState)
508 res = checked (((UIntConstant) left).Value +
509 ((UIntConstant) right).Value);
510 else
511 res = unchecked (((UIntConstant) left).Value +
512 ((UIntConstant) right).Value);
514 result = new UIntConstant (res);
515 } else if (left is IntConstant){
516 int res;
518 if (ec.ConstantCheckState)
519 res = checked (((IntConstant) left).Value +
520 ((IntConstant) right).Value);
521 else
522 res = unchecked (((IntConstant) left).Value +
523 ((IntConstant) right).Value);
525 result = new IntConstant (res);
526 } else {
527 throw new Exception ( "Unexepected input: " + left);
529 } catch (OverflowException){
530 Error_CompileTimeOverflow (loc);
533 if (wrap_as != null)
534 return new EnumConstant (result, wrap_as);
535 else
536 return result;
538 case Binary.Operator.Subtraction:
540 // handle "E operator - (E x, U y)"
541 // handle "E operator - (Y y, E x)"
542 // handle "U operator - (E x, E y)"
544 wrap_as = null;
545 if (left is EnumConstant){
546 if (right is EnumConstant){
547 if (left.Type == right.Type)
548 wrap_as = TypeManager.EnumToUnderlying (left.Type);
549 else
550 return null;
552 if (((EnumConstant) left).Child.Type != right.Type)
553 return null;
555 wrap_as = left.Type;
556 } else if (right is EnumConstant){
557 if (((EnumConstant) right).Child.Type != left.Type)
558 return null;
559 wrap_as = right.Type;
562 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
563 if (left == null || right == null)
564 return null;
566 try {
567 if (left is DoubleConstant){
568 double res;
570 if (ec.ConstantCheckState)
571 res = checked (((DoubleConstant) left).Value -
572 ((DoubleConstant) right).Value);
573 else
574 res = unchecked (((DoubleConstant) left).Value -
575 ((DoubleConstant) right).Value);
577 result = new DoubleConstant (res);
578 } else if (left is FloatConstant){
579 float res;
581 if (ec.ConstantCheckState)
582 res = checked (((FloatConstant) left).Value -
583 ((FloatConstant) right).Value);
584 else
585 res = unchecked (((FloatConstant) left).Value -
586 ((FloatConstant) right).Value);
588 result = new FloatConstant (res);
589 } else if (left is ULongConstant){
590 ulong res;
592 if (ec.ConstantCheckState)
593 res = checked (((ULongConstant) left).Value -
594 ((ULongConstant) right).Value);
595 else
596 res = unchecked (((ULongConstant) left).Value -
597 ((ULongConstant) right).Value);
599 result = new ULongConstant (res);
600 } else if (left is LongConstant){
601 long res;
603 if (ec.ConstantCheckState)
604 res = checked (((LongConstant) left).Value -
605 ((LongConstant) right).Value);
606 else
607 res = unchecked (((LongConstant) left).Value -
608 ((LongConstant) right).Value);
610 result = new LongConstant (res);
611 } else if (left is UIntConstant){
612 uint res;
614 if (ec.ConstantCheckState)
615 res = checked (((UIntConstant) left).Value -
616 ((UIntConstant) right).Value);
617 else
618 res = unchecked (((UIntConstant) left).Value -
619 ((UIntConstant) right).Value);
621 result = new UIntConstant (res);
622 } else if (left is IntConstant){
623 int res;
625 if (ec.ConstantCheckState)
626 res = checked (((IntConstant) left).Value -
627 ((IntConstant) right).Value);
628 else
629 res = unchecked (((IntConstant) left).Value -
630 ((IntConstant) right).Value);
632 result = new IntConstant (res);
633 } else {
634 throw new Exception ( "Unexepected input: " + left);
636 } catch (OverflowException){
637 Error_CompileTimeOverflow (loc);
639 if (wrap_as != null)
640 return new EnumConstant (result, wrap_as);
641 else
642 return result;
644 case Binary.Operator.Multiply:
645 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
646 if (left == null || right == null)
647 return null;
649 try {
650 if (left is DoubleConstant){
651 double res;
653 if (ec.ConstantCheckState)
654 res = checked (((DoubleConstant) left).Value *
655 ((DoubleConstant) right).Value);
656 else
657 res = unchecked (((DoubleConstant) left).Value *
658 ((DoubleConstant) right).Value);
660 return new DoubleConstant (res);
661 } else if (left is FloatConstant){
662 float res;
664 if (ec.ConstantCheckState)
665 res = checked (((FloatConstant) left).Value *
666 ((FloatConstant) right).Value);
667 else
668 res = unchecked (((FloatConstant) left).Value *
669 ((FloatConstant) right).Value);
671 return new FloatConstant (res);
672 } else if (left is ULongConstant){
673 ulong res;
675 if (ec.ConstantCheckState)
676 res = checked (((ULongConstant) left).Value *
677 ((ULongConstant) right).Value);
678 else
679 res = unchecked (((ULongConstant) left).Value *
680 ((ULongConstant) right).Value);
682 return new ULongConstant (res);
683 } else if (left is LongConstant){
684 long res;
686 if (ec.ConstantCheckState)
687 res = checked (((LongConstant) left).Value *
688 ((LongConstant) right).Value);
689 else
690 res = unchecked (((LongConstant) left).Value *
691 ((LongConstant) right).Value);
693 return new LongConstant (res);
694 } else if (left is UIntConstant){
695 uint res;
697 if (ec.ConstantCheckState)
698 res = checked (((UIntConstant) left).Value *
699 ((UIntConstant) right).Value);
700 else
701 res = unchecked (((UIntConstant) left).Value *
702 ((UIntConstant) right).Value);
704 return new UIntConstant (res);
705 } else if (left is IntConstant){
706 int res;
708 if (ec.ConstantCheckState)
709 res = checked (((IntConstant) left).Value *
710 ((IntConstant) right).Value);
711 else
712 res = unchecked (((IntConstant) left).Value *
713 ((IntConstant) right).Value);
715 return new IntConstant (res);
716 } else {
717 throw new Exception ( "Unexepected input: " + left);
719 } catch (OverflowException){
720 Error_CompileTimeOverflow (loc);
722 break;
724 case Binary.Operator.Division:
725 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
726 if (left == null || right == null)
727 return null;
729 try {
730 if (left is DoubleConstant){
731 double res;
733 if (ec.ConstantCheckState)
734 res = checked (((DoubleConstant) left).Value /
735 ((DoubleConstant) right).Value);
736 else
737 res = unchecked (((DoubleConstant) left).Value /
738 ((DoubleConstant) right).Value);
740 return new DoubleConstant (res);
741 } else if (left is FloatConstant){
742 float res;
744 if (ec.ConstantCheckState)
745 res = checked (((FloatConstant) left).Value /
746 ((FloatConstant) right).Value);
747 else
748 res = unchecked (((FloatConstant) left).Value /
749 ((FloatConstant) right).Value);
751 return new FloatConstant (res);
752 } else if (left is ULongConstant){
753 ulong res;
755 if (ec.ConstantCheckState)
756 res = checked (((ULongConstant) left).Value /
757 ((ULongConstant) right).Value);
758 else
759 res = unchecked (((ULongConstant) left).Value /
760 ((ULongConstant) right).Value);
762 return new ULongConstant (res);
763 } else if (left is LongConstant){
764 long res;
766 if (ec.ConstantCheckState)
767 res = checked (((LongConstant) left).Value /
768 ((LongConstant) right).Value);
769 else
770 res = unchecked (((LongConstant) left).Value /
771 ((LongConstant) right).Value);
773 return new LongConstant (res);
774 } else if (left is UIntConstant){
775 uint res;
777 if (ec.ConstantCheckState)
778 res = checked (((UIntConstant) left).Value /
779 ((UIntConstant) right).Value);
780 else
781 res = unchecked (((UIntConstant) left).Value /
782 ((UIntConstant) right).Value);
784 return new UIntConstant (res);
785 } else if (left is IntConstant){
786 int res;
788 if (ec.ConstantCheckState)
789 res = checked (((IntConstant) left).Value /
790 ((IntConstant) right).Value);
791 else
792 res = unchecked (((IntConstant) left).Value /
793 ((IntConstant) right).Value);
795 return new IntConstant (res);
796 } else {
797 throw new Exception ( "Unexepected input: " + left);
799 } catch (OverflowException){
800 Error_CompileTimeOverflow (loc);
802 } catch (DivideByZeroException) {
803 Report.Error (020, loc, "Division by constant zero");
806 break;
808 case Binary.Operator.Modulus:
809 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
810 if (left == null || right == null)
811 return null;
813 try {
814 if (left is DoubleConstant){
815 double res;
817 if (ec.ConstantCheckState)
818 res = checked (((DoubleConstant) left).Value %
819 ((DoubleConstant) right).Value);
820 else
821 res = unchecked (((DoubleConstant) left).Value %
822 ((DoubleConstant) right).Value);
824 return new DoubleConstant (res);
825 } else if (left is FloatConstant){
826 float res;
828 if (ec.ConstantCheckState)
829 res = checked (((FloatConstant) left).Value %
830 ((FloatConstant) right).Value);
831 else
832 res = unchecked (((FloatConstant) left).Value %
833 ((FloatConstant) right).Value);
835 return new FloatConstant (res);
836 } else if (left is ULongConstant){
837 ulong res;
839 if (ec.ConstantCheckState)
840 res = checked (((ULongConstant) left).Value %
841 ((ULongConstant) right).Value);
842 else
843 res = unchecked (((ULongConstant) left).Value %
844 ((ULongConstant) right).Value);
846 return new ULongConstant (res);
847 } else if (left is LongConstant){
848 long res;
850 if (ec.ConstantCheckState)
851 res = checked (((LongConstant) left).Value %
852 ((LongConstant) right).Value);
853 else
854 res = unchecked (((LongConstant) left).Value %
855 ((LongConstant) right).Value);
857 return new LongConstant (res);
858 } else if (left is UIntConstant){
859 uint res;
861 if (ec.ConstantCheckState)
862 res = checked (((UIntConstant) left).Value %
863 ((UIntConstant) right).Value);
864 else
865 res = unchecked (((UIntConstant) left).Value %
866 ((UIntConstant) right).Value);
868 return new UIntConstant (res);
869 } else if (left is IntConstant){
870 int res;
872 if (ec.ConstantCheckState)
873 res = checked (((IntConstant) left).Value %
874 ((IntConstant) right).Value);
875 else
876 res = unchecked (((IntConstant) left).Value %
877 ((IntConstant) right).Value);
879 return new IntConstant (res);
880 } else {
881 throw new Exception ( "Unexepected input: " + left);
883 } catch (DivideByZeroException){
884 Report.Error (020, loc, "Division by constant zero");
885 } catch (OverflowException){
886 Error_CompileTimeOverflow (loc);
888 break;
891 // There is no overflow checking on left shift
893 case Binary.Operator.LeftShift:
894 IntConstant ic = right.ToInt (loc);
895 if (ic == null){
896 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
897 return null;
899 int lshift_val = ic.Value;
901 IntConstant lic;
902 if ((lic = left.ConvertToInt ()) != null)
903 return new IntConstant (lic.Value << lshift_val);
905 UIntConstant luic;
906 if ((luic = left.ConvertToUInt ()) != null)
907 return new UIntConstant (luic.Value << lshift_val);
909 LongConstant llc;
910 if ((llc = left.ConvertToLong ()) != null)
911 return new LongConstant (llc.Value << lshift_val);
913 ULongConstant lulc;
914 if ((lulc = left.ConvertToULong ()) != null)
915 return new ULongConstant (lulc.Value << lshift_val);
917 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
918 break;
921 // There is no overflow checking on right shift
923 case Binary.Operator.RightShift:
924 IntConstant sic = right.ToInt (loc);
925 if (sic == null){
926 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
927 return null;
929 int rshift_val = sic.Value;
931 IntConstant ric;
932 if ((ric = left.ConvertToInt ()) != null)
933 return new IntConstant (ric.Value >> rshift_val);
935 UIntConstant ruic;
936 if ((ruic = left.ConvertToUInt ()) != null)
937 return new UIntConstant (ruic.Value >> rshift_val);
939 LongConstant rlc;
940 if ((rlc = left.ConvertToLong ()) != null)
941 return new LongConstant (rlc.Value >> rshift_val);
943 ULongConstant rulc;
944 if ((rulc = left.ConvertToULong ()) != null)
945 return new ULongConstant (rulc.Value >> rshift_val);
947 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
948 break;
950 case Binary.Operator.LogicalAnd:
951 if (left is BoolConstant && right is BoolConstant){
952 return new BoolConstant (
953 ((BoolConstant) left).Value &&
954 ((BoolConstant) right).Value);
956 break;
958 case Binary.Operator.LogicalOr:
959 if (left is BoolConstant && right is BoolConstant){
960 return new BoolConstant (
961 ((BoolConstant) left).Value ||
962 ((BoolConstant) right).Value);
964 break;
966 case Binary.Operator.Equality:
967 if (left is BoolConstant && right is BoolConstant){
968 return new BoolConstant (
969 ((BoolConstant) left).Value ==
970 ((BoolConstant) right).Value);
973 if (left is NullLiteral){
974 if (right is NullLiteral)
975 return new BoolConstant (true);
976 else if (right is StringConstant)
977 return new BoolConstant (
978 ((StringConstant) right).Value == null);
979 } else if (right is NullLiteral){
980 if (left is NullLiteral)
981 return new BoolConstant (true);
982 else if (left is StringConstant)
983 return new BoolConstant (
984 ((StringConstant) left).Value == null);
986 if (left is StringConstant && right is StringConstant){
987 return new BoolConstant (
988 ((StringConstant) left).Value ==
989 ((StringConstant) right).Value);
993 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
994 if (left == null || right == null)
995 return null;
997 bool_res = false;
998 if (left is DoubleConstant)
999 bool_res = ((DoubleConstant) left).Value ==
1000 ((DoubleConstant) right).Value;
1001 else if (left is FloatConstant)
1002 bool_res = ((FloatConstant) left).Value ==
1003 ((FloatConstant) right).Value;
1004 else if (left is ULongConstant)
1005 bool_res = ((ULongConstant) left).Value ==
1006 ((ULongConstant) right).Value;
1007 else if (left is LongConstant)
1008 bool_res = ((LongConstant) left).Value ==
1009 ((LongConstant) right).Value;
1010 else if (left is UIntConstant)
1011 bool_res = ((UIntConstant) left).Value ==
1012 ((UIntConstant) right).Value;
1013 else if (left is IntConstant)
1014 bool_res = ((IntConstant) left).Value ==
1015 ((IntConstant) right).Value;
1016 else
1017 return null;
1019 return new BoolConstant (bool_res);
1021 case Binary.Operator.Inequality:
1022 if (left is BoolConstant && right is BoolConstant){
1023 return new BoolConstant (
1024 ((BoolConstant) left).Value !=
1025 ((BoolConstant) right).Value);
1027 if (left is NullLiteral){
1028 if (right is NullLiteral)
1029 return new BoolConstant (false);
1030 else if (right is StringConstant)
1031 return new BoolConstant (
1032 ((StringConstant) right).Value != null);
1033 } else if (right is NullLiteral){
1034 if (left is NullLiteral)
1035 return new BoolConstant (false);
1036 else if (left is StringConstant)
1037 return new BoolConstant (
1038 ((StringConstant) left).Value != null);
1040 if (left is StringConstant && right is StringConstant){
1041 return new BoolConstant (
1042 ((StringConstant) left).Value !=
1043 ((StringConstant) right).Value);
1046 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1047 if (left == null || right == null)
1048 return null;
1050 bool_res = false;
1051 if (left is DoubleConstant)
1052 bool_res = ((DoubleConstant) left).Value !=
1053 ((DoubleConstant) right).Value;
1054 else if (left is FloatConstant)
1055 bool_res = ((FloatConstant) left).Value !=
1056 ((FloatConstant) right).Value;
1057 else if (left is ULongConstant)
1058 bool_res = ((ULongConstant) left).Value !=
1059 ((ULongConstant) right).Value;
1060 else if (left is LongConstant)
1061 bool_res = ((LongConstant) left).Value !=
1062 ((LongConstant) right).Value;
1063 else if (left is UIntConstant)
1064 bool_res = ((UIntConstant) left).Value !=
1065 ((UIntConstant) right).Value;
1066 else if (left is IntConstant)
1067 bool_res = ((IntConstant) left).Value !=
1068 ((IntConstant) right).Value;
1069 else
1070 return null;
1072 return new BoolConstant (bool_res);
1074 case Binary.Operator.LessThan:
1075 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1076 if (left == null || right == null)
1077 return null;
1079 bool_res = false;
1080 if (left is DoubleConstant)
1081 bool_res = ((DoubleConstant) left).Value <
1082 ((DoubleConstant) right).Value;
1083 else if (left is FloatConstant)
1084 bool_res = ((FloatConstant) left).Value <
1085 ((FloatConstant) right).Value;
1086 else if (left is ULongConstant)
1087 bool_res = ((ULongConstant) left).Value <
1088 ((ULongConstant) right).Value;
1089 else if (left is LongConstant)
1090 bool_res = ((LongConstant) left).Value <
1091 ((LongConstant) right).Value;
1092 else if (left is UIntConstant)
1093 bool_res = ((UIntConstant) left).Value <
1094 ((UIntConstant) right).Value;
1095 else if (left is IntConstant)
1096 bool_res = ((IntConstant) left).Value <
1097 ((IntConstant) right).Value;
1098 else
1099 return null;
1101 return new BoolConstant (bool_res);
1103 case Binary.Operator.GreaterThan:
1104 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1105 if (left == null || right == null)
1106 return null;
1108 bool_res = false;
1109 if (left is DoubleConstant)
1110 bool_res = ((DoubleConstant) left).Value >
1111 ((DoubleConstant) right).Value;
1112 else if (left is FloatConstant)
1113 bool_res = ((FloatConstant) left).Value >
1114 ((FloatConstant) right).Value;
1115 else if (left is ULongConstant)
1116 bool_res = ((ULongConstant) left).Value >
1117 ((ULongConstant) right).Value;
1118 else if (left is LongConstant)
1119 bool_res = ((LongConstant) left).Value >
1120 ((LongConstant) right).Value;
1121 else if (left is UIntConstant)
1122 bool_res = ((UIntConstant) left).Value >
1123 ((UIntConstant) right).Value;
1124 else if (left is IntConstant)
1125 bool_res = ((IntConstant) left).Value >
1126 ((IntConstant) right).Value;
1127 else
1128 return null;
1130 return new BoolConstant (bool_res);
1132 case Binary.Operator.GreaterThanOrEqual:
1133 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1134 if (left == null || right == null)
1135 return null;
1137 bool_res = false;
1138 if (left is DoubleConstant)
1139 bool_res = ((DoubleConstant) left).Value >=
1140 ((DoubleConstant) right).Value;
1141 else if (left is FloatConstant)
1142 bool_res = ((FloatConstant) left).Value >=
1143 ((FloatConstant) right).Value;
1144 else if (left is ULongConstant)
1145 bool_res = ((ULongConstant) left).Value >=
1146 ((ULongConstant) right).Value;
1147 else if (left is LongConstant)
1148 bool_res = ((LongConstant) left).Value >=
1149 ((LongConstant) right).Value;
1150 else if (left is UIntConstant)
1151 bool_res = ((UIntConstant) left).Value >=
1152 ((UIntConstant) right).Value;
1153 else if (left is IntConstant)
1154 bool_res = ((IntConstant) left).Value >=
1155 ((IntConstant) right).Value;
1156 else
1157 return null;
1159 return new BoolConstant (bool_res);
1161 case Binary.Operator.LessThanOrEqual:
1162 DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
1163 if (left == null || right == null)
1164 return null;
1166 bool_res = false;
1167 if (left is DoubleConstant)
1168 bool_res = ((DoubleConstant) left).Value <=
1169 ((DoubleConstant) right).Value;
1170 else if (left is FloatConstant)
1171 bool_res = ((FloatConstant) left).Value <=
1172 ((FloatConstant) right).Value;
1173 else if (left is ULongConstant)
1174 bool_res = ((ULongConstant) left).Value <=
1175 ((ULongConstant) right).Value;
1176 else if (left is LongConstant)
1177 bool_res = ((LongConstant) left).Value <=
1178 ((LongConstant) right).Value;
1179 else if (left is UIntConstant)
1180 bool_res = ((UIntConstant) left).Value <=
1181 ((UIntConstant) right).Value;
1182 else if (left is IntConstant)
1183 bool_res = ((IntConstant) left).Value <=
1184 ((IntConstant) right).Value;
1185 else
1186 return null;
1188 return new BoolConstant (bool_res);
1191 return null;