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 (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 (ref right
, ref left
, t
);
41 return t
== ltype
|| ConvertPromotion (ref left
, ref right
, t
);
44 left
= left
.ConvertImplicitly (TypeManager
.int32_type
);
45 right
= right
.ConvertImplicitly (TypeManager
.int32_type
);
46 return left
!= null && right
!= null;
49 static bool ConvertPromotion (ref Constant prim
, ref Constant second
, Type type
)
51 Constant c
= prim
.ConvertImplicitly (type
);
57 if (type
== TypeManager
.uint32_type
) {
58 type
= TypeManager
.int64_type
;
59 prim
= prim
.ConvertImplicitly (type
);
60 second
= second
.ConvertImplicitly (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 return BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
,
147 ((EnumConstant
)right
).Child
, loc
).TryReduce (ec
, lt
, loc
);
150 /// U operator -(E x, E y);
152 case Binary
.Operator
.Subtraction
:
153 result
= BinaryFold (ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
154 return result
.TryReduce (ec
, ((EnumConstant
)left
).Child
.Type
, loc
);
157 /// bool operator ==(E x, E y);
158 /// bool operator !=(E x, E y);
159 /// bool operator <(E x, E y);
160 /// bool operator >(E x, E y);
161 /// bool operator <=(E x, E y);
162 /// bool operator >=(E x, E y);
164 case Binary
.Operator
.Equality
:
165 case Binary
.Operator
.Inequality
:
166 case Binary
.Operator
.LessThan
:
167 case Binary
.Operator
.GreaterThan
:
168 case Binary
.Operator
.LessThanOrEqual
:
169 case Binary
.Operator
.GreaterThanOrEqual
:
170 return BinaryFold(ec
, oper
, ((EnumConstant
)left
).Child
, ((EnumConstant
)right
).Child
, loc
);
176 case Binary
.Operator
.BitwiseOr
:
177 if (!DoBinaryNumericPromotions (ref left
, ref right
))
180 if (left
is IntConstant
){
181 int res
= ((IntConstant
) left
).Value
| ((IntConstant
) right
).Value
;
183 return new IntConstant (res
, left
.Location
);
185 if (left
is UIntConstant
){
186 uint res
= ((UIntConstant
)left
).Value
| ((UIntConstant
)right
).Value
;
188 return new UIntConstant (res
, left
.Location
);
190 if (left
is LongConstant
){
191 long res
= ((LongConstant
)left
).Value
| ((LongConstant
)right
).Value
;
193 return new LongConstant (res
, left
.Location
);
195 if (left
is ULongConstant
){
196 ulong res
= ((ULongConstant
)left
).Value
|
197 ((ULongConstant
)right
).Value
;
199 return new ULongConstant (res
, left
.Location
);
203 case Binary
.Operator
.BitwiseAnd
:
204 if (!DoBinaryNumericPromotions (ref left
, ref right
))
208 /// int operator &(int x, int y);
209 /// uint operator &(uint x, uint y);
210 /// long operator &(long x, long y);
211 /// ulong operator &(ulong x, ulong y);
213 if (left
is IntConstant
){
214 int res
= ((IntConstant
) left
).Value
& ((IntConstant
) right
).Value
;
215 return new IntConstant (res
, left
.Location
);
217 if (left
is UIntConstant
){
218 uint res
= ((UIntConstant
)left
).Value
& ((UIntConstant
)right
).Value
;
219 return new UIntConstant (res
, left
.Location
);
221 if (left
is LongConstant
){
222 long res
= ((LongConstant
)left
).Value
& ((LongConstant
)right
).Value
;
223 return new LongConstant (res
, left
.Location
);
225 if (left
is ULongConstant
){
226 ulong res
= ((ULongConstant
)left
).Value
&
227 ((ULongConstant
)right
).Value
;
229 return new ULongConstant (res
, left
.Location
);
233 case Binary
.Operator
.ExclusiveOr
:
234 if (!DoBinaryNumericPromotions (ref left
, ref right
))
237 if (left
is IntConstant
){
238 int res
= ((IntConstant
) left
).Value ^
((IntConstant
) right
).Value
;
239 return new IntConstant (res
, left
.Location
);
241 if (left
is UIntConstant
){
242 uint res
= ((UIntConstant
)left
).Value ^
((UIntConstant
)right
).Value
;
244 return new UIntConstant (res
, left
.Location
);
246 if (left
is LongConstant
){
247 long res
= ((LongConstant
)left
).Value ^
((LongConstant
)right
).Value
;
249 return new LongConstant (res
, left
.Location
);
251 if (left
is ULongConstant
){
252 ulong res
= ((ULongConstant
)left
).Value ^
253 ((ULongConstant
)right
).Value
;
255 return new ULongConstant (res
, left
.Location
);
259 case Binary
.Operator
.Addition
:
260 if (lt
== TypeManager
.null_type
)
263 if (rt
== TypeManager
.null_type
)
267 // If both sides are strings, then concatenate, if
268 // one is a string, and the other is not, then defer
269 // to runtime concatenation
271 if (lt
== TypeManager
.string_type
|| rt
== TypeManager
.string_type
){
273 return new StringConstant ((string)left
.GetValue () + (string)right
.GetValue (),
280 // handle "E operator + (E x, U y)"
281 // handle "E operator + (Y y, E x)"
283 EnumConstant lc
= left
as EnumConstant
;
284 EnumConstant rc
= right
as EnumConstant
;
285 if (lc
!= null || rc
!= null){
292 // U has to be implicitly convetible to E.base
293 right
= right
.ConvertImplicitly (lc
.Child
.Type
);
297 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
301 result
= result
.TryReduce (ec
, lt
, loc
);
305 return new EnumConstant (result
, lt
);
308 if (!DoBinaryNumericPromotions (ref left
, ref right
))
312 if (left
is DoubleConstant
){
315 if (ec
.ConstantCheckState
)
316 res
= checked (((DoubleConstant
) left
).Value
+
317 ((DoubleConstant
) right
).Value
);
319 res
= unchecked (((DoubleConstant
) left
).Value
+
320 ((DoubleConstant
) right
).Value
);
322 return new DoubleConstant (res
, left
.Location
);
324 if (left
is FloatConstant
){
327 if (ec
.ConstantCheckState
)
328 res
= checked (((FloatConstant
) left
).Value
+
329 ((FloatConstant
) right
).Value
);
331 res
= unchecked (((FloatConstant
) left
).Value
+
332 ((FloatConstant
) right
).Value
);
334 result
= new FloatConstant (res
, left
.Location
);
335 } else if (left
is ULongConstant
){
338 if (ec
.ConstantCheckState
)
339 res
= checked (((ULongConstant
) left
).Value
+
340 ((ULongConstant
) right
).Value
);
342 res
= unchecked (((ULongConstant
) left
).Value
+
343 ((ULongConstant
) right
).Value
);
345 result
= new ULongConstant (res
, left
.Location
);
346 } else if (left
is LongConstant
){
349 if (ec
.ConstantCheckState
)
350 res
= checked (((LongConstant
) left
).Value
+
351 ((LongConstant
) right
).Value
);
353 res
= unchecked (((LongConstant
) left
).Value
+
354 ((LongConstant
) right
).Value
);
356 result
= new LongConstant (res
, left
.Location
);
357 } else if (left
is UIntConstant
){
360 if (ec
.ConstantCheckState
)
361 res
= checked (((UIntConstant
) left
).Value
+
362 ((UIntConstant
) right
).Value
);
364 res
= unchecked (((UIntConstant
) left
).Value
+
365 ((UIntConstant
) right
).Value
);
367 result
= new UIntConstant (res
, left
.Location
);
368 } else if (left
is IntConstant
){
371 if (ec
.ConstantCheckState
)
372 res
= checked (((IntConstant
) left
).Value
+
373 ((IntConstant
) right
).Value
);
375 res
= unchecked (((IntConstant
) left
).Value
+
376 ((IntConstant
) right
).Value
);
378 result
= new IntConstant (res
, left
.Location
);
379 } else if (left
is DecimalConstant
) {
382 if (ec
.ConstantCheckState
)
383 res
= checked (((DecimalConstant
) left
).Value
+
384 ((DecimalConstant
) right
).Value
);
386 res
= unchecked (((DecimalConstant
) left
).Value
+
387 ((DecimalConstant
) right
).Value
);
389 result
= new DecimalConstant (res
, left
.Location
);
391 } catch (OverflowException
){
392 Error_CompileTimeOverflow (ec
, loc
);
397 case Binary
.Operator
.Subtraction
:
399 // handle "E operator - (E x, U y)"
400 // handle "E operator - (Y y, E x)"
402 lc
= left
as EnumConstant
;
403 rc
= right
as EnumConstant
;
404 if (lc
!= null || rc
!= null){
411 // U has to be implicitly convetible to E.base
412 right
= right
.ConvertImplicitly (lc
.Child
.Type
);
416 result
= BinaryFold (ec
, oper
, lc
.Child
, right
, loc
);
420 result
= result
.TryReduce (ec
, lt
, loc
);
424 return new EnumConstant (result
, lt
);
427 if (!DoBinaryNumericPromotions (ref left
, ref right
))
431 if (left
is DoubleConstant
){
434 if (ec
.ConstantCheckState
)
435 res
= checked (((DoubleConstant
) left
).Value
-
436 ((DoubleConstant
) right
).Value
);
438 res
= unchecked (((DoubleConstant
) left
).Value
-
439 ((DoubleConstant
) right
).Value
);
441 result
= new DoubleConstant (res
, left
.Location
);
442 } else if (left
is FloatConstant
){
445 if (ec
.ConstantCheckState
)
446 res
= checked (((FloatConstant
) left
).Value
-
447 ((FloatConstant
) right
).Value
);
449 res
= unchecked (((FloatConstant
) left
).Value
-
450 ((FloatConstant
) right
).Value
);
452 result
= new FloatConstant (res
, left
.Location
);
453 } else if (left
is ULongConstant
){
456 if (ec
.ConstantCheckState
)
457 res
= checked (((ULongConstant
) left
).Value
-
458 ((ULongConstant
) right
).Value
);
460 res
= unchecked (((ULongConstant
) left
).Value
-
461 ((ULongConstant
) right
).Value
);
463 result
= new ULongConstant (res
, left
.Location
);
464 } else if (left
is LongConstant
){
467 if (ec
.ConstantCheckState
)
468 res
= checked (((LongConstant
) left
).Value
-
469 ((LongConstant
) right
).Value
);
471 res
= unchecked (((LongConstant
) left
).Value
-
472 ((LongConstant
) right
).Value
);
474 result
= new LongConstant (res
, left
.Location
);
475 } else if (left
is UIntConstant
){
478 if (ec
.ConstantCheckState
)
479 res
= checked (((UIntConstant
) left
).Value
-
480 ((UIntConstant
) right
).Value
);
482 res
= unchecked (((UIntConstant
) left
).Value
-
483 ((UIntConstant
) right
).Value
);
485 result
= new UIntConstant (res
, left
.Location
);
486 } else if (left
is IntConstant
){
489 if (ec
.ConstantCheckState
)
490 res
= checked (((IntConstant
) left
).Value
-
491 ((IntConstant
) right
).Value
);
493 res
= unchecked (((IntConstant
) left
).Value
-
494 ((IntConstant
) right
).Value
);
496 result
= new IntConstant (res
, left
.Location
);
497 } else if (left
is DecimalConstant
) {
500 if (ec
.ConstantCheckState
)
501 res
= checked (((DecimalConstant
) left
).Value
-
502 ((DecimalConstant
) right
).Value
);
504 res
= unchecked (((DecimalConstant
) left
).Value
-
505 ((DecimalConstant
) right
).Value
);
507 return new DecimalConstant (res
, left
.Location
);
509 throw new Exception ( "Unexepected subtraction input: " + left
);
511 } catch (OverflowException
){
512 Error_CompileTimeOverflow (ec
, loc
);
517 case Binary
.Operator
.Multiply
:
518 if (!DoBinaryNumericPromotions (ref left
, ref right
))
522 if (left
is DoubleConstant
){
525 if (ec
.ConstantCheckState
)
526 res
= checked (((DoubleConstant
) left
).Value
*
527 ((DoubleConstant
) right
).Value
);
529 res
= unchecked (((DoubleConstant
) left
).Value
*
530 ((DoubleConstant
) right
).Value
);
532 return new DoubleConstant (res
, left
.Location
);
533 } else if (left
is FloatConstant
){
536 if (ec
.ConstantCheckState
)
537 res
= checked (((FloatConstant
) left
).Value
*
538 ((FloatConstant
) right
).Value
);
540 res
= unchecked (((FloatConstant
) left
).Value
*
541 ((FloatConstant
) right
).Value
);
543 return new FloatConstant (res
, left
.Location
);
544 } else if (left
is ULongConstant
){
547 if (ec
.ConstantCheckState
)
548 res
= checked (((ULongConstant
) left
).Value
*
549 ((ULongConstant
) right
).Value
);
551 res
= unchecked (((ULongConstant
) left
).Value
*
552 ((ULongConstant
) right
).Value
);
554 return new ULongConstant (res
, left
.Location
);
555 } else if (left
is LongConstant
){
558 if (ec
.ConstantCheckState
)
559 res
= checked (((LongConstant
) left
).Value
*
560 ((LongConstant
) right
).Value
);
562 res
= unchecked (((LongConstant
) left
).Value
*
563 ((LongConstant
) right
).Value
);
565 return new LongConstant (res
, left
.Location
);
566 } else if (left
is UIntConstant
){
569 if (ec
.ConstantCheckState
)
570 res
= checked (((UIntConstant
) left
).Value
*
571 ((UIntConstant
) right
).Value
);
573 res
= unchecked (((UIntConstant
) left
).Value
*
574 ((UIntConstant
) right
).Value
);
576 return new UIntConstant (res
, left
.Location
);
577 } else if (left
is IntConstant
){
580 if (ec
.ConstantCheckState
)
581 res
= checked (((IntConstant
) left
).Value
*
582 ((IntConstant
) right
).Value
);
584 res
= unchecked (((IntConstant
) left
).Value
*
585 ((IntConstant
) right
).Value
);
587 return new IntConstant (res
, left
.Location
);
588 } else if (left
is DecimalConstant
) {
591 if (ec
.ConstantCheckState
)
592 res
= checked (((DecimalConstant
) left
).Value
*
593 ((DecimalConstant
) right
).Value
);
595 res
= unchecked (((DecimalConstant
) left
).Value
*
596 ((DecimalConstant
) right
).Value
);
598 return new DecimalConstant (res
, left
.Location
);
600 throw new Exception ( "Unexepected multiply input: " + left
);
602 } catch (OverflowException
){
603 Error_CompileTimeOverflow (ec
, loc
);
607 case Binary
.Operator
.Division
:
608 if (!DoBinaryNumericPromotions (ref left
, ref right
))
612 if (left
is DoubleConstant
){
615 if (ec
.ConstantCheckState
)
616 res
= checked (((DoubleConstant
) left
).Value
/
617 ((DoubleConstant
) right
).Value
);
619 res
= unchecked (((DoubleConstant
) left
).Value
/
620 ((DoubleConstant
) right
).Value
);
622 return new DoubleConstant (res
, left
.Location
);
623 } else if (left
is FloatConstant
){
626 if (ec
.ConstantCheckState
)
627 res
= checked (((FloatConstant
) left
).Value
/
628 ((FloatConstant
) right
).Value
);
630 res
= unchecked (((FloatConstant
) left
).Value
/
631 ((FloatConstant
) right
).Value
);
633 return new FloatConstant (res
, left
.Location
);
634 } else if (left
is ULongConstant
){
637 if (ec
.ConstantCheckState
)
638 res
= checked (((ULongConstant
) left
).Value
/
639 ((ULongConstant
) right
).Value
);
641 res
= unchecked (((ULongConstant
) left
).Value
/
642 ((ULongConstant
) right
).Value
);
644 return new ULongConstant (res
, left
.Location
);
645 } else if (left
is LongConstant
){
648 if (ec
.ConstantCheckState
)
649 res
= checked (((LongConstant
) left
).Value
/
650 ((LongConstant
) right
).Value
);
652 res
= unchecked (((LongConstant
) left
).Value
/
653 ((LongConstant
) right
).Value
);
655 return new LongConstant (res
, left
.Location
);
656 } else if (left
is UIntConstant
){
659 if (ec
.ConstantCheckState
)
660 res
= checked (((UIntConstant
) left
).Value
/
661 ((UIntConstant
) right
).Value
);
663 res
= unchecked (((UIntConstant
) left
).Value
/
664 ((UIntConstant
) right
).Value
);
666 return new UIntConstant (res
, left
.Location
);
667 } else if (left
is IntConstant
){
670 if (ec
.ConstantCheckState
)
671 res
= checked (((IntConstant
) left
).Value
/
672 ((IntConstant
) right
).Value
);
674 res
= unchecked (((IntConstant
) left
).Value
/
675 ((IntConstant
) right
).Value
);
677 return new IntConstant (res
, left
.Location
);
678 } else if (left
is DecimalConstant
) {
681 if (ec
.ConstantCheckState
)
682 res
= checked (((DecimalConstant
) left
).Value
/
683 ((DecimalConstant
) right
).Value
);
685 res
= unchecked (((DecimalConstant
) left
).Value
/
686 ((DecimalConstant
) right
).Value
);
688 return new DecimalConstant (res
, left
.Location
);
690 throw new Exception ( "Unexepected division input: " + left
);
692 } catch (OverflowException
){
693 Error_CompileTimeOverflow (ec
, loc
);
695 } catch (DivideByZeroException
) {
696 ec
.Report
.Error (20, loc
, "Division by constant zero");
701 case Binary
.Operator
.Modulus
:
702 if (!DoBinaryNumericPromotions (ref left
, ref right
))
706 if (left
is DoubleConstant
){
709 if (ec
.ConstantCheckState
)
710 res
= checked (((DoubleConstant
) left
).Value
%
711 ((DoubleConstant
) right
).Value
);
713 res
= unchecked (((DoubleConstant
) left
).Value
%
714 ((DoubleConstant
) right
).Value
);
716 return new DoubleConstant (res
, left
.Location
);
717 } else if (left
is FloatConstant
){
720 if (ec
.ConstantCheckState
)
721 res
= checked (((FloatConstant
) left
).Value
%
722 ((FloatConstant
) right
).Value
);
724 res
= unchecked (((FloatConstant
) left
).Value
%
725 ((FloatConstant
) right
).Value
);
727 return new FloatConstant (res
, left
.Location
);
728 } else if (left
is ULongConstant
){
731 if (ec
.ConstantCheckState
)
732 res
= checked (((ULongConstant
) left
).Value
%
733 ((ULongConstant
) right
).Value
);
735 res
= unchecked (((ULongConstant
) left
).Value
%
736 ((ULongConstant
) right
).Value
);
738 return new ULongConstant (res
, left
.Location
);
739 } else if (left
is LongConstant
){
742 if (ec
.ConstantCheckState
)
743 res
= checked (((LongConstant
) left
).Value
%
744 ((LongConstant
) right
).Value
);
746 res
= unchecked (((LongConstant
) left
).Value
%
747 ((LongConstant
) right
).Value
);
749 return new LongConstant (res
, left
.Location
);
750 } else if (left
is UIntConstant
){
753 if (ec
.ConstantCheckState
)
754 res
= checked (((UIntConstant
) left
).Value
%
755 ((UIntConstant
) right
).Value
);
757 res
= unchecked (((UIntConstant
) left
).Value
%
758 ((UIntConstant
) right
).Value
);
760 return new UIntConstant (res
, left
.Location
);
761 } else if (left
is IntConstant
){
764 if (ec
.ConstantCheckState
)
765 res
= checked (((IntConstant
) left
).Value
%
766 ((IntConstant
) right
).Value
);
768 res
= unchecked (((IntConstant
) left
).Value
%
769 ((IntConstant
) right
).Value
);
771 return new IntConstant (res
, left
.Location
);
773 throw new Exception ( "Unexepected modulus input: " + left
);
775 } catch (DivideByZeroException
){
776 ec
.Report
.Error (20, loc
, "Division by constant zero");
777 } catch (OverflowException
){
778 Error_CompileTimeOverflow (ec
, loc
);
783 // There is no overflow checking on left shift
785 case Binary
.Operator
.LeftShift
:
786 IntConstant ic
= right
.ConvertImplicitly (TypeManager
.int32_type
) as IntConstant
;
788 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
792 int lshift_val
= ic
.Value
;
793 if (left
.Type
== TypeManager
.uint64_type
)
794 return new ULongConstant (((ULongConstant
)left
).Value
<< lshift_val
, left
.Location
);
795 if (left
.Type
== TypeManager
.int64_type
)
796 return new LongConstant (((LongConstant
)left
).Value
<< lshift_val
, left
.Location
);
797 if (left
.Type
== TypeManager
.uint32_type
)
798 return new UIntConstant (((UIntConstant
)left
).Value
<< lshift_val
, left
.Location
);
800 left
= left
.ConvertImplicitly (TypeManager
.int32_type
);
801 if (left
.Type
== TypeManager
.int32_type
)
802 return new IntConstant (((IntConstant
)left
).Value
<< lshift_val
, left
.Location
);
804 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
808 // There is no overflow checking on right shift
810 case Binary
.Operator
.RightShift
:
811 IntConstant sic
= right
.ConvertImplicitly (TypeManager
.int32_type
) as IntConstant
;
813 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
); ;
816 int rshift_val
= sic
.Value
;
817 if (left
.Type
== TypeManager
.uint64_type
)
818 return new ULongConstant (((ULongConstant
)left
).Value
>> rshift_val
, left
.Location
);
819 if (left
.Type
== TypeManager
.int64_type
)
820 return new LongConstant (((LongConstant
)left
).Value
>> rshift_val
, left
.Location
);
821 if (left
.Type
== TypeManager
.uint32_type
)
822 return new UIntConstant (((UIntConstant
)left
).Value
>> rshift_val
, left
.Location
);
824 left
= left
.ConvertImplicitly (TypeManager
.int32_type
);
825 if (left
.Type
== TypeManager
.int32_type
)
826 return new IntConstant (((IntConstant
)left
).Value
>> rshift_val
, left
.Location
);
828 Binary
.Error_OperatorCannotBeApplied (ec
, left
, right
, oper
, loc
);
831 case Binary
.Operator
.Equality
:
832 if (TypeManager
.IsReferenceType (lt
) && TypeManager
.IsReferenceType (lt
)) {
833 if (left
.IsNull
|| right
.IsNull
) {
834 return ReducedExpression
.Create (
835 new BoolConstant (left
.IsNull
== right
.IsNull
, left
.Location
),
836 new Binary (oper
, left
, right
));
839 if (left
is StringConstant
&& right
is StringConstant
)
840 return new BoolConstant (
841 ((StringConstant
) left
).Value
== ((StringConstant
) right
).Value
, left
.Location
);
846 if (!DoBinaryNumericPromotions (ref left
, ref right
))
850 if (left
is DoubleConstant
)
851 bool_res
= ((DoubleConstant
) left
).Value
==
852 ((DoubleConstant
) right
).Value
;
853 else if (left
is FloatConstant
)
854 bool_res
= ((FloatConstant
) left
).Value
==
855 ((FloatConstant
) right
).Value
;
856 else if (left
is ULongConstant
)
857 bool_res
= ((ULongConstant
) left
).Value
==
858 ((ULongConstant
) right
).Value
;
859 else if (left
is LongConstant
)
860 bool_res
= ((LongConstant
) left
).Value
==
861 ((LongConstant
) right
).Value
;
862 else if (left
is UIntConstant
)
863 bool_res
= ((UIntConstant
) left
).Value
==
864 ((UIntConstant
) right
).Value
;
865 else if (left
is IntConstant
)
866 bool_res
= ((IntConstant
) left
).Value
==
867 ((IntConstant
) right
).Value
;
871 return new BoolConstant (bool_res
, left
.Location
);
873 case Binary
.Operator
.Inequality
:
874 if (TypeManager
.IsReferenceType (lt
) && TypeManager
.IsReferenceType (lt
)) {
875 if (left
.IsNull
|| right
.IsNull
) {
876 return ReducedExpression
.Create (
877 new BoolConstant (left
.IsNull
!= right
.IsNull
, left
.Location
),
878 new Binary (oper
, left
, right
));
881 if (left
is StringConstant
&& right
is StringConstant
)
882 return new BoolConstant (
883 ((StringConstant
) left
).Value
!= ((StringConstant
) right
).Value
, left
.Location
);
888 if (!DoBinaryNumericPromotions (ref left
, ref right
))
892 if (left
is DoubleConstant
)
893 bool_res
= ((DoubleConstant
) left
).Value
!=
894 ((DoubleConstant
) right
).Value
;
895 else if (left
is FloatConstant
)
896 bool_res
= ((FloatConstant
) left
).Value
!=
897 ((FloatConstant
) right
).Value
;
898 else if (left
is ULongConstant
)
899 bool_res
= ((ULongConstant
) left
).Value
!=
900 ((ULongConstant
) right
).Value
;
901 else if (left
is LongConstant
)
902 bool_res
= ((LongConstant
) left
).Value
!=
903 ((LongConstant
) right
).Value
;
904 else if (left
is UIntConstant
)
905 bool_res
= ((UIntConstant
) left
).Value
!=
906 ((UIntConstant
) right
).Value
;
907 else if (left
is IntConstant
)
908 bool_res
= ((IntConstant
) left
).Value
!=
909 ((IntConstant
) right
).Value
;
913 return new BoolConstant (bool_res
, left
.Location
);
915 case Binary
.Operator
.LessThan
:
916 if (!DoBinaryNumericPromotions (ref left
, ref right
))
920 if (left
is DoubleConstant
)
921 bool_res
= ((DoubleConstant
) left
).Value
<
922 ((DoubleConstant
) right
).Value
;
923 else if (left
is FloatConstant
)
924 bool_res
= ((FloatConstant
) left
).Value
<
925 ((FloatConstant
) right
).Value
;
926 else if (left
is ULongConstant
)
927 bool_res
= ((ULongConstant
) left
).Value
<
928 ((ULongConstant
) right
).Value
;
929 else if (left
is LongConstant
)
930 bool_res
= ((LongConstant
) left
).Value
<
931 ((LongConstant
) right
).Value
;
932 else if (left
is UIntConstant
)
933 bool_res
= ((UIntConstant
) left
).Value
<
934 ((UIntConstant
) right
).Value
;
935 else if (left
is IntConstant
)
936 bool_res
= ((IntConstant
) left
).Value
<
937 ((IntConstant
) right
).Value
;
941 return new BoolConstant (bool_res
, left
.Location
);
943 case Binary
.Operator
.GreaterThan
:
944 if (!DoBinaryNumericPromotions (ref left
, ref right
))
948 if (left
is DoubleConstant
)
949 bool_res
= ((DoubleConstant
) left
).Value
>
950 ((DoubleConstant
) right
).Value
;
951 else if (left
is FloatConstant
)
952 bool_res
= ((FloatConstant
) left
).Value
>
953 ((FloatConstant
) right
).Value
;
954 else if (left
is ULongConstant
)
955 bool_res
= ((ULongConstant
) left
).Value
>
956 ((ULongConstant
) right
).Value
;
957 else if (left
is LongConstant
)
958 bool_res
= ((LongConstant
) left
).Value
>
959 ((LongConstant
) right
).Value
;
960 else if (left
is UIntConstant
)
961 bool_res
= ((UIntConstant
) left
).Value
>
962 ((UIntConstant
) right
).Value
;
963 else if (left
is IntConstant
)
964 bool_res
= ((IntConstant
) left
).Value
>
965 ((IntConstant
) right
).Value
;
969 return new BoolConstant (bool_res
, left
.Location
);
971 case Binary
.Operator
.GreaterThanOrEqual
:
972 if (!DoBinaryNumericPromotions (ref left
, ref right
))
976 if (left
is DoubleConstant
)
977 bool_res
= ((DoubleConstant
) left
).Value
>=
978 ((DoubleConstant
) right
).Value
;
979 else if (left
is FloatConstant
)
980 bool_res
= ((FloatConstant
) left
).Value
>=
981 ((FloatConstant
) right
).Value
;
982 else if (left
is ULongConstant
)
983 bool_res
= ((ULongConstant
) left
).Value
>=
984 ((ULongConstant
) right
).Value
;
985 else if (left
is LongConstant
)
986 bool_res
= ((LongConstant
) left
).Value
>=
987 ((LongConstant
) right
).Value
;
988 else if (left
is UIntConstant
)
989 bool_res
= ((UIntConstant
) left
).Value
>=
990 ((UIntConstant
) right
).Value
;
991 else if (left
is IntConstant
)
992 bool_res
= ((IntConstant
) left
).Value
>=
993 ((IntConstant
) right
).Value
;
997 return new BoolConstant (bool_res
, left
.Location
);
999 case Binary
.Operator
.LessThanOrEqual
:
1000 if (!DoBinaryNumericPromotions (ref left
, ref right
))
1004 if (left
is DoubleConstant
)
1005 bool_res
= ((DoubleConstant
) left
).Value
<=
1006 ((DoubleConstant
) right
).Value
;
1007 else if (left
is FloatConstant
)
1008 bool_res
= ((FloatConstant
) left
).Value
<=
1009 ((FloatConstant
) right
).Value
;
1010 else if (left
is ULongConstant
)
1011 bool_res
= ((ULongConstant
) left
).Value
<=
1012 ((ULongConstant
) right
).Value
;
1013 else if (left
is LongConstant
)
1014 bool_res
= ((LongConstant
) left
).Value
<=
1015 ((LongConstant
) right
).Value
;
1016 else if (left
is UIntConstant
)
1017 bool_res
= ((UIntConstant
) left
).Value
<=
1018 ((UIntConstant
) right
).Value
;
1019 else if (left
is IntConstant
)
1020 bool_res
= ((IntConstant
) left
).Value
<=
1021 ((IntConstant
) right
).Value
;
1025 return new BoolConstant (bool_res
, left
.Location
);