Fixed to conform to Mono standards for incomplete functionality
[mono.git] / mcs / mbas / cfold.cs
1 //\r
2 // cfold.cs: Constant Folding\r
3 //\r
4 // Author:\r
5 //   Miguel de Icaza (miguel@ximian.com)\r
6 //\r
7 // (C) 2002 Ximian, Inc.\r
8 //\r
9 \r
10 using System;\r
11 \r
12 namespace Mono.CSharp {\r
13 \r
14         public class ConstantFold {\r
15 \r
16                 //\r
17                 // Performs the numeric promotions on the left and right expresions\r
18                 // and desposits the results on `lc' and `rc'.\r
19                 //\r
20                 // On success, the types of `lc' and `rc' on output will always match,\r
21                 // and the pair will be one of:\r
22                 //\r
23                 //   (double, double)\r
24                 //   (float, float)\r
25                 //   (ulong, ulong)\r
26                 //   (long, long)\r
27                 //   (uint, uint)\r
28                 //   (int, int)\r
29                 //\r
30                 static void DoConstantNumericPromotions (Binary.Operator oper,\r
31                                                          ref Constant left, ref Constant right,\r
32                                                          Location loc)\r
33                 {\r
34                         if (left is DoubleConstant || right is DoubleConstant){\r
35                                 //\r
36                                 // If either side is a double, convert the other to a double\r
37                                 //\r
38                                 if (!(left is DoubleConstant))\r
39                                         left = left.ToDouble (loc);\r
40 \r
41                                 if (!(right is DoubleConstant))\r
42                                         right = right.ToDouble (loc);\r
43                                 return;\r
44                         } else if (left is FloatConstant || right is FloatConstant) {\r
45                                 //\r
46                                 // If either side is a float, convert the other to a float\r
47                                 //\r
48                                 if (!(left is FloatConstant))\r
49                                         left = left.ToFloat (loc);\r
50 \r
51                                 if (!(right is FloatConstant))\r
52                                         right = right.ToFloat (loc);\r
53                                 return;\r
54                         } else if (left is ULongConstant || right is ULongConstant){\r
55                                 //\r
56                                 // If either operand is of type ulong, the other operand is\r
57                                 // converted to type ulong.  or an error ocurrs if the other\r
58                                 // operand is of type sbyte, short, int or long\r
59                                 //\r
60                                 Constant match, other;\r
61                                         \r
62                                 if (left is ULongConstant){\r
63                                         other = right;\r
64                                         match = left;\r
65                                         if (!(right is ULongConstant))\r
66                                                 right = right.ToULong (loc);\r
67                                 } else {\r
68                                         other = left;\r
69                                         match = right;\r
70                                         left = left.ToULong (loc);\r
71                                 }\r
72 \r
73 #if WRONG\r
74                                 if (other is SByteConstant || other is ShortConstant ||\r
75                                     other is IntConstant || other is LongConstant){\r
76                                         Binary.Error_OperatorAmbiguous\r
77                                                 (loc, oper, other.Type, match.Type);\r
78                                         left = null;\r
79                                         right = null;\r
80                                 }\r
81 #endif\r
82                                 return;\r
83                         } else if (left is LongConstant || right is LongConstant){\r
84                                 //\r
85                                 // If either operand is of type long, the other operand is converted\r
86                                 // to type long.\r
87                                 //\r
88                                 if (!(left is LongConstant))\r
89                                         left = left.ToLong (loc);\r
90                                 else if (!(right is LongConstant))\r
91                                         right = right.ToLong (loc);\r
92                                 return;\r
93                         } else if (left is UIntConstant || right is UIntConstant){\r
94                                 //\r
95                                 // If either operand is of type uint, and the other\r
96                                 // operand is of type sbyte, short or int, othe operands are\r
97                                 // converted to type long.\r
98                                 //\r
99                                 if (!(left is UIntConstant))\r
100                                         left = left.ToUInt (loc);\r
101                                 else if (!(right is UIntConstant))\r
102                                         right = right.ToUInt (loc);\r
103                                 return;\r
104                         } else {\r
105                                 //\r
106                                 // Force conversions to int32\r
107                                 //\r
108                                 if (!(left is IntConstant))\r
109                                         left = left.ToInt (loc);\r
110                                 if (!(right is IntConstant))\r
111                                         right = right.ToInt (loc);\r
112                         }\r
113                         return;\r
114                 }\r
115 \r
116                 static void Error_CompileTimeOverflow (Location loc)\r
117                 {\r
118                         Report.Error (220, loc, "The operation overflows at compile time in checked mode");\r
119                 }\r
120                 \r
121                 /// <summary>\r
122                 ///   Constant expression folder for binary operations.\r
123                 ///\r
124                 ///   Returns null if the expression can not be folded.\r
125                 /// </summary>\r
126                 static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,\r
127                                                      Constant left, Constant right, Location loc)\r
128                 {\r
129                         Type lt = left.Type;\r
130                         Type rt = right.Type;\r
131                         Type result_type = null;\r
132                         bool bool_res;\r
133                         \r
134                         //\r
135                         // Enumerator folding\r
136                         //\r
137                         if (rt == lt && left is EnumConstant)\r
138                                 result_type = lt;\r
139 \r
140                         switch (oper){\r
141                         case Binary.Operator.BitwiseOr:\r
142                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
143                                 if (left == null || right == null)\r
144                                         return null;\r
145                                 \r
146                                 if (left is IntConstant){\r
147                                         IntConstant v;\r
148                                         int res = ((IntConstant) left).Value | ((IntConstant) right).Value;\r
149                                         \r
150                                         v = new IntConstant (res);\r
151                                         if (result_type == null)\r
152                                                 return v;\r
153                                         else\r
154                                                 return new EnumConstant (v, result_type);\r
155                                 } else if (left is UIntConstant){\r
156                                         UIntConstant v;\r
157                                         uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;\r
158                                         \r
159                                         v = new UIntConstant (res);\r
160                                         if (result_type == null)\r
161                                                 return v;\r
162                                         else\r
163                                                 return new EnumConstant (v, result_type);\r
164                                 } else if (left is LongConstant){\r
165                                         LongConstant v;\r
166                                         long res = ((LongConstant)left).Value | ((LongConstant)right).Value;\r
167                                         \r
168                                         v = new LongConstant (res);\r
169                                         if (result_type == null)\r
170                                                 return v;\r
171                                         else\r
172                                                 return new EnumConstant (v, result_type);\r
173                                 } else if (left is ULongConstant){\r
174                                         ULongConstant v;\r
175                                         ulong res = ((ULongConstant)left).Value |\r
176                                                 ((ULongConstant)right).Value;\r
177                                         \r
178                                         v = new ULongConstant (res);\r
179                                         if (result_type == null)\r
180                                                 return v;\r
181                                         else\r
182                                                 return new EnumConstant (v, result_type);\r
183                                 }\r
184                                 break;\r
185                                 \r
186                         case Binary.Operator.BitwiseAnd:\r
187                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
188                                 if (left == null || right == null)\r
189                                         return null;\r
190                                 \r
191                                 if (left is IntConstant){\r
192                                         IntConstant v;\r
193                                         int res = ((IntConstant) left).Value & ((IntConstant) right).Value;\r
194                                         \r
195                                         v = new IntConstant (res);\r
196                                         if (result_type == null)\r
197                                                 return v;\r
198                                         else\r
199                                                 return new EnumConstant (v, result_type);\r
200                                 } else if (left is UIntConstant){\r
201                                         UIntConstant v;\r
202                                         uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;\r
203                                         \r
204                                         v = new UIntConstant (res);\r
205                                         if (result_type == null)\r
206                                                 return v;\r
207                                         else\r
208                                                 return new EnumConstant (v, result_type);\r
209                                 } else if (left is LongConstant){\r
210                                         LongConstant v;\r
211                                         long res = ((LongConstant)left).Value & ((LongConstant)right).Value;\r
212                                         \r
213                                         v = new LongConstant (res);\r
214                                         if (result_type == null)\r
215                                                 return v;\r
216                                         else\r
217                                                 return new EnumConstant (v, result_type);\r
218                                 } else if (left is ULongConstant){\r
219                                         ULongConstant v;\r
220                                         ulong res = ((ULongConstant)left).Value &\r
221                                                 ((ULongConstant)right).Value;\r
222                                         \r
223                                         v = new ULongConstant (res);\r
224                                         if (result_type == null)\r
225                                                 return v;\r
226                                         else\r
227                                                 return new EnumConstant (v, result_type);\r
228                                 }\r
229                                 break;\r
230 \r
231                         case Binary.Operator.ExclusiveOr:\r
232                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
233                                 if (left == null || right == null)\r
234                                         return null;\r
235                                 \r
236                                 if (left is IntConstant){\r
237                                         IntConstant v;\r
238                                         int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;\r
239                                         \r
240                                         v = new IntConstant (res);\r
241                                         if (result_type == null)\r
242                                                 return v;\r
243                                         else\r
244                                                 return new EnumConstant (v, result_type);\r
245                                 } else if (left is UIntConstant){\r
246                                         UIntConstant v;\r
247                                         uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;\r
248                                         \r
249                                         v = new UIntConstant (res);\r
250                                         if (result_type == null)\r
251                                                 return v;\r
252                                         else\r
253                                                 return new EnumConstant (v, result_type);\r
254                                 } else if (left is LongConstant){\r
255                                         LongConstant v;\r
256                                         long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;\r
257                                         \r
258                                         v = new LongConstant (res);\r
259                                         if (result_type == null)\r
260                                                 return v;\r
261                                         else\r
262                                                 return new EnumConstant (v, result_type);\r
263                                 } else if (left is ULongConstant){\r
264                                         ULongConstant v;\r
265                                         ulong res = ((ULongConstant)left).Value ^\r
266                                                 ((ULongConstant)right).Value;\r
267                                         \r
268                                         v = new ULongConstant (res);\r
269                                         if (result_type == null)\r
270                                                 return v;\r
271                                         else\r
272                                                 return new EnumConstant (v, result_type);\r
273                                 }\r
274                                 break;\r
275 \r
276                         case Binary.Operator.Addition:\r
277                                 bool left_is_string = left is StringConstant;\r
278                                 bool right_is_string = right is StringConstant;\r
279 \r
280                                 //\r
281                                 // If both sides are strings, then concatenate, if\r
282                                 // one is a string, and the other is not, then defer\r
283                                 // to runtime concatenation\r
284                                 //\r
285                                 if (left_is_string || right_is_string){\r
286                                         if (left_is_string && right_is_string)\r
287                                                 return new StringConstant (\r
288                                                         ((StringConstant) left).Value +\r
289                                                         ((StringConstant) right).Value);\r
290                                         \r
291                                         return null;\r
292                                 }\r
293 \r
294                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
295                                 if (left == null || right == null)\r
296                                         return null;\r
297 \r
298                                 try {\r
299                                         if (left is DoubleConstant){\r
300                                                 double res;\r
301                                                 \r
302                                                 if (ec.ConstantCheckState)\r
303                                                         res = checked (((DoubleConstant) left).Value +\r
304                                                                        ((DoubleConstant) right).Value);\r
305                                                 else\r
306                                                         res = unchecked (((DoubleConstant) left).Value +\r
307                                                                          ((DoubleConstant) right).Value);\r
308                                                 \r
309                                                 return new DoubleConstant (res);\r
310                                         } else if (left is FloatConstant){\r
311                                                 float res;\r
312                                                 \r
313                                                 if (ec.ConstantCheckState)\r
314                                                         res = checked (((FloatConstant) left).Value +\r
315                                                                        ((FloatConstant) right).Value);\r
316                                                 else\r
317                                                         res = unchecked (((FloatConstant) left).Value +\r
318                                                                          ((FloatConstant) right).Value);\r
319                                                 \r
320                                                 return new FloatConstant (res);\r
321                                         } else if (left is ULongConstant){\r
322                                                 ulong res;\r
323                                                 \r
324                                                 if (ec.ConstantCheckState)\r
325                                                         res = checked (((ULongConstant) left).Value +\r
326                                                                        ((ULongConstant) right).Value);\r
327                                                 else\r
328                                                         res = unchecked (((ULongConstant) left).Value +\r
329                                                                          ((ULongConstant) right).Value);\r
330                                                 \r
331                                                 return new ULongConstant (res);\r
332                                         } else if (left is LongConstant){\r
333                                                 long res;\r
334                                                 \r
335                                                 if (ec.ConstantCheckState)\r
336                                                         res = checked (((LongConstant) left).Value +\r
337                                                                        ((LongConstant) right).Value);\r
338                                                 else\r
339                                                         res = unchecked (((LongConstant) left).Value +\r
340                                                                          ((LongConstant) right).Value);\r
341                                                 \r
342                                                 return new LongConstant (res);\r
343                                         } else if (left is UIntConstant){\r
344                                                 uint res;\r
345                                                 \r
346                                                 if (ec.ConstantCheckState)\r
347                                                         res = checked (((UIntConstant) left).Value +\r
348                                                                        ((UIntConstant) right).Value);\r
349                                                 else\r
350                                                         res = unchecked (((UIntConstant) left).Value +\r
351                                                                          ((UIntConstant) right).Value);\r
352                                                 \r
353                                                 return new UIntConstant (res);\r
354                                         } else if (left is IntConstant){\r
355                                                 int res;\r
356 \r
357                                                 if (ec.ConstantCheckState)\r
358                                                         res = checked (((IntConstant) left).Value +\r
359                                                                        ((IntConstant) right).Value);\r
360                                                 else\r
361                                                         res = unchecked (((IntConstant) left).Value +\r
362                                                                          ((IntConstant) right).Value);\r
363 \r
364                                                 return new IntConstant (res);\r
365                                         } else {\r
366                                                 throw new Exception ( "Unexepected input: " + left);\r
367                                         }\r
368                                 } catch (OverflowException){\r
369                                         Error_CompileTimeOverflow (loc);\r
370                                 }\r
371                                 break;\r
372 \r
373                         case Binary.Operator.Subtraction:\r
374                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
375                                 if (left == null || right == null)\r
376                                         return null;\r
377 \r
378                                 try {\r
379                                         if (left is DoubleConstant){\r
380                                                 double res;\r
381                                                 \r
382                                                 if (ec.ConstantCheckState)\r
383                                                         res = checked (((DoubleConstant) left).Value -\r
384                                                                        ((DoubleConstant) right).Value);\r
385                                                 else\r
386                                                         res = unchecked (((DoubleConstant) left).Value -\r
387                                                                          ((DoubleConstant) right).Value);\r
388                                                 \r
389                                                 return new DoubleConstant (res);\r
390                                         } else if (left is FloatConstant){\r
391                                                 float res;\r
392                                                 \r
393                                                 if (ec.ConstantCheckState)\r
394                                                         res = checked (((FloatConstant) left).Value -\r
395                                                                        ((FloatConstant) right).Value);\r
396                                                 else\r
397                                                         res = unchecked (((FloatConstant) left).Value -\r
398                                                                          ((FloatConstant) right).Value);\r
399                                                 \r
400                                                 return new FloatConstant (res);\r
401                                         } else if (left is ULongConstant){\r
402                                                 ulong res;\r
403                                                 \r
404                                                 if (ec.ConstantCheckState)\r
405                                                         res = checked (((ULongConstant) left).Value -\r
406                                                                        ((ULongConstant) right).Value);\r
407                                                 else\r
408                                                         res = unchecked (((ULongConstant) left).Value -\r
409                                                                          ((ULongConstant) right).Value);\r
410                                                 \r
411                                                 return new ULongConstant (res);\r
412                                         } else if (left is LongConstant){\r
413                                                 long res;\r
414                                                 \r
415                                                 if (ec.ConstantCheckState)\r
416                                                         res = checked (((LongConstant) left).Value -\r
417                                                                        ((LongConstant) right).Value);\r
418                                                 else\r
419                                                         res = unchecked (((LongConstant) left).Value -\r
420                                                                          ((LongConstant) right).Value);\r
421                                                 \r
422                                                 return new LongConstant (res);\r
423                                         } else if (left is UIntConstant){\r
424                                                 uint res;\r
425                                                 \r
426                                                 if (ec.ConstantCheckState)\r
427                                                         res = checked (((UIntConstant) left).Value -\r
428                                                                        ((UIntConstant) right).Value);\r
429                                                 else\r
430                                                         res = unchecked (((UIntConstant) left).Value -\r
431                                                                          ((UIntConstant) right).Value);\r
432                                                 \r
433                                                 return new UIntConstant (res);\r
434                                         } else if (left is IntConstant){\r
435                                                 int res;\r
436 \r
437                                                 if (ec.ConstantCheckState)\r
438                                                         res = checked (((IntConstant) left).Value -\r
439                                                                        ((IntConstant) right).Value);\r
440                                                 else\r
441                                                         res = unchecked (((IntConstant) left).Value -\r
442                                                                          ((IntConstant) right).Value);\r
443 \r
444                                                 return new IntConstant (res);\r
445                                         } else {\r
446                                                 throw new Exception ( "Unexepected input: " + left);\r
447                                         }\r
448                                 } catch (OverflowException){\r
449                                         Error_CompileTimeOverflow (loc);\r
450                                 }\r
451                                 break;\r
452                                 \r
453                         case Binary.Operator.Multiply:\r
454                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
455                                 if (left == null || right == null)\r
456                                         return null;\r
457 \r
458                                 try {\r
459                                         if (left is DoubleConstant){\r
460                                                 double res;\r
461                                                 \r
462                                                 if (ec.ConstantCheckState)\r
463                                                         res = checked (((DoubleConstant) left).Value *\r
464                                                                        ((DoubleConstant) right).Value);\r
465                                                 else\r
466                                                         res = unchecked (((DoubleConstant) left).Value *\r
467                                                                          ((DoubleConstant) right).Value);\r
468                                                 \r
469                                                 return new DoubleConstant (res);\r
470                                         } else if (left is FloatConstant){\r
471                                                 float res;\r
472                                                 \r
473                                                 if (ec.ConstantCheckState)\r
474                                                         res = checked (((FloatConstant) left).Value *\r
475                                                                        ((FloatConstant) right).Value);\r
476                                                 else\r
477                                                         res = unchecked (((FloatConstant) left).Value *\r
478                                                                          ((FloatConstant) right).Value);\r
479                                                 \r
480                                                 return new FloatConstant (res);\r
481                                         } else if (left is ULongConstant){\r
482                                                 ulong res;\r
483                                                 \r
484                                                 if (ec.ConstantCheckState)\r
485                                                         res = checked (((ULongConstant) left).Value *\r
486                                                                        ((ULongConstant) right).Value);\r
487                                                 else\r
488                                                         res = unchecked (((ULongConstant) left).Value *\r
489                                                                          ((ULongConstant) right).Value);\r
490                                                 \r
491                                                 return new ULongConstant (res);\r
492                                         } else if (left is LongConstant){\r
493                                                 long res;\r
494                                                 \r
495                                                 if (ec.ConstantCheckState)\r
496                                                         res = checked (((LongConstant) left).Value *\r
497                                                                        ((LongConstant) right).Value);\r
498                                                 else\r
499                                                         res = unchecked (((LongConstant) left).Value *\r
500                                                                          ((LongConstant) right).Value);\r
501                                                 \r
502                                                 return new LongConstant (res);\r
503                                         } else if (left is UIntConstant){\r
504                                                 uint res;\r
505                                                 \r
506                                                 if (ec.ConstantCheckState)\r
507                                                         res = checked (((UIntConstant) left).Value *\r
508                                                                        ((UIntConstant) right).Value);\r
509                                                 else\r
510                                                         res = unchecked (((UIntConstant) left).Value *\r
511                                                                          ((UIntConstant) right).Value);\r
512                                                 \r
513                                                 return new UIntConstant (res);\r
514                                         } else if (left is IntConstant){\r
515                                                 int res;\r
516 \r
517                                                 if (ec.ConstantCheckState)\r
518                                                         res = checked (((IntConstant) left).Value *\r
519                                                                        ((IntConstant) right).Value);\r
520                                                 else\r
521                                                         res = unchecked (((IntConstant) left).Value *\r
522                                                                          ((IntConstant) right).Value);\r
523 \r
524                                                 return new IntConstant (res);\r
525                                         } else {\r
526                                                 throw new Exception ( "Unexepected input: " + left);\r
527                                         }\r
528                                 } catch (OverflowException){\r
529                                         Error_CompileTimeOverflow (loc);\r
530                                 }\r
531                                 break;\r
532 \r
533                         case Binary.Operator.Division:\r
534                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
535                                 if (left == null || right == null)\r
536                                         return null;\r
537 \r
538                                 try {\r
539                                         if (left is DoubleConstant){\r
540                                                 double res;\r
541                                                 \r
542                                                 if (ec.ConstantCheckState)\r
543                                                         res = checked (((DoubleConstant) left).Value /\r
544                                                                        ((DoubleConstant) right).Value);\r
545                                                 else\r
546                                                         res = unchecked (((DoubleConstant) left).Value /\r
547                                                                          ((DoubleConstant) right).Value);\r
548                                                 \r
549                                                 return new DoubleConstant (res);\r
550                                         } else if (left is FloatConstant){\r
551                                                 float res;\r
552                                                 \r
553                                                 if (ec.ConstantCheckState)\r
554                                                         res = checked (((FloatConstant) left).Value /\r
555                                                                        ((FloatConstant) right).Value);\r
556                                                 else\r
557                                                         res = unchecked (((FloatConstant) left).Value /\r
558                                                                          ((FloatConstant) right).Value);\r
559                                                 \r
560                                                 return new FloatConstant (res);\r
561                                         } else if (left is ULongConstant){\r
562                                                 ulong res;\r
563                                                 \r
564                                                 if (ec.ConstantCheckState)\r
565                                                         res = checked (((ULongConstant) left).Value /\r
566                                                                        ((ULongConstant) right).Value);\r
567                                                 else\r
568                                                         res = unchecked (((ULongConstant) left).Value /\r
569                                                                          ((ULongConstant) right).Value);\r
570                                                 \r
571                                                 return new ULongConstant (res);\r
572                                         } else if (left is LongConstant){\r
573                                                 long res;\r
574                                                 \r
575                                                 if (ec.ConstantCheckState)\r
576                                                         res = checked (((LongConstant) left).Value /\r
577                                                                        ((LongConstant) right).Value);\r
578                                                 else\r
579                                                         res = unchecked (((LongConstant) left).Value /\r
580                                                                          ((LongConstant) right).Value);\r
581                                                 \r
582                                                 return new LongConstant (res);\r
583                                         } else if (left is UIntConstant){\r
584                                                 uint res;\r
585                                                 \r
586                                                 if (ec.ConstantCheckState)\r
587                                                         res = checked (((UIntConstant) left).Value /\r
588                                                                        ((UIntConstant) right).Value);\r
589                                                 else\r
590                                                         res = unchecked (((UIntConstant) left).Value /\r
591                                                                          ((UIntConstant) right).Value);\r
592                                                 \r
593                                                 return new UIntConstant (res);\r
594                                         } else if (left is IntConstant){\r
595                                                 int res;\r
596 \r
597                                                 if (ec.ConstantCheckState)\r
598                                                         res = checked (((IntConstant) left).Value /\r
599                                                                        ((IntConstant) right).Value);\r
600                                                 else\r
601                                                         res = unchecked (((IntConstant) left).Value /\r
602                                                                          ((IntConstant) right).Value);\r
603 \r
604                                                 return new IntConstant (res);\r
605                                         } else {\r
606                                                 throw new Exception ( "Unexepected input: " + left);\r
607                                         }\r
608                                 } catch (OverflowException){\r
609                                         Error_CompileTimeOverflow (loc);\r
610                                 }\r
611                                 break;\r
612                                 \r
613                         case Binary.Operator.Modulus:\r
614                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
615                                 if (left == null || right == null)\r
616                                         return null;\r
617 \r
618                                 try {\r
619                                         if (left is DoubleConstant){\r
620                                                 double res;\r
621                                                 \r
622                                                 if (ec.ConstantCheckState)\r
623                                                         res = checked (((DoubleConstant) left).Value %\r
624                                                                        ((DoubleConstant) right).Value);\r
625                                                 else\r
626                                                         res = unchecked (((DoubleConstant) left).Value %\r
627                                                                          ((DoubleConstant) right).Value);\r
628                                                 \r
629                                                 return new DoubleConstant (res);\r
630                                         } else if (left is FloatConstant){\r
631                                                 float res;\r
632                                                 \r
633                                                 if (ec.ConstantCheckState)\r
634                                                         res = checked (((FloatConstant) left).Value %\r
635                                                                        ((FloatConstant) right).Value);\r
636                                                 else\r
637                                                         res = unchecked (((FloatConstant) left).Value %\r
638                                                                          ((FloatConstant) right).Value);\r
639                                                 \r
640                                                 return new FloatConstant (res);\r
641                                         } else if (left is ULongConstant){\r
642                                                 ulong res;\r
643                                                 \r
644                                                 if (ec.ConstantCheckState)\r
645                                                         res = checked (((ULongConstant) left).Value %\r
646                                                                        ((ULongConstant) right).Value);\r
647                                                 else\r
648                                                         res = unchecked (((ULongConstant) left).Value %\r
649                                                                          ((ULongConstant) right).Value);\r
650                                                 \r
651                                                 return new ULongConstant (res);\r
652                                         } else if (left is LongConstant){\r
653                                                 long res;\r
654                                                 \r
655                                                 if (ec.ConstantCheckState)\r
656                                                         res = checked (((LongConstant) left).Value %\r
657                                                                        ((LongConstant) right).Value);\r
658                                                 else\r
659                                                         res = unchecked (((LongConstant) left).Value %\r
660                                                                          ((LongConstant) right).Value);\r
661                                                 \r
662                                                 return new LongConstant (res);\r
663                                         } else if (left is UIntConstant){\r
664                                                 uint res;\r
665                                                 \r
666                                                 if (ec.ConstantCheckState)\r
667                                                         res = checked (((UIntConstant) left).Value %\r
668                                                                        ((UIntConstant) right).Value);\r
669                                                 else\r
670                                                         res = unchecked (((UIntConstant) left).Value %\r
671                                                                          ((UIntConstant) right).Value);\r
672                                                 \r
673                                                 return new UIntConstant (res);\r
674                                         } else if (left is IntConstant){\r
675                                                 int res;\r
676 \r
677                                                 if (ec.ConstantCheckState)\r
678                                                         res = checked (((IntConstant) left).Value %\r
679                                                                        ((IntConstant) right).Value);\r
680                                                 else\r
681                                                         res = unchecked (((IntConstant) left).Value %\r
682                                                                          ((IntConstant) right).Value);\r
683 \r
684                                                 return new IntConstant (res);\r
685                                         } else {\r
686                                                 throw new Exception ( "Unexepected input: " + left);\r
687                                         }\r
688                                 } catch (OverflowException){\r
689                                         Error_CompileTimeOverflow (loc);\r
690                                 }\r
691                                 break;\r
692 \r
693                                 //\r
694                                 // There is no overflow checking on left shift\r
695                                 //\r
696                         case Binary.Operator.LeftShift:\r
697                                 IntConstant ic = right.ToInt (loc);\r
698                                 if (ic == null){\r
699                                         Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);\r
700                                         return null;\r
701                                 }\r
702                                 int lshift_val = ic.Value;\r
703 \r
704                                 IntConstant lic;\r
705                                 if ((lic = left.ConvertToInt ()) != null)\r
706                                         return new IntConstant (lic.Value << lshift_val);\r
707 \r
708                                 UIntConstant luic;\r
709                                 if ((luic = left.ConvertToUInt ()) != null)\r
710                                         return new UIntConstant (luic.Value << lshift_val);\r
711 \r
712                                 LongConstant llc;\r
713                                 if ((llc = left.ConvertToLong ()) != null)\r
714                                         return new LongConstant (llc.Value << lshift_val);\r
715 \r
716                                 ULongConstant lulc;\r
717                                 if ((lulc = left.ConvertToULong ()) != null)\r
718                                         return new ULongConstant (lulc.Value << lshift_val);\r
719 \r
720                                 Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);\r
721                                 break;\r
722 \r
723                                 //\r
724                                 // There is no overflow checking on right shift\r
725                                 //\r
726                         case Binary.Operator.RightShift:\r
727                                 IntConstant sic = right.ToInt (loc);\r
728                                 if (sic == null){\r
729                                         Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);\r
730                                         return null;\r
731                                 }\r
732                                 int rshift_val = sic.Value;\r
733 \r
734                                 IntConstant ric;\r
735                                 if ((ric = left.ConvertToInt ()) != null)\r
736                                         return new IntConstant (ric.Value >> rshift_val);\r
737 \r
738                                 UIntConstant ruic;\r
739                                 if ((ruic = left.ConvertToUInt ()) != null)\r
740                                         return new UIntConstant (ruic.Value >> rshift_val);\r
741 \r
742                                 LongConstant rlc;\r
743                                 if ((rlc = left.ConvertToLong ()) != null)\r
744                                         return new LongConstant (rlc.Value >> rshift_val);\r
745 \r
746                                 ULongConstant rulc;\r
747                                 if ((rulc = left.ConvertToULong ()) != null)\r
748                                         return new ULongConstant (rulc.Value >> rshift_val);\r
749 \r
750                                 Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);\r
751                                 break;\r
752 \r
753                         case Binary.Operator.LogicalAnd:\r
754                                 if (left is BoolConstant && right is BoolConstant){\r
755                                         return new BoolConstant (\r
756                                                 ((BoolConstant) left).Value &&\r
757                                                 ((BoolConstant) right).Value);\r
758                                 }\r
759                                 break;\r
760 \r
761                         case Binary.Operator.LogicalOr:\r
762                                 if (left is BoolConstant && right is BoolConstant){\r
763                                         return new BoolConstant (\r
764                                                 ((BoolConstant) left).Value ||\r
765                                                 ((BoolConstant) right).Value);\r
766                                 }\r
767                                 break;\r
768                                 \r
769                         case Binary.Operator.Equality:\r
770                                 if (left is BoolConstant && right is BoolConstant){\r
771                                         return new BoolConstant (\r
772                                                 ((BoolConstant) left).Value ==\r
773                                                 ((BoolConstant) right).Value);\r
774                                 \r
775                                 }\r
776                                 if (left is StringConstant && right is StringConstant){\r
777                                         return new BoolConstant (\r
778                                                 ((StringConstant) left).Value ==\r
779                                                 ((StringConstant) right).Value);\r
780                                         \r
781                                 }\r
782                                 \r
783                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
784                                 if (left == null || right == null)\r
785                                         return null;\r
786 \r
787                                 bool_res = false;\r
788                                 if (left is DoubleConstant)\r
789                                         bool_res = ((DoubleConstant) left).Value ==\r
790                                                 ((DoubleConstant) right).Value;\r
791                                 else if (left is FloatConstant)\r
792                                         bool_res = ((FloatConstant) left).Value ==\r
793                                                 ((FloatConstant) right).Value;\r
794                                 else if (left is ULongConstant)\r
795                                         bool_res = ((ULongConstant) left).Value ==\r
796                                                 ((ULongConstant) right).Value;\r
797                                 else if (left is LongConstant)\r
798                                         bool_res = ((LongConstant) left).Value ==\r
799                                                 ((LongConstant) right).Value;\r
800                                 else if (left is UIntConstant)\r
801                                         bool_res = ((UIntConstant) left).Value ==\r
802                                                 ((UIntConstant) right).Value;\r
803                                 else if (left is IntConstant)\r
804                                         bool_res = ((IntConstant) left).Value ==\r
805                                                 ((IntConstant) right).Value;\r
806                                 else\r
807                                         return null;\r
808 \r
809                                 return new BoolConstant (bool_res);\r
810 \r
811                         case Binary.Operator.Inequality:\r
812                                 if (left is BoolConstant && right is BoolConstant){\r
813                                         return new BoolConstant (\r
814                                                 ((BoolConstant) left).Value !=\r
815                                                 ((BoolConstant) right).Value);\r
816                                 }\r
817                                 if (left is StringConstant && right is StringConstant){\r
818                                         return new BoolConstant (\r
819                                                 ((StringConstant) left).Value !=\r
820                                                 ((StringConstant) right).Value);\r
821                                         \r
822                                 }\r
823                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
824                                 if (left == null || right == null)\r
825                                         return null;\r
826 \r
827                                 bool_res = false;\r
828                                 if (left is DoubleConstant)\r
829                                         bool_res = ((DoubleConstant) left).Value !=\r
830                                                 ((DoubleConstant) right).Value;\r
831                                 else if (left is FloatConstant)\r
832                                         bool_res = ((FloatConstant) left).Value !=\r
833                                                 ((FloatConstant) right).Value;\r
834                                 else if (left is ULongConstant)\r
835                                         bool_res = ((ULongConstant) left).Value !=\r
836                                                 ((ULongConstant) right).Value;\r
837                                 else if (left is LongConstant)\r
838                                         bool_res = ((LongConstant) left).Value !=\r
839                                                 ((LongConstant) right).Value;\r
840                                 else if (left is UIntConstant)\r
841                                         bool_res = ((UIntConstant) left).Value !=\r
842                                                 ((UIntConstant) right).Value;\r
843                                 else if (left is IntConstant)\r
844                                         bool_res = ((IntConstant) left).Value !=\r
845                                                 ((IntConstant) right).Value;\r
846                                 else\r
847                                         return null;\r
848 \r
849                                 return new BoolConstant (bool_res);\r
850 \r
851                         case Binary.Operator.LessThan:\r
852                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
853                                 if (left == null || right == null)\r
854                                         return null;\r
855 \r
856                                 bool_res = false;\r
857                                 if (left is DoubleConstant)\r
858                                         bool_res = ((DoubleConstant) left).Value <\r
859                                                 ((DoubleConstant) right).Value;\r
860                                 else if (left is FloatConstant)\r
861                                         bool_res = ((FloatConstant) left).Value <\r
862                                                 ((FloatConstant) right).Value;\r
863                                 else if (left is ULongConstant)\r
864                                         bool_res = ((ULongConstant) left).Value <\r
865                                                 ((ULongConstant) right).Value;\r
866                                 else if (left is LongConstant)\r
867                                         bool_res = ((LongConstant) left).Value <\r
868                                                 ((LongConstant) right).Value;\r
869                                 else if (left is UIntConstant)\r
870                                         bool_res = ((UIntConstant) left).Value <\r
871                                                 ((UIntConstant) right).Value;\r
872                                 else if (left is IntConstant)\r
873                                         bool_res = ((IntConstant) left).Value <\r
874                                                 ((IntConstant) right).Value;\r
875                                 else\r
876                                         return null;\r
877 \r
878                                 return new BoolConstant (bool_res);\r
879                                 \r
880                         case Binary.Operator.GreaterThan:\r
881                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
882                                 if (left == null || right == null)\r
883                                         return null;\r
884 \r
885                                 bool_res = false;\r
886                                 if (left is DoubleConstant)\r
887                                         bool_res = ((DoubleConstant) left).Value >\r
888                                                 ((DoubleConstant) right).Value;\r
889                                 else if (left is FloatConstant)\r
890                                         bool_res = ((FloatConstant) left).Value >\r
891                                                 ((FloatConstant) right).Value;\r
892                                 else if (left is ULongConstant)\r
893                                         bool_res = ((ULongConstant) left).Value >\r
894                                                 ((ULongConstant) right).Value;\r
895                                 else if (left is LongConstant)\r
896                                         bool_res = ((LongConstant) left).Value >\r
897                                                 ((LongConstant) right).Value;\r
898                                 else if (left is UIntConstant)\r
899                                         bool_res = ((UIntConstant) left).Value >\r
900                                                 ((UIntConstant) right).Value;\r
901                                 else if (left is IntConstant)\r
902                                         bool_res = ((IntConstant) left).Value >\r
903                                                 ((IntConstant) right).Value;\r
904                                 else\r
905                                         return null;\r
906 \r
907                                 return new BoolConstant (bool_res);\r
908 \r
909                         case Binary.Operator.GreaterThanOrEqual:\r
910                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
911                                 if (left == null || right == null)\r
912                                         return null;\r
913 \r
914                                 bool_res = false;\r
915                                 if (left is DoubleConstant)\r
916                                         bool_res = ((DoubleConstant) left).Value >=\r
917                                                 ((DoubleConstant) right).Value;\r
918                                 else if (left is FloatConstant)\r
919                                         bool_res = ((FloatConstant) left).Value >=\r
920                                                 ((FloatConstant) right).Value;\r
921                                 else if (left is ULongConstant)\r
922                                         bool_res = ((ULongConstant) left).Value >=\r
923                                                 ((ULongConstant) right).Value;\r
924                                 else if (left is LongConstant)\r
925                                         bool_res = ((LongConstant) left).Value >=\r
926                                                 ((LongConstant) right).Value;\r
927                                 else if (left is UIntConstant)\r
928                                         bool_res = ((UIntConstant) left).Value >=\r
929                                                 ((UIntConstant) right).Value;\r
930                                 else if (left is IntConstant)\r
931                                         bool_res = ((IntConstant) left).Value >=\r
932                                                 ((IntConstant) right).Value;\r
933                                 else\r
934                                         return null;\r
935 \r
936                                 return new BoolConstant (bool_res);\r
937 \r
938                         case Binary.Operator.LessThanOrEqual:\r
939                                 DoConstantNumericPromotions (oper, ref left, ref right, loc);\r
940                                 if (left == null || right == null)\r
941                                         return null;\r
942 \r
943                                 bool_res = false;\r
944                                 if (left is DoubleConstant)\r
945                                         bool_res = ((DoubleConstant) left).Value <=\r
946                                                 ((DoubleConstant) right).Value;\r
947                                 else if (left is FloatConstant)\r
948                                         bool_res = ((FloatConstant) left).Value <=\r
949                                                 ((FloatConstant) right).Value;\r
950                                 else if (left is ULongConstant)\r
951                                         bool_res = ((ULongConstant) left).Value <=\r
952                                                 ((ULongConstant) right).Value;\r
953                                 else if (left is LongConstant)\r
954                                         bool_res = ((LongConstant) left).Value <=\r
955                                                 ((LongConstant) right).Value;\r
956                                 else if (left is UIntConstant)\r
957                                         bool_res = ((UIntConstant) left).Value <=\r
958                                                 ((UIntConstant) right).Value;\r
959                                 else if (left is IntConstant)\r
960                                         bool_res = ((IntConstant) left).Value <=\r
961                                                 ((IntConstant) right).Value;\r
962                                 else\r
963                                         return null;\r
964 \r
965                                 return new BoolConstant (bool_res);\r
966                         }\r
967                                         \r
968                         return null;\r
969                 }\r
970         }\r
971 }\r