2 // cfold.cs: Constant Folding
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Copyright 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2008, Novell, Inc.
13 namespace Mono
.CSharp
{
15 public class ConstantFold
{
17 static TypeSpec
[] binary_promotions
;
19 public static TypeSpec
[] BinaryPromotionsTypes
{
21 if (binary_promotions
== null) {
22 binary_promotions
= new TypeSpec
[] {
23 TypeManager
.decimal_type
, TypeManager
.double_type
, TypeManager
.float_type
,
24 TypeManager
.uint64_type
, TypeManager
.int64_type
, TypeManager
.uint32_type
};
27 return binary_promotions
;
31 public static void Reset ()
33 binary_promotions
= null;
37 // Performs the numeric promotions on the left and right expresions
38 // and deposits the results on `lc' and `rc'.
40 // On success, the types of `lc' and `rc' on output will always match,
41 // and the pair will be one of:
43 // TODO: BinaryFold should be called as an optimization step only,
44 // error checking here is weak
46 static bool DoBinaryNumericPromotions (ResolveContext rc
, ref Constant left
, ref Constant right
)
48 TypeSpec ltype
= left
.Type
;
49 TypeSpec rtype
= right
.Type
;
51 foreach (TypeSpec t
in BinaryPromotionsTypes
) {
53 return t
== rtype
|| ConvertPromotion (rc
, ref right
, ref left
, t
);
56 return t
== ltype
|| ConvertPromotion (rc
, ref left
, ref right
, t
);
59 left
= left
.ConvertImplicitly (rc
, TypeManager
.int32_type
);
60 right
= right
.ConvertImplicitly (rc
, TypeManager
.int32_type
);
61 return left
!= null && right
!= null;
64 static bool ConvertPromotion (ResolveContext rc
, ref Constant prim
, ref Constant second
, TypeSpec type
)
66 Constant c
= prim
.ConvertImplicitly (rc
, type
);
72 if (type
== TypeManager
.uint32_type
) {
73 type
= TypeManager
.int64_type
;
74 prim
= prim
.ConvertImplicitly (rc
, type
);
75 second
= second
.ConvertImplicitly (rc
, type
);
76 return prim
!= null && second
!= null;
82 internal static void Error_CompileTimeOverflow (ResolveContext rc
, Location loc
)
84 rc
.Report
.Error (220, loc
, "The operation overflows at compile time in checked mode");
88 /// Constant expression folder for binary operations.
90 /// Returns null if the expression can not be folded.
92 static public Constant
BinaryFold (ResolveContext ec
, Binary
.Operator oper
,
93 Constant left
, Constant right
, Location loc
)
95 Constant result
= null;
97 if (left
is EmptyConstantCast
)
98 return BinaryFold (ec
, oper
, ((EmptyConstantCast
)left
).child
, right
, loc
);
100 if (left
is SideEffectConstant
) {
101 result
= BinaryFold (ec
, oper
, ((SideEffectConstant
) left
).value, right
, loc
);
104 return new SideEffectConstant (result
, left
, loc
);
107 if (right
is EmptyConstantCast
)
108 return BinaryFold (ec
, oper
, left
, ((EmptyConstantCast
)right
).child
, loc
);
110 if (right
is SideEffectConstant
) {
111 result
= BinaryFold (ec
, oper
, left
, ((SideEffectConstant
) right
).value, loc
);
114 return new SideEffectConstant (result
, right
, loc
);
117 TypeSpec lt
= left
.Type
;
118 TypeSpec rt
= right
.Type
;
121 if (lt
== TypeManager
.bool_type
&& lt
== rt
) {
122 bool lv
= (bool) left
.GetValue ();
123 bool rv
= (bool) right
.GetValue ();
125 case Binary
.Operator
.BitwiseAnd
:
126 case Binary
.Operator
.LogicalAnd
:
127 return new BoolConstant (lv
&& rv
, left
.Location
);
128 case Binary
.Operator
.BitwiseOr
:
129 case Binary
.Operator
.LogicalOr
:
130 return new BoolConstant (lv
|| rv
, left
.Location
);
131 case Binary
.Operator
.ExclusiveOr
:
132 return new BoolConstant (lv ^ rv
, left
.Location
);
133 case Binary
.Operator
.Equality
:
134 return new BoolConstant (lv
== rv
, left
.Location
);
135 case Binary
.Operator
.Inequality
:
136 return new BoolConstant (lv
!= rv
, left
.Location
);
142 // During an enum evaluation, none of the rules are valid
143 // Not sure whether it is bug in csc or in documentation
145 if (ec
.HasSet (ResolveContext
.Options
.EnumScope
)){
146 if (left
is EnumConstant
)
147 left
= ((EnumConstant
) left
).Child
;
149 if (right
is EnumConstant
)
150 right
= ((EnumConstant
) right
).Child
;
151 } else if (left
is EnumConstant
&& rt
== lt
) {
154 /// E operator |(E x, E y);
155 /// E operator &(E x, E y);
156 /// E operator ^(E x, E y);
158 case Binary
.Operator
.BitwiseOr
:
159 case Binary
.Operator
.BitwiseAnd
:
160 case Binary
.Operator
.ExclusiveOr
:
161 result
= BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
163 result
= result
.Resolve (ec
).TryReduce (ec
, lt
, loc
);
167 /// U operator -(E x, E y);
169 case Binary
.Operator
.Subtraction
:
170 result
= BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
172 result
= result
.Resolve (ec
).TryReduce (ec
, ((EnumConstant
)left
).Child
.Type
, loc
);
176 /// bool operator ==(E x, E y);
177 /// bool operator !=(E x, E y);
178 /// bool operator <(E x, E y);
179 /// bool operator >(E x, E y);
180 /// bool operator <=(E x, E y);
181 /// bool operator >=(E x, E y);
183 case Binary
.Operator
.Equality
:
184 case Binary
.Operator
.Inequality
:
185 case Binary
.Operator
.LessThan
:
186 case Binary
.Operator
.GreaterThan
:
187 case Binary
.Operator
.LessThanOrEqual
:
188 case Binary
.Operator
.GreaterThanOrEqual
:
189 return BinaryFold(ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
195 case Binary
.Operator
.BitwiseOr
:
196 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
199 if (left
is IntConstant
){
200 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
202 return new IntConstant (res
, left
.Location
);
204 if (left
is UIntConstant
){
205 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
207 return new UIntConstant (res
, left
.Location
);
209 if (left
is LongConstant
){
210 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
212 return new LongConstant (res
, left
.Location
);
214 if (left
is ULongConstant
){
215 ulong res
= ((ULongConstant
)left
).Value
|
216 ((ULongConstant
)right
).Value
;
218 return new ULongConstant (res
, left
.Location
);
222 case Binary
.Operator
.BitwiseAnd
:
223 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
227 /// int operator &(int x, int y);
228 /// uint operator &(uint x, uint y);
229 /// long operator &(long x, long y);
230 /// ulong operator &(ulong x, ulong y);
232 if (left
is IntConstant
){
233 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
234 return new IntConstant (res
, left
.Location
);
236 if (left
is UIntConstant
){
237 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
238 return new UIntConstant (res
, left
.Location
);
240 if (left
is LongConstant
){
241 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
242 return new LongConstant (res
, left
.Location
);
244 if (left
is ULongConstant
){
245 ulong res
= ((ULongConstant
)left
).Value
&
246 ((ULongConstant
)right
).Value
;
248 return new ULongConstant (res
, left
.Location
);
252 case Binary
.Operator
.ExclusiveOr
:
253 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
256 if (left
is IntConstant
){
257 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
258 return new IntConstant (res
, left
.Location
);
260 if (left
is UIntConstant
){
261 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
263 return new UIntConstant (res
, left
.Location
);
265 if (left
is LongConstant
){
266 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
268 return new LongConstant (res
, left
.Location
);
270 if (left
is ULongConstant
){
271 ulong res
= ((ULongConstant
)left
).Value ^
272 ((ULongConstant
)right
).Value
;
274 return new ULongConstant (res
, left
.Location
);
278 case Binary
.Operator
.Addition
:
279 if (lt
== TypeManager
.null_type
)
282 if (rt
== TypeManager
.null_type
)
286 // If both sides are strings, then concatenate, if
287 // one is a string, and the other is not, then defer
288 // to runtime concatenation
290 if (lt
== TypeManager
.string_type
|| rt
== TypeManager
.string_type
){
292 return new StringConstant ((string)left
.GetValue () + (string)right
.GetValue (),
299 // handle "E operator + (E x, U y)"
300 // handle "E operator + (Y y, E x)"
302 EnumConstant lc
= left
as EnumConstant
;
303 EnumConstant rc
= right
as EnumConstant
;
304 if (lc
!= null || rc
!= null){
311 // U has to be implicitly convetible to E.base
312 right
= right
.ConvertImplicitly (ec
, lc
.Child
.Type
);
316 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
320 result
= result
.Resolve (ec
).TryReduce (ec
, lt
, loc
);
324 return new EnumConstant (result
, lt
);
327 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
331 if (left
is DoubleConstant
){
334 if (ec
.ConstantCheckState
)
335 res
= checked (((DoubleConstant
) left
).Value
+
336 ((DoubleConstant
) right
).Value
);
338 res
= unchecked (((DoubleConstant
) left
).Value
+
339 ((DoubleConstant
) right
).Value
);
341 return new DoubleConstant (res
, left
.Location
);
343 if (left
is FloatConstant
){
346 if (ec
.ConstantCheckState
)
347 res
= checked (((FloatConstant
) left
).Value
+
348 ((FloatConstant
) right
).Value
);
350 res
= unchecked (((FloatConstant
) left
).Value
+
351 ((FloatConstant
) right
).Value
);
353 result
= new FloatConstant (res
, left
.Location
);
354 } else if (left
is ULongConstant
){
357 if (ec
.ConstantCheckState
)
358 res
= checked (((ULongConstant
) left
).Value
+
359 ((ULongConstant
) right
).Value
);
361 res
= unchecked (((ULongConstant
) left
).Value
+
362 ((ULongConstant
) right
).Value
);
364 result
= new ULongConstant (res
, left
.Location
);
365 } else if (left
is LongConstant
){
368 if (ec
.ConstantCheckState
)
369 res
= checked (((LongConstant
) left
).Value
+
370 ((LongConstant
) right
).Value
);
372 res
= unchecked (((LongConstant
) left
).Value
+
373 ((LongConstant
) right
).Value
);
375 result
= new LongConstant (res
, left
.Location
);
376 } else if (left
is UIntConstant
){
379 if (ec
.ConstantCheckState
)
380 res
= checked (((UIntConstant
) left
).Value
+
381 ((UIntConstant
) right
).Value
);
383 res
= unchecked (((UIntConstant
) left
).Value
+
384 ((UIntConstant
) right
).Value
);
386 result
= new UIntConstant (res
, left
.Location
);
387 } else if (left
is IntConstant
){
390 if (ec
.ConstantCheckState
)
391 res
= checked (((IntConstant
) left
).Value
+
392 ((IntConstant
) right
).Value
);
394 res
= unchecked (((IntConstant
) left
).Value
+
395 ((IntConstant
) right
).Value
);
397 result
= new IntConstant (res
, left
.Location
);
398 } else if (left
is DecimalConstant
) {
401 if (ec
.ConstantCheckState
)
402 res
= checked (((DecimalConstant
) left
).Value
+
403 ((DecimalConstant
) right
).Value
);
405 res
= unchecked (((DecimalConstant
) left
).Value
+
406 ((DecimalConstant
) right
).Value
);
408 result
= new DecimalConstant (res
, left
.Location
);
410 } catch (OverflowException
){
411 Error_CompileTimeOverflow (ec
, loc
);
416 case Binary
.Operator
.Subtraction
:
418 // handle "E operator - (E x, U y)"
419 // handle "E operator - (Y y, E x)"
421 lc
= left
as EnumConstant
;
422 rc
= right
as EnumConstant
;
423 if (lc
!= null || rc
!= null){
430 // U has to be implicitly convetible to E.base
431 right
= right
.ConvertImplicitly (ec
, lc
.Child
.Type
);
435 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
439 result
= result
.Resolve (ec
).TryReduce (ec
, lt
, loc
);
443 return new EnumConstant (result
, lt
);
446 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
450 if (left
is DoubleConstant
){
453 if (ec
.ConstantCheckState
)
454 res
= checked (((DoubleConstant
) left
).Value
-
455 ((DoubleConstant
) right
).Value
);
457 res
= unchecked (((DoubleConstant
) left
).Value
-
458 ((DoubleConstant
) right
).Value
);
460 result
= new DoubleConstant (res
, left
.Location
);
461 } else if (left
is FloatConstant
){
464 if (ec
.ConstantCheckState
)
465 res
= checked (((FloatConstant
) left
).Value
-
466 ((FloatConstant
) right
).Value
);
468 res
= unchecked (((FloatConstant
) left
).Value
-
469 ((FloatConstant
) right
).Value
);
471 result
= new FloatConstant (res
, left
.Location
);
472 } else if (left
is ULongConstant
){
475 if (ec
.ConstantCheckState
)
476 res
= checked (((ULongConstant
) left
).Value
-
477 ((ULongConstant
) right
).Value
);
479 res
= unchecked (((ULongConstant
) left
).Value
-
480 ((ULongConstant
) right
).Value
);
482 result
= new ULongConstant (res
, left
.Location
);
483 } else if (left
is LongConstant
){
486 if (ec
.ConstantCheckState
)
487 res
= checked (((LongConstant
) left
).Value
-
488 ((LongConstant
) right
).Value
);
490 res
= unchecked (((LongConstant
) left
).Value
-
491 ((LongConstant
) right
).Value
);
493 result
= new LongConstant (res
, left
.Location
);
494 } else if (left
is UIntConstant
){
497 if (ec
.ConstantCheckState
)
498 res
= checked (((UIntConstant
) left
).Value
-
499 ((UIntConstant
) right
).Value
);
501 res
= unchecked (((UIntConstant
) left
).Value
-
502 ((UIntConstant
) right
).Value
);
504 result
= new UIntConstant (res
, left
.Location
);
505 } else if (left
is IntConstant
){
508 if (ec
.ConstantCheckState
)
509 res
= checked (((IntConstant
) left
).Value
-
510 ((IntConstant
) right
).Value
);
512 res
= unchecked (((IntConstant
) left
).Value
-
513 ((IntConstant
) right
).Value
);
515 result
= new IntConstant (res
, left
.Location
);
516 } else if (left
is DecimalConstant
) {
519 if (ec
.ConstantCheckState
)
520 res
= checked (((DecimalConstant
) left
).Value
-
521 ((DecimalConstant
) right
).Value
);
523 res
= unchecked (((DecimalConstant
) left
).Value
-
524 ((DecimalConstant
) right
).Value
);
526 return new DecimalConstant (res
, left
.Location
);
528 throw new Exception ( "Unexepected subtraction input: " + left
);
530 } catch (OverflowException
){
531 Error_CompileTimeOverflow (ec
, loc
);
536 case Binary
.Operator
.Multiply
:
537 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
541 if (left
is DoubleConstant
){
544 if (ec
.ConstantCheckState
)
545 res
= checked (((DoubleConstant
) left
).Value
*
546 ((DoubleConstant
) right
).Value
);
548 res
= unchecked (((DoubleConstant
) left
).Value
*
549 ((DoubleConstant
) right
).Value
);
551 return new DoubleConstant (res
, left
.Location
);
552 } else if (left
is FloatConstant
){
555 if (ec
.ConstantCheckState
)
556 res
= checked (((FloatConstant
) left
).Value
*
557 ((FloatConstant
) right
).Value
);
559 res
= unchecked (((FloatConstant
) left
).Value
*
560 ((FloatConstant
) right
).Value
);
562 return new FloatConstant (res
, left
.Location
);
563 } else if (left
is ULongConstant
){
566 if (ec
.ConstantCheckState
)
567 res
= checked (((ULongConstant
) left
).Value
*
568 ((ULongConstant
) right
).Value
);
570 res
= unchecked (((ULongConstant
) left
).Value
*
571 ((ULongConstant
) right
).Value
);
573 return new ULongConstant (res
, left
.Location
);
574 } else if (left
is LongConstant
){
577 if (ec
.ConstantCheckState
)
578 res
= checked (((LongConstant
) left
).Value
*
579 ((LongConstant
) right
).Value
);
581 res
= unchecked (((LongConstant
) left
).Value
*
582 ((LongConstant
) right
).Value
);
584 return new LongConstant (res
, left
.Location
);
585 } else if (left
is UIntConstant
){
588 if (ec
.ConstantCheckState
)
589 res
= checked (((UIntConstant
) left
).Value
*
590 ((UIntConstant
) right
).Value
);
592 res
= unchecked (((UIntConstant
) left
).Value
*
593 ((UIntConstant
) right
).Value
);
595 return new UIntConstant (res
, left
.Location
);
596 } else if (left
is IntConstant
){
599 if (ec
.ConstantCheckState
)
600 res
= checked (((IntConstant
) left
).Value
*
601 ((IntConstant
) right
).Value
);
603 res
= unchecked (((IntConstant
) left
).Value
*
604 ((IntConstant
) right
).Value
);
606 return new IntConstant (res
, left
.Location
);
607 } else if (left
is DecimalConstant
) {
610 if (ec
.ConstantCheckState
)
611 res
= checked (((DecimalConstant
) left
).Value
*
612 ((DecimalConstant
) right
).Value
);
614 res
= unchecked (((DecimalConstant
) left
).Value
*
615 ((DecimalConstant
) right
).Value
);
617 return new DecimalConstant (res
, left
.Location
);
619 throw new Exception ( "Unexepected multiply input: " + left
);
621 } catch (OverflowException
){
622 Error_CompileTimeOverflow (ec
, loc
);
626 case Binary
.Operator
.Division
:
627 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
631 if (left
is DoubleConstant
){
634 if (ec
.ConstantCheckState
)
635 res
= checked (((DoubleConstant
) left
).Value
/
636 ((DoubleConstant
) right
).Value
);
638 res
= unchecked (((DoubleConstant
) left
).Value
/
639 ((DoubleConstant
) right
).Value
);
641 return new DoubleConstant (res
, left
.Location
);
642 } else if (left
is FloatConstant
){
645 if (ec
.ConstantCheckState
)
646 res
= checked (((FloatConstant
) left
).Value
/
647 ((FloatConstant
) right
).Value
);
649 res
= unchecked (((FloatConstant
) left
).Value
/
650 ((FloatConstant
) right
).Value
);
652 return new FloatConstant (res
, left
.Location
);
653 } else if (left
is ULongConstant
){
656 if (ec
.ConstantCheckState
)
657 res
= checked (((ULongConstant
) left
).Value
/
658 ((ULongConstant
) right
).Value
);
660 res
= unchecked (((ULongConstant
) left
).Value
/
661 ((ULongConstant
) right
).Value
);
663 return new ULongConstant (res
, left
.Location
);
664 } else if (left
is LongConstant
){
667 if (ec
.ConstantCheckState
)
668 res
= checked (((LongConstant
) left
).Value
/
669 ((LongConstant
) right
).Value
);
671 res
= unchecked (((LongConstant
) left
).Value
/
672 ((LongConstant
) right
).Value
);
674 return new LongConstant (res
, left
.Location
);
675 } else if (left
is UIntConstant
){
678 if (ec
.ConstantCheckState
)
679 res
= checked (((UIntConstant
) left
).Value
/
680 ((UIntConstant
) right
).Value
);
682 res
= unchecked (((UIntConstant
) left
).Value
/
683 ((UIntConstant
) right
).Value
);
685 return new UIntConstant (res
, left
.Location
);
686 } else if (left
is IntConstant
){
689 if (ec
.ConstantCheckState
)
690 res
= checked (((IntConstant
) left
).Value
/
691 ((IntConstant
) right
).Value
);
693 res
= unchecked (((IntConstant
) left
).Value
/
694 ((IntConstant
) right
).Value
);
696 return new IntConstant (res
, left
.Location
);
697 } else if (left
is DecimalConstant
) {
700 if (ec
.ConstantCheckState
)
701 res
= checked (((DecimalConstant
) left
).Value
/
702 ((DecimalConstant
) right
).Value
);
704 res
= unchecked (((DecimalConstant
) left
).Value
/
705 ((DecimalConstant
) right
).Value
);
707 return new DecimalConstant (res
, left
.Location
);
709 throw new Exception ( "Unexepected division input: " + left
);
711 } catch (OverflowException
){
712 Error_CompileTimeOverflow (ec
, loc
);
714 } catch (DivideByZeroException
) {
715 ec
.Report
.Error (20, loc
, "Division by constant zero");
720 case Binary
.Operator
.Modulus
:
721 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
725 if (left
is DoubleConstant
){
728 if (ec
.ConstantCheckState
)
729 res
= checked (((DoubleConstant
) left
).Value
%
730 ((DoubleConstant
) right
).Value
);
732 res
= unchecked (((DoubleConstant
) left
).Value
%
733 ((DoubleConstant
) right
).Value
);
735 return new DoubleConstant (res
, left
.Location
);
736 } else if (left
is FloatConstant
){
739 if (ec
.ConstantCheckState
)
740 res
= checked (((FloatConstant
) left
).Value
%
741 ((FloatConstant
) right
).Value
);
743 res
= unchecked (((FloatConstant
) left
).Value
%
744 ((FloatConstant
) right
).Value
);
746 return new FloatConstant (res
, left
.Location
);
747 } else if (left
is ULongConstant
){
750 if (ec
.ConstantCheckState
)
751 res
= checked (((ULongConstant
) left
).Value
%
752 ((ULongConstant
) right
).Value
);
754 res
= unchecked (((ULongConstant
) left
).Value
%
755 ((ULongConstant
) right
).Value
);
757 return new ULongConstant (res
, left
.Location
);
758 } else if (left
is LongConstant
){
761 if (ec
.ConstantCheckState
)
762 res
= checked (((LongConstant
) left
).Value
%
763 ((LongConstant
) right
).Value
);
765 res
= unchecked (((LongConstant
) left
).Value
%
766 ((LongConstant
) right
).Value
);
768 return new LongConstant (res
, left
.Location
);
769 } else if (left
is UIntConstant
){
772 if (ec
.ConstantCheckState
)
773 res
= checked (((UIntConstant
) left
).Value
%
774 ((UIntConstant
) right
).Value
);
776 res
= unchecked (((UIntConstant
) left
).Value
%
777 ((UIntConstant
) right
).Value
);
779 return new UIntConstant (res
, left
.Location
);
780 } else if (left
is IntConstant
){
783 if (ec
.ConstantCheckState
)
784 res
= checked (((IntConstant
) left
).Value
%
785 ((IntConstant
) right
).Value
);
787 res
= unchecked (((IntConstant
) left
).Value
%
788 ((IntConstant
) right
).Value
);
790 return new IntConstant (res
, left
.Location
);
792 throw new Exception ( "Unexepected modulus input: " + left
);
794 } catch (DivideByZeroException
){
795 ec
.Report
.Error (20, loc
, "Division by constant zero");
796 } catch (OverflowException
){
797 Error_CompileTimeOverflow (ec
, loc
);
802 // There is no overflow checking on left shift
804 case Binary
.Operator
.LeftShift
:
805 IntConstant ic
= right
.ConvertImplicitly (ec
, TypeManager
.int32_type
) as IntConstant
;
807 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
811 int lshift_val
= ic
.Value
;
812 if (left
.Type
== TypeManager
.uint64_type
)
813 return new ULongConstant (((ULongConstant
)left
).Value
<< lshift_val
, left
.Location
);
814 if (left
.Type
== TypeManager
.int64_type
)
815 return new LongConstant (((LongConstant
)left
).Value
<< lshift_val
, left
.Location
);
816 if (left
.Type
== TypeManager
.uint32_type
)
817 return new UIntConstant (((UIntConstant
)left
).Value
<< lshift_val
, left
.Location
);
819 left
= left
.ConvertImplicitly (ec
, TypeManager
.int32_type
);
820 if (left
.Type
== TypeManager
.int32_type
)
821 return new IntConstant (((IntConstant
)left
).Value
<< lshift_val
, left
.Location
);
823 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
827 // There is no overflow checking on right shift
829 case Binary
.Operator
.RightShift
:
830 IntConstant sic
= right
.ConvertImplicitly (ec
, TypeManager
.int32_type
) as IntConstant
;
832 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
); ;
835 int rshift_val
= sic
.Value
;
836 if (left
.Type
== TypeManager
.uint64_type
)
837 return new ULongConstant (((ULongConstant
)left
).Value
>> rshift_val
, left
.Location
);
838 if (left
.Type
== TypeManager
.int64_type
)
839 return new LongConstant (((LongConstant
)left
).Value
>> rshift_val
, left
.Location
);
840 if (left
.Type
== TypeManager
.uint32_type
)
841 return new UIntConstant (((UIntConstant
)left
).Value
>> rshift_val
, left
.Location
);
843 left
= left
.ConvertImplicitly (ec
, TypeManager
.int32_type
);
844 if (left
.Type
== TypeManager
.int32_type
)
845 return new IntConstant (((IntConstant
)left
).Value
>> rshift_val
, left
.Location
);
847 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
850 case Binary
.Operator
.Equality
:
851 if (TypeManager
.IsReferenceType (lt
) && TypeManager
.IsReferenceType (lt
)) {
852 if (left
.IsNull
|| right
.IsNull
) {
853 return ReducedExpression
.Create (
854 new BoolConstant (left
.IsNull
== right
.IsNull
, left
.Location
).Resolve (ec
),
855 new Binary (oper
, left
, right
, loc
));
858 if (left
is StringConstant
&& right
is StringConstant
)
859 return new BoolConstant (
860 ((StringConstant
) left
).Value
== ((StringConstant
) right
).Value
, left
.Location
);
865 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
869 if (left
is DoubleConstant
)
870 bool_res
= ((DoubleConstant
) left
).Value
==
871 ((DoubleConstant
) right
).Value
;
872 else if (left
is FloatConstant
)
873 bool_res
= ((FloatConstant
) left
).Value
==
874 ((FloatConstant
) right
).Value
;
875 else if (left
is ULongConstant
)
876 bool_res
= ((ULongConstant
) left
).Value
==
877 ((ULongConstant
) right
).Value
;
878 else if (left
is LongConstant
)
879 bool_res
= ((LongConstant
) left
).Value
==
880 ((LongConstant
) right
).Value
;
881 else if (left
is UIntConstant
)
882 bool_res
= ((UIntConstant
) left
).Value
==
883 ((UIntConstant
) right
).Value
;
884 else if (left
is IntConstant
)
885 bool_res
= ((IntConstant
) left
).Value
==
886 ((IntConstant
) right
).Value
;
890 return new BoolConstant (bool_res
, left
.Location
);
892 case Binary
.Operator
.Inequality
:
893 if (TypeManager
.IsReferenceType (lt
) && TypeManager
.IsReferenceType (lt
)) {
894 if (left
.IsNull
|| right
.IsNull
) {
895 return ReducedExpression
.Create (
896 new BoolConstant (left
.IsNull
!= right
.IsNull
, left
.Location
).Resolve (ec
),
897 new Binary (oper
, left
, right
, loc
));
900 if (left
is StringConstant
&& right
is StringConstant
)
901 return new BoolConstant (
902 ((StringConstant
) left
).Value
!= ((StringConstant
) right
).Value
, left
.Location
);
907 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
911 if (left
is DoubleConstant
)
912 bool_res
= ((DoubleConstant
) left
).Value
!=
913 ((DoubleConstant
) right
).Value
;
914 else if (left
is FloatConstant
)
915 bool_res
= ((FloatConstant
) left
).Value
!=
916 ((FloatConstant
) right
).Value
;
917 else if (left
is ULongConstant
)
918 bool_res
= ((ULongConstant
) left
).Value
!=
919 ((ULongConstant
) right
).Value
;
920 else if (left
is LongConstant
)
921 bool_res
= ((LongConstant
) left
).Value
!=
922 ((LongConstant
) right
).Value
;
923 else if (left
is UIntConstant
)
924 bool_res
= ((UIntConstant
) left
).Value
!=
925 ((UIntConstant
) right
).Value
;
926 else if (left
is IntConstant
)
927 bool_res
= ((IntConstant
) left
).Value
!=
928 ((IntConstant
) right
).Value
;
932 return new BoolConstant (bool_res
, left
.Location
);
934 case Binary
.Operator
.LessThan
:
935 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
939 if (left
is DoubleConstant
)
940 bool_res
= ((DoubleConstant
) left
).Value
<
941 ((DoubleConstant
) right
).Value
;
942 else if (left
is FloatConstant
)
943 bool_res
= ((FloatConstant
) left
).Value
<
944 ((FloatConstant
) right
).Value
;
945 else if (left
is ULongConstant
)
946 bool_res
= ((ULongConstant
) left
).Value
<
947 ((ULongConstant
) right
).Value
;
948 else if (left
is LongConstant
)
949 bool_res
= ((LongConstant
) left
).Value
<
950 ((LongConstant
) right
).Value
;
951 else if (left
is UIntConstant
)
952 bool_res
= ((UIntConstant
) left
).Value
<
953 ((UIntConstant
) right
).Value
;
954 else if (left
is IntConstant
)
955 bool_res
= ((IntConstant
) left
).Value
<
956 ((IntConstant
) right
).Value
;
960 return new BoolConstant (bool_res
, left
.Location
);
962 case Binary
.Operator
.GreaterThan
:
963 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
967 if (left
is DoubleConstant
)
968 bool_res
= ((DoubleConstant
) left
).Value
>
969 ((DoubleConstant
) right
).Value
;
970 else if (left
is FloatConstant
)
971 bool_res
= ((FloatConstant
) left
).Value
>
972 ((FloatConstant
) right
).Value
;
973 else if (left
is ULongConstant
)
974 bool_res
= ((ULongConstant
) left
).Value
>
975 ((ULongConstant
) right
).Value
;
976 else if (left
is LongConstant
)
977 bool_res
= ((LongConstant
) left
).Value
>
978 ((LongConstant
) right
).Value
;
979 else if (left
is UIntConstant
)
980 bool_res
= ((UIntConstant
) left
).Value
>
981 ((UIntConstant
) right
).Value
;
982 else if (left
is IntConstant
)
983 bool_res
= ((IntConstant
) left
).Value
>
984 ((IntConstant
) right
).Value
;
988 return new BoolConstant (bool_res
, left
.Location
);
990 case Binary
.Operator
.GreaterThanOrEqual
:
991 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
995 if (left
is DoubleConstant
)
996 bool_res
= ((DoubleConstant
) left
).Value
>=
997 ((DoubleConstant
) right
).Value
;
998 else if (left
is FloatConstant
)
999 bool_res
= ((FloatConstant
) left
).Value
>=
1000 ((FloatConstant
) right
).Value
;
1001 else if (left
is ULongConstant
)
1002 bool_res
= ((ULongConstant
) left
).Value
>=
1003 ((ULongConstant
) right
).Value
;
1004 else if (left
is LongConstant
)
1005 bool_res
= ((LongConstant
) left
).Value
>=
1006 ((LongConstant
) right
).Value
;
1007 else if (left
is UIntConstant
)
1008 bool_res
= ((UIntConstant
) left
).Value
>=
1009 ((UIntConstant
) right
).Value
;
1010 else if (left
is IntConstant
)
1011 bool_res
= ((IntConstant
) left
).Value
>=
1012 ((IntConstant
) right
).Value
;
1016 return new BoolConstant (bool_res
, left
.Location
);
1018 case Binary
.Operator
.LessThanOrEqual
:
1019 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
1023 if (left
is DoubleConstant
)
1024 bool_res
= ((DoubleConstant
) left
).Value
<=
1025 ((DoubleConstant
) right
).Value
;
1026 else if (left
is FloatConstant
)
1027 bool_res
= ((FloatConstant
) left
).Value
<=
1028 ((FloatConstant
) right
).Value
;
1029 else if (left
is ULongConstant
)
1030 bool_res
= ((ULongConstant
) left
).Value
<=
1031 ((ULongConstant
) right
).Value
;
1032 else if (left
is LongConstant
)
1033 bool_res
= ((LongConstant
) left
).Value
<=
1034 ((LongConstant
) right
).Value
;
1035 else if (left
is UIntConstant
)
1036 bool_res
= ((UIntConstant
) left
).Value
<=
1037 ((UIntConstant
) right
).Value
;
1038 else if (left
is IntConstant
)
1039 bool_res
= ((IntConstant
) left
).Value
<=
1040 ((IntConstant
) right
).Value
;
1044 return new BoolConstant (bool_res
, left
.Location
);