monotouch uses the real HttpWebRequest
[mcs.git] / mcs / cfold.cs
bloba23a20a122cf186f500363663fb6e52710d62706
1 //
2 // cfold.cs: Constant Folding
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Copyright 2002, 2003 Ximian, Inc.
9 // Copyright 2003-2008, Novell, Inc.
10 //
11 using System;
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) {
34 if (t == ltype)
35 return t == rtype || ConvertPromotion (ref right, ref left, t);
37 if (t == rtype)
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);
49 if (c != null) {
50 prim = c;
51 return true;
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;
61 return false;
64 internal static void Error_CompileTimeOverflow (Location loc)
66 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
69 /// <summary>
70 /// Constant expression folder for binary operations.
71 ///
72 /// Returns null if the expression can not be folded.
73 /// </summary>
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);
84 if (result == null)
85 return null;
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);
94 if (result == null)
95 return null;
96 return new SideEffectConstant (result, right, loc);
99 Type lt = left.Type;
100 Type rt = right.Type;
101 bool bool_res;
103 if (lt == TypeManager.bool_type && lt == rt) {
104 bool lv = (bool) left.GetValue ();
105 bool rv = (bool) right.GetValue ();
106 switch (oper) {
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);
120 return null;
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) {
134 switch (oper){
136 /// E operator |(E x, E y);
137 /// E operator &(E x, E y);
138 /// E operator ^(E x, E y);
139 ///
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);
148 ///
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);
160 ///
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);
169 return null;
172 switch (oper){
173 case Binary.Operator.BitwiseOr:
174 if (!DoBinaryNumericPromotions (ref left, ref right))
175 return null;
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);
198 break;
200 case Binary.Operator.BitwiseAnd:
201 if (!DoBinaryNumericPromotions (ref left, ref right))
202 return null;
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);
228 break;
230 case Binary.Operator.ExclusiveOr:
231 if (!DoBinaryNumericPromotions (ref left, ref right))
232 return null;
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);
254 break;
256 case Binary.Operator.Addition:
257 if (lt == TypeManager.null_type)
258 return right;
260 if (rt == TypeManager.null_type)
261 return left;
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){
269 if (lt == rt)
270 return new StringConstant ((string)left.GetValue () + (string)right.GetValue (),
271 left.Location);
273 return null;
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){
283 if (lc == null) {
284 lc = rc;
285 lt = lc.Type;
286 right = left;
289 // U has to be implicitly convetible to E.base
290 right = right.ConvertImplicitly (lc.Child.Type);
291 if (right == null)
292 return null;
294 result = BinaryFold (ec, oper, lc.Child, right, loc);
295 if (result == null)
296 return null;
298 result = result.TryReduce (ec, lt, loc);
299 if (result == null)
300 return null;
302 return new EnumConstant (result, lt);
305 if (!DoBinaryNumericPromotions (ref left, ref right))
306 return null;
308 try {
309 if (left is DoubleConstant){
310 double res;
312 if (ec.ConstantCheckState)
313 res = checked (((DoubleConstant) left).Value +
314 ((DoubleConstant) right).Value);
315 else
316 res = unchecked (((DoubleConstant) left).Value +
317 ((DoubleConstant) right).Value);
319 return new DoubleConstant (res, left.Location);
321 if (left is FloatConstant){
322 float res;
324 if (ec.ConstantCheckState)
325 res = checked (((FloatConstant) left).Value +
326 ((FloatConstant) right).Value);
327 else
328 res = unchecked (((FloatConstant) left).Value +
329 ((FloatConstant) right).Value);
331 result = new FloatConstant (res, left.Location);
332 } else if (left is ULongConstant){
333 ulong res;
335 if (ec.ConstantCheckState)
336 res = checked (((ULongConstant) left).Value +
337 ((ULongConstant) right).Value);
338 else
339 res = unchecked (((ULongConstant) left).Value +
340 ((ULongConstant) right).Value);
342 result = new ULongConstant (res, left.Location);
343 } else if (left is LongConstant){
344 long res;
346 if (ec.ConstantCheckState)
347 res = checked (((LongConstant) left).Value +
348 ((LongConstant) right).Value);
349 else
350 res = unchecked (((LongConstant) left).Value +
351 ((LongConstant) right).Value);
353 result = new LongConstant (res, left.Location);
354 } else if (left is UIntConstant){
355 uint res;
357 if (ec.ConstantCheckState)
358 res = checked (((UIntConstant) left).Value +
359 ((UIntConstant) right).Value);
360 else
361 res = unchecked (((UIntConstant) left).Value +
362 ((UIntConstant) right).Value);
364 result = new UIntConstant (res, left.Location);
365 } else if (left is IntConstant){
366 int res;
368 if (ec.ConstantCheckState)
369 res = checked (((IntConstant) left).Value +
370 ((IntConstant) right).Value);
371 else
372 res = unchecked (((IntConstant) left).Value +
373 ((IntConstant) right).Value);
375 result = new IntConstant (res, left.Location);
376 } else if (left is DecimalConstant) {
377 decimal res;
379 if (ec.ConstantCheckState)
380 res = checked (((DecimalConstant) left).Value +
381 ((DecimalConstant) right).Value);
382 else
383 res = unchecked (((DecimalConstant) left).Value +
384 ((DecimalConstant) right).Value);
386 result = new DecimalConstant (res, left.Location);
388 } catch (OverflowException){
389 Error_CompileTimeOverflow (loc);
392 return result;
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){
402 if (lc == null) {
403 lc = rc;
404 lt = lc.Type;
405 right = left;
408 // U has to be implicitly convetible to E.base
409 right = right.ConvertImplicitly (lc.Child.Type);
410 if (right == null)
411 return null;
413 result = BinaryFold (ec, oper, lc.Child, right, loc);
414 if (result == null)
415 return null;
417 result = result.TryReduce (ec, lt, loc);
418 if (result == null)
419 return null;
421 return new EnumConstant (result, lt);
424 if (!DoBinaryNumericPromotions (ref left, ref right))
425 return null;
427 try {
428 if (left is DoubleConstant){
429 double res;
431 if (ec.ConstantCheckState)
432 res = checked (((DoubleConstant) left).Value -
433 ((DoubleConstant) right).Value);
434 else
435 res = unchecked (((DoubleConstant) left).Value -
436 ((DoubleConstant) right).Value);
438 result = new DoubleConstant (res, left.Location);
439 } else if (left is FloatConstant){
440 float res;
442 if (ec.ConstantCheckState)
443 res = checked (((FloatConstant) left).Value -
444 ((FloatConstant) right).Value);
445 else
446 res = unchecked (((FloatConstant) left).Value -
447 ((FloatConstant) right).Value);
449 result = new FloatConstant (res, left.Location);
450 } else if (left is ULongConstant){
451 ulong res;
453 if (ec.ConstantCheckState)
454 res = checked (((ULongConstant) left).Value -
455 ((ULongConstant) right).Value);
456 else
457 res = unchecked (((ULongConstant) left).Value -
458 ((ULongConstant) right).Value);
460 result = new ULongConstant (res, left.Location);
461 } else if (left is LongConstant){
462 long res;
464 if (ec.ConstantCheckState)
465 res = checked (((LongConstant) left).Value -
466 ((LongConstant) right).Value);
467 else
468 res = unchecked (((LongConstant) left).Value -
469 ((LongConstant) right).Value);
471 result = new LongConstant (res, left.Location);
472 } else if (left is UIntConstant){
473 uint res;
475 if (ec.ConstantCheckState)
476 res = checked (((UIntConstant) left).Value -
477 ((UIntConstant) right).Value);
478 else
479 res = unchecked (((UIntConstant) left).Value -
480 ((UIntConstant) right).Value);
482 result = new UIntConstant (res, left.Location);
483 } else if (left is IntConstant){
484 int res;
486 if (ec.ConstantCheckState)
487 res = checked (((IntConstant) left).Value -
488 ((IntConstant) right).Value);
489 else
490 res = unchecked (((IntConstant) left).Value -
491 ((IntConstant) right).Value);
493 result = new IntConstant (res, left.Location);
494 } else if (left is DecimalConstant) {
495 decimal res;
497 if (ec.ConstantCheckState)
498 res = checked (((DecimalConstant) left).Value -
499 ((DecimalConstant) right).Value);
500 else
501 res = unchecked (((DecimalConstant) left).Value -
502 ((DecimalConstant) right).Value);
504 return new DecimalConstant (res, left.Location);
505 } else {
506 throw new Exception ( "Unexepected subtraction input: " + left);
508 } catch (OverflowException){
509 Error_CompileTimeOverflow (loc);
512 return result;
514 case Binary.Operator.Multiply:
515 if (!DoBinaryNumericPromotions (ref left, ref right))
516 return null;
518 try {
519 if (left is DoubleConstant){
520 double res;
522 if (ec.ConstantCheckState)
523 res = checked (((DoubleConstant) left).Value *
524 ((DoubleConstant) right).Value);
525 else
526 res = unchecked (((DoubleConstant) left).Value *
527 ((DoubleConstant) right).Value);
529 return new DoubleConstant (res, left.Location);
530 } else if (left is FloatConstant){
531 float res;
533 if (ec.ConstantCheckState)
534 res = checked (((FloatConstant) left).Value *
535 ((FloatConstant) right).Value);
536 else
537 res = unchecked (((FloatConstant) left).Value *
538 ((FloatConstant) right).Value);
540 return new FloatConstant (res, left.Location);
541 } else if (left is ULongConstant){
542 ulong res;
544 if (ec.ConstantCheckState)
545 res = checked (((ULongConstant) left).Value *
546 ((ULongConstant) right).Value);
547 else
548 res = unchecked (((ULongConstant) left).Value *
549 ((ULongConstant) right).Value);
551 return new ULongConstant (res, left.Location);
552 } else if (left is LongConstant){
553 long res;
555 if (ec.ConstantCheckState)
556 res = checked (((LongConstant) left).Value *
557 ((LongConstant) right).Value);
558 else
559 res = unchecked (((LongConstant) left).Value *
560 ((LongConstant) right).Value);
562 return new LongConstant (res, left.Location);
563 } else if (left is UIntConstant){
564 uint res;
566 if (ec.ConstantCheckState)
567 res = checked (((UIntConstant) left).Value *
568 ((UIntConstant) right).Value);
569 else
570 res = unchecked (((UIntConstant) left).Value *
571 ((UIntConstant) right).Value);
573 return new UIntConstant (res, left.Location);
574 } else if (left is IntConstant){
575 int res;
577 if (ec.ConstantCheckState)
578 res = checked (((IntConstant) left).Value *
579 ((IntConstant) right).Value);
580 else
581 res = unchecked (((IntConstant) left).Value *
582 ((IntConstant) right).Value);
584 return new IntConstant (res, left.Location);
585 } else if (left is DecimalConstant) {
586 decimal res;
588 if (ec.ConstantCheckState)
589 res = checked (((DecimalConstant) left).Value *
590 ((DecimalConstant) right).Value);
591 else
592 res = unchecked (((DecimalConstant) left).Value *
593 ((DecimalConstant) right).Value);
595 return new DecimalConstant (res, left.Location);
596 } else {
597 throw new Exception ( "Unexepected multiply input: " + left);
599 } catch (OverflowException){
600 Error_CompileTimeOverflow (loc);
602 break;
604 case Binary.Operator.Division:
605 if (!DoBinaryNumericPromotions (ref left, ref right))
606 return null;
608 try {
609 if (left is DoubleConstant){
610 double res;
612 if (ec.ConstantCheckState)
613 res = checked (((DoubleConstant) left).Value /
614 ((DoubleConstant) right).Value);
615 else
616 res = unchecked (((DoubleConstant) left).Value /
617 ((DoubleConstant) right).Value);
619 return new DoubleConstant (res, left.Location);
620 } else if (left is FloatConstant){
621 float res;
623 if (ec.ConstantCheckState)
624 res = checked (((FloatConstant) left).Value /
625 ((FloatConstant) right).Value);
626 else
627 res = unchecked (((FloatConstant) left).Value /
628 ((FloatConstant) right).Value);
630 return new FloatConstant (res, left.Location);
631 } else if (left is ULongConstant){
632 ulong res;
634 if (ec.ConstantCheckState)
635 res = checked (((ULongConstant) left).Value /
636 ((ULongConstant) right).Value);
637 else
638 res = unchecked (((ULongConstant) left).Value /
639 ((ULongConstant) right).Value);
641 return new ULongConstant (res, left.Location);
642 } else if (left is LongConstant){
643 long res;
645 if (ec.ConstantCheckState)
646 res = checked (((LongConstant) left).Value /
647 ((LongConstant) right).Value);
648 else
649 res = unchecked (((LongConstant) left).Value /
650 ((LongConstant) right).Value);
652 return new LongConstant (res, left.Location);
653 } else if (left is UIntConstant){
654 uint res;
656 if (ec.ConstantCheckState)
657 res = checked (((UIntConstant) left).Value /
658 ((UIntConstant) right).Value);
659 else
660 res = unchecked (((UIntConstant) left).Value /
661 ((UIntConstant) right).Value);
663 return new UIntConstant (res, left.Location);
664 } else if (left is IntConstant){
665 int res;
667 if (ec.ConstantCheckState)
668 res = checked (((IntConstant) left).Value /
669 ((IntConstant) right).Value);
670 else
671 res = unchecked (((IntConstant) left).Value /
672 ((IntConstant) right).Value);
674 return new IntConstant (res, left.Location);
675 } else if (left is DecimalConstant) {
676 decimal res;
678 if (ec.ConstantCheckState)
679 res = checked (((DecimalConstant) left).Value /
680 ((DecimalConstant) right).Value);
681 else
682 res = unchecked (((DecimalConstant) left).Value /
683 ((DecimalConstant) right).Value);
685 return new DecimalConstant (res, left.Location);
686 } else {
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");
696 break;
698 case Binary.Operator.Modulus:
699 if (!DoBinaryNumericPromotions (ref left, ref right))
700 return null;
702 try {
703 if (left is DoubleConstant){
704 double res;
706 if (ec.ConstantCheckState)
707 res = checked (((DoubleConstant) left).Value %
708 ((DoubleConstant) right).Value);
709 else
710 res = unchecked (((DoubleConstant) left).Value %
711 ((DoubleConstant) right).Value);
713 return new DoubleConstant (res, left.Location);
714 } else if (left is FloatConstant){
715 float res;
717 if (ec.ConstantCheckState)
718 res = checked (((FloatConstant) left).Value %
719 ((FloatConstant) right).Value);
720 else
721 res = unchecked (((FloatConstant) left).Value %
722 ((FloatConstant) right).Value);
724 return new FloatConstant (res, left.Location);
725 } else if (left is ULongConstant){
726 ulong res;
728 if (ec.ConstantCheckState)
729 res = checked (((ULongConstant) left).Value %
730 ((ULongConstant) right).Value);
731 else
732 res = unchecked (((ULongConstant) left).Value %
733 ((ULongConstant) right).Value);
735 return new ULongConstant (res, left.Location);
736 } else if (left is LongConstant){
737 long res;
739 if (ec.ConstantCheckState)
740 res = checked (((LongConstant) left).Value %
741 ((LongConstant) right).Value);
742 else
743 res = unchecked (((LongConstant) left).Value %
744 ((LongConstant) right).Value);
746 return new LongConstant (res, left.Location);
747 } else if (left is UIntConstant){
748 uint res;
750 if (ec.ConstantCheckState)
751 res = checked (((UIntConstant) left).Value %
752 ((UIntConstant) right).Value);
753 else
754 res = unchecked (((UIntConstant) left).Value %
755 ((UIntConstant) right).Value);
757 return new UIntConstant (res, left.Location);
758 } else if (left is IntConstant){
759 int res;
761 if (ec.ConstantCheckState)
762 res = checked (((IntConstant) left).Value %
763 ((IntConstant) right).Value);
764 else
765 res = unchecked (((IntConstant) left).Value %
766 ((IntConstant) right).Value);
768 return new IntConstant (res, left.Location);
769 } else {
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);
777 break;
780 // There is no overflow checking on left shift
782 case Binary.Operator.LeftShift:
783 IntConstant ic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
784 if (ic == null){
785 Binary.Error_OperatorCannotBeApplied (left, right, oper, loc);
786 return null;
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);
802 break;
805 // There is no overflow checking on right shift
807 case Binary.Operator.RightShift:
808 IntConstant sic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
809 if (sic == null){
810 Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); ;
811 return null;
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);
826 break;
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))
850 return null;
852 bool_res = false;
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;
871 else
872 return null;
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))
898 return null;
900 bool_res = false;
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;
919 else
920 return null;
922 return new BoolConstant (bool_res, left.Location);
924 case Binary.Operator.LessThan:
925 if (!DoBinaryNumericPromotions (ref left, ref right))
926 return null;
928 bool_res = false;
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;
947 else
948 return null;
950 return new BoolConstant (bool_res, left.Location);
952 case Binary.Operator.GreaterThan:
953 if (!DoBinaryNumericPromotions (ref left, ref right))
954 return null;
956 bool_res = false;
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;
975 else
976 return null;
978 return new BoolConstant (bool_res, left.Location);
980 case Binary.Operator.GreaterThanOrEqual:
981 if (!DoBinaryNumericPromotions (ref left, ref right))
982 return null;
984 bool_res = false;
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;
1003 else
1004 return null;
1006 return new BoolConstant (bool_res, left.Location);
1008 case Binary.Operator.LessThanOrEqual:
1009 if (!DoBinaryNumericPromotions (ref left, ref right))
1010 return null;
1012 bool_res = false;
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;
1031 else
1032 return null;
1034 return new BoolConstant (bool_res, left.Location);
1037 return null;