2 // cfold.cs: Constant Folding
5 // Miguel de Icaza (miguel@ximian.com)
7 // (C) 2002, 2003 Ximian, Inc.
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:
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
,
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
);
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
);
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
63 Constant match
, other
;
66 if (left
is ULongConstant
){
71 if (!(right
is ULongConstant
))
72 right
= right
.ToULong (loc
);
78 left
= left
.ToULong (loc
);
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
);
91 } else if (left
is LongConstant
|| right
is LongConstant
){
93 // If either operand is of type long, the other operand is converted
96 if (!(left
is LongConstant
))
97 left
= left
.ToLong (loc
);
98 else if (!(right
is LongConstant
))
99 right
= right
.ToLong (loc
);
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.
108 if (left
is UIntConstant
)
114 if (other
is UIntConstant
)
117 IntConstant ic
= other
as IntConstant
;
121 left
= new UIntConstant ((uint) ic
.Value
);
123 right
= new UIntConstant ((uint) ic
.Value
);
128 if (other
is SByteConstant
|| other
is ShortConstant
|| ic
!= null){
129 left
= left
.ToLong (loc
);
130 right
= right
.ToLong (loc
);
132 left
= left
.ToUInt (loc
);
133 right
= left
.ToUInt (loc
);
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.
144 if (left
is EnumConstant
){
146 match
= (EnumConstant
) left
;
149 match
= (EnumConstant
) right
;
152 bool need_check
= (other
is EnumConstant
) ||
153 ((oper
!= Binary
.Operator
.Addition
) &&
154 (oper
!= Binary
.Operator
.Subtraction
));
157 !Convert
.ImplicitConversionExists (ec
, match
, other
.Type
)) {
158 Convert
.Error_CannotImplicitConversion (loc
, match
.Type
, other
.Type
);
164 if (left
is EnumConstant
)
165 left
= ((EnumConstant
) left
).Child
;
166 if (right
is EnumConstant
)
167 right
= ((EnumConstant
) right
).Child
;
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
);
182 static void Error_CompileTimeOverflow (Location loc
)
184 Report
.Error (220, loc
, "The operation overflows at compile time in checked mode");
188 /// Constant expression folder for binary operations.
190 /// Returns null if the expression can not be folded.
192 static public Expression
BinaryFold (EmitContext ec
, Binary
.Operator oper
,
193 Constant left
, Constant right
, Location loc
)
196 Type rt
= right
.Type
;
197 Type result_type
= null;
201 // Enumerator folding
203 if (rt
== lt
&& left
is EnumConstant
)
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
;
218 Constant result
= null;
220 case Binary
.Operator
.BitwiseOr
:
221 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
222 if (left
== null || right
== null)
225 if (left
is IntConstant
){
227 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
229 v
= new IntConstant (res
);
230 if (result_type
== null)
233 return new EnumConstant (v
, result_type
);
234 } else if (left
is UIntConstant
){
236 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
238 v
= new UIntConstant (res
);
239 if (result_type
== null)
242 return new EnumConstant (v
, result_type
);
243 } else if (left
is LongConstant
){
245 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
247 v
= new LongConstant (res
);
248 if (result_type
== null)
251 return new EnumConstant (v
, result_type
);
252 } else if (left
is ULongConstant
){
254 ulong res
= ((ULongConstant
)left
).Value
|
255 ((ULongConstant
)right
).Value
;
257 v
= new ULongConstant (res
);
258 if (result_type
== null)
261 return new EnumConstant (v
, result_type
);
262 } else if (left
is UShortConstant
){
264 ushort res
= (ushort) (((UShortConstant
)left
).Value
|
265 ((UShortConstant
)right
).Value
);
267 v
= new UShortConstant (res
);
268 if (result_type
== null)
271 return new EnumConstant (v
, result_type
);
272 } else if (left
is ShortConstant
){
274 short res
= (short) (((ShortConstant
)left
).Value
|
275 ((ShortConstant
)right
).Value
);
277 v
= new ShortConstant (res
);
278 if (result_type
== null)
281 return new EnumConstant (v
, result_type
);
285 case Binary
.Operator
.BitwiseAnd
:
286 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
287 if (left
== null || right
== null)
290 if (left
is IntConstant
){
292 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
294 v
= new IntConstant (res
);
295 if (result_type
== null)
298 return new EnumConstant (v
, result_type
);
299 } else if (left
is UIntConstant
){
301 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
303 v
= new UIntConstant (res
);
304 if (result_type
== null)
307 return new EnumConstant (v
, result_type
);
308 } else if (left
is LongConstant
){
310 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
312 v
= new LongConstant (res
);
313 if (result_type
== null)
316 return new EnumConstant (v
, result_type
);
317 } else if (left
is ULongConstant
){
319 ulong res
= ((ULongConstant
)left
).Value
&
320 ((ULongConstant
)right
).Value
;
322 v
= new ULongConstant (res
);
323 if (result_type
== null)
326 return new EnumConstant (v
, result_type
);
327 } else if (left
is UShortConstant
){
329 ushort res
= (ushort) (((UShortConstant
)left
).Value
&
330 ((UShortConstant
)right
).Value
);
332 v
= new UShortConstant (res
);
333 if (result_type
== null)
336 return new EnumConstant (v
, result_type
);
337 } else if (left
is ShortConstant
){
339 short res
= (short) (((ShortConstant
)left
).Value
&
340 ((ShortConstant
)right
).Value
);
342 v
= new ShortConstant (res
);
343 if (result_type
== null)
346 return new EnumConstant (v
, result_type
);
350 case Binary
.Operator
.ExclusiveOr
:
351 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
352 if (left
== null || right
== null)
355 if (left
is IntConstant
){
357 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
359 v
= new IntConstant (res
);
360 if (result_type
== null)
363 return new EnumConstant (v
, result_type
);
364 } else if (left
is UIntConstant
){
366 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
368 v
= new UIntConstant (res
);
369 if (result_type
== null)
372 return new EnumConstant (v
, result_type
);
373 } else if (left
is LongConstant
){
375 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
377 v
= new LongConstant (res
);
378 if (result_type
== null)
381 return new EnumConstant (v
, result_type
);
382 } else if (left
is ULongConstant
){
384 ulong res
= ((ULongConstant
)left
).Value ^
385 ((ULongConstant
)right
).Value
;
387 v
= new ULongConstant (res
);
388 if (result_type
== null)
391 return new EnumConstant (v
, result_type
);
392 } else if (left
is UShortConstant
){
394 ushort res
= (ushort) (((UShortConstant
)left
).Value ^
395 ((UShortConstant
)right
).Value
);
397 v
= new UShortConstant (res
);
398 if (result_type
== null)
401 return new EnumConstant (v
, result_type
);
402 } else if (left
is ShortConstant
){
404 short res
= (short)(((ShortConstant
)left
).Value ^
405 ((ShortConstant
)right
).Value
);
407 v
= new ShortConstant (res
);
408 if (result_type
== null)
411 return new EnumConstant (v
, result_type
);
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
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
);
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
){
444 if (((EnumConstant
) left
).Child
.Type
!= right
.Type
)
448 } else if (right
is EnumConstant
){
449 if (((EnumConstant
) right
).Child
.Type
!= left
.Type
)
451 wrap_as
= right
.Type
;
455 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
456 if (left
== null || right
== null)
460 if (left
is DoubleConstant
){
463 if (ec
.ConstantCheckState
)
464 res
= checked (((DoubleConstant
) left
).Value
+
465 ((DoubleConstant
) right
).Value
);
467 res
= unchecked (((DoubleConstant
) left
).Value
+
468 ((DoubleConstant
) right
).Value
);
470 result
= new DoubleConstant (res
);
471 } else if (left
is FloatConstant
){
474 if (ec
.ConstantCheckState
)
475 res
= checked (((FloatConstant
) left
).Value
+
476 ((FloatConstant
) right
).Value
);
478 res
= unchecked (((FloatConstant
) left
).Value
+
479 ((FloatConstant
) right
).Value
);
481 result
= new FloatConstant (res
);
482 } else if (left
is ULongConstant
){
485 if (ec
.ConstantCheckState
)
486 res
= checked (((ULongConstant
) left
).Value
+
487 ((ULongConstant
) right
).Value
);
489 res
= unchecked (((ULongConstant
) left
).Value
+
490 ((ULongConstant
) right
).Value
);
492 result
= new ULongConstant (res
);
493 } else if (left
is LongConstant
){
496 if (ec
.ConstantCheckState
)
497 res
= checked (((LongConstant
) left
).Value
+
498 ((LongConstant
) right
).Value
);
500 res
= unchecked (((LongConstant
) left
).Value
+
501 ((LongConstant
) right
).Value
);
503 result
= new LongConstant (res
);
504 } else if (left
is UIntConstant
){
507 if (ec
.ConstantCheckState
)
508 res
= checked (((UIntConstant
) left
).Value
+
509 ((UIntConstant
) right
).Value
);
511 res
= unchecked (((UIntConstant
) left
).Value
+
512 ((UIntConstant
) right
).Value
);
514 result
= new UIntConstant (res
);
515 } else if (left
is IntConstant
){
518 if (ec
.ConstantCheckState
)
519 res
= checked (((IntConstant
) left
).Value
+
520 ((IntConstant
) right
).Value
);
522 res
= unchecked (((IntConstant
) left
).Value
+
523 ((IntConstant
) right
).Value
);
525 result
= new IntConstant (res
);
527 throw new Exception ( "Unexepected input: " + left
);
529 } catch (OverflowException
){
530 Error_CompileTimeOverflow (loc
);
534 return new EnumConstant (result
, wrap_as
);
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)"
545 if (left
is EnumConstant
){
546 if (right
is EnumConstant
){
547 if (left
.Type
== right
.Type
)
548 wrap_as
= TypeManager
.EnumToUnderlying (left
.Type
);
552 if (((EnumConstant
) left
).Child
.Type
!= right
.Type
)
556 } else if (right
is EnumConstant
){
557 if (((EnumConstant
) right
).Child
.Type
!= left
.Type
)
559 wrap_as
= right
.Type
;
562 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
563 if (left
== null || right
== null)
567 if (left
is DoubleConstant
){
570 if (ec
.ConstantCheckState
)
571 res
= checked (((DoubleConstant
) left
).Value
-
572 ((DoubleConstant
) right
).Value
);
574 res
= unchecked (((DoubleConstant
) left
).Value
-
575 ((DoubleConstant
) right
).Value
);
577 result
= new DoubleConstant (res
);
578 } else if (left
is FloatConstant
){
581 if (ec
.ConstantCheckState
)
582 res
= checked (((FloatConstant
) left
).Value
-
583 ((FloatConstant
) right
).Value
);
585 res
= unchecked (((FloatConstant
) left
).Value
-
586 ((FloatConstant
) right
).Value
);
588 result
= new FloatConstant (res
);
589 } else if (left
is ULongConstant
){
592 if (ec
.ConstantCheckState
)
593 res
= checked (((ULongConstant
) left
).Value
-
594 ((ULongConstant
) right
).Value
);
596 res
= unchecked (((ULongConstant
) left
).Value
-
597 ((ULongConstant
) right
).Value
);
599 result
= new ULongConstant (res
);
600 } else if (left
is LongConstant
){
603 if (ec
.ConstantCheckState
)
604 res
= checked (((LongConstant
) left
).Value
-
605 ((LongConstant
) right
).Value
);
607 res
= unchecked (((LongConstant
) left
).Value
-
608 ((LongConstant
) right
).Value
);
610 result
= new LongConstant (res
);
611 } else if (left
is UIntConstant
){
614 if (ec
.ConstantCheckState
)
615 res
= checked (((UIntConstant
) left
).Value
-
616 ((UIntConstant
) right
).Value
);
618 res
= unchecked (((UIntConstant
) left
).Value
-
619 ((UIntConstant
) right
).Value
);
621 result
= new UIntConstant (res
);
622 } else if (left
is IntConstant
){
625 if (ec
.ConstantCheckState
)
626 res
= checked (((IntConstant
) left
).Value
-
627 ((IntConstant
) right
).Value
);
629 res
= unchecked (((IntConstant
) left
).Value
-
630 ((IntConstant
) right
).Value
);
632 result
= new IntConstant (res
);
634 throw new Exception ( "Unexepected input: " + left
);
636 } catch (OverflowException
){
637 Error_CompileTimeOverflow (loc
);
640 return new EnumConstant (result
, wrap_as
);
644 case Binary
.Operator
.Multiply
:
645 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
646 if (left
== null || right
== null)
650 if (left
is DoubleConstant
){
653 if (ec
.ConstantCheckState
)
654 res
= checked (((DoubleConstant
) left
).Value
*
655 ((DoubleConstant
) right
).Value
);
657 res
= unchecked (((DoubleConstant
) left
).Value
*
658 ((DoubleConstant
) right
).Value
);
660 return new DoubleConstant (res
);
661 } else if (left
is FloatConstant
){
664 if (ec
.ConstantCheckState
)
665 res
= checked (((FloatConstant
) left
).Value
*
666 ((FloatConstant
) right
).Value
);
668 res
= unchecked (((FloatConstant
) left
).Value
*
669 ((FloatConstant
) right
).Value
);
671 return new FloatConstant (res
);
672 } else if (left
is ULongConstant
){
675 if (ec
.ConstantCheckState
)
676 res
= checked (((ULongConstant
) left
).Value
*
677 ((ULongConstant
) right
).Value
);
679 res
= unchecked (((ULongConstant
) left
).Value
*
680 ((ULongConstant
) right
).Value
);
682 return new ULongConstant (res
);
683 } else if (left
is LongConstant
){
686 if (ec
.ConstantCheckState
)
687 res
= checked (((LongConstant
) left
).Value
*
688 ((LongConstant
) right
).Value
);
690 res
= unchecked (((LongConstant
) left
).Value
*
691 ((LongConstant
) right
).Value
);
693 return new LongConstant (res
);
694 } else if (left
is UIntConstant
){
697 if (ec
.ConstantCheckState
)
698 res
= checked (((UIntConstant
) left
).Value
*
699 ((UIntConstant
) right
).Value
);
701 res
= unchecked (((UIntConstant
) left
).Value
*
702 ((UIntConstant
) right
).Value
);
704 return new UIntConstant (res
);
705 } else if (left
is IntConstant
){
708 if (ec
.ConstantCheckState
)
709 res
= checked (((IntConstant
) left
).Value
*
710 ((IntConstant
) right
).Value
);
712 res
= unchecked (((IntConstant
) left
).Value
*
713 ((IntConstant
) right
).Value
);
715 return new IntConstant (res
);
717 throw new Exception ( "Unexepected input: " + left
);
719 } catch (OverflowException
){
720 Error_CompileTimeOverflow (loc
);
724 case Binary
.Operator
.Division
:
725 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
726 if (left
== null || right
== null)
730 if (left
is DoubleConstant
){
733 if (ec
.ConstantCheckState
)
734 res
= checked (((DoubleConstant
) left
).Value
/
735 ((DoubleConstant
) right
).Value
);
737 res
= unchecked (((DoubleConstant
) left
).Value
/
738 ((DoubleConstant
) right
).Value
);
740 return new DoubleConstant (res
);
741 } else if (left
is FloatConstant
){
744 if (ec
.ConstantCheckState
)
745 res
= checked (((FloatConstant
) left
).Value
/
746 ((FloatConstant
) right
).Value
);
748 res
= unchecked (((FloatConstant
) left
).Value
/
749 ((FloatConstant
) right
).Value
);
751 return new FloatConstant (res
);
752 } else if (left
is ULongConstant
){
755 if (ec
.ConstantCheckState
)
756 res
= checked (((ULongConstant
) left
).Value
/
757 ((ULongConstant
) right
).Value
);
759 res
= unchecked (((ULongConstant
) left
).Value
/
760 ((ULongConstant
) right
).Value
);
762 return new ULongConstant (res
);
763 } else if (left
is LongConstant
){
766 if (ec
.ConstantCheckState
)
767 res
= checked (((LongConstant
) left
).Value
/
768 ((LongConstant
) right
).Value
);
770 res
= unchecked (((LongConstant
) left
).Value
/
771 ((LongConstant
) right
).Value
);
773 return new LongConstant (res
);
774 } else if (left
is UIntConstant
){
777 if (ec
.ConstantCheckState
)
778 res
= checked (((UIntConstant
) left
).Value
/
779 ((UIntConstant
) right
).Value
);
781 res
= unchecked (((UIntConstant
) left
).Value
/
782 ((UIntConstant
) right
).Value
);
784 return new UIntConstant (res
);
785 } else if (left
is IntConstant
){
788 if (ec
.ConstantCheckState
)
789 res
= checked (((IntConstant
) left
).Value
/
790 ((IntConstant
) right
).Value
);
792 res
= unchecked (((IntConstant
) left
).Value
/
793 ((IntConstant
) right
).Value
);
795 return new IntConstant (res
);
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");
808 case Binary
.Operator
.Modulus
:
809 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
810 if (left
== null || right
== null)
814 if (left
is DoubleConstant
){
817 if (ec
.ConstantCheckState
)
818 res
= checked (((DoubleConstant
) left
).Value
%
819 ((DoubleConstant
) right
).Value
);
821 res
= unchecked (((DoubleConstant
) left
).Value
%
822 ((DoubleConstant
) right
).Value
);
824 return new DoubleConstant (res
);
825 } else if (left
is FloatConstant
){
828 if (ec
.ConstantCheckState
)
829 res
= checked (((FloatConstant
) left
).Value
%
830 ((FloatConstant
) right
).Value
);
832 res
= unchecked (((FloatConstant
) left
).Value
%
833 ((FloatConstant
) right
).Value
);
835 return new FloatConstant (res
);
836 } else if (left
is ULongConstant
){
839 if (ec
.ConstantCheckState
)
840 res
= checked (((ULongConstant
) left
).Value
%
841 ((ULongConstant
) right
).Value
);
843 res
= unchecked (((ULongConstant
) left
).Value
%
844 ((ULongConstant
) right
).Value
);
846 return new ULongConstant (res
);
847 } else if (left
is LongConstant
){
850 if (ec
.ConstantCheckState
)
851 res
= checked (((LongConstant
) left
).Value
%
852 ((LongConstant
) right
).Value
);
854 res
= unchecked (((LongConstant
) left
).Value
%
855 ((LongConstant
) right
).Value
);
857 return new LongConstant (res
);
858 } else if (left
is UIntConstant
){
861 if (ec
.ConstantCheckState
)
862 res
= checked (((UIntConstant
) left
).Value
%
863 ((UIntConstant
) right
).Value
);
865 res
= unchecked (((UIntConstant
) left
).Value
%
866 ((UIntConstant
) right
).Value
);
868 return new UIntConstant (res
);
869 } else if (left
is IntConstant
){
872 if (ec
.ConstantCheckState
)
873 res
= checked (((IntConstant
) left
).Value
%
874 ((IntConstant
) right
).Value
);
876 res
= unchecked (((IntConstant
) left
).Value
%
877 ((IntConstant
) right
).Value
);
879 return new IntConstant (res
);
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
);
891 // There is no overflow checking on left shift
893 case Binary
.Operator
.LeftShift
:
894 IntConstant ic
= right
.ToInt (loc
);
896 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
899 int lshift_val
= ic
.Value
;
902 if ((lic
= left
.ConvertToInt ()) != null)
903 return new IntConstant (lic
.Value
<< lshift_val
);
906 if ((luic
= left
.ConvertToUInt ()) != null)
907 return new UIntConstant (luic
.Value
<< lshift_val
);
910 if ((llc
= left
.ConvertToLong ()) != null)
911 return new LongConstant (llc
.Value
<< lshift_val
);
914 if ((lulc
= left
.ConvertToULong ()) != null)
915 return new ULongConstant (lulc
.Value
<< lshift_val
);
917 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
921 // There is no overflow checking on right shift
923 case Binary
.Operator
.RightShift
:
924 IntConstant sic
= right
.ToInt (loc
);
926 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
929 int rshift_val
= sic
.Value
;
932 if ((ric
= left
.ConvertToInt ()) != null)
933 return new IntConstant (ric
.Value
>> rshift_val
);
936 if ((ruic
= left
.ConvertToUInt ()) != null)
937 return new UIntConstant (ruic
.Value
>> rshift_val
);
940 if ((rlc
= left
.ConvertToLong ()) != null)
941 return new LongConstant (rlc
.Value
>> rshift_val
);
944 if ((rulc
= left
.ConvertToULong ()) != null)
945 return new ULongConstant (rulc
.Value
>> rshift_val
);
947 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
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
);
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
);
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)
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
;
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)
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
;
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)
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
;
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)
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
;
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)
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
;
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)
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
;
1188 return new BoolConstant (bool_res
);