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 public static readonly Type
[] binary_promotions
= new Type
[] {
18 TypeManager
.decimal_type
, TypeManager
.double_type
, TypeManager
.float_type
,
19 TypeManager
.uint64_type
, TypeManager
.int64_type
, TypeManager
.uint32_type
};
22 // Performs the numeric promotions on the left and right expresions
23 // and deposits the results on `lc' and `rc'.
25 // On success, the types of `lc' and `rc' on output will always match,
26 // and the pair will be one of:
28 static bool DoBinaryNumericPromotions (ref Constant left
, ref Constant right
)
30 Type ltype
= left
.Type
;
31 Type rtype
= right
.Type
;
33 foreach (Type t
in binary_promotions
) {
35 return t
== rtype
|| ConvertPromotion (ref right
, ref left
, t
);
38 return t
== ltype
|| ConvertPromotion (ref left
, ref right
, t
);
41 left
= left
.ConvertImplicitly (TypeManager
.int32_type
);
42 right
= right
.ConvertImplicitly (TypeManager
.int32_type
);
43 return left
!= null && right
!= null;
46 static bool ConvertPromotion (ref Constant prim
, ref Constant second
, Type type
)
48 Constant c
= prim
.ConvertImplicitly (type
);
54 if (type
== TypeManager
.uint32_type
) {
55 type
= TypeManager
.int64_type
;
56 prim
= prim
.ConvertImplicitly (type
);
57 second
= second
.ConvertImplicitly (type
);
58 return prim
!= null && second
!= null;
64 internal static void Error_CompileTimeOverflow (Location loc
)
66 Report
.Error (220, loc
, "The operation overflows at compile time in checked mode");
70 /// Constant expression folder for binary operations.
72 /// Returns null if the expression can not be folded.
74 static public Constant
BinaryFold (EmitContext ec
, Binary
.Operator oper
,
75 Constant left
, Constant right
, Location loc
)
77 Constant result
= null;
79 if (left
is EmptyConstantCast
)
80 return BinaryFold (ec
, oper
, ((EmptyConstantCast
)left
).child
, right
, loc
);
82 if (left
is SideEffectConstant
) {
83 result
= BinaryFold (ec
, oper
, ((SideEffectConstant
) left
).value, right
, loc
);
86 return new SideEffectConstant (result
, left
, loc
);
89 if (right
is EmptyConstantCast
)
90 return BinaryFold (ec
, oper
, left
, ((EmptyConstantCast
)right
).child
, loc
);
92 if (right
is SideEffectConstant
) {
93 result
= BinaryFold (ec
, oper
, left
, ((SideEffectConstant
) right
).value, loc
);
96 return new SideEffectConstant (result
, right
, loc
);
100 Type rt
= right
.Type
;
103 if (lt
== TypeManager
.bool_type
&& lt
== rt
) {
104 bool lv
= (bool) left
.GetValue ();
105 bool rv
= (bool) right
.GetValue ();
107 case Binary
.Operator
.BitwiseAnd
:
108 case Binary
.Operator
.LogicalAnd
:
109 return new BoolConstant (lv
&& rv
, left
.Location
);
110 case Binary
.Operator
.BitwiseOr
:
111 case Binary
.Operator
.LogicalOr
:
112 return new BoolConstant (lv
|| rv
, left
.Location
);
113 case Binary
.Operator
.ExclusiveOr
:
114 return new BoolConstant (lv ^ rv
, left
.Location
);
115 case Binary
.Operator
.Equality
:
116 return new BoolConstant (lv
== rv
, left
.Location
);
117 case Binary
.Operator
.Inequality
:
118 return new BoolConstant (lv
!= rv
, left
.Location
);
124 // During an enum evaluation, none of the rules are valid
125 // Not sure whether it is bug in csc or in documentation
127 if (ec
.InEnumContext
){
128 if (left
is EnumConstant
)
129 left
= ((EnumConstant
) left
).Child
;
131 if (right
is EnumConstant
)
132 right
= ((EnumConstant
) right
).Child
;
133 } else if (left
is EnumConstant
&& rt
== lt
) {
136 /// E operator |(E x, E y);
137 /// E operator &(E x, E y);
138 /// E operator ^(E x, E y);
140 case Binary
.Operator
.BitwiseOr
:
141 case Binary
.Operator
.BitwiseAnd
:
142 case Binary
.Operator
.ExclusiveOr
:
143 return BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
,
144 ((EnumConstant
)right
).Child
, loc
).TryReduce (ec
, lt
, loc
);
147 /// U operator -(E x, E y);
149 case Binary
.Operator
.Subtraction
:
150 result
= BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
151 return result
.TryReduce (ec
, ((EnumConstant
)left
).Child
.Type
, loc
);
154 /// bool operator ==(E x, E y);
155 /// bool operator !=(E x, E y);
156 /// bool operator <(E x, E y);
157 /// bool operator >(E x, E y);
158 /// bool operator <=(E x, E y);
159 /// bool operator >=(E x, E y);
161 case Binary
.Operator
.Equality
:
162 case Binary
.Operator
.Inequality
:
163 case Binary
.Operator
.LessThan
:
164 case Binary
.Operator
.GreaterThan
:
165 case Binary
.Operator
.LessThanOrEqual
:
166 case Binary
.Operator
.GreaterThanOrEqual
:
167 return BinaryFold(ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
173 case Binary
.Operator
.BitwiseOr
:
174 if (!DoBinaryNumericPromotions (ref left
, ref right
))
177 if (left
is IntConstant
){
178 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
180 return new IntConstant (res
, left
.Location
);
182 if (left
is UIntConstant
){
183 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
185 return new UIntConstant (res
, left
.Location
);
187 if (left
is LongConstant
){
188 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
190 return new LongConstant (res
, left
.Location
);
192 if (left
is ULongConstant
){
193 ulong res
= ((ULongConstant
)left
).Value
|
194 ((ULongConstant
)right
).Value
;
196 return new ULongConstant (res
, left
.Location
);
200 case Binary
.Operator
.BitwiseAnd
:
201 if (!DoBinaryNumericPromotions (ref left
, ref right
))
205 /// int operator &(int x, int y);
206 /// uint operator &(uint x, uint y);
207 /// long operator &(long x, long y);
208 /// ulong operator &(ulong x, ulong y);
210 if (left
is IntConstant
){
211 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
212 return new IntConstant (res
, left
.Location
);
214 if (left
is UIntConstant
){
215 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
216 return new UIntConstant (res
, left
.Location
);
218 if (left
is LongConstant
){
219 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
220 return new LongConstant (res
, left
.Location
);
222 if (left
is ULongConstant
){
223 ulong res
= ((ULongConstant
)left
).Value
&
224 ((ULongConstant
)right
).Value
;
226 return new ULongConstant (res
, left
.Location
);
230 case Binary
.Operator
.ExclusiveOr
:
231 if (!DoBinaryNumericPromotions (ref left
, ref right
))
234 if (left
is IntConstant
){
235 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
236 return new IntConstant (res
, left
.Location
);
238 if (left
is UIntConstant
){
239 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
241 return new UIntConstant (res
, left
.Location
);
243 if (left
is LongConstant
){
244 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
246 return new LongConstant (res
, left
.Location
);
248 if (left
is ULongConstant
){
249 ulong res
= ((ULongConstant
)left
).Value ^
250 ((ULongConstant
)right
).Value
;
252 return new ULongConstant (res
, left
.Location
);
256 case Binary
.Operator
.Addition
:
257 if (lt
== TypeManager
.null_type
)
260 if (rt
== TypeManager
.null_type
)
264 // If both sides are strings, then concatenate, if
265 // one is a string, and the other is not, then defer
266 // to runtime concatenation
268 if (lt
== TypeManager
.string_type
|| rt
== TypeManager
.string_type
){
270 return new StringConstant ((string)left
.GetValue () + (string)right
.GetValue (),
277 // handle "E operator + (E x, U y)"
278 // handle "E operator + (Y y, E x)"
280 EnumConstant lc
= left
as EnumConstant
;
281 EnumConstant rc
= right
as EnumConstant
;
282 if (lc
!= null || rc
!= null){
289 // U has to be implicitly convetible to E.base
290 right
= right
.ConvertImplicitly (lc
.Child
.Type
);
294 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
298 result
= result
.TryReduce (ec
, lt
, loc
);
302 return new EnumConstant (result
, lt
);
305 if (!DoBinaryNumericPromotions (ref left
, ref right
))
309 if (left
is DoubleConstant
){
312 if (ec
.ConstantCheckState
)
313 res
= checked (((DoubleConstant
) left
).Value
+
314 ((DoubleConstant
) right
).Value
);
316 res
= unchecked (((DoubleConstant
) left
).Value
+
317 ((DoubleConstant
) right
).Value
);
319 return new DoubleConstant (res
, left
.Location
);
321 if (left
is FloatConstant
){
324 if (ec
.ConstantCheckState
)
325 res
= checked (((FloatConstant
) left
).Value
+
326 ((FloatConstant
) right
).Value
);
328 res
= unchecked (((FloatConstant
) left
).Value
+
329 ((FloatConstant
) right
).Value
);
331 result
= new FloatConstant (res
, left
.Location
);
332 } else if (left
is ULongConstant
){
335 if (ec
.ConstantCheckState
)
336 res
= checked (((ULongConstant
) left
).Value
+
337 ((ULongConstant
) right
).Value
);
339 res
= unchecked (((ULongConstant
) left
).Value
+
340 ((ULongConstant
) right
).Value
);
342 result
= new ULongConstant (res
, left
.Location
);
343 } else if (left
is LongConstant
){
346 if (ec
.ConstantCheckState
)
347 res
= checked (((LongConstant
) left
).Value
+
348 ((LongConstant
) right
).Value
);
350 res
= unchecked (((LongConstant
) left
).Value
+
351 ((LongConstant
) right
).Value
);
353 result
= new LongConstant (res
, left
.Location
);
354 } else if (left
is UIntConstant
){
357 if (ec
.ConstantCheckState
)
358 res
= checked (((UIntConstant
) left
).Value
+
359 ((UIntConstant
) right
).Value
);
361 res
= unchecked (((UIntConstant
) left
).Value
+
362 ((UIntConstant
) right
).Value
);
364 result
= new UIntConstant (res
, left
.Location
);
365 } else if (left
is IntConstant
){
368 if (ec
.ConstantCheckState
)
369 res
= checked (((IntConstant
) left
).Value
+
370 ((IntConstant
) right
).Value
);
372 res
= unchecked (((IntConstant
) left
).Value
+
373 ((IntConstant
) right
).Value
);
375 result
= new IntConstant (res
, left
.Location
);
376 } else if (left
is DecimalConstant
) {
379 if (ec
.ConstantCheckState
)
380 res
= checked (((DecimalConstant
) left
).Value
+
381 ((DecimalConstant
) right
).Value
);
383 res
= unchecked (((DecimalConstant
) left
).Value
+
384 ((DecimalConstant
) right
).Value
);
386 result
= new DecimalConstant (res
, left
.Location
);
388 } catch (OverflowException
){
389 Error_CompileTimeOverflow (loc
);
394 case Binary
.Operator
.Subtraction
:
396 // handle "E operator - (E x, U y)"
397 // handle "E operator - (Y y, E x)"
399 lc
= left
as EnumConstant
;
400 rc
= right
as EnumConstant
;
401 if (lc
!= null || rc
!= null){
408 // U has to be implicitly convetible to E.base
409 right
= right
.ConvertImplicitly (lc
.Child
.Type
);
413 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
417 result
= result
.TryReduce (ec
, lt
, loc
);
421 return new EnumConstant (result
, lt
);
424 if (!DoBinaryNumericPromotions (ref left
, ref right
))
428 if (left
is DoubleConstant
){
431 if (ec
.ConstantCheckState
)
432 res
= checked (((DoubleConstant
) left
).Value
-
433 ((DoubleConstant
) right
).Value
);
435 res
= unchecked (((DoubleConstant
) left
).Value
-
436 ((DoubleConstant
) right
).Value
);
438 result
= new DoubleConstant (res
, left
.Location
);
439 } else if (left
is FloatConstant
){
442 if (ec
.ConstantCheckState
)
443 res
= checked (((FloatConstant
) left
).Value
-
444 ((FloatConstant
) right
).Value
);
446 res
= unchecked (((FloatConstant
) left
).Value
-
447 ((FloatConstant
) right
).Value
);
449 result
= new FloatConstant (res
, left
.Location
);
450 } else if (left
is ULongConstant
){
453 if (ec
.ConstantCheckState
)
454 res
= checked (((ULongConstant
) left
).Value
-
455 ((ULongConstant
) right
).Value
);
457 res
= unchecked (((ULongConstant
) left
).Value
-
458 ((ULongConstant
) right
).Value
);
460 result
= new ULongConstant (res
, left
.Location
);
461 } else if (left
is LongConstant
){
464 if (ec
.ConstantCheckState
)
465 res
= checked (((LongConstant
) left
).Value
-
466 ((LongConstant
) right
).Value
);
468 res
= unchecked (((LongConstant
) left
).Value
-
469 ((LongConstant
) right
).Value
);
471 result
= new LongConstant (res
, left
.Location
);
472 } else if (left
is UIntConstant
){
475 if (ec
.ConstantCheckState
)
476 res
= checked (((UIntConstant
) left
).Value
-
477 ((UIntConstant
) right
).Value
);
479 res
= unchecked (((UIntConstant
) left
).Value
-
480 ((UIntConstant
) right
).Value
);
482 result
= new UIntConstant (res
, left
.Location
);
483 } else if (left
is IntConstant
){
486 if (ec
.ConstantCheckState
)
487 res
= checked (((IntConstant
) left
).Value
-
488 ((IntConstant
) right
).Value
);
490 res
= unchecked (((IntConstant
) left
).Value
-
491 ((IntConstant
) right
).Value
);
493 result
= new IntConstant (res
, left
.Location
);
494 } else if (left
is DecimalConstant
) {
497 if (ec
.ConstantCheckState
)
498 res
= checked (((DecimalConstant
) left
).Value
-
499 ((DecimalConstant
) right
).Value
);
501 res
= unchecked (((DecimalConstant
) left
).Value
-
502 ((DecimalConstant
) right
).Value
);
504 return new DecimalConstant (res
, left
.Location
);
506 throw new Exception ( "Unexepected subtraction input: " + left
);
508 } catch (OverflowException
){
509 Error_CompileTimeOverflow (loc
);
514 case Binary
.Operator
.Multiply
:
515 if (!DoBinaryNumericPromotions (ref left
, ref right
))
519 if (left
is DoubleConstant
){
522 if (ec
.ConstantCheckState
)
523 res
= checked (((DoubleConstant
) left
).Value
*
524 ((DoubleConstant
) right
).Value
);
526 res
= unchecked (((DoubleConstant
) left
).Value
*
527 ((DoubleConstant
) right
).Value
);
529 return new DoubleConstant (res
, left
.Location
);
530 } else if (left
is FloatConstant
){
533 if (ec
.ConstantCheckState
)
534 res
= checked (((FloatConstant
) left
).Value
*
535 ((FloatConstant
) right
).Value
);
537 res
= unchecked (((FloatConstant
) left
).Value
*
538 ((FloatConstant
) right
).Value
);
540 return new FloatConstant (res
, left
.Location
);
541 } else if (left
is ULongConstant
){
544 if (ec
.ConstantCheckState
)
545 res
= checked (((ULongConstant
) left
).Value
*
546 ((ULongConstant
) right
).Value
);
548 res
= unchecked (((ULongConstant
) left
).Value
*
549 ((ULongConstant
) right
).Value
);
551 return new ULongConstant (res
, left
.Location
);
552 } else if (left
is LongConstant
){
555 if (ec
.ConstantCheckState
)
556 res
= checked (((LongConstant
) left
).Value
*
557 ((LongConstant
) right
).Value
);
559 res
= unchecked (((LongConstant
) left
).Value
*
560 ((LongConstant
) right
).Value
);
562 return new LongConstant (res
, left
.Location
);
563 } else if (left
is UIntConstant
){
566 if (ec
.ConstantCheckState
)
567 res
= checked (((UIntConstant
) left
).Value
*
568 ((UIntConstant
) right
).Value
);
570 res
= unchecked (((UIntConstant
) left
).Value
*
571 ((UIntConstant
) right
).Value
);
573 return new UIntConstant (res
, left
.Location
);
574 } else if (left
is IntConstant
){
577 if (ec
.ConstantCheckState
)
578 res
= checked (((IntConstant
) left
).Value
*
579 ((IntConstant
) right
).Value
);
581 res
= unchecked (((IntConstant
) left
).Value
*
582 ((IntConstant
) right
).Value
);
584 return new IntConstant (res
, left
.Location
);
585 } else if (left
is DecimalConstant
) {
588 if (ec
.ConstantCheckState
)
589 res
= checked (((DecimalConstant
) left
).Value
*
590 ((DecimalConstant
) right
).Value
);
592 res
= unchecked (((DecimalConstant
) left
).Value
*
593 ((DecimalConstant
) right
).Value
);
595 return new DecimalConstant (res
, left
.Location
);
597 throw new Exception ( "Unexepected multiply input: " + left
);
599 } catch (OverflowException
){
600 Error_CompileTimeOverflow (loc
);
604 case Binary
.Operator
.Division
:
605 if (!DoBinaryNumericPromotions (ref left
, ref right
))
609 if (left
is DoubleConstant
){
612 if (ec
.ConstantCheckState
)
613 res
= checked (((DoubleConstant
) left
).Value
/
614 ((DoubleConstant
) right
).Value
);
616 res
= unchecked (((DoubleConstant
) left
).Value
/
617 ((DoubleConstant
) right
).Value
);
619 return new DoubleConstant (res
, left
.Location
);
620 } else if (left
is FloatConstant
){
623 if (ec
.ConstantCheckState
)
624 res
= checked (((FloatConstant
) left
).Value
/
625 ((FloatConstant
) right
).Value
);
627 res
= unchecked (((FloatConstant
) left
).Value
/
628 ((FloatConstant
) right
).Value
);
630 return new FloatConstant (res
, left
.Location
);
631 } else if (left
is ULongConstant
){
634 if (ec
.ConstantCheckState
)
635 res
= checked (((ULongConstant
) left
).Value
/
636 ((ULongConstant
) right
).Value
);
638 res
= unchecked (((ULongConstant
) left
).Value
/
639 ((ULongConstant
) right
).Value
);
641 return new ULongConstant (res
, left
.Location
);
642 } else if (left
is LongConstant
){
645 if (ec
.ConstantCheckState
)
646 res
= checked (((LongConstant
) left
).Value
/
647 ((LongConstant
) right
).Value
);
649 res
= unchecked (((LongConstant
) left
).Value
/
650 ((LongConstant
) right
).Value
);
652 return new LongConstant (res
, left
.Location
);
653 } else if (left
is UIntConstant
){
656 if (ec
.ConstantCheckState
)
657 res
= checked (((UIntConstant
) left
).Value
/
658 ((UIntConstant
) right
).Value
);
660 res
= unchecked (((UIntConstant
) left
).Value
/
661 ((UIntConstant
) right
).Value
);
663 return new UIntConstant (res
, left
.Location
);
664 } else if (left
is IntConstant
){
667 if (ec
.ConstantCheckState
)
668 res
= checked (((IntConstant
) left
).Value
/
669 ((IntConstant
) right
).Value
);
671 res
= unchecked (((IntConstant
) left
).Value
/
672 ((IntConstant
) right
).Value
);
674 return new IntConstant (res
, left
.Location
);
675 } else if (left
is DecimalConstant
) {
678 if (ec
.ConstantCheckState
)
679 res
= checked (((DecimalConstant
) left
).Value
/
680 ((DecimalConstant
) right
).Value
);
682 res
= unchecked (((DecimalConstant
) left
).Value
/
683 ((DecimalConstant
) right
).Value
);
685 return new DecimalConstant (res
, left
.Location
);
687 throw new Exception ( "Unexepected division input: " + left
);
689 } catch (OverflowException
){
690 Error_CompileTimeOverflow (loc
);
692 } catch (DivideByZeroException
) {
693 Report
.Error (020, loc
, "Division by constant zero");
698 case Binary
.Operator
.Modulus
:
699 if (!DoBinaryNumericPromotions (ref left
, ref right
))
703 if (left
is DoubleConstant
){
706 if (ec
.ConstantCheckState
)
707 res
= checked (((DoubleConstant
) left
).Value
%
708 ((DoubleConstant
) right
).Value
);
710 res
= unchecked (((DoubleConstant
) left
).Value
%
711 ((DoubleConstant
) right
).Value
);
713 return new DoubleConstant (res
, left
.Location
);
714 } else if (left
is FloatConstant
){
717 if (ec
.ConstantCheckState
)
718 res
= checked (((FloatConstant
) left
).Value
%
719 ((FloatConstant
) right
).Value
);
721 res
= unchecked (((FloatConstant
) left
).Value
%
722 ((FloatConstant
) right
).Value
);
724 return new FloatConstant (res
, left
.Location
);
725 } else if (left
is ULongConstant
){
728 if (ec
.ConstantCheckState
)
729 res
= checked (((ULongConstant
) left
).Value
%
730 ((ULongConstant
) right
).Value
);
732 res
= unchecked (((ULongConstant
) left
).Value
%
733 ((ULongConstant
) right
).Value
);
735 return new ULongConstant (res
, left
.Location
);
736 } else if (left
is LongConstant
){
739 if (ec
.ConstantCheckState
)
740 res
= checked (((LongConstant
) left
).Value
%
741 ((LongConstant
) right
).Value
);
743 res
= unchecked (((LongConstant
) left
).Value
%
744 ((LongConstant
) right
).Value
);
746 return new LongConstant (res
, left
.Location
);
747 } else if (left
is UIntConstant
){
750 if (ec
.ConstantCheckState
)
751 res
= checked (((UIntConstant
) left
).Value
%
752 ((UIntConstant
) right
).Value
);
754 res
= unchecked (((UIntConstant
) left
).Value
%
755 ((UIntConstant
) right
).Value
);
757 return new UIntConstant (res
, left
.Location
);
758 } else if (left
is IntConstant
){
761 if (ec
.ConstantCheckState
)
762 res
= checked (((IntConstant
) left
).Value
%
763 ((IntConstant
) right
).Value
);
765 res
= unchecked (((IntConstant
) left
).Value
%
766 ((IntConstant
) right
).Value
);
768 return new IntConstant (res
, left
.Location
);
770 throw new Exception ( "Unexepected modulus input: " + left
);
772 } catch (DivideByZeroException
){
773 Report
.Error (020, loc
, "Division by constant zero");
774 } catch (OverflowException
){
775 Error_CompileTimeOverflow (loc
);
780 // There is no overflow checking on left shift
782 case Binary
.Operator
.LeftShift
:
783 IntConstant ic
= right
.ConvertImplicitly (TypeManager
.int32_type
) as IntConstant
;
785 Binary
.Error_OperatorCannotBeApplied (left
, right
, oper
, loc
);
789 int lshift_val
= ic
.Value
;
790 if (left
.Type
== TypeManager
.uint64_type
)
791 return new ULongConstant (((ULongConstant
)left
).Value
<< lshift_val
, left
.Location
);
792 if (left
.Type
== TypeManager
.int64_type
)
793 return new LongConstant (((LongConstant
)left
).Value
<< lshift_val
, left
.Location
);
794 if (left
.Type
== TypeManager
.uint32_type
)
795 return new UIntConstant (((UIntConstant
)left
).Value
<< lshift_val
, left
.Location
);
797 left
= left
.ConvertImplicitly (TypeManager
.int32_type
);
798 if (left
.Type
== TypeManager
.int32_type
)
799 return new IntConstant (((IntConstant
)left
).Value
<< lshift_val
, left
.Location
);
801 Binary
.Error_OperatorCannotBeApplied (left
, right
, oper
, loc
);
805 // There is no overflow checking on right shift
807 case Binary
.Operator
.RightShift
:
808 IntConstant sic
= right
.ConvertImplicitly (TypeManager
.int32_type
) as IntConstant
;
810 Binary
.Error_OperatorCannotBeApplied (left
, right
, oper
, loc
); ;
813 int rshift_val
= sic
.Value
;
814 if (left
.Type
== TypeManager
.uint64_type
)
815 return new ULongConstant (((ULongConstant
)left
).Value
>> rshift_val
, left
.Location
);
816 if (left
.Type
== TypeManager
.int64_type
)
817 return new LongConstant (((LongConstant
)left
).Value
>> rshift_val
, left
.Location
);
818 if (left
.Type
== TypeManager
.uint32_type
)
819 return new UIntConstant (((UIntConstant
)left
).Value
>> rshift_val
, left
.Location
);
821 left
= left
.ConvertImplicitly (TypeManager
.int32_type
);
822 if (left
.Type
== TypeManager
.int32_type
)
823 return new IntConstant (((IntConstant
)left
).Value
>> rshift_val
, left
.Location
);
825 Binary
.Error_OperatorCannotBeApplied (left
, right
, oper
, loc
);
828 case Binary
.Operator
.Equality
:
829 if (left
is NullLiteral
){
830 if (right
is NullLiteral
)
831 return new BoolConstant (true, left
.Location
);
832 else if (right
is StringConstant
)
833 return new BoolConstant (
834 ((StringConstant
) right
).Value
== null, left
.Location
);
835 } else if (right
is NullLiteral
) {
836 if (left
is NullLiteral
)
837 return new BoolConstant (true, left
.Location
);
838 else if (left
is StringConstant
)
839 return new BoolConstant (
840 ((StringConstant
) left
).Value
== null, left
.Location
);
842 if (left
is StringConstant
&& right
is StringConstant
){
843 return new BoolConstant (
844 ((StringConstant
) left
).Value
==
845 ((StringConstant
) right
).Value
, left
.Location
);
849 if (!DoBinaryNumericPromotions (ref left
, ref right
))
853 if (left
is DoubleConstant
)
854 bool_res
= ((DoubleConstant
) left
).Value
==
855 ((DoubleConstant
) right
).Value
;
856 else if (left
is FloatConstant
)
857 bool_res
= ((FloatConstant
) left
).Value
==
858 ((FloatConstant
) right
).Value
;
859 else if (left
is ULongConstant
)
860 bool_res
= ((ULongConstant
) left
).Value
==
861 ((ULongConstant
) right
).Value
;
862 else if (left
is LongConstant
)
863 bool_res
= ((LongConstant
) left
).Value
==
864 ((LongConstant
) right
).Value
;
865 else if (left
is UIntConstant
)
866 bool_res
= ((UIntConstant
) left
).Value
==
867 ((UIntConstant
) right
).Value
;
868 else if (left
is IntConstant
)
869 bool_res
= ((IntConstant
) left
).Value
==
870 ((IntConstant
) right
).Value
;
874 return new BoolConstant (bool_res
, left
.Location
);
876 case Binary
.Operator
.Inequality
:
877 if (left
is NullLiteral
) {
878 if (right
is NullLiteral
)
879 return new BoolConstant (false, left
.Location
);
880 else if (right
is StringConstant
)
881 return new BoolConstant (
882 ((StringConstant
) right
).Value
!= null, left
.Location
);
883 } else if (right
is NullLiteral
) {
884 if (left
is NullLiteral
)
885 return new BoolConstant (false, left
.Location
);
886 else if (left
is StringConstant
)
887 return new BoolConstant (
888 ((StringConstant
) left
).Value
!= null, left
.Location
);
890 if (left
is StringConstant
&& right
is StringConstant
){
891 return new BoolConstant (
892 ((StringConstant
) left
).Value
!=
893 ((StringConstant
) right
).Value
, left
.Location
);
897 if (!DoBinaryNumericPromotions (ref left
, ref right
))
901 if (left
is DoubleConstant
)
902 bool_res
= ((DoubleConstant
) left
).Value
!=
903 ((DoubleConstant
) right
).Value
;
904 else if (left
is FloatConstant
)
905 bool_res
= ((FloatConstant
) left
).Value
!=
906 ((FloatConstant
) right
).Value
;
907 else if (left
is ULongConstant
)
908 bool_res
= ((ULongConstant
) left
).Value
!=
909 ((ULongConstant
) right
).Value
;
910 else if (left
is LongConstant
)
911 bool_res
= ((LongConstant
) left
).Value
!=
912 ((LongConstant
) right
).Value
;
913 else if (left
is UIntConstant
)
914 bool_res
= ((UIntConstant
) left
).Value
!=
915 ((UIntConstant
) right
).Value
;
916 else if (left
is IntConstant
)
917 bool_res
= ((IntConstant
) left
).Value
!=
918 ((IntConstant
) right
).Value
;
922 return new BoolConstant (bool_res
, left
.Location
);
924 case Binary
.Operator
.LessThan
:
925 if (!DoBinaryNumericPromotions (ref left
, ref right
))
929 if (left
is DoubleConstant
)
930 bool_res
= ((DoubleConstant
) left
).Value
<
931 ((DoubleConstant
) right
).Value
;
932 else if (left
is FloatConstant
)
933 bool_res
= ((FloatConstant
) left
).Value
<
934 ((FloatConstant
) right
).Value
;
935 else if (left
is ULongConstant
)
936 bool_res
= ((ULongConstant
) left
).Value
<
937 ((ULongConstant
) right
).Value
;
938 else if (left
is LongConstant
)
939 bool_res
= ((LongConstant
) left
).Value
<
940 ((LongConstant
) right
).Value
;
941 else if (left
is UIntConstant
)
942 bool_res
= ((UIntConstant
) left
).Value
<
943 ((UIntConstant
) right
).Value
;
944 else if (left
is IntConstant
)
945 bool_res
= ((IntConstant
) left
).Value
<
946 ((IntConstant
) right
).Value
;
950 return new BoolConstant (bool_res
, left
.Location
);
952 case Binary
.Operator
.GreaterThan
:
953 if (!DoBinaryNumericPromotions (ref left
, ref right
))
957 if (left
is DoubleConstant
)
958 bool_res
= ((DoubleConstant
) left
).Value
>
959 ((DoubleConstant
) right
).Value
;
960 else if (left
is FloatConstant
)
961 bool_res
= ((FloatConstant
) left
).Value
>
962 ((FloatConstant
) right
).Value
;
963 else if (left
is ULongConstant
)
964 bool_res
= ((ULongConstant
) left
).Value
>
965 ((ULongConstant
) right
).Value
;
966 else if (left
is LongConstant
)
967 bool_res
= ((LongConstant
) left
).Value
>
968 ((LongConstant
) right
).Value
;
969 else if (left
is UIntConstant
)
970 bool_res
= ((UIntConstant
) left
).Value
>
971 ((UIntConstant
) right
).Value
;
972 else if (left
is IntConstant
)
973 bool_res
= ((IntConstant
) left
).Value
>
974 ((IntConstant
) right
).Value
;
978 return new BoolConstant (bool_res
, left
.Location
);
980 case Binary
.Operator
.GreaterThanOrEqual
:
981 if (!DoBinaryNumericPromotions (ref left
, ref right
))
985 if (left
is DoubleConstant
)
986 bool_res
= ((DoubleConstant
) left
).Value
>=
987 ((DoubleConstant
) right
).Value
;
988 else if (left
is FloatConstant
)
989 bool_res
= ((FloatConstant
) left
).Value
>=
990 ((FloatConstant
) right
).Value
;
991 else if (left
is ULongConstant
)
992 bool_res
= ((ULongConstant
) left
).Value
>=
993 ((ULongConstant
) right
).Value
;
994 else if (left
is LongConstant
)
995 bool_res
= ((LongConstant
) left
).Value
>=
996 ((LongConstant
) right
).Value
;
997 else if (left
is UIntConstant
)
998 bool_res
= ((UIntConstant
) left
).Value
>=
999 ((UIntConstant
) right
).Value
;
1000 else if (left
is IntConstant
)
1001 bool_res
= ((IntConstant
) left
).Value
>=
1002 ((IntConstant
) right
).Value
;
1006 return new BoolConstant (bool_res
, left
.Location
);
1008 case Binary
.Operator
.LessThanOrEqual
:
1009 if (!DoBinaryNumericPromotions (ref left
, ref right
))
1013 if (left
is DoubleConstant
)
1014 bool_res
= ((DoubleConstant
) left
).Value
<=
1015 ((DoubleConstant
) right
).Value
;
1016 else if (left
is FloatConstant
)
1017 bool_res
= ((FloatConstant
) left
).Value
<=
1018 ((FloatConstant
) right
).Value
;
1019 else if (left
is ULongConstant
)
1020 bool_res
= ((ULongConstant
) left
).Value
<=
1021 ((ULongConstant
) right
).Value
;
1022 else if (left
is LongConstant
)
1023 bool_res
= ((LongConstant
) left
).Value
<=
1024 ((LongConstant
) right
).Value
;
1025 else if (left
is UIntConstant
)
1026 bool_res
= ((UIntConstant
) left
).Value
<=
1027 ((UIntConstant
) right
).Value
;
1028 else if (left
is IntConstant
)
1029 bool_res
= ((IntConstant
) left
).Value
<=
1030 ((IntConstant
) right
).Value
;
1034 return new BoolConstant (bool_res
, left
.Location
);