[man] Add entries for sgen modes and new major/minor types
[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                                         if (lc == null) {
474                                                 lc = rc;
475                                                 lt = lc.Type;
476                                                 right = left;
477                                         }
478
479                                         // U has to be implicitly convetible to E.base
480                                         right = right.ConvertImplicitly (lc.Child.Type);
481                                         if (right == null)
482                                                 return null;
483
484                                         result = BinaryFold (ec, oper, lc.Child, right, loc);
485                                         if (result == null)
486                                                 return null;
487
488                                         result = result.Reduce (ec, lt);
489                                         if (result == null)
490                                                 return null;
491
492                                         return new EnumConstant (result, lt);
493                                 }
494
495                                 if (left is NullLiteral && right is NullLiteral) {
496                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
497                                         lifted_int.ResolveAsType (ec);
498                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
499                                 }
500
501                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
502                                         return null;
503
504                                 try {
505                                         if (left is DoubleConstant){
506                                                 double res;
507                                                 
508                                                 if (ec.ConstantCheckState)
509                                                         res = checked (((DoubleConstant) left).Value -
510                                                                        ((DoubleConstant) right).Value);
511                                                 else
512                                                         res = unchecked (((DoubleConstant) left).Value -
513                                                                          ((DoubleConstant) right).Value);
514
515                                                 result = new DoubleConstant (ec.BuiltinTypes, res, left.Location);
516                                         } else if (left is FloatConstant){
517                                                 double a, b, res;
518                                                 a = ((FloatConstant) left).DoubleValue;
519                                                 b = ((FloatConstant) right).DoubleValue;
520
521                                                 if (ec.ConstantCheckState)
522                                                         res = checked (a - b);
523                                                 else
524                                                         res = unchecked (a - b);
525
526                                                 result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
527                                         } else if (left is ULongConstant){
528                                                 ulong res;
529                                                 
530                                                 if (ec.ConstantCheckState)
531                                                         res = checked (((ULongConstant) left).Value -
532                                                                        ((ULongConstant) right).Value);
533                                                 else
534                                                         res = unchecked (((ULongConstant) left).Value -
535                                                                          ((ULongConstant) right).Value);
536
537                                                 result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
538                                         } else if (left is LongConstant){
539                                                 long res;
540                                                 
541                                                 if (ec.ConstantCheckState)
542                                                         res = checked (((LongConstant) left).Value -
543                                                                        ((LongConstant) right).Value);
544                                                 else
545                                                         res = unchecked (((LongConstant) left).Value -
546                                                                          ((LongConstant) right).Value);
547
548                                                 result = new LongConstant (ec.BuiltinTypes, res, left.Location);
549                                         } else if (left is UIntConstant){
550                                                 uint res;
551                                                 
552                                                 if (ec.ConstantCheckState)
553                                                         res = checked (((UIntConstant) left).Value -
554                                                                        ((UIntConstant) right).Value);
555                                                 else
556                                                         res = unchecked (((UIntConstant) left).Value -
557                                                                          ((UIntConstant) right).Value);
558
559                                                 result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
560                                         } else if (left is IntConstant){
561                                                 int res;
562
563                                                 if (ec.ConstantCheckState)
564                                                         res = checked (((IntConstant) left).Value -
565                                                                        ((IntConstant) right).Value);
566                                                 else
567                                                         res = unchecked (((IntConstant) left).Value -
568                                                                          ((IntConstant) right).Value);
569
570                                                 result = new IntConstant (ec.BuiltinTypes, res, left.Location);
571                                         } else if (left is DecimalConstant) {
572                                                 decimal res;
573
574                                                 if (ec.ConstantCheckState)
575                                                         res = checked (((DecimalConstant) left).Value -
576                                                                 ((DecimalConstant) right).Value);
577                                                 else
578                                                         res = unchecked (((DecimalConstant) left).Value -
579                                                                 ((DecimalConstant) right).Value);
580
581                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
582                                         } else {
583                                                 throw new Exception ( "Unexepected subtraction input: " + left);
584                                         }
585                                 } catch (OverflowException){
586                                         Error_CompileTimeOverflow (ec, loc);
587                                 }
588
589                                 return result;
590                                 
591                         case Binary.Operator.Multiply:
592                                 if (left is NullLiteral && right is NullLiteral) {
593                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
594                                         lifted_int.ResolveAsType (ec);
595                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
596                                 }
597
598                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
599                                         return null;
600
601                                 try {
602                                         if (left is DoubleConstant){
603                                                 double res;
604                                                 
605                                                 if (ec.ConstantCheckState)
606                                                         res = checked (((DoubleConstant) left).Value *
607                                                                 ((DoubleConstant) right).Value);
608                                                 else
609                                                         res = unchecked (((DoubleConstant) left).Value *
610                                                                 ((DoubleConstant) right).Value);
611
612                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
613                                         } else if (left is FloatConstant){
614                                                 double a, b, res;
615                                                 a = ((FloatConstant) left).DoubleValue;
616                                                 b = ((FloatConstant) right).DoubleValue;
617
618                                                 if (ec.ConstantCheckState)
619                                                         res = checked (a * b);
620                                                 else
621                                                         res = unchecked (a * b);
622
623                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
624                                         } else if (left is ULongConstant){
625                                                 ulong res;
626                                                 
627                                                 if (ec.ConstantCheckState)
628                                                         res = checked (((ULongConstant) left).Value *
629                                                                 ((ULongConstant) right).Value);
630                                                 else
631                                                         res = unchecked (((ULongConstant) left).Value *
632                                                                 ((ULongConstant) right).Value);
633
634                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
635                                         } else if (left is LongConstant){
636                                                 long res;
637                                                 
638                                                 if (ec.ConstantCheckState)
639                                                         res = checked (((LongConstant) left).Value *
640                                                                 ((LongConstant) right).Value);
641                                                 else
642                                                         res = unchecked (((LongConstant) left).Value *
643                                                                 ((LongConstant) right).Value);
644
645                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
646                                         } else if (left is UIntConstant){
647                                                 uint res;
648                                                 
649                                                 if (ec.ConstantCheckState)
650                                                         res = checked (((UIntConstant) left).Value *
651                                                                 ((UIntConstant) right).Value);
652                                                 else
653                                                         res = unchecked (((UIntConstant) left).Value *
654                                                                 ((UIntConstant) right).Value);
655
656                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
657                                         } else if (left is IntConstant){
658                                                 int res;
659
660                                                 if (ec.ConstantCheckState)
661                                                         res = checked (((IntConstant) left).Value *
662                                                                 ((IntConstant) right).Value);
663                                                 else
664                                                         res = unchecked (((IntConstant) left).Value *
665                                                                 ((IntConstant) right).Value);
666
667                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
668                                         } else if (left is DecimalConstant) {
669                                                 decimal res;
670
671                                                 if (ec.ConstantCheckState)
672                                                         res = checked (((DecimalConstant) left).Value *
673                                                                 ((DecimalConstant) right).Value);
674                                                 else
675                                                         res = unchecked (((DecimalConstant) left).Value *
676                                                                 ((DecimalConstant) right).Value);
677
678                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
679                                         } else {
680                                                 throw new Exception ( "Unexepected multiply input: " + left);
681                                         }
682                                 } catch (OverflowException){
683                                         Error_CompileTimeOverflow (ec, loc);
684                                 }
685                                 break;
686
687                         case Binary.Operator.Division:
688                                 if (left is NullLiteral && right is NullLiteral) {
689                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
690                                         lifted_int.ResolveAsType (ec);
691                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
692                                 }
693
694                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
695                                         return null;
696
697                                 try {
698                                         if (left is DoubleConstant){
699                                                 double res;
700                                                 
701                                                 if (ec.ConstantCheckState)
702                                                         res = checked (((DoubleConstant) left).Value /
703                                                                 ((DoubleConstant) right).Value);
704                                                 else
705                                                         res = unchecked (((DoubleConstant) left).Value /
706                                                                 ((DoubleConstant) right).Value);
707
708                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
709                                         } else if (left is FloatConstant){
710                                                 double a, b, res;
711                                                 a = ((FloatConstant) left).DoubleValue;
712                                                 b = ((FloatConstant) right).DoubleValue;
713
714                                                 if (ec.ConstantCheckState)
715                                                         res = checked (a / b);
716                                                 else
717                                                         res = unchecked (a / b);
718
719                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
720                                         } else if (left is ULongConstant){
721                                                 ulong res;
722                                                 
723                                                 if (ec.ConstantCheckState)
724                                                         res = checked (((ULongConstant) left).Value /
725                                                                 ((ULongConstant) right).Value);
726                                                 else
727                                                         res = unchecked (((ULongConstant) left).Value /
728                                                                 ((ULongConstant) right).Value);
729
730                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
731                                         } else if (left is LongConstant){
732                                                 long res;
733                                                 
734                                                 if (ec.ConstantCheckState)
735                                                         res = checked (((LongConstant) left).Value /
736                                                                 ((LongConstant) right).Value);
737                                                 else
738                                                         res = unchecked (((LongConstant) left).Value /
739                                                                 ((LongConstant) right).Value);
740
741                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
742                                         } else if (left is UIntConstant){
743                                                 uint res;
744                                                 
745                                                 if (ec.ConstantCheckState)
746                                                         res = checked (((UIntConstant) left).Value /
747                                                                 ((UIntConstant) right).Value);
748                                                 else
749                                                         res = unchecked (((UIntConstant) left).Value /
750                                                                 ((UIntConstant) right).Value);
751
752                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
753                                         } else if (left is IntConstant){
754                                                 int res;
755
756                                                 if (ec.ConstantCheckState)
757                                                         res = checked (((IntConstant) left).Value /
758                                                                 ((IntConstant) right).Value);
759                                                 else
760                                                         res = unchecked (((IntConstant) left).Value /
761                                                                 ((IntConstant) right).Value);
762
763                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
764                                         } else if (left is DecimalConstant) {
765                                                 decimal res;
766
767                                                 if (ec.ConstantCheckState)
768                                                         res = checked (((DecimalConstant) left).Value /
769                                                                 ((DecimalConstant) right).Value);
770                                                 else
771                                                         res = unchecked (((DecimalConstant) left).Value /
772                                                                 ((DecimalConstant) right).Value);
773
774                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
775                                         } else {
776                                                 throw new Exception ( "Unexepected division input: " + left);
777                                         }
778                                 } catch (OverflowException){
779                                         Error_CompileTimeOverflow (ec, loc);
780
781                                 } catch (DivideByZeroException) {
782                                         ec.Report.Error (20, loc, "Division by constant zero");
783                                 }
784                                 
785                                 break;
786                                 
787                         case Binary.Operator.Modulus:
788                                 if (left is NullLiteral && right is NullLiteral) {
789                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
790                                         lifted_int.ResolveAsType (ec);
791                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
792                                 }
793
794                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
795                                         return null;
796
797                                 try {
798                                         if (left is DoubleConstant){
799                                                 double res;
800                                                 
801                                                 if (ec.ConstantCheckState)
802                                                         res = checked (((DoubleConstant) left).Value %
803                                                                        ((DoubleConstant) right).Value);
804                                                 else
805                                                         res = unchecked (((DoubleConstant) left).Value %
806                                                                          ((DoubleConstant) right).Value);
807
808                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
809                                         } else if (left is FloatConstant){
810                                                 double a, b, res;
811                                                 a = ((FloatConstant) left).DoubleValue;
812                                                 b = ((FloatConstant) right).DoubleValue;
813                                                 
814                                                 if (ec.ConstantCheckState)
815                                                         res = checked (a % b);
816                                                 else
817                                                         res = unchecked (a % b);
818
819                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
820                                         } else if (left is ULongConstant){
821                                                 ulong res;
822                                                 
823                                                 if (ec.ConstantCheckState)
824                                                         res = checked (((ULongConstant) left).Value %
825                                                                        ((ULongConstant) right).Value);
826                                                 else
827                                                         res = unchecked (((ULongConstant) left).Value %
828                                                                          ((ULongConstant) right).Value);
829
830                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
831                                         } else if (left is LongConstant){
832                                                 long res;
833                                                 
834                                                 if (ec.ConstantCheckState)
835                                                         res = checked (((LongConstant) left).Value %
836                                                                        ((LongConstant) right).Value);
837                                                 else
838                                                         res = unchecked (((LongConstant) left).Value %
839                                                                          ((LongConstant) right).Value);
840
841                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
842                                         } else if (left is UIntConstant){
843                                                 uint res;
844                                                 
845                                                 if (ec.ConstantCheckState)
846                                                         res = checked (((UIntConstant) left).Value %
847                                                                        ((UIntConstant) right).Value);
848                                                 else
849                                                         res = unchecked (((UIntConstant) left).Value %
850                                                                          ((UIntConstant) right).Value);
851
852                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
853                                         } else if (left is IntConstant){
854                                                 int res;
855
856                                                 if (ec.ConstantCheckState)
857                                                         res = checked (((IntConstant) left).Value %
858                                                                        ((IntConstant) right).Value);
859                                                 else
860                                                         res = unchecked (((IntConstant) left).Value %
861                                                                          ((IntConstant) right).Value);
862
863                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
864                                         }
865
866                                         if (left is DecimalConstant) {
867                                                 decimal res;
868
869                                                 if (ec.ConstantCheckState)
870                                                         res = checked (((DecimalConstant) left).Value %
871                                                                 ((DecimalConstant) right).Value);
872                                                 else
873                                                         res = unchecked (((DecimalConstant) left).Value %
874                                                                 ((DecimalConstant) right).Value);
875
876                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
877                                         }
878
879                                         throw new Exception ( "Unexepected modulus input: " + left);
880                                 } catch (DivideByZeroException){
881                                         ec.Report.Error (20, loc, "Division by constant zero");
882                                 } catch (OverflowException){
883                                         Error_CompileTimeOverflow (ec, loc);
884                                 }
885                                 break;
886
887                                 //
888                                 // There is no overflow checking on left shift
889                                 //
890                         case Binary.Operator.LeftShift:
891                                 if (left is NullLiteral && right is NullLiteral) {
892                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
893                                         lifted_int.ResolveAsType (ec);
894                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
895                                 }
896
897                                 IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
898                                 if (ic == null){
899                                         return null;
900                                 }
901
902                                 int lshift_val = ic.Value;
903                                 switch (left.Type.BuiltinType) {
904                                 case BuiltinTypeSpec.Type.ULong:
905                                         return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location);
906                                 case BuiltinTypeSpec.Type.Long:
907                                         return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location);
908                                 case BuiltinTypeSpec.Type.UInt:
909                                         return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location);
910                                 }
911
912                                 // null << value => null
913                                 if (left is NullLiteral)
914                                         return (Constant) new Binary (oper, left, right).ResolveOperator (ec);
915
916                                 left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
917                                 if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
918                                         return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location);
919
920                                 return null;
921
922                                 //
923                                 // There is no overflow checking on right shift
924                                 //
925                         case Binary.Operator.RightShift:
926                                 if (left is NullLiteral && right is NullLiteral) {
927                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
928                                         lifted_int.ResolveAsType (ec);
929                                         return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
930                                 }
931
932                                 IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
933                                 if (sic == null){
934                                         return null;
935                                 }
936                                 int rshift_val = sic.Value;
937                                 switch (left.Type.BuiltinType) {
938                                 case BuiltinTypeSpec.Type.ULong:
939                                         return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location);
940                                 case BuiltinTypeSpec.Type.Long:
941                                         return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location);
942                                 case BuiltinTypeSpec.Type.UInt:
943                                         return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location);
944                                 }
945
946                                 // null >> value => null
947                                 if (left is NullLiteral)
948                                         return (Constant) new Binary (oper, left, right).ResolveOperator (ec);
949
950                                 left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
951                                 if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
952                                         return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location);
953
954                                 return null;
955
956                         case Binary.Operator.Equality:
957                                 if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
958                                         (left is Nullable.LiftedNull && right.IsNull) ||
959                                         (right is Nullable.LiftedNull && left.IsNull)) {
960                                         if (left.IsNull || right.IsNull) {
961                                                 return ReducedExpression.Create (
962                                                         new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location),
963                                                         new Binary (oper, left, right));
964                                         }
965
966                                         if (left is StringConstant && right is StringConstant)
967                                                 return new BoolConstant (ec.BuiltinTypes,
968                                                         ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
969
970                                         return null;
971                                 }
972
973                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
974                                         return null;
975
976                                 bool_res = false;
977                                 if (left is DoubleConstant)
978                                         bool_res = ((DoubleConstant) left).Value ==
979                                                 ((DoubleConstant) right).Value;
980                                 else if (left is FloatConstant)
981                                         bool_res = ((FloatConstant) left).DoubleValue ==
982                                                 ((FloatConstant) right).DoubleValue;
983                                 else if (left is ULongConstant)
984                                         bool_res = ((ULongConstant) left).Value ==
985                                                 ((ULongConstant) right).Value;
986                                 else if (left is LongConstant)
987                                         bool_res = ((LongConstant) left).Value ==
988                                                 ((LongConstant) right).Value;
989                                 else if (left is UIntConstant)
990                                         bool_res = ((UIntConstant) left).Value ==
991                                                 ((UIntConstant) right).Value;
992                                 else if (left is IntConstant)
993                                         bool_res = ((IntConstant) left).Value ==
994                                                 ((IntConstant) right).Value;
995                                 else
996                                         return null;
997
998                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
999
1000                         case Binary.Operator.Inequality:
1001                                 if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
1002                                         (left is Nullable.LiftedNull && right.IsNull) ||
1003                                         (right is Nullable.LiftedNull && left.IsNull)) {
1004                                         if (left.IsNull || right.IsNull) {
1005                                                 return ReducedExpression.Create (
1006                                                         new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location),
1007                                                         new Binary (oper, left, right));
1008                                         }
1009
1010                                         if (left is StringConstant && right is StringConstant)
1011                                                 return new BoolConstant (ec.BuiltinTypes,
1012                                                         ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
1013
1014                                         return null;
1015                                 }
1016
1017                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1018                                         return null;
1019
1020                                 bool_res = false;
1021                                 if (left is DoubleConstant)
1022                                         bool_res = ((DoubleConstant) left).Value !=
1023                                                 ((DoubleConstant) right).Value;
1024                                 else if (left is FloatConstant)
1025                                         bool_res = ((FloatConstant) left).DoubleValue !=
1026                                                 ((FloatConstant) right).DoubleValue;
1027                                 else if (left is ULongConstant)
1028                                         bool_res = ((ULongConstant) left).Value !=
1029                                                 ((ULongConstant) right).Value;
1030                                 else if (left is LongConstant)
1031                                         bool_res = ((LongConstant) left).Value !=
1032                                                 ((LongConstant) right).Value;
1033                                 else if (left is UIntConstant)
1034                                         bool_res = ((UIntConstant) left).Value !=
1035                                                 ((UIntConstant) right).Value;
1036                                 else if (left is IntConstant)
1037                                         bool_res = ((IntConstant) left).Value !=
1038                                                 ((IntConstant) right).Value;
1039                                 else
1040                                         return null;
1041
1042                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1043
1044                         case Binary.Operator.LessThan:
1045                                 if (right is NullLiteral) {
1046                                         if (left is NullLiteral) {
1047                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1048                                                 lifted_int.ResolveAsType (ec);
1049                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1050                                         }
1051                                 }
1052
1053                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1054                                         return null;
1055
1056                                 bool_res = false;
1057                                 if (left is DoubleConstant)
1058                                         bool_res = ((DoubleConstant) left).Value <
1059                                                 ((DoubleConstant) right).Value;
1060                                 else if (left is FloatConstant)
1061                                         bool_res = ((FloatConstant) left).DoubleValue <
1062                                                 ((FloatConstant) right).DoubleValue;
1063                                 else if (left is ULongConstant)
1064                                         bool_res = ((ULongConstant) left).Value <
1065                                                 ((ULongConstant) right).Value;
1066                                 else if (left is LongConstant)
1067                                         bool_res = ((LongConstant) left).Value <
1068                                                 ((LongConstant) right).Value;
1069                                 else if (left is UIntConstant)
1070                                         bool_res = ((UIntConstant) left).Value <
1071                                                 ((UIntConstant) right).Value;
1072                                 else if (left is IntConstant)
1073                                         bool_res = ((IntConstant) left).Value <
1074                                                 ((IntConstant) right).Value;
1075                                 else
1076                                         return null;
1077
1078                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1079                                 
1080                         case Binary.Operator.GreaterThan:
1081                                 if (right is NullLiteral) {
1082                                         if (left is NullLiteral) {
1083                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1084                                                 lifted_int.ResolveAsType (ec);
1085                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1086                                         }
1087                                 }
1088
1089                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1090                                         return null;
1091
1092                                 bool_res = false;
1093                                 if (left is DoubleConstant)
1094                                         bool_res = ((DoubleConstant) left).Value >
1095                                                 ((DoubleConstant) right).Value;
1096                                 else if (left is FloatConstant)
1097                                         bool_res = ((FloatConstant) left).DoubleValue >
1098                                                 ((FloatConstant) right).DoubleValue;
1099                                 else if (left is ULongConstant)
1100                                         bool_res = ((ULongConstant) left).Value >
1101                                                 ((ULongConstant) right).Value;
1102                                 else if (left is LongConstant)
1103                                         bool_res = ((LongConstant) left).Value >
1104                                                 ((LongConstant) right).Value;
1105                                 else if (left is UIntConstant)
1106                                         bool_res = ((UIntConstant) left).Value >
1107                                                 ((UIntConstant) right).Value;
1108                                 else if (left is IntConstant)
1109                                         bool_res = ((IntConstant) left).Value >
1110                                                 ((IntConstant) right).Value;
1111                                 else
1112                                         return null;
1113
1114                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1115
1116                         case Binary.Operator.GreaterThanOrEqual:
1117                                 if (right is NullLiteral) {
1118                                         if (left is NullLiteral) {
1119                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1120                                                 lifted_int.ResolveAsType (ec);
1121                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1122                                         }
1123                                 }
1124
1125                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1126                                         return null;
1127
1128                                 bool_res = false;
1129                                 if (left is DoubleConstant)
1130                                         bool_res = ((DoubleConstant) left).Value >=
1131                                                 ((DoubleConstant) right).Value;
1132                                 else if (left is FloatConstant)
1133                                         bool_res = ((FloatConstant) left).DoubleValue >=
1134                                                 ((FloatConstant) right).DoubleValue;
1135                                 else if (left is ULongConstant)
1136                                         bool_res = ((ULongConstant) left).Value >=
1137                                                 ((ULongConstant) right).Value;
1138                                 else if (left is LongConstant)
1139                                         bool_res = ((LongConstant) left).Value >=
1140                                                 ((LongConstant) right).Value;
1141                                 else if (left is UIntConstant)
1142                                         bool_res = ((UIntConstant) left).Value >=
1143                                                 ((UIntConstant) right).Value;
1144                                 else if (left is IntConstant)
1145                                         bool_res = ((IntConstant) left).Value >=
1146                                                 ((IntConstant) right).Value;
1147                                 else
1148                                         return null;
1149
1150                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1151
1152                         case Binary.Operator.LessThanOrEqual:
1153                                 if (right is NullLiteral) {
1154                                         if (left is NullLiteral) {
1155                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1156                                                 lifted_int.ResolveAsType (ec);
1157                                                 return (Constant) new Binary (oper, lifted_int, right).ResolveOperator (ec);
1158                                         }
1159                                 }
1160
1161                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1162                                         return null;
1163
1164                                 bool_res = false;
1165                                 if (left is DoubleConstant)
1166                                         bool_res = ((DoubleConstant) left).Value <=
1167                                                 ((DoubleConstant) right).Value;
1168                                 else if (left is FloatConstant)
1169                                         bool_res = ((FloatConstant) left).DoubleValue <=
1170                                                 ((FloatConstant) right).DoubleValue;
1171                                 else if (left is ULongConstant)
1172                                         bool_res = ((ULongConstant) left).Value <=
1173                                                 ((ULongConstant) right).Value;
1174                                 else if (left is LongConstant)
1175                                         bool_res = ((LongConstant) left).Value <=
1176                                                 ((LongConstant) right).Value;
1177                                 else if (left is UIntConstant)
1178                                         bool_res = ((UIntConstant) left).Value <=
1179                                                 ((UIntConstant) right).Value;
1180                                 else if (left is IntConstant)
1181                                         bool_res = ((IntConstant) left).Value <=
1182                                                 ((IntConstant) right).Value;
1183                                 else
1184                                         return null;
1185
1186                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1187                         }
1188
1189                         return null;
1190                 }
1191         }
1192 }