* DataGrid.cs: remove the XXX'ed check at the top of
[mcs.git] / mcs / cfold.cs
bloba8775a54f93ee53e749b0d1a3dede4b27711416e
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 // (C) 2002, 2003 Ximian, Inc.
9 //
11 using System;
13 namespace Mono.CSharp {
15 public class ConstantFold {
17 static 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 desposits 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 void 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 || t == rtype) {
35 left = left.ConvertImplicitly (t);
36 right = right.ConvertImplicitly (t);
37 return;
41 left = left.ConvertImplicitly (TypeManager.int32_type);
42 right = right.ConvertImplicitly (TypeManager.int32_type);
45 internal static void Error_CompileTimeOverflow (Location loc)
47 Report.Error (220, loc, "The operation overflows at compile time in checked mode");
50 /// <summary>
51 /// Constant expression folder for binary operations.
52 ///
53 /// Returns null if the expression can not be folded.
54 /// </summary>
55 static public Constant BinaryFold (EmitContext ec, Binary.Operator oper,
56 Constant left, Constant right, Location loc)
58 if (left is EmptyConstantCast)
59 return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
61 if (right is EmptyConstantCast)
62 return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
64 Type lt = left.Type;
65 Type rt = right.Type;
66 bool bool_res;
67 Constant result = null;
69 if (lt == TypeManager.bool_type && lt == rt) {
70 bool lv = ((BoolConstant) left ).Value;
71 bool rv = ((BoolConstant) right).Value;
72 switch (oper) {
73 case Binary.Operator.BitwiseAnd:
74 case Binary.Operator.LogicalAnd:
75 return new BoolConstant (lv && rv, left.Location);
76 case Binary.Operator.BitwiseOr:
77 case Binary.Operator.LogicalOr:
78 return new BoolConstant (lv || rv, left.Location);
79 case Binary.Operator.ExclusiveOr:
80 return new BoolConstant (lv ^ rv, left.Location);
81 case Binary.Operator.Equality:
82 return new BoolConstant (lv == rv, left.Location);
83 case Binary.Operator.Inequality:
84 return new BoolConstant (lv != rv, left.Location);
86 return null;
90 // During an enum evaluation, none of the rules are valid
91 // Not sure whether it is bug in csc or in documentation
93 if (ec.InEnumContext){
94 if (left is EnumConstant)
95 left = ((EnumConstant) left).Child;
97 if (right is EnumConstant)
98 right = ((EnumConstant) right).Child;
99 } else if (left is EnumConstant && rt == lt) {
100 switch (oper){
102 /// E operator |(E x, E y);
103 /// E operator &(E x, E y);
104 /// E operator ^(E x, E y);
105 ///
106 case Binary.Operator.BitwiseOr:
107 case Binary.Operator.BitwiseAnd:
108 case Binary.Operator.ExclusiveOr:
109 return BinaryFold (ec, oper, ((EnumConstant)left).Child,
110 ((EnumConstant)right).Child, loc).TryReduce (ec, lt, loc);
113 /// U operator -(E x, E y);
114 ///
115 case Binary.Operator.Subtraction:
116 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
117 return result.TryReduce (ec, ((EnumConstant)left).Child.Type, loc);
120 /// bool operator ==(E x, E y);
121 /// bool operator !=(E x, E y);
122 /// bool operator <(E x, E y);
123 /// bool operator >(E x, E y);
124 /// bool operator <=(E x, E y);
125 /// bool operator >=(E x, E y);
126 ///
127 case Binary.Operator.Equality:
128 case Binary.Operator.Inequality:
129 case Binary.Operator.LessThan:
130 case Binary.Operator.GreaterThan:
131 case Binary.Operator.LessThanOrEqual:
132 case Binary.Operator.GreaterThanOrEqual:
133 return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
135 return null;
138 switch (oper){
139 case Binary.Operator.BitwiseOr:
140 DoBinaryNumericPromotions (ref left, ref right);
141 if (left == null || right == null)
142 return null;
144 if (left is IntConstant){
145 int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
147 return new IntConstant (res, left.Location);
149 if (left is UIntConstant){
150 uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
152 return new UIntConstant (res, left.Location);
154 if (left is LongConstant){
155 long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
157 return new LongConstant (res, left.Location);
159 if (left is ULongConstant){
160 ulong res = ((ULongConstant)left).Value |
161 ((ULongConstant)right).Value;
163 return new ULongConstant (res, left.Location);
165 break;
167 case Binary.Operator.BitwiseAnd:
168 DoBinaryNumericPromotions (ref left, ref right);
169 if (left == null || right == null)
170 return null;
173 /// int operator &(int x, int y);
174 /// uint operator &(uint x, uint y);
175 /// long operator &(long x, long y);
176 /// ulong operator &(ulong x, ulong y);
178 if (left is IntConstant){
179 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;
184 return new UIntConstant (res, left.Location);
186 if (left is LongConstant){
187 long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
188 return new LongConstant (res, left.Location);
190 if (left is ULongConstant){
191 ulong res = ((ULongConstant)left).Value &
192 ((ULongConstant)right).Value;
194 return new ULongConstant (res, left.Location);
196 break;
198 case Binary.Operator.ExclusiveOr:
199 DoBinaryNumericPromotions (ref left, ref right);
200 if (left == null || right == null)
201 return null;
203 if (left is IntConstant){
204 int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
205 return new IntConstant (res, left.Location);
207 if (left is UIntConstant){
208 uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
210 return new UIntConstant (res, left.Location);
212 if (left is LongConstant){
213 long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
215 return new LongConstant (res, left.Location);
217 if (left is ULongConstant){
218 ulong res = ((ULongConstant)left).Value ^
219 ((ULongConstant)right).Value;
221 return new ULongConstant (res, left.Location);
223 break;
225 case Binary.Operator.Addition:
227 // If both sides are strings, then concatenate, if
228 // one is a string, and the other is not, then defer
229 // to runtime concatenation
231 if (lt == TypeManager.string_type || rt == TypeManager.string_type){
232 if (lt == TypeManager.string_type && rt == TypeManager.string_type)
233 return new StringConstant (
234 ((StringConstant) left).Value +
235 ((StringConstant) right).Value, left.Location);
237 return null;
241 // handle "E operator + (E x, U y)"
242 // handle "E operator + (Y y, E x)"
244 EnumConstant lc = left as EnumConstant;
245 EnumConstant rc = right as EnumConstant;
246 if (lc != null || rc != null){
247 if (lc == null) {
248 lc = rc;
249 lt = lc.Type;
250 right = left;
253 // U has to be implicitly convetible to E.base
254 right = right.ConvertImplicitly (lc.Child.Type);
255 if (right == null)
256 return null;
258 result = BinaryFold (ec, oper, lc.Child, right, loc);
259 if (result == null)
260 return null;
262 result = result.TryReduce (ec, lt, loc);
263 if (result == null)
264 return null;
266 return new EnumConstant (result, lt);
269 DoBinaryNumericPromotions (ref left, ref right);
270 if (left == null || right == null)
271 return null;
273 try {
274 if (left is DoubleConstant){
275 double res;
277 if (ec.ConstantCheckState)
278 res = checked (((DoubleConstant) left).Value +
279 ((DoubleConstant) right).Value);
280 else
281 res = unchecked (((DoubleConstant) left).Value +
282 ((DoubleConstant) right).Value);
284 return new DoubleConstant (res, left.Location);
286 if (left is FloatConstant){
287 float res;
289 if (ec.ConstantCheckState)
290 res = checked (((FloatConstant) left).Value +
291 ((FloatConstant) right).Value);
292 else
293 res = unchecked (((FloatConstant) left).Value +
294 ((FloatConstant) right).Value);
296 result = new FloatConstant (res, left.Location);
297 } else if (left is ULongConstant){
298 ulong res;
300 if (ec.ConstantCheckState)
301 res = checked (((ULongConstant) left).Value +
302 ((ULongConstant) right).Value);
303 else
304 res = unchecked (((ULongConstant) left).Value +
305 ((ULongConstant) right).Value);
307 result = new ULongConstant (res, left.Location);
308 } else if (left is LongConstant){
309 long res;
311 if (ec.ConstantCheckState)
312 res = checked (((LongConstant) left).Value +
313 ((LongConstant) right).Value);
314 else
315 res = unchecked (((LongConstant) left).Value +
316 ((LongConstant) right).Value);
318 result = new LongConstant (res, left.Location);
319 } else if (left is UIntConstant){
320 uint res;
322 if (ec.ConstantCheckState)
323 res = checked (((UIntConstant) left).Value +
324 ((UIntConstant) right).Value);
325 else
326 res = unchecked (((UIntConstant) left).Value +
327 ((UIntConstant) right).Value);
329 result = new UIntConstant (res, left.Location);
330 } else if (left is IntConstant){
331 int res;
333 if (ec.ConstantCheckState)
334 res = checked (((IntConstant) left).Value +
335 ((IntConstant) right).Value);
336 else
337 res = unchecked (((IntConstant) left).Value +
338 ((IntConstant) right).Value);
340 result = new IntConstant (res, left.Location);
341 } else if (left is DecimalConstant) {
342 decimal res;
344 if (ec.ConstantCheckState)
345 res = checked (((DecimalConstant) left).Value +
346 ((DecimalConstant) right).Value);
347 else
348 res = unchecked (((DecimalConstant) left).Value +
349 ((DecimalConstant) right).Value);
351 result = new DecimalConstant (res, left.Location);
352 } else {
353 throw new Exception ( "Unexepected addition input: " + left);
355 } catch (OverflowException){
356 Error_CompileTimeOverflow (loc);
359 return result;
361 case Binary.Operator.Subtraction:
363 // handle "E operator - (E x, U y)"
364 // handle "E operator - (Y y, E x)"
366 lc = left as EnumConstant;
367 rc = right as EnumConstant;
368 if (lc != null || rc != null){
369 if (lc == null) {
370 lc = rc;
371 lt = lc.Type;
372 right = left;
375 // U has to be implicitly convetible to E.base
376 right = right.ConvertImplicitly (lc.Child.Type);
377 if (right == null)
378 return null;
380 result = BinaryFold (ec, oper, lc.Child, right, loc);
381 if (result == null)
382 return null;
384 result = result.TryReduce (ec, lt, loc);
385 if (result == null)
386 return null;
388 return new EnumConstant (result, lt);
391 DoBinaryNumericPromotions (ref left, ref right);
392 if (left == null || right == null)
393 return null;
395 try {
396 if (left is DoubleConstant){
397 double res;
399 if (ec.ConstantCheckState)
400 res = checked (((DoubleConstant) left).Value -
401 ((DoubleConstant) right).Value);
402 else
403 res = unchecked (((DoubleConstant) left).Value -
404 ((DoubleConstant) right).Value);
406 result = new DoubleConstant (res, left.Location);
407 } else if (left is FloatConstant){
408 float res;
410 if (ec.ConstantCheckState)
411 res = checked (((FloatConstant) left).Value -
412 ((FloatConstant) right).Value);
413 else
414 res = unchecked (((FloatConstant) left).Value -
415 ((FloatConstant) right).Value);
417 result = new FloatConstant (res, left.Location);
418 } else if (left is ULongConstant){
419 ulong res;
421 if (ec.ConstantCheckState)
422 res = checked (((ULongConstant) left).Value -
423 ((ULongConstant) right).Value);
424 else
425 res = unchecked (((ULongConstant) left).Value -
426 ((ULongConstant) right).Value);
428 result = new ULongConstant (res, left.Location);
429 } else if (left is LongConstant){
430 long res;
432 if (ec.ConstantCheckState)
433 res = checked (((LongConstant) left).Value -
434 ((LongConstant) right).Value);
435 else
436 res = unchecked (((LongConstant) left).Value -
437 ((LongConstant) right).Value);
439 result = new LongConstant (res, left.Location);
440 } else if (left is UIntConstant){
441 uint res;
443 if (ec.ConstantCheckState)
444 res = checked (((UIntConstant) left).Value -
445 ((UIntConstant) right).Value);
446 else
447 res = unchecked (((UIntConstant) left).Value -
448 ((UIntConstant) right).Value);
450 result = new UIntConstant (res, left.Location);
451 } else if (left is IntConstant){
452 int res;
454 if (ec.ConstantCheckState)
455 res = checked (((IntConstant) left).Value -
456 ((IntConstant) right).Value);
457 else
458 res = unchecked (((IntConstant) left).Value -
459 ((IntConstant) right).Value);
461 result = new IntConstant (res, left.Location);
462 } else if (left is DecimalConstant) {
463 decimal res;
465 if (ec.ConstantCheckState)
466 res = checked (((DecimalConstant) left).Value -
467 ((DecimalConstant) right).Value);
468 else
469 res = unchecked (((DecimalConstant) left).Value -
470 ((DecimalConstant) right).Value);
472 return new DecimalConstant (res, left.Location);
473 } else {
474 throw new Exception ( "Unexepected subtraction input: " + left);
476 } catch (OverflowException){
477 Error_CompileTimeOverflow (loc);
480 return result;
482 case Binary.Operator.Multiply:
483 DoBinaryNumericPromotions (ref left, ref right);
484 if (left == null || right == null)
485 return null;
487 try {
488 if (left is DoubleConstant){
489 double res;
491 if (ec.ConstantCheckState)
492 res = checked (((DoubleConstant) left).Value *
493 ((DoubleConstant) right).Value);
494 else
495 res = unchecked (((DoubleConstant) left).Value *
496 ((DoubleConstant) right).Value);
498 return new DoubleConstant (res, left.Location);
499 } else if (left is FloatConstant){
500 float res;
502 if (ec.ConstantCheckState)
503 res = checked (((FloatConstant) left).Value *
504 ((FloatConstant) right).Value);
505 else
506 res = unchecked (((FloatConstant) left).Value *
507 ((FloatConstant) right).Value);
509 return new FloatConstant (res, left.Location);
510 } else if (left is ULongConstant){
511 ulong res;
513 if (ec.ConstantCheckState)
514 res = checked (((ULongConstant) left).Value *
515 ((ULongConstant) right).Value);
516 else
517 res = unchecked (((ULongConstant) left).Value *
518 ((ULongConstant) right).Value);
520 return new ULongConstant (res, left.Location);
521 } else if (left is LongConstant){
522 long res;
524 if (ec.ConstantCheckState)
525 res = checked (((LongConstant) left).Value *
526 ((LongConstant) right).Value);
527 else
528 res = unchecked (((LongConstant) left).Value *
529 ((LongConstant) right).Value);
531 return new LongConstant (res, left.Location);
532 } else if (left is UIntConstant){
533 uint res;
535 if (ec.ConstantCheckState)
536 res = checked (((UIntConstant) left).Value *
537 ((UIntConstant) right).Value);
538 else
539 res = unchecked (((UIntConstant) left).Value *
540 ((UIntConstant) right).Value);
542 return new UIntConstant (res, left.Location);
543 } else if (left is IntConstant){
544 int res;
546 if (ec.ConstantCheckState)
547 res = checked (((IntConstant) left).Value *
548 ((IntConstant) right).Value);
549 else
550 res = unchecked (((IntConstant) left).Value *
551 ((IntConstant) right).Value);
553 return new IntConstant (res, left.Location);
554 } else if (left is DecimalConstant) {
555 decimal res;
557 if (ec.ConstantCheckState)
558 res = checked (((DecimalConstant) left).Value *
559 ((DecimalConstant) right).Value);
560 else
561 res = unchecked (((DecimalConstant) left).Value *
562 ((DecimalConstant) right).Value);
564 return new DecimalConstant (res, left.Location);
565 } else {
566 throw new Exception ( "Unexepected multiply input: " + left);
568 } catch (OverflowException){
569 Error_CompileTimeOverflow (loc);
571 break;
573 case Binary.Operator.Division:
574 DoBinaryNumericPromotions (ref left, ref right);
575 if (left == null || right == null)
576 return null;
578 try {
579 if (left is DoubleConstant){
580 double res;
582 if (ec.ConstantCheckState)
583 res = checked (((DoubleConstant) left).Value /
584 ((DoubleConstant) right).Value);
585 else
586 res = unchecked (((DoubleConstant) left).Value /
587 ((DoubleConstant) right).Value);
589 return new DoubleConstant (res, left.Location);
590 } else if (left is FloatConstant){
591 float res;
593 if (ec.ConstantCheckState)
594 res = checked (((FloatConstant) left).Value /
595 ((FloatConstant) right).Value);
596 else
597 res = unchecked (((FloatConstant) left).Value /
598 ((FloatConstant) right).Value);
600 return new FloatConstant (res, left.Location);
601 } else if (left is ULongConstant){
602 ulong res;
604 if (ec.ConstantCheckState)
605 res = checked (((ULongConstant) left).Value /
606 ((ULongConstant) right).Value);
607 else
608 res = unchecked (((ULongConstant) left).Value /
609 ((ULongConstant) right).Value);
611 return new ULongConstant (res, left.Location);
612 } else if (left is LongConstant){
613 long res;
615 if (ec.ConstantCheckState)
616 res = checked (((LongConstant) left).Value /
617 ((LongConstant) right).Value);
618 else
619 res = unchecked (((LongConstant) left).Value /
620 ((LongConstant) right).Value);
622 return new LongConstant (res, left.Location);
623 } else if (left is UIntConstant){
624 uint res;
626 if (ec.ConstantCheckState)
627 res = checked (((UIntConstant) left).Value /
628 ((UIntConstant) right).Value);
629 else
630 res = unchecked (((UIntConstant) left).Value /
631 ((UIntConstant) right).Value);
633 return new UIntConstant (res, left.Location);
634 } else if (left is IntConstant){
635 int res;
637 if (ec.ConstantCheckState)
638 res = checked (((IntConstant) left).Value /
639 ((IntConstant) right).Value);
640 else
641 res = unchecked (((IntConstant) left).Value /
642 ((IntConstant) right).Value);
644 return new IntConstant (res, left.Location);
645 } else if (left is DecimalConstant) {
646 decimal res;
648 if (ec.ConstantCheckState)
649 res = checked (((DecimalConstant) left).Value /
650 ((DecimalConstant) right).Value);
651 else
652 res = unchecked (((DecimalConstant) left).Value /
653 ((DecimalConstant) right).Value);
655 return new DecimalConstant (res, left.Location);
656 } else {
657 throw new Exception ( "Unexepected division input: " + left);
659 } catch (OverflowException){
660 Error_CompileTimeOverflow (loc);
662 } catch (DivideByZeroException) {
663 Report.Error (020, loc, "Division by constant zero");
666 break;
668 case Binary.Operator.Modulus:
669 DoBinaryNumericPromotions (ref left, ref right);
670 if (left == null || right == null)
671 return null;
673 try {
674 if (left is DoubleConstant){
675 double res;
677 if (ec.ConstantCheckState)
678 res = checked (((DoubleConstant) left).Value %
679 ((DoubleConstant) right).Value);
680 else
681 res = unchecked (((DoubleConstant) left).Value %
682 ((DoubleConstant) right).Value);
684 return new DoubleConstant (res, left.Location);
685 } else if (left is FloatConstant){
686 float res;
688 if (ec.ConstantCheckState)
689 res = checked (((FloatConstant) left).Value %
690 ((FloatConstant) right).Value);
691 else
692 res = unchecked (((FloatConstant) left).Value %
693 ((FloatConstant) right).Value);
695 return new FloatConstant (res, left.Location);
696 } else if (left is ULongConstant){
697 ulong res;
699 if (ec.ConstantCheckState)
700 res = checked (((ULongConstant) left).Value %
701 ((ULongConstant) right).Value);
702 else
703 res = unchecked (((ULongConstant) left).Value %
704 ((ULongConstant) right).Value);
706 return new ULongConstant (res, left.Location);
707 } else if (left is LongConstant){
708 long res;
710 if (ec.ConstantCheckState)
711 res = checked (((LongConstant) left).Value %
712 ((LongConstant) right).Value);
713 else
714 res = unchecked (((LongConstant) left).Value %
715 ((LongConstant) right).Value);
717 return new LongConstant (res, left.Location);
718 } else if (left is UIntConstant){
719 uint res;
721 if (ec.ConstantCheckState)
722 res = checked (((UIntConstant) left).Value %
723 ((UIntConstant) right).Value);
724 else
725 res = unchecked (((UIntConstant) left).Value %
726 ((UIntConstant) right).Value);
728 return new UIntConstant (res, left.Location);
729 } else if (left is IntConstant){
730 int res;
732 if (ec.ConstantCheckState)
733 res = checked (((IntConstant) left).Value %
734 ((IntConstant) right).Value);
735 else
736 res = unchecked (((IntConstant) left).Value %
737 ((IntConstant) right).Value);
739 return new IntConstant (res, left.Location);
740 } else {
741 throw new Exception ( "Unexepected modulus input: " + left);
743 } catch (DivideByZeroException){
744 Report.Error (020, loc, "Division by constant zero");
745 } catch (OverflowException){
746 Error_CompileTimeOverflow (loc);
748 break;
751 // There is no overflow checking on left shift
753 case Binary.Operator.LeftShift:
754 IntConstant ic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
755 if (ic == null){
756 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
757 return null;
760 int lshift_val = ic.Value;
761 if (left.Type == TypeManager.uint64_type)
762 return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
763 if (left.Type == TypeManager.int64_type)
764 return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
765 if (left.Type == TypeManager.uint32_type)
766 return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
768 left = left.ConvertImplicitly (TypeManager.int32_type);
769 if (left.Type == TypeManager.int32_type)
770 return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
772 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
773 break;
776 // There is no overflow checking on right shift
778 case Binary.Operator.RightShift:
779 IntConstant sic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant;
780 if (sic == null){
781 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
782 return null;
784 int rshift_val = sic.Value;
785 if (left.Type == TypeManager.uint64_type)
786 return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
787 if (left.Type == TypeManager.int64_type)
788 return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
789 if (left.Type == TypeManager.uint32_type)
790 return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
792 left = left.ConvertImplicitly (TypeManager.int32_type);
793 if (left.Type == TypeManager.int32_type)
794 return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
796 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
797 break;
799 case Binary.Operator.Equality:
800 if (left is NullConstant){
801 if (right is NullConstant)
802 return new BoolConstant (true, left.Location);
803 else if (right is StringConstant)
804 return new BoolConstant (
805 ((StringConstant) right).Value == null, left.Location);
806 } else if (right is NullConstant){
807 if (left is NullConstant)
808 return new BoolConstant (true, left.Location);
809 else if (left is StringConstant)
810 return new BoolConstant (
811 ((StringConstant) left).Value == null, left.Location);
813 if (left is StringConstant && right is StringConstant){
814 return new BoolConstant (
815 ((StringConstant) left).Value ==
816 ((StringConstant) right).Value, left.Location);
820 DoBinaryNumericPromotions (ref left, ref right);
821 if (left == null || right == null)
822 return null;
824 bool_res = false;
825 if (left is DoubleConstant)
826 bool_res = ((DoubleConstant) left).Value ==
827 ((DoubleConstant) right).Value;
828 else if (left is FloatConstant)
829 bool_res = ((FloatConstant) left).Value ==
830 ((FloatConstant) right).Value;
831 else if (left is ULongConstant)
832 bool_res = ((ULongConstant) left).Value ==
833 ((ULongConstant) right).Value;
834 else if (left is LongConstant)
835 bool_res = ((LongConstant) left).Value ==
836 ((LongConstant) right).Value;
837 else if (left is UIntConstant)
838 bool_res = ((UIntConstant) left).Value ==
839 ((UIntConstant) right).Value;
840 else if (left is IntConstant)
841 bool_res = ((IntConstant) left).Value ==
842 ((IntConstant) right).Value;
843 else
844 return null;
846 return new BoolConstant (bool_res, left.Location);
848 case Binary.Operator.Inequality:
849 if (left is NullConstant){
850 if (right is NullConstant)
851 return new BoolConstant (false, left.Location);
852 else if (right is StringConstant)
853 return new BoolConstant (
854 ((StringConstant) right).Value != null, left.Location);
855 } else if (right is NullConstant){
856 if (left is NullConstant)
857 return new BoolConstant (false, left.Location);
858 else if (left is StringConstant)
859 return new BoolConstant (
860 ((StringConstant) left).Value != null, left.Location);
862 if (left is StringConstant && right is StringConstant){
863 return new BoolConstant (
864 ((StringConstant) left).Value !=
865 ((StringConstant) right).Value, left.Location);
869 DoBinaryNumericPromotions (ref left, ref right);
870 if (left == null || right == null)
871 return null;
873 bool_res = false;
874 if (left is DoubleConstant)
875 bool_res = ((DoubleConstant) left).Value !=
876 ((DoubleConstant) right).Value;
877 else if (left is FloatConstant)
878 bool_res = ((FloatConstant) left).Value !=
879 ((FloatConstant) right).Value;
880 else if (left is ULongConstant)
881 bool_res = ((ULongConstant) left).Value !=
882 ((ULongConstant) right).Value;
883 else if (left is LongConstant)
884 bool_res = ((LongConstant) left).Value !=
885 ((LongConstant) right).Value;
886 else if (left is UIntConstant)
887 bool_res = ((UIntConstant) left).Value !=
888 ((UIntConstant) right).Value;
889 else if (left is IntConstant)
890 bool_res = ((IntConstant) left).Value !=
891 ((IntConstant) right).Value;
892 else
893 return null;
895 return new BoolConstant (bool_res, left.Location);
897 case Binary.Operator.LessThan:
898 DoBinaryNumericPromotions (ref left, ref right);
899 if (left == null || right == null)
900 return null;
902 bool_res = false;
903 if (left is DoubleConstant)
904 bool_res = ((DoubleConstant) left).Value <
905 ((DoubleConstant) right).Value;
906 else if (left is FloatConstant)
907 bool_res = ((FloatConstant) left).Value <
908 ((FloatConstant) right).Value;
909 else if (left is ULongConstant)
910 bool_res = ((ULongConstant) left).Value <
911 ((ULongConstant) right).Value;
912 else if (left is LongConstant)
913 bool_res = ((LongConstant) left).Value <
914 ((LongConstant) right).Value;
915 else if (left is UIntConstant)
916 bool_res = ((UIntConstant) left).Value <
917 ((UIntConstant) right).Value;
918 else if (left is IntConstant)
919 bool_res = ((IntConstant) left).Value <
920 ((IntConstant) right).Value;
921 else
922 return null;
924 return new BoolConstant (bool_res, left.Location);
926 case Binary.Operator.GreaterThan:
927 DoBinaryNumericPromotions (ref left, ref right);
928 if (left == null || right == null)
929 return null;
931 bool_res = false;
932 if (left is DoubleConstant)
933 bool_res = ((DoubleConstant) left).Value >
934 ((DoubleConstant) right).Value;
935 else if (left is FloatConstant)
936 bool_res = ((FloatConstant) left).Value >
937 ((FloatConstant) right).Value;
938 else if (left is ULongConstant)
939 bool_res = ((ULongConstant) left).Value >
940 ((ULongConstant) right).Value;
941 else if (left is LongConstant)
942 bool_res = ((LongConstant) left).Value >
943 ((LongConstant) right).Value;
944 else if (left is UIntConstant)
945 bool_res = ((UIntConstant) left).Value >
946 ((UIntConstant) right).Value;
947 else if (left is IntConstant)
948 bool_res = ((IntConstant) left).Value >
949 ((IntConstant) right).Value;
950 else
951 return null;
953 return new BoolConstant (bool_res, left.Location);
955 case Binary.Operator.GreaterThanOrEqual:
956 DoBinaryNumericPromotions (ref left, ref right);
957 if (left == null || right == null)
958 return null;
960 bool_res = false;
961 if (left is DoubleConstant)
962 bool_res = ((DoubleConstant) left).Value >=
963 ((DoubleConstant) right).Value;
964 else if (left is FloatConstant)
965 bool_res = ((FloatConstant) left).Value >=
966 ((FloatConstant) right).Value;
967 else if (left is ULongConstant)
968 bool_res = ((ULongConstant) left).Value >=
969 ((ULongConstant) right).Value;
970 else if (left is LongConstant)
971 bool_res = ((LongConstant) left).Value >=
972 ((LongConstant) right).Value;
973 else if (left is UIntConstant)
974 bool_res = ((UIntConstant) left).Value >=
975 ((UIntConstant) right).Value;
976 else if (left is IntConstant)
977 bool_res = ((IntConstant) left).Value >=
978 ((IntConstant) right).Value;
979 else
980 return null;
982 return new BoolConstant (bool_res, left.Location);
984 case Binary.Operator.LessThanOrEqual:
985 DoBinaryNumericPromotions (ref left, ref right);
986 if (left == null || right == null)
987 return null;
989 bool_res = false;
990 if (left is DoubleConstant)
991 bool_res = ((DoubleConstant) left).Value <=
992 ((DoubleConstant) right).Value;
993 else if (left is FloatConstant)
994 bool_res = ((FloatConstant) left).Value <=
995 ((FloatConstant) right).Value;
996 else if (left is ULongConstant)
997 bool_res = ((ULongConstant) left).Value <=
998 ((ULongConstant) right).Value;
999 else if (left is LongConstant)
1000 bool_res = ((LongConstant) left).Value <=
1001 ((LongConstant) right).Value;
1002 else if (left is UIntConstant)
1003 bool_res = ((UIntConstant) left).Value <=
1004 ((UIntConstant) right).Value;
1005 else if (left is IntConstant)
1006 bool_res = ((IntConstant) left).Value <=
1007 ((IntConstant) right).Value;
1008 else
1009 return null;
1011 return new BoolConstant (bool_res, left.Location);
1014 return null;