Merge remote-tracking branch 'joncham/sgen-msvc2'
[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 Nullable.LiftedBinaryOperator (oper, left, right).Resolve (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 Nullable.LiftedBinaryOperator (oper, left, right).Resolve (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                                 if (lt == InternalType.NullLiteral)
303                                         return right;
304
305                                 if (rt == InternalType.NullLiteral)
306                                         return left;
307
308                                 //
309                                 // If both sides are strings, then concatenate, if
310                                 // one is a string, and the other is not, then defer
311                                 // to runtime concatenation
312                                 //
313                                 if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){
314                                         if (lt == rt)
315                                                 return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (),
316                                                         left.Location);
317                                         
318                                         return null;
319                                 }
320
321                                 //
322                                 // handle "E operator + (E x, U y)"
323                                 // handle "E operator + (Y y, E x)"
324                                 //
325                                 EnumConstant lc = left as EnumConstant;
326                                 EnumConstant rc = right as EnumConstant;
327                                 if (lc != null || rc != null){
328                                         if (lc == null) {
329                                                 lc = rc;
330                                                 lt = lc.Type;
331                                                 right = left;
332                                         }
333
334                                         // U has to be implicitly convetible to E.base
335                                         right = right.ConvertImplicitly (lc.Child.Type);
336                                         if (right == null)
337                                                 return null;
338
339                                         result = BinaryFold (ec, oper, lc.Child, right, loc);
340                                         if (result == null)
341                                                 return null;
342
343                                         result = result.Reduce (ec, lt);
344                                         if (result == null)
345                                                 return null;
346
347                                         return new EnumConstant (result, lt);
348                                 }
349
350                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
351                                         return null;
352
353                                 try {
354                                         if (left is DoubleConstant){
355                                                 double res;
356                                                 
357                                                 if (ec.ConstantCheckState)
358                                                         res = checked (((DoubleConstant) left).Value +
359                                                                        ((DoubleConstant) right).Value);
360                                                 else
361                                                         res = unchecked (((DoubleConstant) left).Value +
362                                                                          ((DoubleConstant) right).Value);
363
364                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
365                                         }
366                                         if (left is FloatConstant){
367                                                 float res;
368                                                 
369                                                 if (ec.ConstantCheckState)
370                                                         res = checked (((FloatConstant) left).Value +
371                                                                        ((FloatConstant) right).Value);
372                                                 else
373                                                         res = unchecked (((FloatConstant) left).Value +
374                                                                          ((FloatConstant) right).Value);
375
376                                                 result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
377                                         } else if (left is ULongConstant){
378                                                 ulong res;
379                                                 
380                                                 if (ec.ConstantCheckState)
381                                                         res = checked (((ULongConstant) left).Value +
382                                                                        ((ULongConstant) right).Value);
383                                                 else
384                                                         res = unchecked (((ULongConstant) left).Value +
385                                                                          ((ULongConstant) right).Value);
386
387                                                 result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
388                                         } else if (left is LongConstant){
389                                                 long res;
390                                                 
391                                                 if (ec.ConstantCheckState)
392                                                         res = checked (((LongConstant) left).Value +
393                                                                        ((LongConstant) right).Value);
394                                                 else
395                                                         res = unchecked (((LongConstant) left).Value +
396                                                                          ((LongConstant) right).Value);
397
398                                                 result = new LongConstant (ec.BuiltinTypes, res, left.Location);
399                                         } else if (left is UIntConstant){
400                                                 uint res;
401                                                 
402                                                 if (ec.ConstantCheckState)
403                                                         res = checked (((UIntConstant) left).Value +
404                                                                        ((UIntConstant) right).Value);
405                                                 else
406                                                         res = unchecked (((UIntConstant) left).Value +
407                                                                          ((UIntConstant) right).Value);
408
409                                                 result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
410                                         } else if (left is IntConstant){
411                                                 int res;
412
413                                                 if (ec.ConstantCheckState)
414                                                         res = checked (((IntConstant) left).Value +
415                                                                        ((IntConstant) right).Value);
416                                                 else
417                                                         res = unchecked (((IntConstant) left).Value +
418                                                                          ((IntConstant) right).Value);
419
420                                                 result = new IntConstant (ec.BuiltinTypes, res, left.Location);
421                                         } else if (left is DecimalConstant) {
422                                                 decimal res;
423
424                                                 if (ec.ConstantCheckState)
425                                                         res = checked (((DecimalConstant) left).Value +
426                                                                 ((DecimalConstant) right).Value);
427                                                 else
428                                                         res = unchecked (((DecimalConstant) left).Value +
429                                                                 ((DecimalConstant) right).Value);
430
431                                                 result = new DecimalConstant (ec.BuiltinTypes, res, left.Location);
432                                         }
433                                 } catch (OverflowException){
434                                         Error_CompileTimeOverflow (ec, loc);
435                                 }
436
437                                 return result;
438
439                         case Binary.Operator.Subtraction:
440                                 //
441                                 // handle "E operator - (E x, U y)"
442                                 // handle "E operator - (Y y, E x)"
443                                 //
444                                 lc = left as EnumConstant;
445                                 rc = right as EnumConstant;
446                                 if (lc != null || rc != null){
447                                         if (lc == null) {
448                                                 lc = rc;
449                                                 lt = lc.Type;
450                                                 right = left;
451                                         }
452
453                                         // U has to be implicitly convetible to E.base
454                                         right = right.ConvertImplicitly (lc.Child.Type);
455                                         if (right == null)
456                                                 return null;
457
458                                         result = BinaryFold (ec, oper, lc.Child, right, loc);
459                                         if (result == null)
460                                                 return null;
461
462                                         result = result.Reduce (ec, lt);
463                                         if (result == null)
464                                                 return null;
465
466                                         return new EnumConstant (result, lt);
467                                 }
468
469                                 if (left is NullLiteral && right is NullLiteral) {
470                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
471                                         lifted_int.ResolveAsType (ec);
472                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
473                                 }
474
475                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
476                                         return null;
477
478                                 try {
479                                         if (left is DoubleConstant){
480                                                 double res;
481                                                 
482                                                 if (ec.ConstantCheckState)
483                                                         res = checked (((DoubleConstant) left).Value -
484                                                                        ((DoubleConstant) right).Value);
485                                                 else
486                                                         res = unchecked (((DoubleConstant) left).Value -
487                                                                          ((DoubleConstant) right).Value);
488
489                                                 result = new DoubleConstant (ec.BuiltinTypes, res, left.Location);
490                                         } else if (left is FloatConstant){
491                                                 float res;
492                                                 
493                                                 if (ec.ConstantCheckState)
494                                                         res = checked (((FloatConstant) left).Value -
495                                                                        ((FloatConstant) right).Value);
496                                                 else
497                                                         res = unchecked (((FloatConstant) left).Value -
498                                                                          ((FloatConstant) right).Value);
499
500                                                 result = new FloatConstant (ec.BuiltinTypes, res, left.Location);
501                                         } else if (left is ULongConstant){
502                                                 ulong res;
503                                                 
504                                                 if (ec.ConstantCheckState)
505                                                         res = checked (((ULongConstant) left).Value -
506                                                                        ((ULongConstant) right).Value);
507                                                 else
508                                                         res = unchecked (((ULongConstant) left).Value -
509                                                                          ((ULongConstant) right).Value);
510
511                                                 result = new ULongConstant (ec.BuiltinTypes, res, left.Location);
512                                         } else if (left is LongConstant){
513                                                 long res;
514                                                 
515                                                 if (ec.ConstantCheckState)
516                                                         res = checked (((LongConstant) left).Value -
517                                                                        ((LongConstant) right).Value);
518                                                 else
519                                                         res = unchecked (((LongConstant) left).Value -
520                                                                          ((LongConstant) right).Value);
521
522                                                 result = new LongConstant (ec.BuiltinTypes, res, left.Location);
523                                         } else if (left is UIntConstant){
524                                                 uint res;
525                                                 
526                                                 if (ec.ConstantCheckState)
527                                                         res = checked (((UIntConstant) left).Value -
528                                                                        ((UIntConstant) right).Value);
529                                                 else
530                                                         res = unchecked (((UIntConstant) left).Value -
531                                                                          ((UIntConstant) right).Value);
532
533                                                 result = new UIntConstant (ec.BuiltinTypes, res, left.Location);
534                                         } else if (left is IntConstant){
535                                                 int res;
536
537                                                 if (ec.ConstantCheckState)
538                                                         res = checked (((IntConstant) left).Value -
539                                                                        ((IntConstant) right).Value);
540                                                 else
541                                                         res = unchecked (((IntConstant) left).Value -
542                                                                          ((IntConstant) right).Value);
543
544                                                 result = new IntConstant (ec.BuiltinTypes, res, left.Location);
545                                         } else if (left is DecimalConstant) {
546                                                 decimal res;
547
548                                                 if (ec.ConstantCheckState)
549                                                         res = checked (((DecimalConstant) left).Value -
550                                                                 ((DecimalConstant) right).Value);
551                                                 else
552                                                         res = unchecked (((DecimalConstant) left).Value -
553                                                                 ((DecimalConstant) right).Value);
554
555                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
556                                         } else {
557                                                 throw new Exception ( "Unexepected subtraction input: " + left);
558                                         }
559                                 } catch (OverflowException){
560                                         Error_CompileTimeOverflow (ec, loc);
561                                 }
562
563                                 return result;
564                                 
565                         case Binary.Operator.Multiply:
566                                 if (left is NullLiteral && right is NullLiteral) {
567                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
568                                         lifted_int.ResolveAsType (ec);
569                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
570                                 }
571
572                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
573                                         return null;
574
575                                 try {
576                                         if (left is DoubleConstant){
577                                                 double res;
578                                                 
579                                                 if (ec.ConstantCheckState)
580                                                         res = checked (((DoubleConstant) left).Value *
581                                                                 ((DoubleConstant) right).Value);
582                                                 else
583                                                         res = unchecked (((DoubleConstant) left).Value *
584                                                                 ((DoubleConstant) right).Value);
585
586                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
587                                         } else if (left is FloatConstant){
588                                                 float res;
589                                                 
590                                                 if (ec.ConstantCheckState)
591                                                         res = checked (((FloatConstant) left).Value *
592                                                                 ((FloatConstant) right).Value);
593                                                 else
594                                                         res = unchecked (((FloatConstant) left).Value *
595                                                                 ((FloatConstant) right).Value);
596
597                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
598                                         } else if (left is ULongConstant){
599                                                 ulong res;
600                                                 
601                                                 if (ec.ConstantCheckState)
602                                                         res = checked (((ULongConstant) left).Value *
603                                                                 ((ULongConstant) right).Value);
604                                                 else
605                                                         res = unchecked (((ULongConstant) left).Value *
606                                                                 ((ULongConstant) right).Value);
607
608                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
609                                         } else if (left is LongConstant){
610                                                 long res;
611                                                 
612                                                 if (ec.ConstantCheckState)
613                                                         res = checked (((LongConstant) left).Value *
614                                                                 ((LongConstant) right).Value);
615                                                 else
616                                                         res = unchecked (((LongConstant) left).Value *
617                                                                 ((LongConstant) right).Value);
618
619                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
620                                         } else if (left is UIntConstant){
621                                                 uint res;
622                                                 
623                                                 if (ec.ConstantCheckState)
624                                                         res = checked (((UIntConstant) left).Value *
625                                                                 ((UIntConstant) right).Value);
626                                                 else
627                                                         res = unchecked (((UIntConstant) left).Value *
628                                                                 ((UIntConstant) right).Value);
629
630                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
631                                         } else if (left is IntConstant){
632                                                 int res;
633
634                                                 if (ec.ConstantCheckState)
635                                                         res = checked (((IntConstant) left).Value *
636                                                                 ((IntConstant) right).Value);
637                                                 else
638                                                         res = unchecked (((IntConstant) left).Value *
639                                                                 ((IntConstant) right).Value);
640
641                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
642                                         } else if (left is DecimalConstant) {
643                                                 decimal res;
644
645                                                 if (ec.ConstantCheckState)
646                                                         res = checked (((DecimalConstant) left).Value *
647                                                                 ((DecimalConstant) right).Value);
648                                                 else
649                                                         res = unchecked (((DecimalConstant) left).Value *
650                                                                 ((DecimalConstant) right).Value);
651
652                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
653                                         } else {
654                                                 throw new Exception ( "Unexepected multiply input: " + left);
655                                         }
656                                 } catch (OverflowException){
657                                         Error_CompileTimeOverflow (ec, loc);
658                                 }
659                                 break;
660
661                         case Binary.Operator.Division:
662                                 if (left is NullLiteral && right is NullLiteral) {
663                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
664                                         lifted_int.ResolveAsType (ec);
665                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
666                                 }
667
668                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
669                                         return null;
670
671                                 try {
672                                         if (left is DoubleConstant){
673                                                 double res;
674                                                 
675                                                 if (ec.ConstantCheckState)
676                                                         res = checked (((DoubleConstant) left).Value /
677                                                                 ((DoubleConstant) right).Value);
678                                                 else
679                                                         res = unchecked (((DoubleConstant) left).Value /
680                                                                 ((DoubleConstant) right).Value);
681
682                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
683                                         } else if (left is FloatConstant){
684                                                 float res;
685                                                 
686                                                 if (ec.ConstantCheckState)
687                                                         res = checked (((FloatConstant) left).Value /
688                                                                 ((FloatConstant) right).Value);
689                                                 else
690                                                         res = unchecked (((FloatConstant) left).Value /
691                                                                 ((FloatConstant) right).Value);
692
693                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
694                                         } else if (left is ULongConstant){
695                                                 ulong res;
696                                                 
697                                                 if (ec.ConstantCheckState)
698                                                         res = checked (((ULongConstant) left).Value /
699                                                                 ((ULongConstant) right).Value);
700                                                 else
701                                                         res = unchecked (((ULongConstant) left).Value /
702                                                                 ((ULongConstant) right).Value);
703
704                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
705                                         } else if (left is LongConstant){
706                                                 long res;
707                                                 
708                                                 if (ec.ConstantCheckState)
709                                                         res = checked (((LongConstant) left).Value /
710                                                                 ((LongConstant) right).Value);
711                                                 else
712                                                         res = unchecked (((LongConstant) left).Value /
713                                                                 ((LongConstant) right).Value);
714
715                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
716                                         } else if (left is UIntConstant){
717                                                 uint res;
718                                                 
719                                                 if (ec.ConstantCheckState)
720                                                         res = checked (((UIntConstant) left).Value /
721                                                                 ((UIntConstant) right).Value);
722                                                 else
723                                                         res = unchecked (((UIntConstant) left).Value /
724                                                                 ((UIntConstant) right).Value);
725
726                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
727                                         } else if (left is IntConstant){
728                                                 int res;
729
730                                                 if (ec.ConstantCheckState)
731                                                         res = checked (((IntConstant) left).Value /
732                                                                 ((IntConstant) right).Value);
733                                                 else
734                                                         res = unchecked (((IntConstant) left).Value /
735                                                                 ((IntConstant) right).Value);
736
737                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
738                                         } else if (left is DecimalConstant) {
739                                                 decimal res;
740
741                                                 if (ec.ConstantCheckState)
742                                                         res = checked (((DecimalConstant) left).Value /
743                                                                 ((DecimalConstant) right).Value);
744                                                 else
745                                                         res = unchecked (((DecimalConstant) left).Value /
746                                                                 ((DecimalConstant) right).Value);
747
748                                                 return new DecimalConstant (ec.BuiltinTypes, res, left.Location);
749                                         } else {
750                                                 throw new Exception ( "Unexepected division input: " + left);
751                                         }
752                                 } catch (OverflowException){
753                                         Error_CompileTimeOverflow (ec, loc);
754
755                                 } catch (DivideByZeroException) {
756                                         ec.Report.Error (20, loc, "Division by constant zero");
757                                 }
758                                 
759                                 break;
760                                 
761                         case Binary.Operator.Modulus:
762                                 if (left is NullLiteral && right is NullLiteral) {
763                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
764                                         lifted_int.ResolveAsType (ec);
765                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
766                                 }
767
768                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
769                                         return null;
770
771                                 try {
772                                         if (left is DoubleConstant){
773                                                 double res;
774                                                 
775                                                 if (ec.ConstantCheckState)
776                                                         res = checked (((DoubleConstant) left).Value %
777                                                                        ((DoubleConstant) right).Value);
778                                                 else
779                                                         res = unchecked (((DoubleConstant) left).Value %
780                                                                          ((DoubleConstant) right).Value);
781
782                                                 return new DoubleConstant (ec.BuiltinTypes, res, left.Location);
783                                         } else if (left is FloatConstant){
784                                                 float res;
785                                                 
786                                                 if (ec.ConstantCheckState)
787                                                         res = checked (((FloatConstant) left).Value %
788                                                                        ((FloatConstant) right).Value);
789                                                 else
790                                                         res = unchecked (((FloatConstant) left).Value %
791                                                                          ((FloatConstant) right).Value);
792
793                                                 return new FloatConstant (ec.BuiltinTypes, res, left.Location);
794                                         } else if (left is ULongConstant){
795                                                 ulong res;
796                                                 
797                                                 if (ec.ConstantCheckState)
798                                                         res = checked (((ULongConstant) left).Value %
799                                                                        ((ULongConstant) right).Value);
800                                                 else
801                                                         res = unchecked (((ULongConstant) left).Value %
802                                                                          ((ULongConstant) right).Value);
803
804                                                 return new ULongConstant (ec.BuiltinTypes, res, left.Location);
805                                         } else if (left is LongConstant){
806                                                 long res;
807                                                 
808                                                 if (ec.ConstantCheckState)
809                                                         res = checked (((LongConstant) left).Value %
810                                                                        ((LongConstant) right).Value);
811                                                 else
812                                                         res = unchecked (((LongConstant) left).Value %
813                                                                          ((LongConstant) right).Value);
814
815                                                 return new LongConstant (ec.BuiltinTypes, res, left.Location);
816                                         } else if (left is UIntConstant){
817                                                 uint res;
818                                                 
819                                                 if (ec.ConstantCheckState)
820                                                         res = checked (((UIntConstant) left).Value %
821                                                                        ((UIntConstant) right).Value);
822                                                 else
823                                                         res = unchecked (((UIntConstant) left).Value %
824                                                                          ((UIntConstant) right).Value);
825
826                                                 return new UIntConstant (ec.BuiltinTypes, res, left.Location);
827                                         } else if (left is IntConstant){
828                                                 int res;
829
830                                                 if (ec.ConstantCheckState)
831                                                         res = checked (((IntConstant) left).Value %
832                                                                        ((IntConstant) right).Value);
833                                                 else
834                                                         res = unchecked (((IntConstant) left).Value %
835                                                                          ((IntConstant) right).Value);
836
837                                                 return new IntConstant (ec.BuiltinTypes, res, left.Location);
838                                         } else {
839                                                 throw new Exception ( "Unexepected modulus input: " + left);
840                                         }
841                                 } catch (DivideByZeroException){
842                                         ec.Report.Error (20, loc, "Division by constant zero");
843                                 } catch (OverflowException){
844                                         Error_CompileTimeOverflow (ec, loc);
845                                 }
846                                 break;
847
848                                 //
849                                 // There is no overflow checking on left shift
850                                 //
851                         case Binary.Operator.LeftShift:
852                                 if (left is NullLiteral && right is NullLiteral) {
853                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
854                                         lifted_int.ResolveAsType (ec);
855                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
856                                 }
857
858                                 IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
859                                 if (ic == null){
860                                         Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
861                                         return null;
862                                 }
863
864                                 int lshift_val = ic.Value;
865                                 switch (left.Type.BuiltinType) {
866                                 case BuiltinTypeSpec.Type.ULong:
867                                         return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location);
868                                 case BuiltinTypeSpec.Type.Long:
869                                         return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location);
870                                 case BuiltinTypeSpec.Type.UInt:
871                                         return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location);
872                                 }
873
874                                 // null << value => null
875                                 if (left is NullLiteral)
876                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec);
877
878                                 left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
879                                 if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
880                                         return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location);
881
882                                 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
883                                 break;
884
885                                 //
886                                 // There is no overflow checking on right shift
887                                 //
888                         case Binary.Operator.RightShift:
889                                 if (left is NullLiteral && right is NullLiteral) {
890                                         var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
891                                         lifted_int.ResolveAsType (ec);
892                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
893                                 }
894
895                                 IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant;
896                                 if (sic == null){
897                                         Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
898                                         return null;
899                                 }
900                                 int rshift_val = sic.Value;
901                                 switch (left.Type.BuiltinType) {
902                                 case BuiltinTypeSpec.Type.ULong:
903                                         return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location);
904                                 case BuiltinTypeSpec.Type.Long:
905                                         return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location);
906                                 case BuiltinTypeSpec.Type.UInt:
907                                         return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location);
908                                 }
909
910                                 // null >> value => null
911                                 if (left is NullLiteral)
912                                         return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec);
913
914                                 left = left.ConvertImplicitly (ec.BuiltinTypes.Int);
915                                 if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int)
916                                         return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location);
917
918                                 Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
919                                 break;
920
921                         case Binary.Operator.Equality:
922                                 if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
923                                         (left is Nullable.LiftedNull && right.IsNull) ||
924                                         (right is Nullable.LiftedNull && left.IsNull)) {
925                                         if (left.IsNull || right.IsNull) {
926                                                 return ReducedExpression.Create (
927                                                         new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location),
928                                                         new Binary (oper, left, right));
929                                         }
930
931                                         if (left is StringConstant && right is StringConstant)
932                                                 return new BoolConstant (ec.BuiltinTypes,
933                                                         ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
934
935                                         return null;
936                                 }
937
938                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
939                                         return null;
940
941                                 bool_res = false;
942                                 if (left is DoubleConstant)
943                                         bool_res = ((DoubleConstant) left).Value ==
944                                                 ((DoubleConstant) right).Value;
945                                 else if (left is FloatConstant)
946                                         bool_res = ((FloatConstant) left).Value ==
947                                                 ((FloatConstant) right).Value;
948                                 else if (left is ULongConstant)
949                                         bool_res = ((ULongConstant) left).Value ==
950                                                 ((ULongConstant) right).Value;
951                                 else if (left is LongConstant)
952                                         bool_res = ((LongConstant) left).Value ==
953                                                 ((LongConstant) right).Value;
954                                 else if (left is UIntConstant)
955                                         bool_res = ((UIntConstant) left).Value ==
956                                                 ((UIntConstant) right).Value;
957                                 else if (left is IntConstant)
958                                         bool_res = ((IntConstant) left).Value ==
959                                                 ((IntConstant) right).Value;
960                                 else
961                                         return null;
962
963                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
964
965                         case Binary.Operator.Inequality:
966                                 if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) ||
967                                         (left is Nullable.LiftedNull && right.IsNull) ||
968                                         (right is Nullable.LiftedNull && left.IsNull)) {
969                                         if (left.IsNull || right.IsNull) {
970                                                 return ReducedExpression.Create (
971                                                         new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location),
972                                                         new Binary (oper, left, right));
973                                         }
974
975                                         if (left is StringConstant && right is StringConstant)
976                                                 return new BoolConstant (ec.BuiltinTypes,
977                                                         ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
978
979                                         return null;
980                                 }
981
982                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
983                                         return null;
984
985                                 bool_res = false;
986                                 if (left is DoubleConstant)
987                                         bool_res = ((DoubleConstant) left).Value !=
988                                                 ((DoubleConstant) right).Value;
989                                 else if (left is FloatConstant)
990                                         bool_res = ((FloatConstant) left).Value !=
991                                                 ((FloatConstant) right).Value;
992                                 else if (left is ULongConstant)
993                                         bool_res = ((ULongConstant) left).Value !=
994                                                 ((ULongConstant) right).Value;
995                                 else if (left is LongConstant)
996                                         bool_res = ((LongConstant) left).Value !=
997                                                 ((LongConstant) right).Value;
998                                 else if (left is UIntConstant)
999                                         bool_res = ((UIntConstant) left).Value !=
1000                                                 ((UIntConstant) right).Value;
1001                                 else if (left is IntConstant)
1002                                         bool_res = ((IntConstant) left).Value !=
1003                                                 ((IntConstant) right).Value;
1004                                 else
1005                                         return null;
1006
1007                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1008
1009                         case Binary.Operator.LessThan:
1010                                 if (right is NullLiteral) {
1011                                         if (left is NullLiteral) {
1012                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1013                                                 lifted_int.ResolveAsType (ec);
1014                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
1015                                         }
1016
1017                                         if (left is Nullable.LiftedNull) {
1018                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec);
1019                                         }
1020                                 }
1021
1022                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1023                                         return null;
1024
1025                                 bool_res = false;
1026                                 if (left is DoubleConstant)
1027                                         bool_res = ((DoubleConstant) left).Value <
1028                                                 ((DoubleConstant) right).Value;
1029                                 else if (left is FloatConstant)
1030                                         bool_res = ((FloatConstant) left).Value <
1031                                                 ((FloatConstant) right).Value;
1032                                 else if (left is ULongConstant)
1033                                         bool_res = ((ULongConstant) left).Value <
1034                                                 ((ULongConstant) right).Value;
1035                                 else if (left is LongConstant)
1036                                         bool_res = ((LongConstant) left).Value <
1037                                                 ((LongConstant) right).Value;
1038                                 else if (left is UIntConstant)
1039                                         bool_res = ((UIntConstant) left).Value <
1040                                                 ((UIntConstant) right).Value;
1041                                 else if (left is IntConstant)
1042                                         bool_res = ((IntConstant) left).Value <
1043                                                 ((IntConstant) right).Value;
1044                                 else
1045                                         return null;
1046
1047                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1048                                 
1049                         case Binary.Operator.GreaterThan:
1050                                 if (right is NullLiteral) {
1051                                         if (left is NullLiteral) {
1052                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1053                                                 lifted_int.ResolveAsType (ec);
1054                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
1055                                         }
1056
1057                                         if (left is Nullable.LiftedNull) {
1058                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec);
1059                                         }
1060                                 }
1061
1062                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1063                                         return null;
1064
1065                                 bool_res = false;
1066                                 if (left is DoubleConstant)
1067                                         bool_res = ((DoubleConstant) left).Value >
1068                                                 ((DoubleConstant) right).Value;
1069                                 else if (left is FloatConstant)
1070                                         bool_res = ((FloatConstant) left).Value >
1071                                                 ((FloatConstant) right).Value;
1072                                 else if (left is ULongConstant)
1073                                         bool_res = ((ULongConstant) left).Value >
1074                                                 ((ULongConstant) right).Value;
1075                                 else if (left is LongConstant)
1076                                         bool_res = ((LongConstant) left).Value >
1077                                                 ((LongConstant) right).Value;
1078                                 else if (left is UIntConstant)
1079                                         bool_res = ((UIntConstant) left).Value >
1080                                                 ((UIntConstant) right).Value;
1081                                 else if (left is IntConstant)
1082                                         bool_res = ((IntConstant) left).Value >
1083                                                 ((IntConstant) right).Value;
1084                                 else
1085                                         return null;
1086
1087                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1088
1089                         case Binary.Operator.GreaterThanOrEqual:
1090                                 if (right is NullLiteral) {
1091                                         if (left is NullLiteral) {
1092                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1093                                                 lifted_int.ResolveAsType (ec);
1094                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
1095                                         }
1096
1097                                         if (left is Nullable.LiftedNull) {
1098                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec);
1099                                         }
1100                                 }
1101
1102                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1103                                         return null;
1104
1105                                 bool_res = false;
1106                                 if (left is DoubleConstant)
1107                                         bool_res = ((DoubleConstant) left).Value >=
1108                                                 ((DoubleConstant) right).Value;
1109                                 else if (left is FloatConstant)
1110                                         bool_res = ((FloatConstant) left).Value >=
1111                                                 ((FloatConstant) right).Value;
1112                                 else if (left is ULongConstant)
1113                                         bool_res = ((ULongConstant) left).Value >=
1114                                                 ((ULongConstant) right).Value;
1115                                 else if (left is LongConstant)
1116                                         bool_res = ((LongConstant) left).Value >=
1117                                                 ((LongConstant) right).Value;
1118                                 else if (left is UIntConstant)
1119                                         bool_res = ((UIntConstant) left).Value >=
1120                                                 ((UIntConstant) right).Value;
1121                                 else if (left is IntConstant)
1122                                         bool_res = ((IntConstant) left).Value >=
1123                                                 ((IntConstant) right).Value;
1124                                 else
1125                                         return null;
1126
1127                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1128
1129                         case Binary.Operator.LessThanOrEqual:
1130                                 if (right is NullLiteral) {
1131                                         if (left is NullLiteral) {
1132                                                 var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc);
1133                                                 lifted_int.ResolveAsType (ec);
1134                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right).Resolve (ec);
1135                                         }
1136
1137                                         if (left is Nullable.LiftedNull) {
1138                                                 return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right).Resolve (ec);
1139                                         }
1140                                 }
1141
1142                                 if (!DoBinaryNumericPromotions (ec, ref left, ref right))
1143                                         return null;
1144
1145                                 bool_res = false;
1146                                 if (left is DoubleConstant)
1147                                         bool_res = ((DoubleConstant) left).Value <=
1148                                                 ((DoubleConstant) right).Value;
1149                                 else if (left is FloatConstant)
1150                                         bool_res = ((FloatConstant) left).Value <=
1151                                                 ((FloatConstant) right).Value;
1152                                 else if (left is ULongConstant)
1153                                         bool_res = ((ULongConstant) left).Value <=
1154                                                 ((ULongConstant) right).Value;
1155                                 else if (left is LongConstant)
1156                                         bool_res = ((LongConstant) left).Value <=
1157                                                 ((LongConstant) right).Value;
1158                                 else if (left is UIntConstant)
1159                                         bool_res = ((UIntConstant) left).Value <=
1160                                                 ((UIntConstant) right).Value;
1161                                 else if (left is IntConstant)
1162                                         bool_res = ((IntConstant) left).Value <=
1163                                                 ((IntConstant) right).Value;
1164                                 else
1165                                         return null;
1166
1167                                 return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location);
1168                         }
1169                                         
1170                         return null;
1171                 }
1172         }
1173 }