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
, ic
.Location
);
123 right
= new UIntConstant ((uint) ic
.Value
, ic
.Location
);
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 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
);
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
);
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
);
164 static void Error_CompileTimeOverflow (Location loc
)
166 Report
.Error (220, loc
, "The operation overflows at compile time in checked mode");
170 /// Constant expression folder for binary operations.
172 /// Returns null if the expression can not be folded.
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
);
184 Type rt
= right
.Type
;
185 Type result_type
= null;
189 // Enumerator folding
191 if (rt
== lt
&& left
is EnumConstant
)
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
;
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
);
218 throw new InternalErrorException ("Invalid operator on booleans: " + oper
);
223 Constant result
= null;
225 case Binary
.Operator
.BitwiseOr
:
226 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
227 if (left
== null || right
== null)
230 if (left
is IntConstant
){
232 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
234 v
= new IntConstant (res
, left
.Location
);
235 if (result_type
== null)
238 return new EnumConstant (v
, result_type
);
239 } else if (left
is UIntConstant
){
241 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
243 v
= new UIntConstant (res
, left
.Location
);
244 if (result_type
== null)
247 return new EnumConstant (v
, result_type
);
248 } else if (left
is LongConstant
){
250 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
252 v
= new LongConstant (res
, left
.Location
);
253 if (result_type
== null)
256 return new EnumConstant (v
, result_type
);
257 } else if (left
is ULongConstant
){
259 ulong res
= ((ULongConstant
)left
).Value
|
260 ((ULongConstant
)right
).Value
;
262 v
= new ULongConstant (res
, left
.Location
);
263 if (result_type
== null)
266 return new EnumConstant (v
, result_type
);
267 } else if (left
is UShortConstant
){
269 ushort res
= (ushort) (((UShortConstant
)left
).Value
|
270 ((UShortConstant
)right
).Value
);
272 v
= new UShortConstant (res
, left
.Location
);
273 if (result_type
== null)
276 return new EnumConstant (v
, result_type
);
277 } else if (left
is ShortConstant
){
279 short res
= (short) (((ShortConstant
)left
).Value
|
280 ((ShortConstant
)right
).Value
);
282 v
= new ShortConstant (res
, left
.Location
);
283 if (result_type
== null)
286 return new EnumConstant (v
, result_type
);
290 case Binary
.Operator
.BitwiseAnd
:
291 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
292 if (left
== null || right
== null)
295 if (left
is IntConstant
){
297 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
299 v
= new IntConstant (res
, left
.Location
);
300 if (result_type
== null)
303 return new EnumConstant (v
, result_type
);
304 } else if (left
is UIntConstant
){
306 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
308 v
= new UIntConstant (res
, left
.Location
);
309 if (result_type
== null)
312 return new EnumConstant (v
, result_type
);
313 } else if (left
is LongConstant
){
315 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
317 v
= new LongConstant (res
, left
.Location
);
318 if (result_type
== null)
321 return new EnumConstant (v
, result_type
);
322 } else if (left
is ULongConstant
){
324 ulong res
= ((ULongConstant
)left
).Value
&
325 ((ULongConstant
)right
).Value
;
327 v
= new ULongConstant (res
, left
.Location
);
328 if (result_type
== null)
331 return new EnumConstant (v
, result_type
);
332 } else if (left
is UShortConstant
){
334 ushort res
= (ushort) (((UShortConstant
)left
).Value
&
335 ((UShortConstant
)right
).Value
);
337 v
= new UShortConstant (res
, left
.Location
);
338 if (result_type
== null)
341 return new EnumConstant (v
, result_type
);
342 } else if (left
is ShortConstant
){
344 short res
= (short) (((ShortConstant
)left
).Value
&
345 ((ShortConstant
)right
).Value
);
347 v
= new ShortConstant (res
, left
.Location
);
348 if (result_type
== null)
351 return new EnumConstant (v
, result_type
);
355 case Binary
.Operator
.ExclusiveOr
:
356 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
357 if (left
== null || right
== null)
360 if (left
is IntConstant
){
362 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
364 v
= new IntConstant (res
, left
.Location
);
365 if (result_type
== null)
368 return new EnumConstant (v
, result_type
);
369 } else if (left
is UIntConstant
){
371 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
373 v
= new UIntConstant (res
, left
.Location
);
374 if (result_type
== null)
377 return new EnumConstant (v
, result_type
);
378 } else if (left
is LongConstant
){
380 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
382 v
= new LongConstant (res
, left
.Location
);
383 if (result_type
== null)
386 return new EnumConstant (v
, result_type
);
387 } else if (left
is ULongConstant
){
389 ulong res
= ((ULongConstant
)left
).Value ^
390 ((ULongConstant
)right
).Value
;
392 v
= new ULongConstant (res
, left
.Location
);
393 if (result_type
== null)
396 return new EnumConstant (v
, result_type
);
397 } else if (left
is UShortConstant
){
399 ushort res
= (ushort) (((UShortConstant
)left
).Value ^
400 ((UShortConstant
)right
).Value
);
402 v
= new UShortConstant (res
, left
.Location
);
403 if (result_type
== null)
406 return new EnumConstant (v
, result_type
);
407 } else if (left
is ShortConstant
){
409 short res
= (short)(((ShortConstant
)left
).Value ^
410 ((ShortConstant
)right
).Value
);
412 v
= new ShortConstant (res
, left
.Location
);
413 if (result_type
== null)
416 return new EnumConstant (v
, result_type
);
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
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
);
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
){
450 right
= right
.ToType (((EnumConstant
) left
).Child
.Type
, loc
);
455 } else if (right
is EnumConstant
){
456 left
= left
.ToType (((EnumConstant
) right
).Child
.Type
, loc
);
460 wrap_as
= right
.Type
;
464 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
465 if (left
== null || right
== null)
469 if (left
is DoubleConstant
){
472 if (ec
.ConstantCheckState
)
473 res
= checked (((DoubleConstant
) left
).Value
+
474 ((DoubleConstant
) right
).Value
);
476 res
= unchecked (((DoubleConstant
) left
).Value
+
477 ((DoubleConstant
) right
).Value
);
479 result
= new DoubleConstant (res
, left
.Location
);
480 } else if (left
is FloatConstant
){
483 if (ec
.ConstantCheckState
)
484 res
= checked (((FloatConstant
) left
).Value
+
485 ((FloatConstant
) right
).Value
);
487 res
= unchecked (((FloatConstant
) left
).Value
+
488 ((FloatConstant
) right
).Value
);
490 result
= new FloatConstant (res
, left
.Location
);
491 } else if (left
is ULongConstant
){
494 if (ec
.ConstantCheckState
)
495 res
= checked (((ULongConstant
) left
).Value
+
496 ((ULongConstant
) right
).Value
);
498 res
= unchecked (((ULongConstant
) left
).Value
+
499 ((ULongConstant
) right
).Value
);
501 result
= new ULongConstant (res
, left
.Location
);
502 } else if (left
is LongConstant
){
505 if (ec
.ConstantCheckState
)
506 res
= checked (((LongConstant
) left
).Value
+
507 ((LongConstant
) right
).Value
);
509 res
= unchecked (((LongConstant
) left
).Value
+
510 ((LongConstant
) right
).Value
);
512 result
= new LongConstant (res
, left
.Location
);
513 } else if (left
is UIntConstant
){
516 if (ec
.ConstantCheckState
)
517 res
= checked (((UIntConstant
) left
).Value
+
518 ((UIntConstant
) right
).Value
);
520 res
= unchecked (((UIntConstant
) left
).Value
+
521 ((UIntConstant
) right
).Value
);
523 result
= new UIntConstant (res
, left
.Location
);
524 } else if (left
is IntConstant
){
527 if (ec
.ConstantCheckState
)
528 res
= checked (((IntConstant
) left
).Value
+
529 ((IntConstant
) right
).Value
);
531 res
= unchecked (((IntConstant
) left
).Value
+
532 ((IntConstant
) right
).Value
);
534 result
= new IntConstant (res
, left
.Location
);
535 } else if (left
is DecimalConstant
) {
538 if (ec
.ConstantCheckState
)
539 res
= checked (((DecimalConstant
) left
).Value
+
540 ((DecimalConstant
) right
).Value
);
542 res
= unchecked (((DecimalConstant
) left
).Value
+
543 ((DecimalConstant
) right
).Value
);
545 result
= new DecimalConstant (res
, left
.Location
);
547 throw new Exception ( "Unexepected addition input: " + left
);
549 } catch (OverflowException
){
550 Error_CompileTimeOverflow (loc
);
553 if (wrap_as
!= null) {
555 return result
.TryReduce (ec
, wrap_as
, loc
);
557 catch (OverflowException
) {
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)"
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
);
578 wrap_as
= TypeManager
.EnumToUnderlying (left
.Type
);
579 right
= ((EnumConstant
) right
).Child
.ToType (wrap_as
, loc
);
583 left
= ((EnumConstant
) left
).Child
.ToType (wrap_as
, loc
);
588 right
= right
.ToType (((EnumConstant
) left
).Child
.Type
, loc
);
594 } else if (right
is EnumConstant
){
595 left
= left
.ToType (((EnumConstant
) right
).Child
.Type
, loc
);
599 wrap_as
= right
.Type
;
602 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
603 if (left
== null || right
== null)
607 if (left
is DoubleConstant
){
610 if (ec
.ConstantCheckState
)
611 res
= checked (((DoubleConstant
) left
).Value
-
612 ((DoubleConstant
) right
).Value
);
614 res
= unchecked (((DoubleConstant
) left
).Value
-
615 ((DoubleConstant
) right
).Value
);
617 result
= new DoubleConstant (res
, left
.Location
);
618 } else if (left
is FloatConstant
){
621 if (ec
.ConstantCheckState
)
622 res
= checked (((FloatConstant
) left
).Value
-
623 ((FloatConstant
) right
).Value
);
625 res
= unchecked (((FloatConstant
) left
).Value
-
626 ((FloatConstant
) right
).Value
);
628 result
= new FloatConstant (res
, left
.Location
);
629 } else if (left
is ULongConstant
){
632 if (ec
.ConstantCheckState
)
633 res
= checked (((ULongConstant
) left
).Value
-
634 ((ULongConstant
) right
).Value
);
636 res
= unchecked (((ULongConstant
) left
).Value
-
637 ((ULongConstant
) right
).Value
);
639 result
= new ULongConstant (res
, left
.Location
);
640 } else if (left
is LongConstant
){
643 if (ec
.ConstantCheckState
)
644 res
= checked (((LongConstant
) left
).Value
-
645 ((LongConstant
) right
).Value
);
647 res
= unchecked (((LongConstant
) left
).Value
-
648 ((LongConstant
) right
).Value
);
650 result
= new LongConstant (res
, left
.Location
);
651 } else if (left
is UIntConstant
){
654 if (ec
.ConstantCheckState
)
655 res
= checked (((UIntConstant
) left
).Value
-
656 ((UIntConstant
) right
).Value
);
658 res
= unchecked (((UIntConstant
) left
).Value
-
659 ((UIntConstant
) right
).Value
);
661 result
= new UIntConstant (res
, left
.Location
);
662 } else if (left
is IntConstant
){
665 if (ec
.ConstantCheckState
)
666 res
= checked (((IntConstant
) left
).Value
-
667 ((IntConstant
) right
).Value
);
669 res
= unchecked (((IntConstant
) left
).Value
-
670 ((IntConstant
) right
).Value
);
672 result
= new IntConstant (res
, left
.Location
);
673 } else if (left
is DecimalConstant
) {
676 if (ec
.ConstantCheckState
)
677 res
= checked (((DecimalConstant
) left
).Value
-
678 ((DecimalConstant
) right
).Value
);
680 res
= unchecked (((DecimalConstant
) left
).Value
-
681 ((DecimalConstant
) right
).Value
);
683 return new DecimalConstant (res
, left
.Location
);
685 throw new Exception ( "Unexepected subtraction input: " + left
);
687 } catch (OverflowException
){
688 Error_CompileTimeOverflow (loc
);
691 if (wrap_as
!= null) {
693 return result
.TryReduce (ec
, wrap_as
, loc
);
695 catch (OverflowException
) {
702 case Binary
.Operator
.Multiply
:
703 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
704 if (left
== null || right
== null)
708 if (left
is DoubleConstant
){
711 if (ec
.ConstantCheckState
)
712 res
= checked (((DoubleConstant
) left
).Value
*
713 ((DoubleConstant
) right
).Value
);
715 res
= unchecked (((DoubleConstant
) left
).Value
*
716 ((DoubleConstant
) right
).Value
);
718 return new DoubleConstant (res
, left
.Location
);
719 } else if (left
is FloatConstant
){
722 if (ec
.ConstantCheckState
)
723 res
= checked (((FloatConstant
) left
).Value
*
724 ((FloatConstant
) right
).Value
);
726 res
= unchecked (((FloatConstant
) left
).Value
*
727 ((FloatConstant
) right
).Value
);
729 return new FloatConstant (res
, left
.Location
);
730 } else if (left
is ULongConstant
){
733 if (ec
.ConstantCheckState
)
734 res
= checked (((ULongConstant
) left
).Value
*
735 ((ULongConstant
) right
).Value
);
737 res
= unchecked (((ULongConstant
) left
).Value
*
738 ((ULongConstant
) right
).Value
);
740 return new ULongConstant (res
, left
.Location
);
741 } else if (left
is LongConstant
){
744 if (ec
.ConstantCheckState
)
745 res
= checked (((LongConstant
) left
).Value
*
746 ((LongConstant
) right
).Value
);
748 res
= unchecked (((LongConstant
) left
).Value
*
749 ((LongConstant
) right
).Value
);
751 return new LongConstant (res
, left
.Location
);
752 } else if (left
is UIntConstant
){
755 if (ec
.ConstantCheckState
)
756 res
= checked (((UIntConstant
) left
).Value
*
757 ((UIntConstant
) right
).Value
);
759 res
= unchecked (((UIntConstant
) left
).Value
*
760 ((UIntConstant
) right
).Value
);
762 return new UIntConstant (res
, left
.Location
);
763 } else if (left
is IntConstant
){
766 if (ec
.ConstantCheckState
)
767 res
= checked (((IntConstant
) left
).Value
*
768 ((IntConstant
) right
).Value
);
770 res
= unchecked (((IntConstant
) left
).Value
*
771 ((IntConstant
) right
).Value
);
773 return new IntConstant (res
, left
.Location
);
774 } else if (left
is DecimalConstant
) {
777 if (ec
.ConstantCheckState
)
778 res
= checked (((DecimalConstant
) left
).Value
*
779 ((DecimalConstant
) right
).Value
);
781 res
= unchecked (((DecimalConstant
) left
).Value
*
782 ((DecimalConstant
) right
).Value
);
784 return new DecimalConstant (res
, left
.Location
);
786 throw new Exception ( "Unexepected multiply input: " + left
);
788 } catch (OverflowException
){
789 Error_CompileTimeOverflow (loc
);
793 case Binary
.Operator
.Division
:
794 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
795 if (left
== null || right
== null)
799 if (left
is DoubleConstant
){
802 if (ec
.ConstantCheckState
)
803 res
= checked (((DoubleConstant
) left
).Value
/
804 ((DoubleConstant
) right
).Value
);
806 res
= unchecked (((DoubleConstant
) left
).Value
/
807 ((DoubleConstant
) right
).Value
);
809 return new DoubleConstant (res
, left
.Location
);
810 } else if (left
is FloatConstant
){
813 if (ec
.ConstantCheckState
)
814 res
= checked (((FloatConstant
) left
).Value
/
815 ((FloatConstant
) right
).Value
);
817 res
= unchecked (((FloatConstant
) left
).Value
/
818 ((FloatConstant
) right
).Value
);
820 return new FloatConstant (res
, left
.Location
);
821 } else if (left
is ULongConstant
){
824 if (ec
.ConstantCheckState
)
825 res
= checked (((ULongConstant
) left
).Value
/
826 ((ULongConstant
) right
).Value
);
828 res
= unchecked (((ULongConstant
) left
).Value
/
829 ((ULongConstant
) right
).Value
);
831 return new ULongConstant (res
, left
.Location
);
832 } else if (left
is LongConstant
){
835 if (ec
.ConstantCheckState
)
836 res
= checked (((LongConstant
) left
).Value
/
837 ((LongConstant
) right
).Value
);
839 res
= unchecked (((LongConstant
) left
).Value
/
840 ((LongConstant
) right
).Value
);
842 return new LongConstant (res
, left
.Location
);
843 } else if (left
is UIntConstant
){
846 if (ec
.ConstantCheckState
)
847 res
= checked (((UIntConstant
) left
).Value
/
848 ((UIntConstant
) right
).Value
);
850 res
= unchecked (((UIntConstant
) left
).Value
/
851 ((UIntConstant
) right
).Value
);
853 return new UIntConstant (res
, left
.Location
);
854 } else if (left
is IntConstant
){
857 if (ec
.ConstantCheckState
)
858 res
= checked (((IntConstant
) left
).Value
/
859 ((IntConstant
) right
).Value
);
861 res
= unchecked (((IntConstant
) left
).Value
/
862 ((IntConstant
) right
).Value
);
864 return new IntConstant (res
, left
.Location
);
865 } else if (left
is DecimalConstant
) {
868 if (ec
.ConstantCheckState
)
869 res
= checked (((DecimalConstant
) left
).Value
/
870 ((DecimalConstant
) right
).Value
);
872 res
= unchecked (((DecimalConstant
) left
).Value
/
873 ((DecimalConstant
) right
).Value
);
875 return new DecimalConstant (res
, left
.Location
);
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");
888 case Binary
.Operator
.Modulus
:
889 DoConstantNumericPromotions (ec
, oper
, ref left
, ref right
, loc
);
890 if (left
== null || right
== null)
894 if (left
is DoubleConstant
){
897 if (ec
.ConstantCheckState
)
898 res
= checked (((DoubleConstant
) left
).Value
%
899 ((DoubleConstant
) right
).Value
);
901 res
= unchecked (((DoubleConstant
) left
).Value
%
902 ((DoubleConstant
) right
).Value
);
904 return new DoubleConstant (res
, left
.Location
);
905 } else if (left
is FloatConstant
){
908 if (ec
.ConstantCheckState
)
909 res
= checked (((FloatConstant
) left
).Value
%
910 ((FloatConstant
) right
).Value
);
912 res
= unchecked (((FloatConstant
) left
).Value
%
913 ((FloatConstant
) right
).Value
);
915 return new FloatConstant (res
, left
.Location
);
916 } else if (left
is ULongConstant
){
919 if (ec
.ConstantCheckState
)
920 res
= checked (((ULongConstant
) left
).Value
%
921 ((ULongConstant
) right
).Value
);
923 res
= unchecked (((ULongConstant
) left
).Value
%
924 ((ULongConstant
) right
).Value
);
926 return new ULongConstant (res
, left
.Location
);
927 } else if (left
is LongConstant
){
930 if (ec
.ConstantCheckState
)
931 res
= checked (((LongConstant
) left
).Value
%
932 ((LongConstant
) right
).Value
);
934 res
= unchecked (((LongConstant
) left
).Value
%
935 ((LongConstant
) right
).Value
);
937 return new LongConstant (res
, left
.Location
);
938 } else if (left
is UIntConstant
){
941 if (ec
.ConstantCheckState
)
942 res
= checked (((UIntConstant
) left
).Value
%
943 ((UIntConstant
) right
).Value
);
945 res
= unchecked (((UIntConstant
) left
).Value
%
946 ((UIntConstant
) right
).Value
);
948 return new UIntConstant (res
, left
.Location
);
949 } else if (left
is IntConstant
){
952 if (ec
.ConstantCheckState
)
953 res
= checked (((IntConstant
) left
).Value
%
954 ((IntConstant
) right
).Value
);
956 res
= unchecked (((IntConstant
) left
).Value
%
957 ((IntConstant
) right
).Value
);
959 return new IntConstant (res
, left
.Location
);
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
);
971 // There is no overflow checking on left shift
973 case Binary
.Operator
.LeftShift
:
974 IntConstant ic
= right
.ToInt (loc
);
976 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
979 int lshift_val
= ic
.Value
;
982 if ((lic
= left
.ConvertToInt ()) != null)
983 return new IntConstant (lic
.Value
<< lshift_val
, left
.Location
);
986 if ((luic
= left
.ConvertToUInt ()) != null)
987 return new UIntConstant (luic
.Value
<< lshift_val
, left
.Location
);
990 if ((llc
= left
.ConvertToLong ()) != null)
991 return new LongConstant (llc
.Value
<< lshift_val
, left
.Location
);
994 if ((lulc
= left
.ConvertToULong ()) != null)
995 return new ULongConstant (lulc
.Value
<< lshift_val
, left
.Location
);
997 Binary
.Error_OperatorCannotBeApplied (loc
, "<<", lt
, rt
);
1001 // There is no overflow checking on right shift
1003 case Binary
.Operator
.RightShift
:
1004 IntConstant sic
= right
.ToInt (loc
);
1006 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
1009 int rshift_val
= sic
.Value
;
1012 if ((ric
= left
.ConvertToInt ()) != null)
1013 return new IntConstant (ric
.Value
>> rshift_val
, left
.Location
);
1016 if ((ruic
= left
.ConvertToUInt ()) != null)
1017 return new UIntConstant (ruic
.Value
>> rshift_val
, left
.Location
);
1020 if ((rlc
= left
.ConvertToLong ()) != null)
1021 return new LongConstant (rlc
.Value
>> rshift_val
, left
.Location
);
1024 if ((rulc
= left
.ConvertToULong ()) != null)
1025 return new ULongConstant (rulc
.Value
>> rshift_val
, left
.Location
);
1027 Binary
.Error_OperatorCannotBeApplied (loc
, ">>", lt
, rt
);
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)
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
;
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)
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
;
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)
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
;
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)
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
;
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)
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
;
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)
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
;
1252 return new BoolConstant (bool_res
, left
.Location
);