Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / mcs / cfold.cs
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-2011, Novell, Inc.
10 // 
11 using System;
12
13 namespace Mono.CSharp {
14
15         public static class ConstantFold
16         {
17                 public static TypeSpec[] CreateBinaryPromotionsTypes (BuiltinTypes types)
18                 {
19                         return new TypeSpec[] { 
20                                 types.Decimal, types.Double, types.Float,
21                                 types.ULong, types.Long, types.UInt
22                         };
23                 }
24
25                 //
26                 // Performs the numeric promotions on the left and right expresions
27                 // and deposits the results on `lc' and `rc'.
28                 //
29                 // On success, the types of `lc' and `rc' on output will always match,
30                 // and the pair will be one of:
31                 //
32                 // TODO: BinaryFold should be called as an optimization step only,
33                 // error checking here is weak
34                 //              
35                 static bool DoBinaryNumericPromotions (ResolveContext rc, ref Constant left, ref Constant right)
36                 {
37                         TypeSpec ltype = left.Type;
38                         TypeSpec rtype = right.Type;
39
40                         foreach (TypeSpec t in rc.BuiltinTypes.BinaryPromotionsTypes) {
41                                 if (t == ltype)
42                                         return t == rtype || ConvertPromotion (rc, ref right, ref left, t);
43
44                                 if (t == rtype)
45                                         return t == ltype || ConvertPromotion (rc, ref left, ref right, t);
46                         }
47
48                         left = left.ConvertImplicitly (rc.BuiltinTypes.Int);
49                         right = right.ConvertImplicitly (rc.BuiltinTypes.Int);
50                         return left != null && right != null;
51                 }
52
53                 static bool ConvertPromotion (ResolveContext rc, ref Constant prim, ref Constant second, TypeSpec type)
54                 {
55                         Constant c = prim.ConvertImplicitly (type);
56                         if (c != null) {
57                                 prim = c;
58                                 return true;
59                         }
60
61                         if (type.BuiltinType == BuiltinTypeSpec.Type.UInt) {
62                                 type = rc.BuiltinTypes.Long;
63                                 prim = prim.ConvertImplicitly (type);
64                                 second = second.ConvertImplicitly (type);
65                                 return prim != null && second != null;
66                         }
67
68                         return false;
69                 }
70
71                 internal static void Error_CompileTimeOverflow (ResolveContext rc, Location loc)
72                 {
73                         rc.Report.Error (220, loc, "The operation overflows at compile time in checked mode");
74                 }
75                 
76                 /// <summary>
77                 ///   Constant expression folder for binary operations.
78                 ///
79                 ///   Returns null if the expression can not be folded.
80                 /// </summary>
81                 static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper,
82                                                      Constant left, Constant right, Location loc)
83                 {
84                         Constant result = null;
85
86                         if (left is EmptyConstantCast)
87                                 return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
88
89                         if (left is SideEffectConstant) {
90                                 result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc);
91                                 if (result == null)
92                                         return null;
93                                 return new SideEffectConstant (result, left, loc);
94                         }
95
96                         if (right is EmptyConstantCast)
97                                 return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
98
99                         if (right is SideEffectConstant) {
100                                 result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc);
101                                 if (result == null)
102                                         return null;
103                                 return new SideEffectConstant (result, right, loc);
104                         }
105
106                         TypeSpec lt = left.Type;
107                         TypeSpec rt = right.Type;
108                         bool bool_res;
109
110                         if (lt.BuiltinType == BuiltinTypeSpec.Type.Bool && lt == rt) {
111                                 bool lv = (bool) left.GetValue ();
112                                 bool rv = (bool) right.GetValue ();                     
113                                 switch (oper) {
114                                 case Binary.Operator.BitwiseAnd:
115                                 case Binary.Operator.LogicalAnd:
116                                         return new BoolConstant (ec.BuiltinTypes, lv && rv, left.Location);
117                                 case Binary.Operator.BitwiseOr:
118                                 case Binary.Operator.LogicalOr:
119                                         return new BoolConstant (ec.BuiltinTypes, lv || rv, left.Location);
120                                 case Binary.Operator.ExclusiveOr:
121                                         return new BoolConstant (ec.BuiltinTypes, lv ^ rv, left.Location);
122                                 case Binary.Operator.Equality:
123                                         return new BoolConstant (ec.BuiltinTypes, lv == rv, left.Location);
124                                 case Binary.Operator.Inequality:
125                                         return new BoolConstant (ec.BuiltinTypes, lv != rv, left.Location);
126                                 }
127                                 return null;
128                         }
129
130                         //
131                         // During an enum evaluation, none of the rules are valid
132                         // Not sure whether it is bug in csc or in documentation
133                         //
134                         if (ec.HasSet (ResolveContext.Options.EnumScope)){
135                                 if (left is EnumConstant)
136                                         left = ((EnumConstant) left).Child;
137                                 
138                                 if (right is EnumConstant)
139                                         right = ((EnumConstant) right).Child;
140                         } else if (left is EnumConstant && rt == lt) {
141                                 switch (oper){
142                                         ///
143                                         /// E operator |(E x, E y);
144                                         /// E operator &(E x, E y);
145                                         /// E operator ^(E x, E y);
146                                         /// 
147                                         case Binary.Operator.BitwiseOr:
148                                         case Binary.Operator.BitwiseAnd:
149                                         case Binary.Operator.ExclusiveOr:
150                                                 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
151                                                 if (result != null)
152                                                         result = result.Reduce (ec, lt);
153                                                 return result;
154
155                                         ///
156                                         /// U operator -(E x, E y);
157                                         /// 
158                                         case Binary.Operator.Subtraction:
159                                                 result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
160                                                 if (result != null)
161                                                         result = result.Reduce (ec, EnumSpec.GetUnderlyingType (lt));
162                                                 return result;
163
164                                         ///
165                                         /// bool operator ==(E x, E y);
166                                         /// bool operator !=(E x, E y);
167                                         /// bool operator <(E x, E y);
168                                         /// bool operator >(E x, E y);
169                                         /// bool operator <=(E x, E y);
170                                         /// bool operator >=(E x, E y);
171                                         /// 
172                                         case Binary.Operator.Equality:                          
173                                         case Binary.Operator.Inequality:
174                                         case Binary.Operator.LessThan:                          
175                                         case Binary.Operator.GreaterThan:
176                                         case Binary.Operator.LessThanOrEqual:                           
177                                         case Binary.Operator.GreaterThanOrEqual:
178                                                 return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
179                                 }
180                                 return null;
181                         }
182
183                         switch (oper){
184                         case Binary.Operator.BitwiseOr:
185                                 //
186                                 // bool? operator |(bool? x, bool? y);
187                                 //
188                                 if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) ||
189                                         (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) {
190                                         var b = new Binary (oper, left, right).ResolveOperator (ec);
191
192                                         // false | null => null
193                                         // null | false => null
194                                         if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue))
195                                                 return Nullable.LiftedNull.CreateFromExpression (ec, b);
196
197                                         // true | null => true
198                                         // null | true => true
199                                         return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, true, loc), b);                                     
200                                 }
201
202                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
203                                         return null;
204
205                                 if (left is IntConstant){
206                                         int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
207
208                                         return new IntConstant (ec.BuiltinTypes, res, left.Location);
209                                 }
210                                 if (left is UIntConstant){
211                                         uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
212
213                                         return new UIntConstant (ec.BuiltinTypes, res, left.Location);
214                                 }
215                                 if (left is LongConstant){
216                                         long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
217
218                                         return new LongConstant (ec.BuiltinTypes, res, left.Location);
219                                 }
220                                 if (left is ULongConstant){
221                                         ulong res = ((ULongConstant)left).Value |
222                                                 ((ULongConstant)right).Value;
223
224                                         return new ULongConstant (ec.BuiltinTypes, res, left.Location);
225                                 }
226                                 break;
227                                 
228                         case Binary.Operator.BitwiseAnd:
229                                 //
230                                 // bool? operator &(bool? x, bool? y);
231                                 //
232                                 if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) ||
233                                         (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) {
234                                         var b = new Binary (oper, left, right).ResolveOperator (ec);
235
236                                         // false & null => false
237                                         // null & false => false
238                                         if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue))
239                                                 return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, false, loc), b);
240
241                                         // true & null => null
242                                         // null & true => null
243                                         return Nullable.LiftedNull.CreateFromExpression (ec, b);
244                                 }
245
246                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
247                                         return null;
248                                 
249                                 ///
250                                 /// int operator &(int x, int y);
251                                 /// uint operator &(uint x, uint y);
252                                 /// long operator &(long x, long y);
253                                 /// ulong operator &(ulong x, ulong y);
254                                 ///
255                                 if (left is IntConstant){
256                                         int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
257                                         return new IntConstant (ec.BuiltinTypes, res, left.Location);
258                                 }
259                                 if (left is UIntConstant){
260                                         uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
261                                         return new UIntConstant (ec.BuiltinTypes, res, left.Location);
262                                 }
263                                 if (left is LongConstant){
264                                         long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
265                                         return new LongConstant (ec.BuiltinTypes, res, left.Location);
266                                 }
267                                 if (left is ULongConstant){
268                                         ulong res = ((ULongConstant)left).Value &
269                                                 ((ULongConstant)right).Value;
270
271                                         return new ULongConstant (ec.BuiltinTypes, res, left.Location);
272                                 }
273                                 break;
274
275                         case Binary.Operator.ExclusiveOr:
276                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
277                                         return null;
278                                 
279                                 if (left is IntConstant){
280                                         int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
281                                         return new IntConstant (ec.BuiltinTypes, res, left.Location);
282                                 }
283                                 if (left is UIntConstant){
284                                         uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
285
286                                         return new UIntConstant (ec.BuiltinTypes, res, left.Location);
287                                 }
288                                 if (left is LongConstant){
289                                         long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
290
291                                         return new LongConstant (ec.BuiltinTypes, res, left.Location);
292                                 }
293                                 if (left is ULongConstant){
294                                         ulong res = ((ULongConstant)left).Value ^
295                                                 ((ULongConstant)right).Value;
296
297                                         return new ULongConstant (ec.BuiltinTypes, res, left.Location);
298                                 }
299                                 break;
300
301                         case Binary.Operator.Addition:
302                                 //
303                                 // If both sides are strings, then concatenate
304                                 //
305                                 // string operator + (string x, string y)
306                                 //
307                                 if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){
308                                         if (lt == rt)
309                                                 return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (),
310                                                         left.Location);
311
312                                         if (lt == InternalType.NullLiteral || left.IsNull)
313                                                 return new StringConstant (ec.BuiltinTypes, "" + right.GetValue (), left.Location);
314
315                                         if (rt == InternalType.NullLiteral || right.IsNull)
316                                                 return new StringConstant (ec.BuiltinTypes, left.GetValue () + "", left.Location);
317
318                                         return null;
319                                 }
320
321                                 //
322                                 // string operator + (string x, object y)
323                                 //
324                                 if (lt == InternalType.NullLiteral) {
325                                         if (rt.BuiltinType == BuiltinTypeSpec.Type.Object)
326                                                 return new StringConstant (ec.BuiltinTypes, "" + right.GetValue (), left.Location);
327
328                                         if (lt == rt) {
329                                                 ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'",
330                                                         "+", lt.GetSignatureForError (), rt.GetSignatureForError ());
331                                                 return null;
332                                         }
333
334                                         return right;
335                                 }
336
337                                 //
338                                 // string operator + (object x, string y)
339                                 //
340                                 if (rt == InternalType.NullLiteral) {
341                                         if (lt.BuiltinType == BuiltinTypeSpec.Type.Object)
342                                                 return new StringConstant (ec.BuiltinTypes, right.GetValue () + "", left.Location);
343         
344                                         return left;
345                                 }
346
347                                 //
348                                 // handle "E operator + (E x, U y)"
349                                 // handle "E operator + (Y y, E x)"
350                                 //
351                                 EnumConstant lc = left as EnumConstant;
352                                 EnumConstant rc = right as EnumConstant;
353                                 if (lc != null || rc != null){
354                                         if (lc == null) {
355                                                 lc = rc;
356                                                 lt = lc.Type;
357                                                 right = left;
358                                         }
359
360                                         // U has to be implicitly convetible to E.base
361                                         right = right.ConvertImplicitly (lc.Child.Type);
362                                         if (right == null)
363                                                 return null;
364
365                                         result = BinaryFold (ec, oper, lc.Child, right, loc);
366                                         if (result == null)
367                                                 return null;
368
369                                         result = result.Reduce (ec, lt);
370                                         if (result == null || lt.IsEnum)
371                                                 return result;
372
373                                         return new EnumConstant (result, lt);
374                                 }
375
376                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
377                                         return null;
378
379                                 try {
380                                         if (left is DoubleConstant){
381                                                 double res;
382                                                 
383                                                 if (ec.ConstantCheckState)
384                                                         res = checked (((DoubleConstant) left).Value +
385                                                                        ((DoubleConstant) right).Value);
386                                                 else
387                                                         res = unchecked (((DoubleConstant) left).Value +
388                                                                          ((DoubleConstant) right).Value);
389
390                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
391                                         }
392                                         if (left is FloatConstant){
393                                                 double a, b, res;
394                                                 a = ((FloatConstant) left).DoubleValue;
395                                                 b = ((FloatConstant) right).DoubleValue;
396
397                                                 if (ec.ConstantCheckState)
398                                                         res = checked (a + b);
399                                                 else
400                                                         res = unchecked (a + b);
401
402                                                 result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
403                                         } else if (left is ULongConstant){
404                                                 ulong res;
405                                                 
406                                                 if (ec.ConstantCheckState)
407                                                         res = checked (((ULongConstant) left).Value +
408                                                                        ((ULongConstant) right).Value);
409                                                 else
410                                                         res = unchecked (((ULongConstant) left).Value +
411                                                                          ((ULongConstant) right).Value);
412
413                                                 result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
414                                         } else if (left is LongConstant){
415                                                 long res;
416                                                 
417                                                 if (ec.ConstantCheckState)
418                                                         res = checked (((LongConstant) left).Value +
419                                                                        ((LongConstant) right).Value);
420                                                 else
421                                                         res = unchecked (((LongConstant) left).Value +
422                                                                          ((LongConstant) right).Value);
423
424                                                 result = new LongConstant (ec.BuiltinTypes, res, left.Location);
425                                         } else if (left is UIntConstant){
426                                                 uint res;
427                                                 
428                                                 if (ec.ConstantCheckState)
429                                                         res = checked (((UIntConstant) left).Value +
430                                                                        ((UIntConstant) right).Value);
431                                                 else
432                                                         res = unchecked (((UIntConstant) left).Value +
433                                                                          ((UIntConstant) right).Value);
434
435                                                 result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
436                                         } else if (left is IntConstant){
437                                                 int res;
438
439                                                 if (ec.ConstantCheckState)
440                                                         res = checked (((IntConstant) left).Value +
441                                                                        ((IntConstant) right).Value);
442                                                 else
443                                                         res = unchecked (((IntConstant) left).Value +
444                                                                          ((IntConstant) right).Value);
445
446                                                 result = new IntConstant (ec.BuiltinTypes, res, left.Location);
447                                         } else if (left is DecimalConstant) {
448                                                 decimal res;
449
450                                                 if (ec.ConstantCheckState)
451                                                         res = checked (((DecimalConstant) left).Value +
452                                                                 ((DecimalConstant) right).Value);
453                                                 else
454                                                         res = unchecked (((DecimalConstant) left).Value +
455                                                                 ((DecimalConstant) right).Value);
456
457                                                 result = new DecimalConstant (ec.BuiltinTypes, res, left.Location);
458                                         }
459                                 } catch (OverflowException){
460                                         Error_CompileTimeOverflow (ec, loc);
461                                 }
462
463                                 return result;
464
465                         case Binary.Operator.Subtraction:
466                                 //
467                                 // handle "E operator - (E x, U y)"
468                                 // handle "E operator - (Y y, E x)"
469                                 //
470                                 lc = left as EnumConstant;
471                                 rc = right as EnumConstant;
472                                 if (lc != null || rc != null) {
473                                         TypeSpec res_type;
474                                         if (lc == null) {
475                                                 res_type = right.Type;
476
477                                                 // Y has to be implicitly convertible to E.base
478                                                 left = left.ConvertImplicitly (rc.Child.Type);
479                                                 if (left == null)
480                                                         return null;
481
482                                                 right = rc.Child;
483                                         } else {
484                                                 res_type = left.Type;
485
486                                                 // U has to be implicitly convertible to E.base
487                                                 right = right.ConvertImplicitly (lc.Child.Type);
488                                                 if (right == null)
489                                                         return null;
490
491                                                 left = lc.Child;
492                                         }
493
494                                         result = BinaryFold (ec, oper, left, right, loc);
495                                         if (result == null)
496                                                 return null;
497
498                                         result = result.Reduce (ec, res_type);
499                                         if (result == null)
500                                                 return null;
501
502                                         return new EnumConstant (result, res_type);
503                                 }
504
505                                 if (left is NullLiteral && right is NullLiteral) {
506                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
507                                         lifted_int.ResolveAsType (ec);
508                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
509                                 }
510
511                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
512                                         return null;
513
514                                 try {
515                                         if (left is DoubleConstant){
516                                                 double res;
517                                                 
518                                                 if (ec.ConstantCheckState)
519                                                         res = checked (((DoubleConstant) left).Value -
520                                                                        ((DoubleConstant) right).Value);
521                                                 else
522                                                         res = unchecked (((DoubleConstant) left).Value -
523                                                                          ((DoubleConstant) right).Value);
524
525                                                 result = new DoubleConstant (ec.BuiltinTypes, res, left.Location);
526                                         } else if (left is FloatConstant){
527                                                 double a, b, res;
528                                                 a = ((FloatConstant) left).DoubleValue;
529                                                 b = ((FloatConstant) right).DoubleValue;
530
531                                                 if (ec.ConstantCheckState)
532                                                         res = checked (a - b);
533                                                 else
534                                                         res = unchecked (a - b);
535
536                                                 result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
537                                         } else if (left is ULongConstant){
538                                                 ulong res;
539                                                 
540                                                 if (ec.ConstantCheckState)
541                                                         res = checked (((ULongConstant) left).Value -
542                                                                        ((ULongConstant) right).Value);
543                                                 else
544                                                         res = unchecked (((ULongConstant) left).Value -
545                                                                          ((ULongConstant) right).Value);
546
547                                                 result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
548                                         } else if (left is LongConstant){
549                                                 long res;
550                                                 
551                                                 if (ec.ConstantCheckState)
552                                                         res = checked (((LongConstant) left).Value -
553                                                                        ((LongConstant) right).Value);
554                                                 else
555                                                         res = unchecked (((LongConstant) left).Value -
556                                                                          ((LongConstant) right).Value);
557
558                                                 result = new LongConstant (ec.BuiltinTypes, res, left.Location);
559                                         } else if (left is UIntConstant){
560                                                 uint res;
561                                                 
562                                                 if (ec.ConstantCheckState)
563                                                         res = checked (((UIntConstant) left).Value -
564                                                                        ((UIntConstant) right).Value);
565                                                 else
566                                                         res = unchecked (((UIntConstant) left).Value -
567                                                                          ((UIntConstant) right).Value);
568
569                                                 result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
570                                         } else if (left is IntConstant){
571                                                 int res;
572
573                                                 if (ec.ConstantCheckState)
574                                                         res = checked (((IntConstant) left).Value -
575                                                                        ((IntConstant) right).Value);
576                                                 else
577                                                         res = unchecked (((IntConstant) left).Value -
578                                                                          ((IntConstant) right).Value);
579
580                                                 result = new IntConstant (ec.BuiltinTypes, res, left.Location);
581                                         } else if (left is DecimalConstant) {
582                                                 decimal res;
583
584                                                 if (ec.ConstantCheckState)
585                                                         res = checked (((DecimalConstant) left).Value -
586                                                                 ((DecimalConstant) right).Value);
587                                                 else
588                                                         res = unchecked (((DecimalConstant) left).Value -
589                                                                 ((DecimalConstant) right).Value);
590
591                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
592                                         } else {
593                                                 throw new Exception ( "Unexepected subtraction input: " + left);
594                                         }
595                                 } catch (OverflowException){
596                                         Error_CompileTimeOverflow (ec, loc);
597                                 }
598
599                                 return result;
600                                 
601                         case Binary.Operator.Multiply:
602                                 if (left is NullLiteral && right is NullLiteral) {
603                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
604                                         lifted_int.ResolveAsType (ec);
605                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
606                                 }
607
608                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
609                                         return null;
610
611                                 try {
612                                         if (left is DoubleConstant){
613                                                 double res;
614                                                 
615                                                 if (ec.ConstantCheckState)
616                                                         res = checked (((DoubleConstant) left).Value *
617                                                                 ((DoubleConstant) right).Value);
618                                                 else
619                                                         res = unchecked (((DoubleConstant) left).Value *
620                                                                 ((DoubleConstant) right).Value);
621
622                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
623                                         } else if (left is FloatConstant){
624                                                 double a, b, res;
625                                                 a = ((FloatConstant) left).DoubleValue;
626                                                 b = ((FloatConstant) right).DoubleValue;
627
628                                                 if (ec.ConstantCheckState)
629                                                         res = checked (a * b);
630                                                 else
631                                                         res = unchecked (a * b);
632
633                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
634                                         } else if (left is ULongConstant){
635                                                 ulong res;
636                                                 
637                                                 if (ec.ConstantCheckState)
638                                                         res = checked (((ULongConstant) left).Value *
639                                                                 ((ULongConstant) right).Value);
640                                                 else
641                                                         res = unchecked (((ULongConstant) left).Value *
642                                                                 ((ULongConstant) right).Value);
643
644                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
645                                         } else if (left is LongConstant){
646                                                 long res;
647                                                 
648                                                 if (ec.ConstantCheckState)
649                                                         res = checked (((LongConstant) left).Value *
650                                                                 ((LongConstant) right).Value);
651                                                 else
652                                                         res = unchecked (((LongConstant) left).Value *
653                                                                 ((LongConstant) right).Value);
654
655                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
656                                         } else if (left is UIntConstant){
657                                                 uint res;
658                                                 
659                                                 if (ec.ConstantCheckState)
660                                                         res = checked (((UIntConstant) left).Value *
661                                                                 ((UIntConstant) right).Value);
662                                                 else
663                                                         res = unchecked (((UIntConstant) left).Value *
664                                                                 ((UIntConstant) right).Value);
665
666                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
667                                         } else if (left is IntConstant){
668                                                 int res;
669
670                                                 if (ec.ConstantCheckState)
671                                                         res = checked (((IntConstant) left).Value *
672                                                                 ((IntConstant) right).Value);
673                                                 else
674                                                         res = unchecked (((IntConstant) left).Value *
675                                                                 ((IntConstant) right).Value);
676
677                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
678                                         } else if (left is DecimalConstant) {
679                                                 decimal res;
680
681                                                 if (ec.ConstantCheckState)
682                                                         res = checked (((DecimalConstant) left).Value *
683                                                                 ((DecimalConstant) right).Value);
684                                                 else
685                                                         res = unchecked (((DecimalConstant) left).Value *
686                                                                 ((DecimalConstant) right).Value);
687
688                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
689                                         } else {
690                                                 throw new Exception ( "Unexepected multiply input: " + left);
691                                         }
692                                 } catch (OverflowException){
693                                         Error_CompileTimeOverflow (ec, loc);
694                                 }
695                                 break;
696
697                         case Binary.Operator.Division:
698                                 if (left is NullLiteral && right is NullLiteral) {
699                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
700                                         lifted_int.ResolveAsType (ec);
701                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
702                                 }
703
704                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
705                                         return null;
706
707                                 try {
708                                         if (left is DoubleConstant){
709                                                 double res;
710                                                 
711                                                 if (ec.ConstantCheckState)
712                                                         res = checked (((DoubleConstant) left).Value /
713                                                                 ((DoubleConstant) right).Value);
714                                                 else
715                                                         res = unchecked (((DoubleConstant) left).Value /
716                                                                 ((DoubleConstant) right).Value);
717
718                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
719                                         } else if (left is FloatConstant){
720                                                 double a, b, res;
721                                                 a = ((FloatConstant) left).DoubleValue;
722                                                 b = ((FloatConstant) right).DoubleValue;
723
724                                                 if (ec.ConstantCheckState)
725                                                         res = checked (a / b);
726                                                 else
727                                                         res = unchecked (a / b);
728
729                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
730                                         } else if (left is ULongConstant){
731                                                 ulong res;
732                                                 
733                                                 if (ec.ConstantCheckState)
734                                                         res = checked (((ULongConstant) left).Value /
735                                                                 ((ULongConstant) right).Value);
736                                                 else
737                                                         res = unchecked (((ULongConstant) left).Value /
738                                                                 ((ULongConstant) right).Value);
739
740                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
741                                         } else if (left is LongConstant){
742                                                 long res;
743                                                 
744                                                 if (ec.ConstantCheckState)
745                                                         res = checked (((LongConstant) left).Value /
746                                                                 ((LongConstant) right).Value);
747                                                 else
748                                                         res = unchecked (((LongConstant) left).Value /
749                                                                 ((LongConstant) right).Value);
750
751                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
752                                         } else if (left is UIntConstant){
753                                                 uint res;
754                                                 
755                                                 if (ec.ConstantCheckState)
756                                                         res = checked (((UIntConstant) left).Value /
757                                                                 ((UIntConstant) right).Value);
758                                                 else
759                                                         res = unchecked (((UIntConstant) left).Value /
760                                                                 ((UIntConstant) right).Value);
761
762                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
763                                         } else if (left is IntConstant){
764                                                 int res;
765
766                                                 if (ec.ConstantCheckState)
767                                                         res = checked (((IntConstant) left).Value /
768                                                                 ((IntConstant) right).Value);
769                                                 else
770                                                         res = unchecked (((IntConstant) left).Value /
771                                                                 ((IntConstant) right).Value);
772
773                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
774                                         } else if (left is DecimalConstant) {
775                                                 decimal res;
776
777                                                 if (ec.ConstantCheckState)
778                                                         res = checked (((DecimalConstant) left).Value /
779                                                                 ((DecimalConstant) right).Value);
780                                                 else
781                                                         res = unchecked (((DecimalConstant) left).Value /
782                                                                 ((DecimalConstant) right).Value);
783
784                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
785                                         } else {
786                                                 throw new Exception ( "Unexepected division input: " + left);
787                                         }
788                                 } catch (OverflowException){
789                                         Error_CompileTimeOverflow (ec, loc);
790
791                                 } catch (DivideByZeroException) {
792                                         ec.Report.Error (20, loc, "Division by constant zero");
793                                 }
794                                 
795                                 break;
796                                 
797                         case Binary.Operator.Modulus:
798                                 if (left is NullLiteral && right is NullLiteral) {
799                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
800                                         lifted_int.ResolveAsType (ec);
801                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
802                                 }
803
804                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
805                                         return null;
806
807                                 try {
808                                         if (left is DoubleConstant){
809                                                 double res;
810                                                 
811                                                 if (ec.ConstantCheckState)
812                                                         res = checked (((DoubleConstant) left).Value %
813                                                                        ((DoubleConstant) right).Value);
814                                                 else
815                                                         res = unchecked (((DoubleConstant) left).Value %
816                                                                          ((DoubleConstant) right).Value);
817
818                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
819                                         } else if (left is FloatConstant){
820                                                 double a, b, res;
821                                                 a = ((FloatConstant) left).DoubleValue;
822                                                 b = ((FloatConstant) right).DoubleValue;
823                                                 
824                                                 if (ec.ConstantCheckState)
825                                                         res = checked (a % b);
826                                                 else
827                                                         res = unchecked (a % b);
828
829                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
830                                         } else if (left is ULongConstant){
831                                                 ulong res;
832                                                 
833                                                 if (ec.ConstantCheckState)
834                                                         res = checked (((ULongConstant) left).Value %
835                                                                        ((ULongConstant) right).Value);
836                                                 else
837                                                         res = unchecked (((ULongConstant) left).Value %
838                                                                          ((ULongConstant) right).Value);
839
840                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
841                                         } else if (left is LongConstant){
842                                                 long res;
843                                                 
844                                                 if (ec.ConstantCheckState)
845                                                         res = checked (((LongConstant) left).Value %
846                                                                        ((LongConstant) right).Value);
847                                                 else
848                                                         res = unchecked (((LongConstant) left).Value %
849                                                                          ((LongConstant) right).Value);
850
851                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
852                                         } else if (left is UIntConstant){
853                                                 uint res;
854                                                 
855                                                 if (ec.ConstantCheckState)
856                                                         res = checked (((UIntConstant) left).Value %
857                                                                        ((UIntConstant) right).Value);
858                                                 else
859                                                         res = unchecked (((UIntConstant) left).Value %
860                                                                          ((UIntConstant) right).Value);
861
862                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
863                                         } else if (left is IntConstant){
864                                                 int res;
865
866                                                 if (ec.ConstantCheckState)
867                                                         res = checked (((IntConstant) left).Value %
868                                                                        ((IntConstant) right).Value);
869                                                 else
870                                                         res = unchecked (((IntConstant) left).Value %
871                                                                          ((IntConstant) right).Value);
872
873                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
874                                         }
875
876                                         if (left is DecimalConstant) {
877                                                 decimal res;
878
879                                                 if (ec.ConstantCheckState)
880                                                         res = checked (((DecimalConstant) left).Value %
881                                                                 ((DecimalConstant) right).Value);
882                                                 else
883                                                         res = unchecked (((DecimalConstant) left).Value %
884                                                                 ((DecimalConstant) right).Value);
885
886                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
887                                         }
888
889                                         throw new Exception ( "Unexepected modulus input: " + left);
890                                 } catch (DivideByZeroException){
891                                         ec.Report.Error (20, loc, "Division by constant zero");
892                                 } catch (OverflowException){
893                                         Error_CompileTimeOverflow (ec, loc);
894                                 }
895                                 break;
896
897                                 //
898                                 // There is no overflow checking on left shift
899                                 //
900                         case Binary.Operator.LeftShift:
901                                 if (left is NullLiteral && right is NullLiteral) {
902                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
903                                         lifted_int.ResolveAsType (ec);
904                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
905                                 }
906
907                                 IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
908                                 if (ic == null){
909                                         return null;
910                                 }
911
912                                 int lshift_val = ic.Value;
913                                 switch (left.Type.BuiltinType) {
914                                 case BuiltinTypeSpec.Type.ULong:
915                                         return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location);
916                                 case BuiltinTypeSpec.Type.Long:
917                                         return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location);
918                                 case BuiltinTypeSpec.Type.UInt:
919                                         return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location);
920                                 }
921
922                                 // null << value => null
923                                 if (left is NullLiteral)
924                                         return (Constant) new Binary (oper, left, right).ResolveOperator (ec);
925
926                                 left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
927                                 if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
928                                         return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location);
929
930                                 return null;
931
932                                 //
933                                 // There is no overflow checking on right shift
934                                 //
935                         case Binary.Operator.RightShift:
936                                 if (left is NullLiteral && right is NullLiteral) {
937                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
938                                         lifted_int.ResolveAsType (ec);
939                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
940                                 }
941
942                                 IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
943                                 if (sic == null){
944                                         return null;
945                                 }
946                                 int rshift_val = sic.Value;
947                                 switch (left.Type.BuiltinType) {
948                                 case BuiltinTypeSpec.Type.ULong:
949                                         return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location);
950                                 case BuiltinTypeSpec.Type.Long:
951                                         return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location);
952                                 case BuiltinTypeSpec.Type.UInt:
953                                         return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location);
954                                 }
955
956                                 // null >> value => null
957                                 if (left is NullLiteral)
958                                         return (Constant) new Binary (oper, left, right).ResolveOperator (ec);
959
960                                 left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
961                                 if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
962                                         return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location);
963
964                                 return null;
965
966                         case Binary.Operator.Equality:
967                                 if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
968                                         (left is Nullable.LiftedNull && right.IsNull) ||
969                                         (right is Nullable.LiftedNull && left.IsNull)) {
970                                         if (left.IsNull || right.IsNull) {
971                                                 return ReducedExpression.Create (
972                                                         new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location),
973                                                         new Binary (oper, left, right));
974                                         }
975
976                                         if (left is StringConstant && right is StringConstant)
977                                                 return new BoolConstant (ec.BuiltinTypes,
978                                                         ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
979
980                                         return null;
981                                 }
982
983                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
984                                         return null;
985
986                                 bool_res = false;
987                                 if (left is DoubleConstant)
988                                         bool_res = ((DoubleConstant) left).Value ==
989                                                 ((DoubleConstant) right).Value;
990                                 else if (left is FloatConstant)
991                                         bool_res = ((FloatConstant) left).DoubleValue ==
992                                                 ((FloatConstant) right).DoubleValue;
993                                 else if (left is ULongConstant)
994                                         bool_res = ((ULongConstant) left).Value ==
995                                                 ((ULongConstant) right).Value;
996                                 else if (left is LongConstant)
997                                         bool_res = ((LongConstant) left).Value ==
998                                                 ((LongConstant) right).Value;
999                                 else if (left is UIntConstant)
1000                                         bool_res = ((UIntConstant) left).Value ==
1001                                                 ((UIntConstant) right).Value;
1002                                 else if (left is IntConstant)
1003                                         bool_res = ((IntConstant) left).Value ==
1004                                                 ((IntConstant) right).Value;
1005                                 else
1006                                         return null;
1007
1008                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1009
1010                         case Binary.Operator.Inequality:
1011                                 if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
1012                                         (left is Nullable.LiftedNull && right.IsNull) ||
1013                                         (right is Nullable.LiftedNull && left.IsNull)) {
1014                                         if (left.IsNull || right.IsNull) {
1015                                                 return ReducedExpression.Create (
1016                                                         new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location),
1017                                                         new Binary (oper, left, right));
1018                                         }
1019
1020                                         if (left is StringConstant && right is StringConstant)
1021                                                 return new BoolConstant (ec.BuiltinTypes,
1022                                                         ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
1023
1024                                         return null;
1025                                 }
1026
1027                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1028                                         return null;
1029
1030                                 bool_res = false;
1031                                 if (left is DoubleConstant)
1032                                         bool_res = ((DoubleConstant) left).Value !=
1033                                                 ((DoubleConstant) right).Value;
1034                                 else if (left is FloatConstant)
1035                                         bool_res = ((FloatConstant) left).DoubleValue !=
1036                                                 ((FloatConstant) right).DoubleValue;
1037                                 else if (left is ULongConstant)
1038                                         bool_res = ((ULongConstant) left).Value !=
1039                                                 ((ULongConstant) right).Value;
1040                                 else if (left is LongConstant)
1041                                         bool_res = ((LongConstant) left).Value !=
1042                                                 ((LongConstant) right).Value;
1043                                 else if (left is UIntConstant)
1044                                         bool_res = ((UIntConstant) left).Value !=
1045                                                 ((UIntConstant) right).Value;
1046                                 else if (left is IntConstant)
1047                                         bool_res = ((IntConstant) left).Value !=
1048                                                 ((IntConstant) right).Value;
1049                                 else
1050                                         return null;
1051
1052                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1053
1054                         case Binary.Operator.LessThan:
1055                                 if (right is NullLiteral) {
1056                                         if (left is NullLiteral) {
1057                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1058                                                 lifted_int.ResolveAsType (ec);
1059                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1060                                         }
1061                                 }
1062
1063                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1064                                         return null;
1065
1066                                 bool_res = false;
1067                                 if (left is DoubleConstant)
1068                                         bool_res = ((DoubleConstant) left).Value <
1069                                                 ((DoubleConstant) right).Value;
1070                                 else if (left is FloatConstant)
1071                                         bool_res = ((FloatConstant) left).DoubleValue <
1072                                                 ((FloatConstant) right).DoubleValue;
1073                                 else if (left is ULongConstant)
1074                                         bool_res = ((ULongConstant) left).Value <
1075                                                 ((ULongConstant) right).Value;
1076                                 else if (left is LongConstant)
1077                                         bool_res = ((LongConstant) left).Value <
1078                                                 ((LongConstant) right).Value;
1079                                 else if (left is UIntConstant)
1080                                         bool_res = ((UIntConstant) left).Value <
1081                                                 ((UIntConstant) right).Value;
1082                                 else if (left is IntConstant)
1083                                         bool_res = ((IntConstant) left).Value <
1084                                                 ((IntConstant) right).Value;
1085                                 else
1086                                         return null;
1087
1088                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1089                                 
1090                         case Binary.Operator.GreaterThan:
1091                                 if (right is NullLiteral) {
1092                                         if (left is NullLiteral) {
1093                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1094                                                 lifted_int.ResolveAsType (ec);
1095                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1096                                         }
1097                                 }
1098
1099                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1100                                         return null;
1101
1102                                 bool_res = false;
1103                                 if (left is DoubleConstant)
1104                                         bool_res = ((DoubleConstant) left).Value >
1105                                                 ((DoubleConstant) right).Value;
1106                                 else if (left is FloatConstant)
1107                                         bool_res = ((FloatConstant) left).DoubleValue >
1108                                                 ((FloatConstant) right).DoubleValue;
1109                                 else if (left is ULongConstant)
1110                                         bool_res = ((ULongConstant) left).Value >
1111                                                 ((ULongConstant) right).Value;
1112                                 else if (left is LongConstant)
1113                                         bool_res = ((LongConstant) left).Value >
1114                                                 ((LongConstant) right).Value;
1115                                 else if (left is UIntConstant)
1116                                         bool_res = ((UIntConstant) left).Value >
1117                                                 ((UIntConstant) right).Value;
1118                                 else if (left is IntConstant)
1119                                         bool_res = ((IntConstant) left).Value >
1120                                                 ((IntConstant) right).Value;
1121                                 else
1122                                         return null;
1123
1124                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1125
1126                         case Binary.Operator.GreaterThanOrEqual:
1127                                 if (right is NullLiteral) {
1128                                         if (left is NullLiteral) {
1129                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1130                                                 lifted_int.ResolveAsType (ec);
1131                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1132                                         }
1133                                 }
1134
1135                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1136                                         return null;
1137
1138                                 bool_res = false;
1139                                 if (left is DoubleConstant)
1140                                         bool_res = ((DoubleConstant) left).Value >=
1141                                                 ((DoubleConstant) right).Value;
1142                                 else if (left is FloatConstant)
1143                                         bool_res = ((FloatConstant) left).DoubleValue >=
1144                                                 ((FloatConstant) right).DoubleValue;
1145                                 else if (left is ULongConstant)
1146                                         bool_res = ((ULongConstant) left).Value >=
1147                                                 ((ULongConstant) right).Value;
1148                                 else if (left is LongConstant)
1149                                         bool_res = ((LongConstant) left).Value >=
1150                                                 ((LongConstant) right).Value;
1151                                 else if (left is UIntConstant)
1152                                         bool_res = ((UIntConstant) left).Value >=
1153                                                 ((UIntConstant) right).Value;
1154                                 else if (left is IntConstant)
1155                                         bool_res = ((IntConstant) left).Value >=
1156                                                 ((IntConstant) right).Value;
1157                                 else
1158                                         return null;
1159
1160                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1161
1162                         case Binary.Operator.LessThanOrEqual:
1163                                 if (right is NullLiteral) {
1164                                         if (left is NullLiteral) {
1165                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1166                                                 lifted_int.ResolveAsType (ec);
1167                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1168                                         }
1169                                 }
1170
1171                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1172                                         return null;
1173
1174                                 bool_res = false;
1175                                 if (left is DoubleConstant)
1176                                         bool_res = ((DoubleConstant) left).Value <=
1177                                                 ((DoubleConstant) right).Value;
1178                                 else if (left is FloatConstant)
1179                                         bool_res = ((FloatConstant) left).DoubleValue <=
1180                                                 ((FloatConstant) right).DoubleValue;
1181                                 else if (left is ULongConstant)
1182                                         bool_res = ((ULongConstant) left).Value <=
1183                                                 ((ULongConstant) right).Value;
1184                                 else if (left is LongConstant)
1185                                         bool_res = ((LongConstant) left).Value <=
1186                                                 ((LongConstant) right).Value;
1187                                 else if (left is UIntConstant)
1188                                         bool_res = ((UIntConstant) left).Value <=
1189                                                 ((UIntConstant) right).Value;
1190                                 else if (left is IntConstant)
1191                                         bool_res = ((IntConstant) left).Value <=
1192                                                 ((IntConstant) right).Value;
1193                                 else
1194                                         return null;
1195
1196                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1197                         }
1198
1199                         return null;
1200                 }
1201         }
1202 }