~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/mcs/cfold.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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-2008, 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.TryReduce (ec, lt, loc);
 
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.TryReduce (ec, EnumSpec.GetUnderlyingType (lt), loc);
 
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, loc).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, loc).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.TryReduce (ec, lt, loc);
 
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.TryReduce (ec, lt, loc);
 
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, loc).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, loc).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, loc).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, loc).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, loc).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, loc).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, loc).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, loc).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, loc));
 
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, loc));
 
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, loc).Resolve (ec);
 
1015
                                        }
 
1016
 
 
1017
                                        if (left is Nullable.LiftedNull) {
 
1018
                                                return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).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, loc).Resolve (ec);
 
1055
                                        }
 
1056
 
 
1057
                                        if (left is Nullable.LiftedNull) {
 
1058
                                                return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).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, loc).Resolve (ec);
 
1095
                                        }
 
1096
 
 
1097
                                        if (left is Nullable.LiftedNull) {
 
1098
                                                return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).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, loc).Resolve (ec);
 
1135
                                        }
 
1136
 
 
1137
                                        if (left is Nullable.LiftedNull) {
 
1138
                                                return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).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
}