Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/cfold.cs @ 16240

Last change on this file since 16240 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 38.0 KB
Line 
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//
11using System;
12
13namespace 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}
Note: See TracBrowser for help on using the repository browser.