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 // TODO: BinaryFold should be called as an optimization step only,
29 // error checking here is weak
31 static bool DoBinaryNumericPromotions (ResolveContext rc
, ref Constant left
, ref Constant right
)
33 Type ltype
= left
.Type
;
34 Type rtype
= right
.Type
;
36 foreach (Type t
in binary_promotions
) {
38 return t
== rtype
|| ConvertPromotion (rc
, ref right
, ref left
, t
);
41 return t
== ltype
|| ConvertPromotion (rc
, ref left
, ref right
, t
);
44 left
= left
.ConvertImplicitly (rc
, TypeManager
.int32_type
);
45 right
= right
.ConvertImplicitly (rc
, TypeManager
.int32_type
);
46 return left
!= null && right
!= null;
49 static bool ConvertPromotion (ResolveContext rc
, ref Constant prim
, ref Constant second
, Type type
)
51 Constant c
= prim
.ConvertImplicitly (rc
, type
);
57 if (type
== TypeManager
.uint32_type
) {
58 type
= TypeManager
.int64_type
;
59 prim
= prim
.ConvertImplicitly (rc
, type
);
60 second
= second
.ConvertImplicitly (rc
, type
);
61 return prim
!= null && second
!= null;
67 internal static void Error_CompileTimeOverflow (ResolveContext rc
, Location loc
)
69 rc
.Report
.Error (220, loc
, "The operation overflows at compile time in checked mode");
73 /// Constant expression folder for binary operations.
75 /// Returns null if the expression can not be folded.
77 static public Constant
BinaryFold (ResolveContext ec
, Binary
.Operator oper
,
78 Constant left
, Constant right
, Location loc
)
80 Constant result
= null;
82 if (left
is EmptyConstantCast
)
83 return BinaryFold (ec
, oper
, ((EmptyConstantCast
)left
).child
, right
, loc
);
85 if (left
is SideEffectConstant
) {
86 result
= BinaryFold (ec
, oper
, ((SideEffectConstant
) left
).value, right
, loc
);
89 return new SideEffectConstant (result
, left
, loc
);
92 if (right
is EmptyConstantCast
)
93 return BinaryFold (ec
, oper
, left
, ((EmptyConstantCast
)right
).child
, loc
);
95 if (right
is SideEffectConstant
) {
96 result
= BinaryFold (ec
, oper
, left
, ((SideEffectConstant
) right
).value, loc
);
99 return new SideEffectConstant (result
, right
, loc
);
103 Type rt
= right
.Type
;
106 if (lt
== TypeManager
.bool_type
&& lt
== rt
) {
107 bool lv
= (bool) left
.GetValue ();
108 bool rv
= (bool) right
.GetValue ();
110 case Binary
.Operator
.BitwiseAnd
:
111 case Binary
.Operator
.LogicalAnd
:
112 return new BoolConstant (lv
&& rv
, left
.Location
);
113 case Binary
.Operator
.BitwiseOr
:
114 case Binary
.Operator
.LogicalOr
:
115 return new BoolConstant (lv
|| rv
, left
.Location
);
116 case Binary
.Operator
.ExclusiveOr
:
117 return new BoolConstant (lv ^ rv
, left
.Location
);
118 case Binary
.Operator
.Equality
:
119 return new BoolConstant (lv
== rv
, left
.Location
);
120 case Binary
.Operator
.Inequality
:
121 return new BoolConstant (lv
!= rv
, left
.Location
);
127 // During an enum evaluation, none of the rules are valid
128 // Not sure whether it is bug in csc or in documentation
130 if (ec
.HasSet (ResolveContext
.Options
.EnumScope
)){
131 if (left
is EnumConstant
)
132 left
= ((EnumConstant
) left
).Child
;
134 if (right
is EnumConstant
)
135 right
= ((EnumConstant
) right
).Child
;
136 } else if (left
is EnumConstant
&& rt
== lt
) {
139 /// E operator |(E x, E y);
140 /// E operator &(E x, E y);
141 /// E operator ^(E x, E y);
143 case Binary
.Operator
.BitwiseOr
:
144 case Binary
.Operator
.BitwiseAnd
:
145 case Binary
.Operator
.ExclusiveOr
:
146 result
= BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
148 result
= result
.Resolve (ec
).TryReduce (ec
, lt
, loc
);
152 /// U operator -(E x, E y);
154 case Binary
.Operator
.Subtraction
:
155 result
= BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
157 result
= result
.Resolve (ec
).TryReduce (ec
, ((EnumConstant
)left
).Child
.Type
, loc
);
161 /// bool operator ==(E x, E y);
162 /// bool operator !=(E x, E y);
163 /// bool operator <(E x, E y);
164 /// bool operator >(E x, E y);
165 /// bool operator <=(E x, E y);
166 /// bool operator >=(E x, E y);
168 case Binary
.Operator
.Equality
:
169 case Binary
.Operator
.Inequality
:
170 case Binary
.Operator
.LessThan
:
171 case Binary
.Operator
.GreaterThan
:
172 case Binary
.Operator
.LessThanOrEqual
:
173 case Binary
.Operator
.GreaterThanOrEqual
:
174 return BinaryFold(ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
180 case Binary
.Operator
.BitwiseOr
:
181 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
184 if (left
is IntConstant
){
185 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
187 return new IntConstant (res
, left
.Location
);
189 if (left
is UIntConstant
){
190 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
192 return new UIntConstant (res
, left
.Location
);
194 if (left
is LongConstant
){
195 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
197 return new LongConstant (res
, left
.Location
);
199 if (left
is ULongConstant
){
200 ulong res
= ((ULongConstant
)left
).Value
|
201 ((ULongConstant
)right
).Value
;
203 return new ULongConstant (res
, left
.Location
);
207 case Binary
.Operator
.BitwiseAnd
:
208 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
212 /// int operator &(int x, int y);
213 /// uint operator &(uint x, uint y);
214 /// long operator &(long x, long y);
215 /// ulong operator &(ulong x, ulong y);
217 if (left
is IntConstant
){
218 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
219 return new IntConstant (res
, left
.Location
);
221 if (left
is UIntConstant
){
222 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
223 return new UIntConstant (res
, left
.Location
);
225 if (left
is LongConstant
){
226 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
227 return new LongConstant (res
, left
.Location
);
229 if (left
is ULongConstant
){
230 ulong res
= ((ULongConstant
)left
).Value
&
231 ((ULongConstant
)right
).Value
;
233 return new ULongConstant (res
, left
.Location
);
237 case Binary
.Operator
.ExclusiveOr
:
238 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
241 if (left
is IntConstant
){
242 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
243 return new IntConstant (res
, left
.Location
);
245 if (left
is UIntConstant
){
246 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
248 return new UIntConstant (res
, left
.Location
);
250 if (left
is LongConstant
){
251 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
253 return new LongConstant (res
, left
.Location
);
255 if (left
is ULongConstant
){
256 ulong res
= ((ULongConstant
)left
).Value ^
257 ((ULongConstant
)right
).Value
;
259 return new ULongConstant (res
, left
.Location
);
263 case Binary
.Operator
.Addition
:
264 if (lt
== TypeManager
.null_type
)
267 if (rt
== TypeManager
.null_type
)
271 // If both sides are strings, then concatenate, if
272 // one is a string, and the other is not, then defer
273 // to runtime concatenation
275 if (lt
== TypeManager
.string_type
|| rt
== TypeManager
.string_type
){
277 return new StringConstant ((string)left
.GetValue () + (string)right
.GetValue (),
284 // handle "E operator + (E x, U y)"
285 // handle "E operator + (Y y, E x)"
287 EnumConstant lc
= left
as EnumConstant
;
288 EnumConstant rc
= right
as EnumConstant
;
289 if (lc
!= null || rc
!= null){
296 // U has to be implicitly convetible to E.base
297 right
= right
.ConvertImplicitly (ec
, lc
.Child
.Type
);
301 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
305 result
= result
.Resolve (ec
).TryReduce (ec
, lt
, loc
);
309 return new EnumConstant (result
, lt
);
312 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
316 if (left
is DoubleConstant
){
319 if (ec
.ConstantCheckState
)
320 res
= checked (((DoubleConstant
) left
).Value
+
321 ((DoubleConstant
) right
).Value
);
323 res
= unchecked (((DoubleConstant
) left
).Value
+
324 ((DoubleConstant
) right
).Value
);
326 return new DoubleConstant (res
, left
.Location
);
328 if (left
is FloatConstant
){
331 if (ec
.ConstantCheckState
)
332 res
= checked (((FloatConstant
) left
).Value
+
333 ((FloatConstant
) right
).Value
);
335 res
= unchecked (((FloatConstant
) left
).Value
+
336 ((FloatConstant
) right
).Value
);
338 result
= new FloatConstant (res
, left
.Location
);
339 } else if (left
is ULongConstant
){
342 if (ec
.ConstantCheckState
)
343 res
= checked (((ULongConstant
) left
).Value
+
344 ((ULongConstant
) right
).Value
);
346 res
= unchecked (((ULongConstant
) left
).Value
+
347 ((ULongConstant
) right
).Value
);
349 result
= new ULongConstant (res
, left
.Location
);
350 } else if (left
is LongConstant
){
353 if (ec
.ConstantCheckState
)
354 res
= checked (((LongConstant
) left
).Value
+
355 ((LongConstant
) right
).Value
);
357 res
= unchecked (((LongConstant
) left
).Value
+
358 ((LongConstant
) right
).Value
);
360 result
= new LongConstant (res
, left
.Location
);
361 } else if (left
is UIntConstant
){
364 if (ec
.ConstantCheckState
)
365 res
= checked (((UIntConstant
) left
).Value
+
366 ((UIntConstant
) right
).Value
);
368 res
= unchecked (((UIntConstant
) left
).Value
+
369 ((UIntConstant
) right
).Value
);
371 result
= new UIntConstant (res
, left
.Location
);
372 } else if (left
is IntConstant
){
375 if (ec
.ConstantCheckState
)
376 res
= checked (((IntConstant
) left
).Value
+
377 ((IntConstant
) right
).Value
);
379 res
= unchecked (((IntConstant
) left
).Value
+
380 ((IntConstant
) right
).Value
);
382 result
= new IntConstant (res
, left
.Location
);
383 } else if (left
is DecimalConstant
) {
386 if (ec
.ConstantCheckState
)
387 res
= checked (((DecimalConstant
) left
).Value
+
388 ((DecimalConstant
) right
).Value
);
390 res
= unchecked (((DecimalConstant
) left
).Value
+
391 ((DecimalConstant
) right
).Value
);
393 result
= new DecimalConstant (res
, left
.Location
);
395 } catch (OverflowException
){
396 Error_CompileTimeOverflow (ec
, loc
);
401 case Binary
.Operator
.Subtraction
:
403 // handle "E operator - (E x, U y)"
404 // handle "E operator - (Y y, E x)"
406 lc
= left
as EnumConstant
;
407 rc
= right
as EnumConstant
;
408 if (lc
!= null || rc
!= null){
415 // U has to be implicitly convetible to E.base
416 right
= right
.ConvertImplicitly (ec
, lc
.Child
.Type
);
420 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
424 result
= result
.Resolve (ec
).TryReduce (ec
, lt
, loc
);
428 return new EnumConstant (result
, lt
);
431 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
435 if (left
is DoubleConstant
){
438 if (ec
.ConstantCheckState
)
439 res
= checked (((DoubleConstant
) left
).Value
-
440 ((DoubleConstant
) right
).Value
);
442 res
= unchecked (((DoubleConstant
) left
).Value
-
443 ((DoubleConstant
) right
).Value
);
445 result
= new DoubleConstant (res
, left
.Location
);
446 } else if (left
is FloatConstant
){
449 if (ec
.ConstantCheckState
)
450 res
= checked (((FloatConstant
) left
).Value
-
451 ((FloatConstant
) right
).Value
);
453 res
= unchecked (((FloatConstant
) left
).Value
-
454 ((FloatConstant
) right
).Value
);
456 result
= new FloatConstant (res
, left
.Location
);
457 } else if (left
is ULongConstant
){
460 if (ec
.ConstantCheckState
)
461 res
= checked (((ULongConstant
) left
).Value
-
462 ((ULongConstant
) right
).Value
);
464 res
= unchecked (((ULongConstant
) left
).Value
-
465 ((ULongConstant
) right
).Value
);
467 result
= new ULongConstant (res
, left
.Location
);
468 } else if (left
is LongConstant
){
471 if (ec
.ConstantCheckState
)
472 res
= checked (((LongConstant
) left
).Value
-
473 ((LongConstant
) right
).Value
);
475 res
= unchecked (((LongConstant
) left
).Value
-
476 ((LongConstant
) right
).Value
);
478 result
= new LongConstant (res
, left
.Location
);
479 } else if (left
is UIntConstant
){
482 if (ec
.ConstantCheckState
)
483 res
= checked (((UIntConstant
) left
).Value
-
484 ((UIntConstant
) right
).Value
);
486 res
= unchecked (((UIntConstant
) left
).Value
-
487 ((UIntConstant
) right
).Value
);
489 result
= new UIntConstant (res
, left
.Location
);
490 } else if (left
is IntConstant
){
493 if (ec
.ConstantCheckState
)
494 res
= checked (((IntConstant
) left
).Value
-
495 ((IntConstant
) right
).Value
);
497 res
= unchecked (((IntConstant
) left
).Value
-
498 ((IntConstant
) right
).Value
);
500 result
= new IntConstant (res
, left
.Location
);
501 } else if (left
is DecimalConstant
) {
504 if (ec
.ConstantCheckState
)
505 res
= checked (((DecimalConstant
) left
).Value
-
506 ((DecimalConstant
) right
).Value
);
508 res
= unchecked (((DecimalConstant
) left
).Value
-
509 ((DecimalConstant
) right
).Value
);
511 return new DecimalConstant (res
, left
.Location
);
513 throw new Exception ( "Unexepected subtraction input: " + left
);
515 } catch (OverflowException
){
516 Error_CompileTimeOverflow (ec
, loc
);
521 case Binary
.Operator
.Multiply
:
522 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
526 if (left
is DoubleConstant
){
529 if (ec
.ConstantCheckState
)
530 res
= checked (((DoubleConstant
) left
).Value
*
531 ((DoubleConstant
) right
).Value
);
533 res
= unchecked (((DoubleConstant
) left
).Value
*
534 ((DoubleConstant
) right
).Value
);
536 return new DoubleConstant (res
, left
.Location
);
537 } else if (left
is FloatConstant
){
540 if (ec
.ConstantCheckState
)
541 res
= checked (((FloatConstant
) left
).Value
*
542 ((FloatConstant
) right
).Value
);
544 res
= unchecked (((FloatConstant
) left
).Value
*
545 ((FloatConstant
) right
).Value
);
547 return new FloatConstant (res
, left
.Location
);
548 } else if (left
is ULongConstant
){
551 if (ec
.ConstantCheckState
)
552 res
= checked (((ULongConstant
) left
).Value
*
553 ((ULongConstant
) right
).Value
);
555 res
= unchecked (((ULongConstant
) left
).Value
*
556 ((ULongConstant
) right
).Value
);
558 return new ULongConstant (res
, left
.Location
);
559 } else if (left
is LongConstant
){
562 if (ec
.ConstantCheckState
)
563 res
= checked (((LongConstant
) left
).Value
*
564 ((LongConstant
) right
).Value
);
566 res
= unchecked (((LongConstant
) left
).Value
*
567 ((LongConstant
) right
).Value
);
569 return new LongConstant (res
, left
.Location
);
570 } else if (left
is UIntConstant
){
573 if (ec
.ConstantCheckState
)
574 res
= checked (((UIntConstant
) left
).Value
*
575 ((UIntConstant
) right
).Value
);
577 res
= unchecked (((UIntConstant
) left
).Value
*
578 ((UIntConstant
) right
).Value
);
580 return new UIntConstant (res
, left
.Location
);
581 } else if (left
is IntConstant
){
584 if (ec
.ConstantCheckState
)
585 res
= checked (((IntConstant
) left
).Value
*
586 ((IntConstant
) right
).Value
);
588 res
= unchecked (((IntConstant
) left
).Value
*
589 ((IntConstant
) right
).Value
);
591 return new IntConstant (res
, left
.Location
);
592 } else if (left
is DecimalConstant
) {
595 if (ec
.ConstantCheckState
)
596 res
= checked (((DecimalConstant
) left
).Value
*
597 ((DecimalConstant
) right
).Value
);
599 res
= unchecked (((DecimalConstant
) left
).Value
*
600 ((DecimalConstant
) right
).Value
);
602 return new DecimalConstant (res
, left
.Location
);
604 throw new Exception ( "Unexepected multiply input: " + left
);
606 } catch (OverflowException
){
607 Error_CompileTimeOverflow (ec
, loc
);
611 case Binary
.Operator
.Division
:
612 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
616 if (left
is DoubleConstant
){
619 if (ec
.ConstantCheckState
)
620 res
= checked (((DoubleConstant
) left
).Value
/
621 ((DoubleConstant
) right
).Value
);
623 res
= unchecked (((DoubleConstant
) left
).Value
/
624 ((DoubleConstant
) right
).Value
);
626 return new DoubleConstant (res
, left
.Location
);
627 } else if (left
is FloatConstant
){
630 if (ec
.ConstantCheckState
)
631 res
= checked (((FloatConstant
) left
).Value
/
632 ((FloatConstant
) right
).Value
);
634 res
= unchecked (((FloatConstant
) left
).Value
/
635 ((FloatConstant
) right
).Value
);
637 return new FloatConstant (res
, left
.Location
);
638 } else if (left
is ULongConstant
){
641 if (ec
.ConstantCheckState
)
642 res
= checked (((ULongConstant
) left
).Value
/
643 ((ULongConstant
) right
).Value
);
645 res
= unchecked (((ULongConstant
) left
).Value
/
646 ((ULongConstant
) right
).Value
);
648 return new ULongConstant (res
, left
.Location
);
649 } else if (left
is LongConstant
){
652 if (ec
.ConstantCheckState
)
653 res
= checked (((LongConstant
) left
).Value
/
654 ((LongConstant
) right
).Value
);
656 res
= unchecked (((LongConstant
) left
).Value
/
657 ((LongConstant
) right
).Value
);
659 return new LongConstant (res
, left
.Location
);
660 } else if (left
is UIntConstant
){
663 if (ec
.ConstantCheckState
)
664 res
= checked (((UIntConstant
) left
).Value
/
665 ((UIntConstant
) right
).Value
);
667 res
= unchecked (((UIntConstant
) left
).Value
/
668 ((UIntConstant
) right
).Value
);
670 return new UIntConstant (res
, left
.Location
);
671 } else if (left
is IntConstant
){
674 if (ec
.ConstantCheckState
)
675 res
= checked (((IntConstant
) left
).Value
/
676 ((IntConstant
) right
).Value
);
678 res
= unchecked (((IntConstant
) left
).Value
/
679 ((IntConstant
) right
).Value
);
681 return new IntConstant (res
, left
.Location
);
682 } else if (left
is DecimalConstant
) {
685 if (ec
.ConstantCheckState
)
686 res
= checked (((DecimalConstant
) left
).Value
/
687 ((DecimalConstant
) right
).Value
);
689 res
= unchecked (((DecimalConstant
) left
).Value
/
690 ((DecimalConstant
) right
).Value
);
692 return new DecimalConstant (res
, left
.Location
);
694 throw new Exception ( "Unexepected division input: " + left
);
696 } catch (OverflowException
){
697 Error_CompileTimeOverflow (ec
, loc
);
699 } catch (DivideByZeroException
) {
700 ec
.Report
.Error (20, loc
, "Division by constant zero");
705 case Binary
.Operator
.Modulus
:
706 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
710 if (left
is DoubleConstant
){
713 if (ec
.ConstantCheckState
)
714 res
= checked (((DoubleConstant
) left
).Value
%
715 ((DoubleConstant
) right
).Value
);
717 res
= unchecked (((DoubleConstant
) left
).Value
%
718 ((DoubleConstant
) right
).Value
);
720 return new DoubleConstant (res
, left
.Location
);
721 } else if (left
is FloatConstant
){
724 if (ec
.ConstantCheckState
)
725 res
= checked (((FloatConstant
) left
).Value
%
726 ((FloatConstant
) right
).Value
);
728 res
= unchecked (((FloatConstant
) left
).Value
%
729 ((FloatConstant
) right
).Value
);
731 return new FloatConstant (res
, left
.Location
);
732 } else if (left
is ULongConstant
){
735 if (ec
.ConstantCheckState
)
736 res
= checked (((ULongConstant
) left
).Value
%
737 ((ULongConstant
) right
).Value
);
739 res
= unchecked (((ULongConstant
) left
).Value
%
740 ((ULongConstant
) right
).Value
);
742 return new ULongConstant (res
, left
.Location
);
743 } else if (left
is LongConstant
){
746 if (ec
.ConstantCheckState
)
747 res
= checked (((LongConstant
) left
).Value
%
748 ((LongConstant
) right
).Value
);
750 res
= unchecked (((LongConstant
) left
).Value
%
751 ((LongConstant
) right
).Value
);
753 return new LongConstant (res
, left
.Location
);
754 } else if (left
is UIntConstant
){
757 if (ec
.ConstantCheckState
)
758 res
= checked (((UIntConstant
) left
).Value
%
759 ((UIntConstant
) right
).Value
);
761 res
= unchecked (((UIntConstant
) left
).Value
%
762 ((UIntConstant
) right
).Value
);
764 return new UIntConstant (res
, left
.Location
);
765 } else if (left
is IntConstant
){
768 if (ec
.ConstantCheckState
)
769 res
= checked (((IntConstant
) left
).Value
%
770 ((IntConstant
) right
).Value
);
772 res
= unchecked (((IntConstant
) left
).Value
%
773 ((IntConstant
) right
).Value
);
775 return new IntConstant (res
, left
.Location
);
777 throw new Exception ( "Unexepected modulus input: " + left
);
779 } catch (DivideByZeroException
){
780 ec
.Report
.Error (20, loc
, "Division by constant zero");
781 } catch (OverflowException
){
782 Error_CompileTimeOverflow (ec
, loc
);
787 // There is no overflow checking on left shift
789 case Binary
.Operator
.LeftShift
:
790 IntConstant ic
= right
.ConvertImplicitly (ec
, TypeManager
.int32_type
) as IntConstant
;
792 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
796 int lshift_val
= ic
.Value
;
797 if (left
.Type
== TypeManager
.uint64_type
)
798 return new ULongConstant (((ULongConstant
)left
).Value
<< lshift_val
, left
.Location
);
799 if (left
.Type
== TypeManager
.int64_type
)
800 return new LongConstant (((LongConstant
)left
).Value
<< lshift_val
, left
.Location
);
801 if (left
.Type
== TypeManager
.uint32_type
)
802 return new UIntConstant (((UIntConstant
)left
).Value
<< lshift_val
, left
.Location
);
804 left
= left
.ConvertImplicitly (ec
, TypeManager
.int32_type
);
805 if (left
.Type
== TypeManager
.int32_type
)
806 return new IntConstant (((IntConstant
)left
).Value
<< lshift_val
, left
.Location
);
808 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
812 // There is no overflow checking on right shift
814 case Binary
.Operator
.RightShift
:
815 IntConstant sic
= right
.ConvertImplicitly (ec
, TypeManager
.int32_type
) as IntConstant
;
817 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
); ;
820 int rshift_val
= sic
.Value
;
821 if (left
.Type
== TypeManager
.uint64_type
)
822 return new ULongConstant (((ULongConstant
)left
).Value
>> rshift_val
, left
.Location
);
823 if (left
.Type
== TypeManager
.int64_type
)
824 return new LongConstant (((LongConstant
)left
).Value
>> rshift_val
, left
.Location
);
825 if (left
.Type
== TypeManager
.uint32_type
)
826 return new UIntConstant (((UIntConstant
)left
).Value
>> rshift_val
, left
.Location
);
828 left
= left
.ConvertImplicitly (ec
, TypeManager
.int32_type
);
829 if (left
.Type
== TypeManager
.int32_type
)
830 return new IntConstant (((IntConstant
)left
).Value
>> rshift_val
, left
.Location
);
832 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
835 case Binary
.Operator
.Equality
:
836 if (TypeManager
.IsReferenceType (lt
) && TypeManager
.IsReferenceType (lt
)) {
837 if (left
.IsNull
|| right
.IsNull
) {
838 return ReducedExpression
.Create (
839 new BoolConstant (left
.IsNull
== right
.IsNull
, left
.Location
).Resolve (ec
),
840 new Binary (oper
, left
, right
, loc
));
843 if (left
is StringConstant
&& right
is StringConstant
)
844 return new BoolConstant (
845 ((StringConstant
) left
).Value
== ((StringConstant
) right
).Value
, left
.Location
);
850 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
854 if (left
is DoubleConstant
)
855 bool_res
= ((DoubleConstant
) left
).Value
==
856 ((DoubleConstant
) right
).Value
;
857 else if (left
is FloatConstant
)
858 bool_res
= ((FloatConstant
) left
).Value
==
859 ((FloatConstant
) right
).Value
;
860 else if (left
is ULongConstant
)
861 bool_res
= ((ULongConstant
) left
).Value
==
862 ((ULongConstant
) right
).Value
;
863 else if (left
is LongConstant
)
864 bool_res
= ((LongConstant
) left
).Value
==
865 ((LongConstant
) right
).Value
;
866 else if (left
is UIntConstant
)
867 bool_res
= ((UIntConstant
) left
).Value
==
868 ((UIntConstant
) right
).Value
;
869 else if (left
is IntConstant
)
870 bool_res
= ((IntConstant
) left
).Value
==
871 ((IntConstant
) right
).Value
;
875 return new BoolConstant (bool_res
, left
.Location
);
877 case Binary
.Operator
.Inequality
:
878 if (TypeManager
.IsReferenceType (lt
) && TypeManager
.IsReferenceType (lt
)) {
879 if (left
.IsNull
|| right
.IsNull
) {
880 return ReducedExpression
.Create (
881 new BoolConstant (left
.IsNull
!= right
.IsNull
, left
.Location
).Resolve (ec
),
882 new Binary (oper
, left
, right
, loc
));
885 if (left
is StringConstant
&& right
is StringConstant
)
886 return new BoolConstant (
887 ((StringConstant
) left
).Value
!= ((StringConstant
) right
).Value
, left
.Location
);
892 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
896 if (left
is DoubleConstant
)
897 bool_res
= ((DoubleConstant
) left
).Value
!=
898 ((DoubleConstant
) right
).Value
;
899 else if (left
is FloatConstant
)
900 bool_res
= ((FloatConstant
) left
).Value
!=
901 ((FloatConstant
) right
).Value
;
902 else if (left
is ULongConstant
)
903 bool_res
= ((ULongConstant
) left
).Value
!=
904 ((ULongConstant
) right
).Value
;
905 else if (left
is LongConstant
)
906 bool_res
= ((LongConstant
) left
).Value
!=
907 ((LongConstant
) right
).Value
;
908 else if (left
is UIntConstant
)
909 bool_res
= ((UIntConstant
) left
).Value
!=
910 ((UIntConstant
) right
).Value
;
911 else if (left
is IntConstant
)
912 bool_res
= ((IntConstant
) left
).Value
!=
913 ((IntConstant
) right
).Value
;
917 return new BoolConstant (bool_res
, left
.Location
);
919 case Binary
.Operator
.LessThan
:
920 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
924 if (left
is DoubleConstant
)
925 bool_res
= ((DoubleConstant
) left
).Value
<
926 ((DoubleConstant
) right
).Value
;
927 else if (left
is FloatConstant
)
928 bool_res
= ((FloatConstant
) left
).Value
<
929 ((FloatConstant
) right
).Value
;
930 else if (left
is ULongConstant
)
931 bool_res
= ((ULongConstant
) left
).Value
<
932 ((ULongConstant
) right
).Value
;
933 else if (left
is LongConstant
)
934 bool_res
= ((LongConstant
) left
).Value
<
935 ((LongConstant
) right
).Value
;
936 else if (left
is UIntConstant
)
937 bool_res
= ((UIntConstant
) left
).Value
<
938 ((UIntConstant
) right
).Value
;
939 else if (left
is IntConstant
)
940 bool_res
= ((IntConstant
) left
).Value
<
941 ((IntConstant
) right
).Value
;
945 return new BoolConstant (bool_res
, left
.Location
);
947 case Binary
.Operator
.GreaterThan
:
948 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
952 if (left
is DoubleConstant
)
953 bool_res
= ((DoubleConstant
) left
).Value
>
954 ((DoubleConstant
) right
).Value
;
955 else if (left
is FloatConstant
)
956 bool_res
= ((FloatConstant
) left
).Value
>
957 ((FloatConstant
) right
).Value
;
958 else if (left
is ULongConstant
)
959 bool_res
= ((ULongConstant
) left
).Value
>
960 ((ULongConstant
) right
).Value
;
961 else if (left
is LongConstant
)
962 bool_res
= ((LongConstant
) left
).Value
>
963 ((LongConstant
) right
).Value
;
964 else if (left
is UIntConstant
)
965 bool_res
= ((UIntConstant
) left
).Value
>
966 ((UIntConstant
) right
).Value
;
967 else if (left
is IntConstant
)
968 bool_res
= ((IntConstant
) left
).Value
>
969 ((IntConstant
) right
).Value
;
973 return new BoolConstant (bool_res
, left
.Location
);
975 case Binary
.Operator
.GreaterThanOrEqual
:
976 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
980 if (left
is DoubleConstant
)
981 bool_res
= ((DoubleConstant
) left
).Value
>=
982 ((DoubleConstant
) right
).Value
;
983 else if (left
is FloatConstant
)
984 bool_res
= ((FloatConstant
) left
).Value
>=
985 ((FloatConstant
) right
).Value
;
986 else if (left
is ULongConstant
)
987 bool_res
= ((ULongConstant
) left
).Value
>=
988 ((ULongConstant
) right
).Value
;
989 else if (left
is LongConstant
)
990 bool_res
= ((LongConstant
) left
).Value
>=
991 ((LongConstant
) right
).Value
;
992 else if (left
is UIntConstant
)
993 bool_res
= ((UIntConstant
) left
).Value
>=
994 ((UIntConstant
) right
).Value
;
995 else if (left
is IntConstant
)
996 bool_res
= ((IntConstant
) left
).Value
>=
997 ((IntConstant
) right
).Value
;
1001 return new BoolConstant (bool_res
, left
.Location
);
1003 case Binary
.Operator
.LessThanOrEqual
:
1004 if (!DoBinaryNumericPromotions (ec
, ref left
, ref right
))
1008 if (left
is DoubleConstant
)
1009 bool_res
= ((DoubleConstant
) left
).Value
<=
1010 ((DoubleConstant
) right
).Value
;
1011 else if (left
is FloatConstant
)
1012 bool_res
= ((FloatConstant
) left
).Value
<=
1013 ((FloatConstant
) right
).Value
;
1014 else if (left
is ULongConstant
)
1015 bool_res
= ((ULongConstant
) left
).Value
<=
1016 ((ULongConstant
) right
).Value
;
1017 else if (left
is LongConstant
)
1018 bool_res
= ((LongConstant
) left
).Value
<=
1019 ((LongConstant
) right
).Value
;
1020 else if (left
is UIntConstant
)
1021 bool_res
= ((UIntConstant
) left
).Value
<=
1022 ((UIntConstant
) right
).Value
;
1023 else if (left
is IntConstant
)
1024 bool_res
= ((IntConstant
) left
).Value
<=
1025 ((IntConstant
) right
).Value
;
1029 return new BoolConstant (bool_res
, left
.Location
);