Flush
[mono.git] / mcs / mcs / ecore.cs
1 //
2 // ecore.cs: Core of the Expression representation for the intermediate tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10
11 namespace Mono.CSharp {
12         using System;
13         using System.Collections;
14         using System.Diagnostics;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Text;
18
19         /// <remarks>
20         ///   The ExprClass class contains the is used to pass the 
21         ///   classification of an expression (value, variable, namespace,
22         ///   type, method group, property access, event access, indexer access,
23         ///   nothing).
24         /// </remarks>
25         public enum ExprClass : byte {
26                 Invalid,
27                 
28                 Value,
29                 Variable,
30                 Namespace,
31                 Type,
32                 MethodGroup,
33                 PropertyAccess,
34                 EventAccess,
35                 IndexerAccess,
36                 Nothing, 
37         }
38
39         /// <summary>
40         ///   This interface is implemented by variables
41         /// </summary>
42         public interface IMemoryLocation {
43                 /// <summary>
44                 ///   The AddressOf method should generate code that loads
45                 ///   the address of the object and leaves it on the stack
46                 /// </summary>
47                 void AddressOf (EmitContext ec);
48         }
49
50         /// <remarks>
51         ///   Base class for expressions
52         /// </remarks>
53         public abstract class Expression {
54                 protected ExprClass eclass;
55                 protected Type      type;
56                 
57                 public Type Type {
58                         get {
59                                 return type;
60                         }
61
62                         set {
63                                 type = value;
64                         }
65                 }
66
67                 public ExprClass ExprClass {
68                         get {
69                                 return eclass;
70                         }
71
72                         set {
73                                 eclass = value;
74                         }
75                 }
76
77                 /// <summary>
78                 ///   Utility wrapper routine for Error, just to beautify the code
79                 /// </summary>
80                 static protected void Error (int error, string s)
81                 {
82                         Report.Error (error, s);
83                 }
84
85                 static protected void Error (int error, Location loc, string s)
86                 {
87                         Report.Error (error, loc, s);
88                 }
89                 
90                 /// <summary>
91                 ///   Utility wrapper routine for Warning, just to beautify the code
92                 /// </summary>
93                 static protected void Warning (int warning, string s)
94                 {
95                         Report.Warning (warning, s);
96                 }
97
98                 static public void error30 (Location loc, Type source, Type target)
99                 {
100                         Report.Error (30, loc, "Cannot convert type '" +
101                                       TypeManager.CSharpName (source) + "' to '" +
102                                       TypeManager.CSharpName (target) + "'");
103                 }
104
105                 /// <summary>
106                 ///   Performs semantic analysis on the Expression
107                 /// </summary>
108                 ///
109                 /// <remarks>
110                 ///   The Resolve method is invoked to perform the semantic analysis
111                 ///   on the node.
112                 ///
113                 ///   The return value is an expression (it can be the
114                 ///   same expression in some cases) or a new
115                 ///   expression that better represents this node.
116                 ///   
117                 ///   For example, optimizations of Unary (LiteralInt)
118                 ///   would return a new LiteralInt with a negated
119                 ///   value.
120                 ///   
121                 ///   If there is an error during semantic analysis,
122                 ///   then an error should be reported (using Report)
123                 ///   and a null value should be returned.
124                 ///   
125                 ///   There are two side effects expected from calling
126                 ///   Resolve(): the the field variable "eclass" should
127                 ///   be set to any value of the enumeration
128                 ///   `ExprClass' and the type variable should be set
129                 ///   to a valid type (this is the type of the
130                 ///   expression).
131                 /// </remarks>
132                 public abstract Expression DoResolve (EmitContext ec);
133
134                 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
135                 {
136                         return DoResolve (ec);
137                 }
138                 
139                 /// <summary>
140                 ///   Resolves an expression and performs semantic analysis on it.
141                 /// </summary>
142                 ///
143                 /// <remarks>
144                 ///   Currently Resolve wraps DoResolve to perform sanity
145                 ///   checking and assertion checking on what we expect from Resolve.
146                 /// </remarks>
147                 public Expression Resolve (EmitContext ec)
148                 {
149                         Expression e = DoResolve (ec);
150
151                         if (e != null){
152                                 if (e is SimpleName){
153                                         SimpleName s = (SimpleName) e;
154                                         
155                                         Report.Error (
156                                                 103, s.Location,
157                                                 "The name `" + s.Name + "' could not be found in `" +
158                                                 ec.TypeContainer.Name + "'");
159                                         return null;
160                                 }
161                                 
162                                 if (e.ExprClass == ExprClass.Invalid)
163                                         throw new Exception ("Expression " + e +
164                                                              " ExprClass is Invalid after resolve");
165
166                                 if (e.ExprClass != ExprClass.MethodGroup)
167                                         if (e.type == null)
168                                                 throw new Exception ("Expression " + e +
169                                                                      " did not set its type after Resolve");
170                         }
171
172                         return e;
173                 }
174
175                 /// <summary>
176                 ///   Performs expression resolution and semantic analysis, but
177                 ///   allows SimpleNames to be returned.
178                 /// </summary>
179                 ///
180                 /// <remarks>
181                 ///   This is used by MemberAccess to construct long names that can not be
182                 ///   partially resolved (namespace-qualified names for example).
183                 /// </remarks>
184                 public Expression ResolveWithSimpleName (EmitContext ec)
185                 {
186                         Expression e = DoResolve (ec);
187
188                         if (e != null){
189                                 if (e is SimpleName)
190                                         return e;
191
192                                 if (e.ExprClass == ExprClass.Invalid)
193                                         throw new Exception ("Expression " + e +
194                                                              " ExprClass is Invalid after resolve");
195
196                                 if (e.ExprClass != ExprClass.MethodGroup)
197                                         if (e.type == null)
198                                                 throw new Exception ("Expression " + e +
199                                                                      " did not set its type after Resolve");
200                         }
201
202                         return e;
203                 }
204                 
205                 /// <summary>
206                 ///   Resolves an expression for LValue assignment
207                 /// </summary>
208                 ///
209                 /// <remarks>
210                 ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
211                 ///   checking and assertion checking on what we expect from Resolve
212                 /// </remarks>
213                 public Expression ResolveLValue (EmitContext ec, Expression right_side)
214                 {
215                         Expression e = DoResolveLValue (ec, right_side);
216
217                         if (e != null){
218                                 if (e is SimpleName){
219                                         SimpleName s = (SimpleName) e;
220                                         
221                                         Report.Error (
222                                                 103, s.Location,
223                                                 "The name `" + s.Name + "' could not be found in `" +
224                                                 ec.TypeContainer.Name + "'");
225                                         return null;
226                                 }
227
228                                 if (e.ExprClass == ExprClass.Invalid)
229                                         throw new Exception ("Expression " + e +
230                                                              " ExprClass is Invalid after resolve");
231
232                                 if (e.ExprClass != ExprClass.MethodGroup)
233                                         if (e.type == null)
234                                                 throw new Exception ("Expression " + e +
235                                                                      " did not set its type after Resolve");
236                         }
237
238                         return e;
239                 }
240                 
241                 /// <summary>
242                 ///   Emits the code for the expression
243                 /// </summary>
244                 ///
245                 /// <remarks>
246                 ///   The Emit method is invoked to generate the code
247                 ///   for the expression.  
248                 /// </remarks>
249                 public abstract void Emit (EmitContext ec);
250
251                 /// <summary>
252                 ///   This method should perform a reduction of the expression.  This should
253                 ///   never return null.
254                 /// </summary>
255                 public virtual Expression Reduce (EmitContext ec)
256                 {
257                         return this;
258                 }
259
260                 /// <summary>
261                 ///   Protected constructor.  Only derivate types should
262                 ///   be able to be created
263                 /// </summary>
264
265                 protected Expression ()
266                 {
267                         eclass = ExprClass.Invalid;
268                         type = null;
269                 }
270
271                 /// <summary>
272                 ///   Returns a literalized version of a literal FieldInfo
273                 /// </summary>
274                 ///
275                 /// <remarks>
276                 ///   The possible return values are:
277                 ///      IntLiteral, UIntLiteral
278                 ///      LongLiteral, ULongLiteral
279                 ///      FloatLiteral, DoubleLiteral
280                 ///      StringLiteral
281                 /// </remarks>
282                 public static Expression Literalize (object v, Type t)
283                 {
284                         if (t == TypeManager.int32_type)
285                                 return new IntLiteral ((int) v);
286                         else if (t == TypeManager.uint32_type)
287                                 return new UIntLiteral ((uint) v);
288                         else if (t == TypeManager.int64_type)
289                                 return new LongLiteral ((long) v);
290                         else if (t == TypeManager.uint64_type)
291                                 return new ULongLiteral ((ulong) v);
292                         else if (t == TypeManager.float_type)
293                                 return new FloatLiteral ((float) v);
294                         else if (t == TypeManager.double_type)
295                                 return new DoubleLiteral ((double) v);
296                         else if (t == TypeManager.string_type)
297                                 return new StringLiteral ((string) v);
298                         else if (t == TypeManager.short_type)
299                                 return new IntLiteral ((int) ((short)v));
300                         else if (t == TypeManager.ushort_type)
301                                 return new IntLiteral ((int) ((ushort)v));
302                         else if (t == TypeManager.sbyte_type)
303                                 return new IntLiteral ((int) ((sbyte)v));
304                         else if (t == TypeManager.byte_type)
305                                 return new IntLiteral ((int) ((byte)v));
306                         else if (t == TypeManager.char_type)
307                                 return new IntLiteral ((int) ((char)v));
308                         else
309                                 throw new Exception ("Unknown type for literal (" + t +
310                                                      "), details: " + v);
311                 }
312
313                 /// <summary>
314                 ///   Returns a fully formed expression after a MemberLookup
315                 /// </summary>
316                 static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
317                 {
318                         if (mi is EventInfo)
319                                 return new EventExpr ((EventInfo) mi, loc);
320                         else if (mi is FieldInfo)
321                                 return new FieldExpr ((FieldInfo) mi, loc);
322                         else if (mi is PropertyInfo)
323                                 return new PropertyExpr ((PropertyInfo) mi, loc);
324                         else if (mi is Type){
325                                 return new TypeExpr ((Type) mi);
326                         }
327
328                         return null;
329                 }
330
331                 //
332                 // We copy methods from `new_members' into `target_list' if the signature
333                 // for the method from in the new list does not exist in the target_list
334                 //
335                 // The name is assumed to be the same.
336                 //
337                 static ArrayList CopyNewMethods (ArrayList target_list, MemberInfo [] new_members)
338                 {
339                         if (target_list == null){
340                                 target_list = new ArrayList ();
341
342                                 target_list.AddRange (new_members);
343                                 return target_list;
344                         }
345                         
346                         MemberInfo [] target_array = new MemberInfo [target_list.Count];
347                         target_list.CopyTo (target_array, 0);
348                         
349                         foreach (MemberInfo mi in new_members){
350                                 MethodBase new_method = (MethodBase) mi;
351                                 Type [] new_args = TypeManager.GetArgumentTypes (new_method);
352                                         
353                                 foreach (MethodBase method in target_array){
354                                         Type [] old_args = TypeManager.GetArgumentTypes (method);
355                                         int new_count = new_args.Length;
356                                         int old_count = old_args.Length;
357                                         
358                                         if (new_count != old_count){
359                                                 target_list.Add (method);
360                                                 continue;
361                                         }
362
363                                         for (int i = 0; i < old_count; i++){
364                                                 if (old_args [i] == new_args [i])
365                                                         continue;
366                                                 target_list.Add (method);
367                                                 break;
368                                         }
369                                 }
370                         }
371                         return target_list;
372                 }
373                 
374                 //
375                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
376                 //
377                 // FIXME: We need to cope with access permissions here, or this wont
378                 // work!
379                 //
380                 // This code could use some optimizations, but we need to do some
381                 // measurements.  For example, we could use a delegate to `flag' when
382                 // something can not any longer be a method-group (because it is something
383                 // else).
384                 //
385                 // Return values:
386                 //     If the return value is an Array, then it is an array of
387                 //     MethodBases
388                 //   
389                 //     If the return value is an MemberInfo, it is anything, but a Method
390                 //
391                 //     null on error.
392                 //
393                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
394                 // the arguments here and have MemberLookup return only the methods that
395                 // match the argument count/type, unlike we are doing now (we delay this
396                 // decision).
397                 //
398                 // This is so we can catch correctly attempts to invoke instance methods
399                 // from a static body (scan for error 120 in ResolveSimpleName).
400                 //
401                 //
402                 // FIXME: Potential optimization, have a static ArrayList
403                 //
404                 public static Expression MemberLookup (EmitContext ec, Type t, string name,
405                                                        bool same_type, MemberTypes mt,
406                                                        BindingFlags bf, Location loc)
407                 {
408                         if (same_type)
409                                 bf |= BindingFlags.NonPublic;
410
411                         //
412                         // Lookup for members starting in the type requested and going
413                         // up the hierarchy until a match is found.
414                         //
415                         // As soon as a non-method match is found, we return.
416                         //
417                         // If methods are found though, then the search proceeds scanning
418                         // for more public methods in the hierarchy with signatures that
419                         // do not match any of the signatures found so far.
420                         //
421                         ArrayList method_list = null;
422                         Type current_type = t;
423                         bool searching = true;
424                         do {
425                                 MemberInfo [] mi;
426
427                                 mi = RootContext.TypeManager.FindMembers (
428                                         current_type, mt, bf | BindingFlags.DeclaredOnly,
429                                         System.Type.FilterName, name);
430                                 
431                                 if (current_type == TypeManager.object_type)
432                                         searching = false;
433                                 else {
434                                         current_type = current_type.BaseType;
435
436                                         //
437                                         // This happens with interfaces, they have a null
438                                         // basetype
439                                         //
440                                         if (current_type == null)
441                                                 searching = false;
442                                 }
443
444                                 if (mi == null)
445                                         continue;
446                                 
447                                 int count = mi.Length;
448
449                                 if (count == 0)
450                                         continue;
451                                 
452                                 if (count == 1 && !(mi [0] is MethodBase))
453                                         return Expression.ExprClassFromMemberInfo (ec, mi [0], loc);
454
455                                 //
456                                 // We found methods, turn the search into "method scan"
457                                 // mode.
458                                 //
459                                 method_list = CopyNewMethods (method_list, mi);
460                                 mt &= (MemberTypes.Method | MemberTypes.Constructor);
461                         } while (searching);
462
463                         if (method_list != null && method_list.Count > 0)
464                                 return new MethodGroupExpr (method_list);
465
466                         return null;
467                 }
468
469                 public const MemberTypes AllMemberTypes =
470                         MemberTypes.Constructor |
471                         MemberTypes.Event       |
472                         MemberTypes.Field       |
473                         MemberTypes.Method      |
474                         MemberTypes.NestedType  |
475                         MemberTypes.Property;
476                 
477                 public const BindingFlags AllBindingsFlags =
478                         BindingFlags.Public |
479                         BindingFlags.Static |
480                         BindingFlags.Instance;
481
482                 public static Expression MemberLookup (EmitContext ec, Type t, string name,
483                                                        bool same_type, Location loc)
484                 {
485                         return MemberLookup (ec, t, name, same_type, AllMemberTypes, AllBindingsFlags, loc);
486                 }
487
488                 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
489                 {
490                         Type expr_type = expr.Type;
491
492                         if (target_type == TypeManager.object_type) {
493                                 if (expr_type.IsClass)
494                                         return new EmptyCast (expr, target_type);
495                                 if (expr_type.IsValueType)
496                                         return new BoxedCast (expr);
497                         } else if (expr_type.IsSubclassOf (target_type)) {
498                                 return new EmptyCast (expr, target_type);
499                         } else {
500                                 // from any class-type S to any interface-type T.
501                                 if (expr_type.IsClass && target_type.IsInterface) {
502                                         if (TypeManager.ImplementsInterface (expr_type, target_type))
503                                                 return new EmptyCast (expr, target_type);
504                                         else
505                                                 return null;
506                                 }
507
508                                 // from any interface type S to interface-type T.
509                                 if (expr_type.IsInterface && target_type.IsInterface) {
510
511                                         if (TypeManager.ImplementsInterface (expr_type, target_type))
512                                                 return new EmptyCast (expr, target_type);
513                                         else
514                                                 return null;
515                                 }
516                                 
517                                 // from an array-type S to an array-type of type T
518                                 if (expr_type.IsArray && target_type.IsArray) {
519                                         if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
520
521                                                 Type expr_element_type = expr_type.GetElementType ();
522                                                 Type target_element_type = target_type.GetElementType ();
523
524                                                 if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
525                                                         if (StandardConversionExists (expr_element_type,
526                                                                                       target_element_type))
527                                                                 return new EmptyCast (expr, target_type);
528                                         }
529                                 }
530                                 
531                                 
532                                 // from an array-type to System.Array
533                                 if (expr_type.IsArray && target_type == TypeManager.array_type)
534                                         return new EmptyCast (expr, target_type);
535                                 
536                                 // from any delegate type to System.Delegate
537                                 if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
538                                     target_type == TypeManager.delegate_type)
539                                         return new EmptyCast (expr, target_type);
540                                         
541                                 // from any array-type or delegate type into System.ICloneable.
542                                 if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
543                                         if (target_type == TypeManager.icloneable_type)
544                                                 return new EmptyCast (expr, target_type);
545                                 
546                                 // from the null type to any reference-type.
547                                 if (expr is NullLiteral)
548                                         return new EmptyCast (expr, target_type);
549
550                                 return null;
551
552                         }
553                         
554                         return null;
555                 }
556
557                 /// <summary>
558                 ///   Handles expressions like this: decimal d; d = 1;
559                 ///   and changes them into: decimal d; d = new System.Decimal (1);
560                 /// </summary>
561                 static Expression InternalTypeConstructor (EmitContext ec, Expression expr, Type target)
562                 {
563                         ArrayList args = new ArrayList ();
564
565                         args.Add (new Argument (expr, Argument.AType.Expression));
566
567                         Expression ne = new New (target.FullName, args,
568                                                  new Location (-1));
569
570                         return ne.Resolve (ec);
571                 }
572
573                 /// <summary>
574                 ///   Implicit Numeric Conversions.
575                 ///
576                 ///   expr is the expression to convert, returns a new expression of type
577                 ///   target_type or null if an implicit conversion is not possible.
578                 /// </summary>
579                 static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
580                                                                     Type target_type, Location loc)
581                 {
582                         Type expr_type = expr.Type;
583                         
584                         //
585                         // Attempt to do the implicit constant expression conversions
586
587                         if (expr is IntLiteral){
588                                 Expression e;
589                                 
590                                 e = TryImplicitIntConversion (target_type, (IntLiteral) expr);
591
592                                 if (e != null)
593                                         return e;
594                         } else if (expr is LongLiteral && target_type == TypeManager.uint64_type){
595                                 //
596                                 // Try the implicit constant expression conversion
597                                 // from long to ulong, instead of a nice routine,
598                                 // we just inline it
599                                 //
600                                 if (((LongLiteral) expr).Value > 0)
601                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
602                         }
603                         
604                         if (expr_type == TypeManager.sbyte_type){
605                                 //
606                                 // From sbyte to short, int, long, float, double.
607                                 //
608                                 if (target_type == TypeManager.int32_type)
609                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
610                                 if (target_type == TypeManager.int64_type)
611                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
612                                 if (target_type == TypeManager.double_type)
613                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
614                                 if (target_type == TypeManager.float_type)
615                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
616                                 if (target_type == TypeManager.short_type)
617                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
618                                 if (target_type == TypeManager.decimal_type)
619                                         return InternalTypeConstructor (ec, expr, target_type);
620                         } else if (expr_type == TypeManager.byte_type){
621                                 //
622                                 // From byte to short, ushort, int, uint, long, ulong, float, double
623                                 // 
624                                 if ((target_type == TypeManager.short_type) ||
625                                     (target_type == TypeManager.ushort_type) ||
626                                     (target_type == TypeManager.int32_type) ||
627                                     (target_type == TypeManager.uint32_type))
628                                         return new EmptyCast (expr, target_type);
629
630                                 if (target_type == TypeManager.uint64_type)
631                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
632                                 if (target_type == TypeManager.int64_type)
633                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
634                                 if (target_type == TypeManager.float_type)
635                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
636                                 if (target_type == TypeManager.double_type)
637                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
638                                 if (target_type == TypeManager.decimal_type)
639                                         return InternalTypeConstructor (ec, expr, target_type);
640                         } else if (expr_type == TypeManager.short_type){
641                                 //
642                                 // From short to int, long, float, double
643                                 // 
644                                 if (target_type == TypeManager.int32_type)
645                                         return new EmptyCast (expr, target_type);
646                                 if (target_type == TypeManager.int64_type)
647                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
648                                 if (target_type == TypeManager.double_type)
649                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
650                                 if (target_type == TypeManager.float_type)
651                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
652                                 if (target_type == TypeManager.decimal_type)
653                                         return InternalTypeConstructor (ec, expr, target_type);
654                         } else if (expr_type == TypeManager.ushort_type){
655                                 //
656                                 // From ushort to int, uint, long, ulong, float, double
657                                 //
658                                 if (target_type == TypeManager.uint32_type)
659                                         return new EmptyCast (expr, target_type);
660
661                                 if (target_type == TypeManager.uint64_type)
662                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
663                                 if (target_type == TypeManager.int32_type)
664                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
665                                 if (target_type == TypeManager.int64_type)
666                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
667                                 if (target_type == TypeManager.double_type)
668                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
669                                 if (target_type == TypeManager.float_type)
670                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
671                                 if (target_type == TypeManager.decimal_type)
672                                         return InternalTypeConstructor (ec, expr, target_type);
673                         } else if (expr_type == TypeManager.int32_type){
674                                 //
675                                 // From int to long, float, double
676                                 //
677                                 if (target_type == TypeManager.int64_type)
678                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
679                                 if (target_type == TypeManager.double_type)
680                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
681                                 if (target_type == TypeManager.float_type)
682                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
683                                 if (target_type == TypeManager.decimal_type)
684                                         return InternalTypeConstructor (ec, expr, target_type);
685                         } else if (expr_type == TypeManager.uint32_type){
686                                 //
687                                 // From uint to long, ulong, float, double
688                                 //
689                                 if (target_type == TypeManager.int64_type)
690                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
691                                 if (target_type == TypeManager.uint64_type)
692                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
693                                 if (target_type == TypeManager.double_type)
694                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
695                                                                OpCodes.Conv_R8);
696                                 if (target_type == TypeManager.float_type)
697                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
698                                                                OpCodes.Conv_R4);
699                                 if (target_type == TypeManager.decimal_type)
700                                         return InternalTypeConstructor (ec, expr, target_type);
701                         } else if ((expr_type == TypeManager.uint64_type) ||
702                                    (expr_type == TypeManager.int64_type)){
703                                 //
704                                 // From long/ulong to float, double
705                                 //
706                                 if (target_type == TypeManager.double_type)
707                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
708                                                                OpCodes.Conv_R8);
709                                 if (target_type == TypeManager.float_type)
710                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
711                                                                OpCodes.Conv_R4);        
712                                 if (target_type == TypeManager.decimal_type)
713                                         return InternalTypeConstructor (ec, expr, target_type);
714                         } else if (expr_type == TypeManager.char_type){
715                                 //
716                                 // From char to ushort, int, uint, long, ulong, float, double
717                                 // 
718                                 if ((target_type == TypeManager.ushort_type) ||
719                                     (target_type == TypeManager.int32_type) ||
720                                     (target_type == TypeManager.uint32_type))
721                                         return new EmptyCast (expr, target_type);
722                                 if (target_type == TypeManager.uint64_type)
723                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
724                                 if (target_type == TypeManager.int64_type)
725                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
726                                 if (target_type == TypeManager.float_type)
727                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
728                                 if (target_type == TypeManager.double_type)
729                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
730                                 if (target_type == TypeManager.decimal_type)
731                                         return InternalTypeConstructor (ec, expr, target_type);
732                         } else if (expr_type == TypeManager.float_type){
733                                 //
734                                 // float to double
735                                 //
736                                 if (target_type == TypeManager.double_type)
737                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
738                         }
739
740                         return null;
741                 }
742
743                 /// <summary>
744                 ///  Determines if a standard implicit conversion exists from
745                 ///  expr_type to target_type
746                 /// </summary>
747                 public static bool StandardConversionExists (Type expr_type, Type target_type)
748                 {
749                         if (expr_type == target_type)
750                                 return true;
751
752                         // First numeric conversions 
753                         
754                         if (expr_type == TypeManager.sbyte_type){
755                                 //
756                                 // From sbyte to short, int, long, float, double.
757                                 //
758                                 if ((target_type == TypeManager.int32_type) || 
759                                     (target_type == TypeManager.int64_type) ||
760                                     (target_type == TypeManager.double_type) ||
761                                     (target_type == TypeManager.float_type)  ||
762                                     (target_type == TypeManager.short_type) ||
763                                     (target_type == TypeManager.decimal_type))
764                                         return true;
765                                 
766                         } else if (expr_type == TypeManager.byte_type){
767                                 //
768                                 // From byte to short, ushort, int, uint, long, ulong, float, double
769                                 // 
770                                 if ((target_type == TypeManager.short_type) ||
771                                     (target_type == TypeManager.ushort_type) ||
772                                     (target_type == TypeManager.int32_type) ||
773                                     (target_type == TypeManager.uint32_type) ||
774                                     (target_type == TypeManager.uint64_type) ||
775                                     (target_type == TypeManager.int64_type) ||
776                                     (target_type == TypeManager.float_type) ||
777                                     (target_type == TypeManager.double_type) ||
778                                     (target_type == TypeManager.decimal_type))
779                                         return true;
780         
781                         } else if (expr_type == TypeManager.short_type){
782                                 //
783                                 // From short to int, long, float, double
784                                 // 
785                                 if ((target_type == TypeManager.int32_type) ||
786                                     (target_type == TypeManager.int64_type) ||
787                                     (target_type == TypeManager.double_type) ||
788                                     (target_type == TypeManager.float_type) ||
789                                     (target_type == TypeManager.decimal_type))
790                                         return true;
791                                         
792                         } else if (expr_type == TypeManager.ushort_type){
793                                 //
794                                 // From ushort to int, uint, long, ulong, float, double
795                                 //
796                                 if ((target_type == TypeManager.uint32_type) ||
797                                     (target_type == TypeManager.uint64_type) ||
798                                     (target_type == TypeManager.int32_type) ||
799                                     (target_type == TypeManager.int64_type) ||
800                                     (target_type == TypeManager.double_type) ||
801                                     (target_type == TypeManager.float_type) ||
802                                     (target_type == TypeManager.decimal_type))
803                                         return true;
804                                     
805                         } else if (expr_type == TypeManager.int32_type){
806                                 //
807                                 // From int to long, float, double
808                                 //
809                                 if ((target_type == TypeManager.int64_type) ||
810                                     (target_type == TypeManager.double_type) ||
811                                     (target_type == TypeManager.float_type) ||
812                                     (target_type == TypeManager.decimal_type))
813                                         return true;
814                                         
815                         } else if (expr_type == TypeManager.uint32_type){
816                                 //
817                                 // From uint to long, ulong, float, double
818                                 //
819                                 if ((target_type == TypeManager.int64_type) ||
820                                     (target_type == TypeManager.uint64_type) ||
821                                     (target_type == TypeManager.double_type) ||
822                                     (target_type == TypeManager.float_type) ||
823                                     (target_type == TypeManager.decimal_type))
824                                         return true;
825                                         
826                         } else if ((expr_type == TypeManager.uint64_type) ||
827                                    (expr_type == TypeManager.int64_type)) {
828                                 //
829                                 // From long/ulong to float, double
830                                 //
831                                 if ((target_type == TypeManager.double_type) ||
832                                     (target_type == TypeManager.float_type) ||
833                                     (target_type == TypeManager.decimal_type))
834                                         return true;
835                                     
836                         } else if (expr_type == TypeManager.char_type){
837                                 //
838                                 // From char to ushort, int, uint, long, ulong, float, double
839                                 // 
840                                 if ((target_type == TypeManager.ushort_type) ||
841                                     (target_type == TypeManager.int32_type) ||
842                                     (target_type == TypeManager.uint32_type) ||
843                                     (target_type == TypeManager.uint64_type) ||
844                                     (target_type == TypeManager.int64_type) ||
845                                     (target_type == TypeManager.float_type) ||
846                                     (target_type == TypeManager.double_type) ||
847                                     (target_type == TypeManager.decimal_type))
848                                         return true;
849
850                         } else if (expr_type == TypeManager.float_type){
851                                 //
852                                 // float to double
853                                 //
854                                 if (target_type == TypeManager.double_type)
855                                         return true;
856                         }       
857                         
858                         // Next reference conversions
859
860                         if (target_type == TypeManager.object_type) {
861                                 if ((expr_type.IsClass) ||
862                                     (expr_type.IsValueType))
863                                         return true;
864                                 
865                         } else if (expr_type.IsSubclassOf (target_type)) {
866                                 return true;
867                                 
868                         } else {
869                                 // from any class-type S to any interface-type T.
870                                 if (expr_type.IsClass && target_type.IsInterface)
871                                         return true;
872                                 
873                                 // from any interface type S to interface-type T.
874                                 // FIXME : Is it right to use IsAssignableFrom ?
875                                 if (expr_type.IsInterface && target_type.IsInterface)
876                                         if (target_type.IsAssignableFrom (expr_type))
877                                                 return true;
878                                 
879                                 // from an array-type S to an array-type of type T
880                                 if (expr_type.IsArray && target_type.IsArray) {
881                                         if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
882                                                 
883                                                 Type expr_element_type = expr_type.GetElementType ();
884                                                 Type target_element_type = target_type.GetElementType ();
885                                                 
886                                                 if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
887                                                         if (StandardConversionExists (expr_element_type,
888                                                                                       target_element_type))
889                                                                 return true;
890                                         }
891                                 }
892                                 
893                                 // from an array-type to System.Array
894                                 if (expr_type.IsArray && target_type.IsAssignableFrom (expr_type))
895                                         return true;
896                                 
897                                 // from any delegate type to System.Delegate
898                                 if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
899                                     target_type == TypeManager.delegate_type)
900                                         if (target_type.IsAssignableFrom (expr_type))
901                                                 return true;
902                                         
903                                 // from any array-type or delegate type into System.ICloneable.
904                                 if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
905                                         if (target_type == TypeManager.icloneable_type)
906                                                 return true;
907                                 
908                                 // from the null type to any reference-type.
909                                 // FIXME : How do we do this ?
910
911                         }
912
913                         return false;
914                 }
915
916                 static EmptyExpression MyEmptyExpr;
917                 /// <summary>
918                 ///   Tells whether an implicit conversion exists from expr_type to
919                 ///   target_type
920                 /// </summary>
921                 public bool ImplicitConversionExists (EmitContext ec, Type expr_type, Type target_type,
922                                                       Location l)
923                 {
924                         if (MyEmptyExpr == null)
925                                 MyEmptyExpr = new EmptyExpression (expr_type);
926                         else
927                                 MyEmptyExpr.SetType (expr_type);
928
929                         return ConvertImplicit (ec, MyEmptyExpr, target_type, l) != null;
930                 }
931                 
932                 /// <summary>
933                 ///  Finds "most encompassed type" according to the spec (13.4.2)
934                 ///  amongst the methods in the MethodGroupExpr which convert from a
935                 ///  type encompassing source_type
936                 /// </summary>
937                 static Type FindMostEncompassedType (MethodGroupExpr me, Type source_type)
938                 {
939                         Type best = null;
940                         
941                         for (int i = me.Methods.Length; i > 0; ) {
942                                 i--;
943
944                                 MethodBase mb = me.Methods [i];
945                                 ParameterData pd = Invocation.GetParameterData (mb);
946                                 Type param_type = pd.ParameterType (0);
947
948                                 if (StandardConversionExists (source_type, param_type)) {
949                                         if (best == null)
950                                                 best = param_type;
951                                         
952                                         if (StandardConversionExists (param_type, best))
953                                                 best = param_type;
954                                 }
955                         }
956
957                         return best;
958                 }
959                 
960                 /// <summary>
961                 ///  Finds "most encompassing type" according to the spec (13.4.2)
962                 ///  amongst the methods in the MethodGroupExpr which convert to a
963                 ///  type encompassed by target_type
964                 /// </summary>
965                 static Type FindMostEncompassingType (MethodGroupExpr me, Type target)
966                 {
967                         Type best = null;
968                         
969                         for (int i = me.Methods.Length; i > 0; ) {
970                                 i--;
971                                 
972                                 MethodInfo mi = (MethodInfo) me.Methods [i];
973                                 Type ret_type = mi.ReturnType;
974                                 
975                                 if (StandardConversionExists (ret_type, target)) {
976                                         if (best == null)
977                                                 best = ret_type;
978
979                                         if (!StandardConversionExists (ret_type, best))
980                                                 best = ret_type;
981                                 }
982                                 
983                         }
984                         
985                         return best;
986
987                 }
988                 
989
990                 /// <summary>
991                 ///  User-defined Implicit conversions
992                 /// </summary>
993                 static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
994                                                                  Type target, Location loc)
995                 {
996                         return UserDefinedConversion (ec, source, target, loc, false);
997                 }
998
999                 /// <summary>
1000                 ///  User-defined Explicit conversions
1001                 /// </summary>
1002                 static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
1003                                                                  Type target, Location loc)
1004                 {
1005                         return UserDefinedConversion (ec, source, target, loc, true);
1006                 }
1007                 
1008                 /// <summary>
1009                 ///   User-defined conversions
1010                 /// </summary>
1011                 static public Expression UserDefinedConversion (EmitContext ec, Expression source,
1012                                                                 Type target, Location loc,
1013                                                                 bool look_for_explicit)
1014                 {
1015                         Expression mg1 = null, mg2 = null, mg3 = null, mg4 = null;
1016                         Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
1017                         Expression e;
1018                         MethodBase method = null;
1019                         Type source_type = source.Type;
1020
1021                         string op_name;
1022                         
1023                         // If we have a boolean type, we need to check for the True operator
1024
1025                         // FIXME : How does the False operator come into the picture ?
1026                         // FIXME : This doesn't look complete and very correct !
1027                         if (target == TypeManager.bool_type)
1028                                 op_name = "op_True";
1029                         else
1030                                 op_name = "op_Implicit";
1031                         
1032                         mg1 = MemberLookup (ec, source_type, op_name, false, loc);
1033
1034                         if (source_type.BaseType != null)
1035                                 mg2 = MemberLookup (ec, source_type.BaseType, op_name, false, loc);
1036                         
1037                         mg3 = MemberLookup (ec, target, op_name, false, loc);
1038
1039                         if (target.BaseType != null)
1040                                 mg4 = MemberLookup (ec, target.BaseType, op_name, false, loc);
1041
1042                         MethodGroupExpr union1 = Invocation.MakeUnionSet (mg1, mg2);
1043                         MethodGroupExpr union2 = Invocation.MakeUnionSet (mg3, mg4);
1044
1045                         MethodGroupExpr union3 = Invocation.MakeUnionSet (union1, union2);
1046
1047                         MethodGroupExpr union4 = null;
1048
1049                         if (look_for_explicit) {
1050
1051                                 op_name = "op_Explicit";
1052                                 
1053                                 mg5 = MemberLookup (ec, source_type, op_name, false, loc);
1054
1055                                 if (source_type.BaseType != null)
1056                                         mg6 = MemberLookup (ec, source_type.BaseType, op_name, false, loc);
1057                                 
1058                                 mg7 = MemberLookup (ec, target, op_name, false, loc);
1059                                 
1060                                 if (target.BaseType != null)
1061                                         mg8 = MemberLookup (ec, target.BaseType, op_name, false, loc);
1062                                 
1063                                 MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6);
1064                                 MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8);
1065
1066                                 union4 = Invocation.MakeUnionSet (union5, union6);
1067                         }
1068                         
1069                         MethodGroupExpr union = Invocation.MakeUnionSet (union3, union4);
1070
1071                         if (union != null) {
1072
1073                                 Type most_specific_source, most_specific_target;
1074
1075                                 most_specific_source = FindMostEncompassedType (union, source_type);
1076                                 if (most_specific_source == null)
1077                                         return null;
1078
1079                                 most_specific_target = FindMostEncompassingType (union, target);
1080                                 if (most_specific_target == null) 
1081                                         return null;
1082                                 
1083                                 int count = 0;
1084                                 
1085                                 for (int i = union.Methods.Length; i > 0;) {
1086                                         i--;
1087
1088                                         MethodBase mb = union.Methods [i];
1089                                         ParameterData pd = Invocation.GetParameterData (mb);
1090                                         MethodInfo mi = (MethodInfo) union.Methods [i];
1091
1092                                         if (pd.ParameterType (0) == most_specific_source &&
1093                                             mi.ReturnType == most_specific_target) {
1094                                                 method = mb;
1095                                                 count++;
1096                                         }
1097                                 }
1098
1099                                 if (method == null || count > 1) {
1100                                         Report.Error (-11, loc, "Ambiguous user defined conversion");
1101                                         return null;
1102                                 }
1103                                 
1104                                 //
1105                                 // This will do the conversion to the best match that we
1106                                 // found.  Now we need to perform an implict standard conversion
1107                                 // if the best match was not the type that we were requested
1108                                 // by target.
1109                                 //
1110                                 if (look_for_explicit)
1111                                         source = ConvertExplicitStandard (ec, source, most_specific_source, loc);
1112                                 else
1113                                         source = ConvertImplicitStandard (ec, source,
1114                                                                           most_specific_source, loc);
1115
1116                                 if (source == null)
1117                                         return null;
1118
1119                                 e =  new UserCast ((MethodInfo) method, source);
1120                                 
1121                                 if (e.Type != target){
1122                                         if (!look_for_explicit)
1123                                                 e = ConvertImplicitStandard (ec, e, target, loc);
1124                                         else
1125                                                 e = ConvertExplicitStandard (ec, e, target, loc);
1126
1127                                         return e;
1128                                 } else
1129                                         return e;
1130                         }
1131                         
1132                         return null;
1133                 }
1134                 
1135                 /// <summary>
1136                 ///   Converts implicitly the resolved expression `expr' into the
1137                 ///   `target_type'.  It returns a new expression that can be used
1138                 ///   in a context that expects a `target_type'. 
1139                 /// </summary>
1140                 static public Expression ConvertImplicit (EmitContext ec, Expression expr,
1141                                                           Type target_type, Location loc)
1142                 {
1143                         Type expr_type = expr.Type;
1144                         Expression e;
1145
1146                         if (expr_type == target_type)
1147                                 return expr;
1148
1149                         if (target_type == null)
1150                                 throw new Exception ("Target type is null");
1151
1152                         e = ImplicitNumericConversion (ec, expr, target_type, loc);
1153                         if (e != null)
1154                                 return e;
1155
1156                         e = ImplicitReferenceConversion (expr, target_type);
1157                         if (e != null)
1158                                 return e;
1159
1160                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1161                         if (e != null)
1162                                 return e;
1163
1164                         if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
1165                                 IntLiteral i = (IntLiteral) expr;
1166
1167                                 if (i.Value == 0)
1168                                         return new EmptyCast (expr, target_type);
1169                         }
1170
1171                         return null;
1172                 }
1173
1174                 
1175                 /// <summary>
1176                 ///   Attempts to apply the `Standard Implicit
1177                 ///   Conversion' rules to the expression `expr' into
1178                 ///   the `target_type'.  It returns a new expression
1179                 ///   that can be used in a context that expects a
1180                 ///   `target_type'.
1181                 ///
1182                 ///   This is different from `ConvertImplicit' in that the
1183                 ///   user defined implicit conversions are excluded. 
1184                 /// </summary>
1185                 static public Expression ConvertImplicitStandard (EmitContext ec, Expression expr,
1186                                                                   Type target_type, Location loc)
1187                 {
1188                         Type expr_type = expr.Type;
1189                         Expression e;
1190
1191                         if (expr_type == target_type)
1192                                 return expr;
1193
1194                         e = ImplicitNumericConversion (ec, expr, target_type, loc);
1195                         if (e != null)
1196                                 return e;
1197
1198                         e = ImplicitReferenceConversion (expr, target_type);
1199                         if (e != null)
1200                                 return e;
1201
1202                         if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
1203                                 IntLiteral i = (IntLiteral) expr;
1204
1205                                 if (i.Value == 0)
1206                                         return new EmptyCast (expr, target_type);
1207                         }
1208                         return null;
1209                 }
1210
1211                 /// <summary>
1212                 ///   Attemps to perform an implict constant conversion of the IntLiteral
1213                 ///   into a different data type using casts (See Implicit Constant
1214                 ///   Expression Conversions)
1215                 /// </summary>
1216                 static protected Expression TryImplicitIntConversion (Type target_type, IntLiteral il)
1217                 {
1218                         int value = il.Value;
1219                         
1220                         if (target_type == TypeManager.sbyte_type){
1221                                 if (value >= SByte.MinValue && value <= SByte.MaxValue)
1222                                         return new EmptyCast (il, target_type);
1223                         } else if (target_type == TypeManager.byte_type){
1224                                 if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
1225                                         return new EmptyCast (il, target_type);
1226                         } else if (target_type == TypeManager.short_type){
1227                                 if (value >= Int16.MinValue && value <= Int16.MaxValue)
1228                                         return new EmptyCast (il, target_type);
1229                         } else if (target_type == TypeManager.ushort_type){
1230                                 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1231                                         return new EmptyCast (il, target_type);
1232                         } else if (target_type == TypeManager.uint32_type){
1233                                 //
1234                                 // we can optimize this case: a positive int32
1235                                 // always fits on a uint32
1236                                 //
1237                                 if (value >= 0)
1238                                         return new EmptyCast (il, target_type);
1239                         } else if (target_type == TypeManager.uint64_type){
1240                                 //
1241                                 // we can optimize this case: a positive int32
1242                                 // always fits on a uint64.  But we need an opcode
1243                                 // to do it.
1244                                 //
1245                                 if (value >= 0)
1246                                         return new OpcodeCast (il, target_type, OpCodes.Conv_I8);
1247                         }
1248
1249                         return null;
1250                 }
1251
1252                 /// <summary>
1253                 ///   Attemptes to implicityly convert `target' into `type', using
1254                 ///   ConvertImplicit.  If there is no implicit conversion, then
1255                 ///   an error is signaled
1256                 /// </summary>
1257                 static public Expression ConvertImplicitRequired (EmitContext ec, Expression source,
1258                                                                   Type target_type, Location loc)
1259                 {
1260                         Expression e;
1261                         
1262                         e = ConvertImplicit (ec, source, target_type, loc);
1263                         if (e != null)
1264                                 return e;
1265
1266                         if (source is DoubleLiteral && target_type == TypeManager.float_type){
1267                                 Error (664, loc,
1268                                        "Double literal cannot be implicitly converted to " +
1269                                        "float type, use F suffix to create a float literal");
1270                         }
1271                         
1272                         string msg = "Cannot convert implicitly from `"+
1273                                 TypeManager.CSharpName (source.Type) + "' to `" +
1274                                 TypeManager.CSharpName (target_type) + "'";
1275
1276                         Error (29, loc, msg);
1277
1278                         return null;
1279                 }
1280
1281                 /// <summary>
1282                 ///   Performs the explicit numeric conversions
1283                 /// </summary>
1284                 static Expression ConvertNumericExplicit (EmitContext ec, Expression expr,
1285                                                           Type target_type)
1286                 {
1287                         Type expr_type = expr.Type;
1288                         
1289                         if (expr_type == TypeManager.sbyte_type){
1290                                 //
1291                                 // From sbyte to byte, ushort, uint, ulong, char
1292                                 //
1293                                 if (target_type == TypeManager.byte_type)
1294                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1);
1295                                 if (target_type == TypeManager.ushort_type)
1296                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2);
1297                                 if (target_type == TypeManager.uint32_type)
1298                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4);
1299                                 if (target_type == TypeManager.uint64_type)
1300                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8);
1301                                 if (target_type == TypeManager.char_type)
1302                                         return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH);
1303                         } else if (expr_type == TypeManager.byte_type){
1304                                 //
1305                                 // From byte to sbyte and char
1306                                 //
1307                                 if (target_type == TypeManager.sbyte_type)
1308                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1);
1309                                 if (target_type == TypeManager.char_type)
1310                                         return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH);
1311                         } else if (expr_type == TypeManager.short_type){
1312                                 //
1313                                 // From short to sbyte, byte, ushort, uint, ulong, char
1314                                 //
1315                                 if (target_type == TypeManager.sbyte_type)
1316                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1);
1317                                 if (target_type == TypeManager.byte_type)
1318                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1);
1319                                 if (target_type == TypeManager.ushort_type)
1320                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2);
1321                                 if (target_type == TypeManager.uint32_type)
1322                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4);
1323                                 if (target_type == TypeManager.uint64_type)
1324                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8);
1325                                 if (target_type == TypeManager.char_type)
1326                                         return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH);
1327                         } else if (expr_type == TypeManager.ushort_type){
1328                                 //
1329                                 // From ushort to sbyte, byte, short, char
1330                                 //
1331                                 if (target_type == TypeManager.sbyte_type)
1332                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1);
1333                                 if (target_type == TypeManager.byte_type)
1334                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1);
1335                                 if (target_type == TypeManager.short_type)
1336                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2);
1337                                 if (target_type == TypeManager.char_type)
1338                                         return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH);
1339                         } else if (expr_type == TypeManager.int32_type){
1340                                 //
1341                                 // From int to sbyte, byte, short, ushort, uint, ulong, char
1342                                 //
1343                                 if (target_type == TypeManager.sbyte_type)
1344                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1);
1345                                 if (target_type == TypeManager.byte_type)
1346                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1);
1347                                 if (target_type == TypeManager.short_type)
1348                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2);
1349                                 if (target_type == TypeManager.ushort_type)
1350                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2);
1351                                 if (target_type == TypeManager.uint32_type)
1352                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4);
1353                                 if (target_type == TypeManager.uint64_type)
1354                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8);
1355                                 if (target_type == TypeManager.char_type)
1356                                         return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH);
1357                         } else if (expr_type == TypeManager.uint32_type){
1358                                 //
1359                                 // From uint to sbyte, byte, short, ushort, int, char
1360                                 //
1361                                 if (target_type == TypeManager.sbyte_type)
1362                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1);
1363                                 if (target_type == TypeManager.byte_type)
1364                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1);
1365                                 if (target_type == TypeManager.short_type)
1366                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2);
1367                                 if (target_type == TypeManager.ushort_type)
1368                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2);
1369                                 if (target_type == TypeManager.int32_type)
1370                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4);
1371                                 if (target_type == TypeManager.char_type)
1372                                         return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH);
1373                         } else if (expr_type == TypeManager.int64_type){
1374                                 //
1375                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1376                                 //
1377                                 if (target_type == TypeManager.sbyte_type)
1378                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1);
1379                                 if (target_type == TypeManager.byte_type)
1380                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1);
1381                                 if (target_type == TypeManager.short_type)
1382                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2);
1383                                 if (target_type == TypeManager.ushort_type)
1384                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2);
1385                                 if (target_type == TypeManager.int32_type)
1386                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4);
1387                                 if (target_type == TypeManager.uint32_type)
1388                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4);
1389                                 if (target_type == TypeManager.uint64_type)
1390                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8);
1391                                 if (target_type == TypeManager.char_type)
1392                                         return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH);
1393                         } else if (expr_type == TypeManager.uint64_type){
1394                                 //
1395                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1396                                 //
1397                                 if (target_type == TypeManager.sbyte_type)
1398                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1);
1399                                 if (target_type == TypeManager.byte_type)
1400                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1);
1401                                 if (target_type == TypeManager.short_type)
1402                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2);
1403                                 if (target_type == TypeManager.ushort_type)
1404                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2);
1405                                 if (target_type == TypeManager.int32_type)
1406                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4);
1407                                 if (target_type == TypeManager.uint32_type)
1408                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4);
1409                                 if (target_type == TypeManager.int64_type)
1410                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8);
1411                                 if (target_type == TypeManager.char_type)
1412                                         return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH);
1413                         } else if (expr_type == TypeManager.char_type){
1414                                 //
1415                                 // From char to sbyte, byte, short
1416                                 //
1417                                 if (target_type == TypeManager.sbyte_type)
1418                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1);
1419                                 if (target_type == TypeManager.byte_type)
1420                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1);
1421                                 if (target_type == TypeManager.short_type)
1422                                         return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2);
1423                         } else if (expr_type == TypeManager.float_type){
1424                                 //
1425                                 // From float to sbyte, byte, short,
1426                                 // ushort, int, uint, long, ulong, char
1427                                 // or decimal
1428                                 //
1429                                 if (target_type == TypeManager.sbyte_type)
1430                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1);
1431                                 if (target_type == TypeManager.byte_type)
1432                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1);
1433                                 if (target_type == TypeManager.short_type)
1434                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2);
1435                                 if (target_type == TypeManager.ushort_type)
1436                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2);
1437                                 if (target_type == TypeManager.int32_type)
1438                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4);
1439                                 if (target_type == TypeManager.uint32_type)
1440                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4);
1441                                 if (target_type == TypeManager.int64_type)
1442                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8);
1443                                 if (target_type == TypeManager.uint64_type)
1444                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8);
1445                                 if (target_type == TypeManager.char_type)
1446                                         return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH);
1447                                 if (target_type == TypeManager.decimal_type)
1448                                         return InternalTypeConstructor (ec, expr, target_type);
1449                         } else if (expr_type == TypeManager.double_type){
1450                                 //
1451                                 // From double to byte, byte, short,
1452                                 // ushort, int, uint, long, ulong,
1453                                 // char, float or decimal
1454                                 //
1455                                 if (target_type == TypeManager.sbyte_type)
1456                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1);
1457                                 if (target_type == TypeManager.byte_type)
1458                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1);
1459                                 if (target_type == TypeManager.short_type)
1460                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2);
1461                                 if (target_type == TypeManager.ushort_type)
1462                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2);
1463                                 if (target_type == TypeManager.int32_type)
1464                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4);
1465                                 if (target_type == TypeManager.uint32_type)
1466                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4);
1467                                 if (target_type == TypeManager.int64_type)
1468                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8);
1469                                 if (target_type == TypeManager.uint64_type)
1470                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8);
1471                                 if (target_type == TypeManager.char_type)
1472                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH);
1473                                 if (target_type == TypeManager.float_type)
1474                                         return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4);
1475                                 if (target_type == TypeManager.decimal_type)
1476                                         return InternalTypeConstructor (ec, expr, target_type);
1477                         } 
1478
1479                         // decimal is taken care of by the op_Explicit methods.
1480
1481                         return null;
1482                 }
1483
1484                 /// <summary>
1485                 ///  Returns whether an explicit reference conversion can be performed
1486                 ///  from source_type to target_type
1487                 /// </summary>
1488                 static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
1489                 {
1490                         bool target_is_value_type = target_type.IsValueType;
1491                         
1492                         if (source_type == target_type)
1493                                 return true;
1494                         
1495                         //
1496                         // From object to any reference type
1497                         //
1498                         if (source_type == TypeManager.object_type && !target_is_value_type)
1499                                 return true;
1500                                         
1501                         //
1502                         // From any class S to any class-type T, provided S is a base class of T
1503                         //
1504                         if (target_type.IsSubclassOf (source_type))
1505                                 return true;
1506
1507                         //
1508                         // From any interface type S to any interface T provided S is not derived from T
1509                         //
1510                         if (source_type.IsInterface && target_type.IsInterface){
1511                                 if (!target_type.IsSubclassOf (source_type))
1512                                         return true;
1513                         }
1514                             
1515                         //
1516                         // From any class type S to any interface T, provides S is not sealed
1517                         // and provided S does not implement T.
1518                         //
1519                         if (target_type.IsInterface && !source_type.IsSealed &&
1520                             !target_type.IsAssignableFrom (source_type))
1521                                 return true;
1522
1523                         //
1524                         // From any interface-type S to to any class type T, provided T is not
1525                         // sealed, or provided T implements S.
1526                         //
1527                         if (source_type.IsInterface &&
1528                             (!target_type.IsSealed || source_type.IsAssignableFrom (target_type)))
1529                                 return true;
1530
1531                         // From an array type S with an element type Se to an array type T with an 
1532                         // element type Te provided all the following are true:
1533                         //     * S and T differe only in element type, in other words, S and T
1534                         //       have the same number of dimensions.
1535                         //     * Both Se and Te are reference types
1536                         //     * An explicit referenc conversions exist from Se to Te
1537                         //
1538                         if (source_type.IsArray && target_type.IsArray) {
1539                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
1540                                         
1541                                         Type source_element_type = source_type.GetElementType ();
1542                                         Type target_element_type = target_type.GetElementType ();
1543                                         
1544                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
1545                                                 if (ExplicitReferenceConversionExists (source_element_type,
1546                                                                                        target_element_type))
1547                                                         return true;
1548                                 }
1549                         }
1550                         
1551
1552                         // From System.Array to any array-type
1553                         if (source_type == TypeManager.array_type &&
1554                             target_type.IsSubclassOf (TypeManager.array_type)){
1555                                 return true;
1556                         }
1557
1558                         //
1559                         // From System delegate to any delegate-type
1560                         //
1561                         if (source_type == TypeManager.delegate_type &&
1562                             target_type.IsSubclassOf (TypeManager.delegate_type))
1563                                 return true;
1564
1565                         //
1566                         // From ICloneable to Array or Delegate types
1567                         //
1568                         if (source_type == TypeManager.icloneable_type &&
1569                             (target_type == TypeManager.array_type ||
1570                              target_type == TypeManager.delegate_type))
1571                                 return true;
1572                         
1573                         return false;
1574                 }
1575
1576                 /// <summary>
1577                 ///   Implements Explicit Reference conversions
1578                 /// </summary>
1579                 static Expression ConvertReferenceExplicit (Expression source, Type target_type)
1580                 {
1581                         Type source_type = source.Type;
1582                         bool target_is_value_type = target_type.IsValueType;
1583                         
1584                         //
1585                         // From object to any reference type
1586                         //
1587                         if (source_type == TypeManager.object_type && !target_is_value_type)
1588                                 return new ClassCast (source, target_type);
1589
1590
1591                         //
1592                         // From any class S to any class-type T, provided S is a base class of T
1593                         //
1594                         if (target_type.IsSubclassOf (source_type))
1595                                 return new ClassCast (source, target_type);
1596
1597                         //
1598                         // From any interface type S to any interface T provided S is not derived from T
1599                         //
1600                         if (source_type.IsInterface && target_type.IsInterface){
1601
1602                                 Type [] ifaces = source_type.GetInterfaces ();
1603
1604                                 if (TypeManager.ImplementsInterface (source_type, target_type))
1605                                         return null;
1606                                 else
1607                                         return new ClassCast (source, target_type);
1608                         }
1609                             
1610                         //
1611                         // From any class type S to any interface T, provides S is not sealed
1612                         // and provided S does not implement T.
1613                         //
1614                         if (target_type.IsInterface && !source_type.IsSealed) {
1615                                 
1616                                 if (TypeManager.ImplementsInterface (source_type, target_type))
1617                                         return null;
1618                                 else
1619                                         return new ClassCast (source, target_type);
1620                                 
1621                         }
1622
1623                         //
1624                         // From any interface-type S to to any class type T, provided T is not
1625                         // sealed, or provided T implements S.
1626                         //
1627                         if (source_type.IsInterface) {
1628
1629                                 if (target_type.IsSealed)
1630                                         return null;
1631                                 
1632                                 if (TypeManager.ImplementsInterface (target_type, source_type))
1633                                         return new ClassCast (source, target_type);
1634                                 else
1635                                         return null;
1636                         }
1637                         
1638                         // From an array type S with an element type Se to an array type T with an 
1639                         // element type Te provided all the following are true:
1640                         //     * S and T differe only in element type, in other words, S and T
1641                         //       have the same number of dimensions.
1642                         //     * Both Se and Te are reference types
1643                         //     * An explicit referenc conversions exist from Se to Te
1644                         //
1645                         if (source_type.IsArray && target_type.IsArray) {
1646                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
1647                                         
1648                                         Type source_element_type = source_type.GetElementType ();
1649                                         Type target_element_type = target_type.GetElementType ();
1650                                         
1651                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
1652                                                 if (ExplicitReferenceConversionExists (source_element_type,
1653                                                                                        target_element_type))
1654                                                         return new ClassCast (source, target_type);
1655                                 }
1656                         }
1657                         
1658
1659                         // From System.Array to any array-type
1660                         if (source_type == TypeManager.array_type &&
1661                             target_type.IsSubclassOf (TypeManager.array_type)){
1662                                 return new ClassCast (source, target_type);
1663                         }
1664
1665                         //
1666                         // From System delegate to any delegate-type
1667                         //
1668                         if (source_type == TypeManager.delegate_type &&
1669                             target_type.IsSubclassOf (TypeManager.delegate_type))
1670                                 return new ClassCast (source, target_type);
1671
1672                         //
1673                         // From ICloneable to Array or Delegate types
1674                         //
1675                         if (source_type == TypeManager.icloneable_type &&
1676                             (target_type == TypeManager.array_type ||
1677                              target_type == TypeManager.delegate_type))
1678                                 return new ClassCast (source, target_type);
1679                         
1680                         return null;
1681                 }
1682                 
1683                 /// <summary>
1684                 ///   Performs an explicit conversion of the expression `expr' whose
1685                 ///   type is expr.Type to `target_type'.
1686                 /// </summary>
1687                 static public Expression ConvertExplicit (EmitContext ec, Expression expr,
1688                                                           Type target_type, Location loc)
1689                 {
1690                         Type expr_type = expr.Type;
1691                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, loc);
1692
1693                         if (ne != null)
1694                                 return ne;
1695
1696                         ne = ConvertNumericExplicit (ec, expr, target_type);
1697                         if (ne != null)
1698                                 return ne;
1699
1700                         //
1701                         // Unboxing conversion.
1702                         //
1703                         if (expr_type == TypeManager.object_type && target_type.IsValueType)
1704                                 return new UnboxCast (expr, target_type);
1705
1706                         //
1707                         // Enum types
1708                         //
1709                         if (expr is EnumLiteral) {
1710                                 Expression e = ((EnumLiteral) expr).Child;
1711                                 
1712                                 return ConvertImplicit (ec, e, target_type, loc);
1713                         }
1714                         
1715                         ne = ConvertReferenceExplicit (expr, target_type);
1716                         if (ne != null)
1717                                 return ne;
1718
1719                         ne = ExplicitUserConversion (ec, expr, target_type, loc);
1720                         if (ne != null)
1721                                 return ne;
1722
1723                         error30 (loc, expr_type, target_type);
1724                         return null;
1725                 }
1726
1727                 /// <summary>
1728                 ///   Same as ConverExplicit, only it doesn't include user defined conversions
1729                 /// </summary>
1730                 static public Expression ConvertExplicitStandard (EmitContext ec, Expression expr,
1731                                                                   Type target_type, Location l)
1732                 {
1733                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, l);
1734
1735                         if (ne != null)
1736                                 return ne;
1737
1738                         ne = ConvertNumericExplicit (ec, expr, target_type);
1739                         if (ne != null)
1740                                 return ne;
1741
1742                         ne = ConvertReferenceExplicit (expr, target_type);
1743                         if (ne != null)
1744                                 return ne;
1745
1746                         error30 (l, expr.Type, target_type);
1747                         return null;
1748                 }
1749
1750                 static string ExprClassName (ExprClass c)
1751                 {
1752                         switch (c){
1753                         case ExprClass.Invalid:
1754                                 return "Invalid";
1755                         case ExprClass.Value:
1756                                 return "value";
1757                         case ExprClass.Variable:
1758                                 return "variable";
1759                         case ExprClass.Namespace:
1760                                 return "namespace";
1761                         case ExprClass.Type:
1762                                 return "type";
1763                         case ExprClass.MethodGroup:
1764                                 return "method group";
1765                         case ExprClass.PropertyAccess:
1766                                 return "property access";
1767                         case ExprClass.EventAccess:
1768                                 return "event access";
1769                         case ExprClass.IndexerAccess:
1770                                 return "indexer access";
1771                         case ExprClass.Nothing:
1772                                 return "null";
1773                         }
1774                         throw new Exception ("Should not happen");
1775                 }
1776                 
1777                 /// <summary>
1778                 ///   Reports that we were expecting `expr' to be of class `expected'
1779                 /// </summary>
1780                 protected void report118 (Location loc, Expression expr, string expected)
1781                 {
1782                         string kind = "Unknown";
1783                         
1784                         if (expr != null)
1785                                 kind = ExprClassName (expr.ExprClass);
1786
1787                         Error (118, loc, "Expression denotes a `" + kind +
1788                                "' where a `" + expected + "' was expected");
1789                 }
1790
1791                 /// <summary>
1792                 ///   This function tries to reduce the expression performing
1793                 ///   constant folding and common subexpression elimination
1794                 /// </summary>
1795                 static public Expression Reduce (EmitContext ec, Expression e)
1796                 {
1797                         //Console.WriteLine ("Calling reduce");
1798                         return e.Reduce (ec);
1799                 }
1800
1801                 static void error31 (Location l, string val, Type t)
1802                 {
1803                         Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " +
1804                                       TypeManager.CSharpName (t));
1805                 }
1806                 
1807                 /// <summary>
1808                 ///   Converts the IntLiteral, UIntLiteral, LongLiteral or
1809                 ///   ULongLiteral into the integral target_type.
1810                 ///
1811                 ///   This is used by the switch statement, so the domain
1812                 ///   of work is restricted to the literals above, and the
1813                 ///   targets are int32, uint32, char, byte, sbyte, ushort,
1814                 ///   short, uint64 and int64
1815                 /// </summary>
1816                 public static Literal ConvertIntLiteral (Literal l, Type target_type, Location loc)
1817                 {
1818                         string s = "";
1819
1820                         if (l.Type == target_type)
1821                                 return l;
1822
1823                         //
1824                         // Make into one of the literals we handle, we dont really care
1825                         // about this value as we will just return a few limited types
1826                         // 
1827                         if (l is EnumLiteral)
1828                                 l = ((EnumLiteral)l).WidenToCompilerLiteral ();
1829
1830                         if (l is IntLiteral){
1831                                 int v = ((IntLiteral) l).Value;
1832                                 
1833                                 if (target_type == TypeManager.uint32_type){
1834                                         if (v >= 0)
1835                                                 return new UIntLiteral ((uint) v);
1836                                 } else if (target_type == TypeManager.char_type){
1837                                         if (v >= Char.MinValue && v <= Char.MaxValue)
1838                                                 return l;
1839                                 } else if (target_type == TypeManager.byte_type){
1840                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
1841                                                 return l;
1842                                 } else if (target_type == TypeManager.sbyte_type){
1843                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
1844                                                 return l;
1845                                 } else if (target_type == TypeManager.short_type){
1846                                         if (v >= Int16.MinValue && v <= UInt16.MaxValue)
1847                                                 return l;
1848                                 } else if (target_type == TypeManager.ushort_type){
1849                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
1850                                                 return l;
1851                                 } else if (target_type == TypeManager.int64_type)
1852                                         return new LongLiteral (v);
1853                                 else if (target_type == TypeManager.uint64_type){
1854                                         if (v > 0)
1855                                                 return new ULongLiteral ((ulong) v);
1856                                 }
1857
1858                                 s = v.ToString ();
1859                         } else if (l is UIntLiteral){
1860                                 uint v = ((UIntLiteral) l).Value;
1861
1862                                 if (target_type == TypeManager.int32_type){
1863                                         if (v <= Int32.MaxValue)
1864                                                 return new IntLiteral ((int) v);
1865                                 } else if (target_type == TypeManager.char_type){
1866                                         if (v >= Char.MinValue && v <= Char.MaxValue)
1867                                                 return l;
1868                                 } else if (target_type == TypeManager.byte_type){
1869                                         if (v <= Byte.MaxValue)
1870                                                 return l;
1871                                 } else if (target_type == TypeManager.sbyte_type){
1872                                         if (v <= SByte.MaxValue)
1873                                                 return l;
1874                                 } else if (target_type == TypeManager.short_type){
1875                                         if (v <= UInt16.MaxValue)
1876                                                 return l;
1877                                 } else if (target_type == TypeManager.ushort_type){
1878                                         if (v <= UInt16.MaxValue)
1879                                                 return l;
1880                                 } else if (target_type == TypeManager.int64_type)
1881                                         return new LongLiteral (v);
1882                                 else if (target_type == TypeManager.uint64_type)
1883                                         return new ULongLiteral (v);
1884                                 s = v.ToString ();
1885                         } else if (l is LongLiteral){ 
1886                                 long v = ((LongLiteral) l).Value;
1887
1888                                 if (target_type == TypeManager.int32_type){
1889                                         if (v >= UInt32.MinValue && v <= UInt32.MaxValue)
1890                                                 return new IntLiteral ((int) v);
1891                                 } else if (target_type == TypeManager.uint32_type){
1892                                         if (v >= 0 && v <= UInt32.MaxValue)
1893                                                 return new UIntLiteral ((uint) v);
1894                                 } else if (target_type == TypeManager.char_type){
1895                                         if (v >= Char.MinValue && v <= Char.MaxValue)
1896                                                 return new IntLiteral ((int) v);
1897                                 } else if (target_type == TypeManager.byte_type){
1898                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
1899                                                 return new IntLiteral ((int) v);
1900                                 } else if (target_type == TypeManager.sbyte_type){
1901                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
1902                                                 return new IntLiteral ((int) v);
1903                                 } else if (target_type == TypeManager.short_type){
1904                                         if (v >= Int16.MinValue && v <= UInt16.MaxValue)
1905                                                 return new IntLiteral ((int) v);
1906                                 } else if (target_type == TypeManager.ushort_type){
1907                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
1908                                                 return new IntLiteral ((int) v);
1909                                 } else if (target_type == TypeManager.uint64_type){
1910                                         if (v > 0)
1911                                                 return new ULongLiteral ((ulong) v);
1912                                 }
1913                                 s = v.ToString ();
1914                         } else if (l is ULongLiteral){
1915                                 ulong v = ((ULongLiteral) l).Value;
1916
1917                                 if (target_type == TypeManager.int32_type){
1918                                         if (v <= Int32.MaxValue)
1919                                                 return new IntLiteral ((int) v);
1920                                 } else if (target_type == TypeManager.uint32_type){
1921                                         if (v <= UInt32.MaxValue)
1922                                                 return new UIntLiteral ((uint) v);
1923                                 } else if (target_type == TypeManager.char_type){
1924                                         if (v >= Char.MinValue && v <= Char.MaxValue)
1925                                                 return new IntLiteral ((int) v);
1926                                 } else if (target_type == TypeManager.byte_type){
1927                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
1928                                                 return new IntLiteral ((int) v);
1929                                 } else if (target_type == TypeManager.sbyte_type){
1930                                         if (v <= (int) SByte.MaxValue)
1931                                                 return new IntLiteral ((int) v);
1932                                 } else if (target_type == TypeManager.short_type){
1933                                         if (v <= UInt16.MaxValue)
1934                                                 return new IntLiteral ((int) v);
1935                                 } else if (target_type == TypeManager.ushort_type){
1936                                         if (v <= UInt16.MaxValue)
1937                                                 return new IntLiteral ((int) v);
1938                                 } else if (target_type == TypeManager.int64_type){
1939                                         if (v <= Int64.MaxValue)
1940                                                 return new LongLiteral ((long) v);
1941                                 }
1942                                 s = v.ToString ();
1943                         } 
1944                         
1945                         error31 (loc, s, target_type);
1946                         return null;
1947                 }
1948                         
1949         }
1950
1951         /// <summary>
1952         ///   This is just a base class for expressions that can
1953         ///   appear on statements (invocations, object creation,
1954         ///   assignments, post/pre increment and decrement).  The idea
1955         ///   being that they would support an extra Emition interface that
1956         ///   does not leave a result on the stack.
1957         /// </summary>
1958         public abstract class ExpressionStatement : Expression {
1959
1960                 /// <summary>
1961                 ///   Requests the expression to be emitted in a `statement'
1962                 ///   context.  This means that no new value is left on the
1963                 ///   stack after invoking this method (constrasted with
1964                 ///   Emit that will always leave a value on the stack).
1965                 /// </summary>
1966                 public abstract void EmitStatement (EmitContext ec);
1967         }
1968
1969         /// <summary>
1970         ///   This kind of cast is used to encapsulate the child
1971         ///   whose type is child.Type into an expression that is
1972         ///   reported to return "return_type".  This is used to encapsulate
1973         ///   expressions which have compatible types, but need to be dealt
1974         ///   at higher levels with.
1975         ///
1976         ///   For example, a "byte" expression could be encapsulated in one
1977         ///   of these as an "unsigned int".  The type for the expression
1978         ///   would be "unsigned int".
1979         ///
1980         /// </summary>
1981         public class EmptyCast : Expression {
1982                 protected Expression child;
1983
1984                 public EmptyCast (Expression child, Type return_type)
1985                 {
1986                         ExprClass = child.ExprClass;
1987                         type = return_type;
1988                         this.child = child;
1989                 }
1990
1991                 public override Expression DoResolve (EmitContext ec)
1992                 {
1993                         // This should never be invoked, we are born in fully
1994                         // initialized state.
1995
1996                         return this;
1997                 }
1998
1999                 public override void Emit (EmitContext ec)
2000                 {
2001                         child.Emit (ec);
2002                 }
2003
2004         }
2005
2006         /// <summary>
2007         ///  This class is used to wrap literals which belong inside Enums
2008         /// </summary>
2009         public class EnumLiteral : Literal {
2010                 public Expression Child;
2011
2012                 public EnumLiteral (Expression child, Type enum_type)
2013                 {
2014                         ExprClass = child.ExprClass;
2015                         this.Child = child;
2016                         type = enum_type;
2017                 }
2018                 
2019                 public override Expression DoResolve (EmitContext ec)
2020                 {
2021                         // This should never be invoked, we are born in fully
2022                         // initialized state.
2023
2024                         return this;
2025                 }
2026
2027                 public override void Emit (EmitContext ec)
2028                 {
2029                         Child.Emit (ec);
2030                 }
2031
2032                 public override object GetValue ()
2033                 {
2034                         return ((Literal) Child).GetValue ();
2035                 }
2036
2037                 //
2038                 // Converts from one of the valid underlying types for an enumeration
2039                 // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to
2040                 // one of the internal compiler literals: Int/UInt/Long/ULong Literals.
2041                 //
2042                 public Literal WidenToCompilerLiteral ()
2043                 {
2044                         Type t = Child.Type.UnderlyingSystemType;
2045                         object v = ((Literal) Child).GetValue ();;
2046                         
2047                         if (t == TypeManager.int32_type)
2048                                 return new IntLiteral ((int) v);
2049                         if (t == TypeManager.uint32_type)
2050                                 return new UIntLiteral ((uint) v);
2051                         if (t == TypeManager.int64_type)
2052                                 return new LongLiteral ((long) v);
2053                         if (t == TypeManager.uint64_type)
2054                                 return new ULongLiteral ((ulong) v);
2055                         if (t == TypeManager.short_type)
2056                                 return new IntLiteral ((short) v);
2057                         if (t == TypeManager.ushort_type)
2058                                 return new UIntLiteral ((ushort) v);
2059                         if (t == TypeManager.byte_type)
2060                                 return new UIntLiteral ((byte) v);
2061                         if (t == TypeManager.sbyte_type)
2062                                 return new IntLiteral ((sbyte) v);
2063
2064                         throw new Exception ("Invalid enumeration underlying type: " + t);
2065                 }
2066
2067                 public override string AsString ()
2068                 {
2069                         return ((Literal) Child).AsString ();
2070                 }
2071         }
2072
2073         /// <summary>
2074         ///   This kind of cast is used to encapsulate Value Types in objects.
2075         ///
2076         ///   The effect of it is to box the value type emitted by the previous
2077         ///   operation.
2078         /// </summary>
2079         public class BoxedCast : EmptyCast {
2080
2081                 public BoxedCast (Expression expr)
2082                         : base (expr, TypeManager.object_type)
2083                 {
2084                 }
2085
2086                 public override Expression DoResolve (EmitContext ec)
2087                 {
2088                         // This should never be invoked, we are born in fully
2089                         // initialized state.
2090
2091                         return this;
2092                 }
2093
2094                 public override void Emit (EmitContext ec)
2095                 {
2096                         base.Emit (ec);
2097                         ec.ig.Emit (OpCodes.Box, child.Type);
2098                 }
2099         }
2100
2101         public class UnboxCast : EmptyCast {
2102                 public UnboxCast (Expression expr, Type return_type)
2103                         : base (expr, return_type)
2104                 {
2105                 }
2106
2107                 public override Expression DoResolve (EmitContext ec)
2108                 {
2109                         // This should never be invoked, we are born in fully
2110                         // initialized state.
2111
2112                         return this;
2113                 }
2114
2115                 public override void Emit (EmitContext ec)
2116                 {
2117                         Type t = type;
2118                         ILGenerator ig = ec.ig;
2119                         
2120                         base.Emit (ec);
2121                         ig.Emit (OpCodes.Unbox, t);
2122
2123                         //
2124                         // Load the object from the pointer
2125                         //
2126                         if (t == TypeManager.int32_type)
2127                                 ig.Emit (OpCodes.Ldind_I4);
2128                         else if (t == TypeManager.uint32_type)
2129                                 ig.Emit (OpCodes.Ldind_U4);
2130                         else if (t == TypeManager.short_type)
2131                                 ig.Emit (OpCodes.Ldind_I2);
2132                         else if (t == TypeManager.ushort_type)
2133                                 ig.Emit (OpCodes.Ldind_U2);
2134                         else if (t == TypeManager.char_type)
2135                                 ig.Emit (OpCodes.Ldind_U2);
2136                         else if (t == TypeManager.byte_type)
2137                                 ig.Emit (OpCodes.Ldind_U1);
2138                         else if (t == TypeManager.sbyte_type)
2139                                 ig.Emit (OpCodes.Ldind_I1);
2140                         else if (t == TypeManager.uint64_type)
2141                                 ig.Emit (OpCodes.Ldind_I8);
2142                         else if (t == TypeManager.int64_type)
2143                                 ig.Emit (OpCodes.Ldind_I8);
2144                         else if (t == TypeManager.float_type)
2145                                 ig.Emit (OpCodes.Ldind_R4);
2146                         else if (t == TypeManager.double_type)
2147                                 ig.Emit (OpCodes.Ldind_R8);
2148                         else if (t == TypeManager.bool_type)
2149                                 ig.Emit (OpCodes.Ldind_I1);
2150                         else if (t == TypeManager.intptr_type)
2151                                 ig.Emit (OpCodes.Ldind_I);
2152                         else 
2153                                 ig.Emit (OpCodes.Ldobj, t);
2154                 }
2155         }
2156         
2157         /// <summary>
2158         ///   This is used to perform explicit numeric conversions.
2159         ///
2160         ///   Explicit numeric conversions might trigger exceptions in a checked
2161         ///   context, so they should generate the conv.ovf opcodes instead of
2162         ///   conv opcodes.
2163         /// </summary>
2164         public class ConvCast : EmptyCast {
2165                 public enum Mode : byte {
2166                         I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
2167                         U1_I1, U1_CH,
2168                         I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
2169                         U2_I1, U2_U1, U2_I2, U2_CH,
2170                         I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
2171                         U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
2172                         I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
2173                         U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
2174                         CH_I1, CH_U1, CH_I2,
2175                         R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
2176                         R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
2177                 }
2178
2179                 Mode mode;
2180                 
2181                 public ConvCast (Expression child, Type return_type, Mode m)
2182                         : base (child, return_type)
2183                 {
2184                         mode = m;
2185                 }
2186
2187                 public override Expression DoResolve (EmitContext ec)
2188                 {
2189                         // This should never be invoked, we are born in fully
2190                         // initialized state.
2191
2192                         return this;
2193                 }
2194
2195                 public override void Emit (EmitContext ec)
2196                 {
2197                         ILGenerator ig = ec.ig;
2198                         
2199                         base.Emit (ec);
2200
2201                         if (ec.CheckState){
2202                                 switch (mode){
2203                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2204                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2205                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2206                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2207                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2208
2209                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
2210                                 case Mode.U1_CH: /* nothing */ break;
2211
2212                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2213                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2214                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2215                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2216                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2217                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2218
2219                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
2220                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
2221                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
2222                                 case Mode.U2_CH: /* nothing */ break;
2223
2224                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2225                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2226                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
2227                                 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2228                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2229                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2230                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2231
2232                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
2233                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
2234                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
2235                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
2236                                 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
2237                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
2238
2239                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2240                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2241                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
2242                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2243                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
2244                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2245                                 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2246                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2247
2248                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
2249                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
2250                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
2251                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
2252                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
2253                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
2254                                 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
2255                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
2256
2257                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
2258                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
2259                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
2260
2261                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2262                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2263                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
2264                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2265                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
2266                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2267                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
2268                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2269                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2270
2271                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
2272                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
2273                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
2274                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2275                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
2276                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
2277                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
2278                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
2279                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
2280                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
2281                                 }
2282                         } else {
2283                                 switch (mode){
2284                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
2285                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
2286                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
2287                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
2288                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
2289
2290                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
2291                                 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
2292
2293                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
2294                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
2295                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
2296                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
2297                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
2298                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
2299
2300                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
2301                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
2302                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
2303                                 case Mode.U2_CH: /* nothing */ break;
2304
2305                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
2306                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
2307                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
2308                                 case Mode.I4_U4: /* nothing */ break;
2309                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
2310                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
2311                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
2312
2313                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
2314                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
2315                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
2316                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
2317                                 case Mode.U4_I4: /* nothing */ break;
2318                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
2319
2320                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
2321                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
2322                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
2323                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
2324                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
2325                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
2326                                 case Mode.I8_U8: /* nothing */ break;
2327                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
2328
2329                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
2330                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
2331                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
2332                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
2333                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
2334                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
2335                                 case Mode.U8_I8: /* nothing */ break;
2336                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
2337
2338                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
2339                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
2340                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
2341
2342                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
2343                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
2344                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
2345                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
2346                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
2347                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
2348                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
2349                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
2350                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
2351
2352                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
2353                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
2354                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
2355                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
2356                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
2357                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
2358                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
2359                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
2360                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
2361                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
2362                                 }
2363                         }
2364                 }
2365         }
2366         
2367         public class OpcodeCast : EmptyCast {
2368                 OpCode op, op2;
2369                 bool second_valid;
2370                 
2371                 public OpcodeCast (Expression child, Type return_type, OpCode op)
2372                         : base (child, return_type)
2373                         
2374                 {
2375                         this.op = op;
2376                         second_valid = false;
2377                 }
2378
2379                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
2380                         : base (child, return_type)
2381                         
2382                 {
2383                         this.op = op;
2384                         this.op2 = op2;
2385                         second_valid = true;
2386                 }
2387
2388                 public override Expression DoResolve (EmitContext ec)
2389                 {
2390                         // This should never be invoked, we are born in fully
2391                         // initialized state.
2392
2393                         return this;
2394                 }
2395
2396                 public override void Emit (EmitContext ec)
2397                 {
2398                         base.Emit (ec);
2399                         ec.ig.Emit (op);
2400
2401                         if (second_valid)
2402                                 ec.ig.Emit (op2);
2403                 }                       
2404         }
2405
2406         /// <summary>
2407         ///   This kind of cast is used to encapsulate a child and cast it
2408         ///   to the class requested
2409         /// </summary>
2410         public class ClassCast : EmptyCast {
2411                 public ClassCast (Expression child, Type return_type)
2412                         : base (child, return_type)
2413                         
2414                 {
2415                 }
2416
2417                 public override Expression DoResolve (EmitContext ec)
2418                 {
2419                         // This should never be invoked, we are born in fully
2420                         // initialized state.
2421
2422                         return this;
2423                 }
2424
2425                 public override void Emit (EmitContext ec)
2426                 {
2427                         base.Emit (ec);
2428
2429                         ec.ig.Emit (OpCodes.Castclass, type);
2430                 }                       
2431                 
2432         }
2433         
2434         /// <summary>
2435         ///   SimpleName expressions are initially formed of a single
2436         ///   word and it only happens at the beginning of the expression.
2437         /// </summary>
2438         ///
2439         /// <remarks>
2440         ///   The expression will try to be bound to a Field, a Method
2441         ///   group or a Property.  If those fail we pass the name to our
2442         ///   caller and the SimpleName is compounded to perform a type
2443         ///   lookup.  The idea behind this process is that we want to avoid
2444         ///   creating a namespace map from the assemblies, as that requires
2445         ///   the GetExportedTypes function to be called and a hashtable to
2446         ///   be constructed which reduces startup time.  If later we find
2447         ///   that this is slower, we should create a `NamespaceExpr' expression
2448         ///   that fully participates in the resolution process. 
2449         ///   
2450         ///   For example `System.Console.WriteLine' is decomposed into
2451         ///   MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
2452         ///   
2453         ///   The first SimpleName wont produce a match on its own, so it will
2454         ///   be turned into:
2455         ///   MemberAccess (SimpleName ("System.Console"), "WriteLine").
2456         ///   
2457         ///   System.Console will produce a TypeExpr match.
2458         ///   
2459         ///   The downside of this is that we might be hitting `LookupType' too many
2460         ///   times with this scheme.
2461         /// </remarks>
2462         public class SimpleName : Expression {
2463                 public readonly string Name;
2464                 public readonly Location Location;
2465                 
2466                 public SimpleName (string name, Location l)
2467                 {
2468                         Name = name;
2469                         Location = l;
2470                 }
2471
2472                 public static void Error120 (Location l, string name)
2473                 {
2474                         Report.Error (
2475                                 120, l,
2476                                 "An object reference is required " +
2477                                 "for the non-static field `"+name+"'");
2478                 }
2479                 
2480                 //
2481                 // Checks whether we are trying to access an instance
2482                 // property, method or field from a static body.
2483                 //
2484                 Expression MemberStaticCheck (Expression e)
2485                 {
2486                         if (e is FieldExpr){
2487                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
2488                                 
2489                                 if (!fi.IsStatic){
2490                                         Error120 (Location, Name);
2491                                         return null;
2492                                 }
2493                         } else if (e is MethodGroupExpr){
2494                                 MethodGroupExpr mg = (MethodGroupExpr) e;
2495
2496                                 if (!mg.RemoveInstanceMethods ()){
2497                                         Error120 (Location, mg.Methods [0].Name);
2498                                         return null;
2499                                 }
2500                                 return e;
2501                         } else if (e is PropertyExpr){
2502                                 if (!((PropertyExpr) e).IsStatic){
2503                                         Error120 (Location, Name);
2504                                         return null;
2505                                 }
2506                         }
2507
2508                         return e;
2509                 }
2510                 
2511                 // <remarks>
2512                 //   7.5.2: Simple Names. 
2513                 //
2514                 //   Local Variables and Parameters are handled at
2515                 //   parse time, so they never occur as SimpleNames.
2516                 // </remarks>
2517                 public override Expression DoResolve (EmitContext ec)
2518                 {
2519                         Expression e;
2520
2521                         //
2522                         // Stage 1: Performed by the parser (binding to locals or parameters).
2523                         //
2524
2525                         //
2526                         // Stage 2: Lookup members
2527                         //
2528                         e = MemberLookup (ec, ec.TypeContainer.TypeBuilder, Name, true, Location);
2529                         if (e == null) {
2530                                 //
2531                                 // Stage 3: Lookup symbol in the various namespaces. 
2532                                 // 
2533                                 DeclSpace ds = ec.TypeContainer;
2534                                 Type t;
2535                                 string alias_value;
2536
2537                                 if ((t = RootContext.LookupType (ds, Name, true, Location)) != null)
2538                                         return new TypeExpr (t);
2539
2540                                 //
2541                                 // Stage 3 part b: Lookup up if we are an alias to a type
2542                                 // or a namespace.
2543                                 //
2544                                 // Since we are cheating: we only do the Alias lookup for
2545                                 // namespaces if the name does not include any dots in it
2546                                 //
2547
2548                                 if (Name.IndexOf ('.') == -1 && (alias_value = ec.TypeContainer.LookupAlias (Name)) != null) {
2549                                         // System.Console.WriteLine (Name + " --> " + alias_value);
2550                                         if ((t = RootContext.LookupType (ds, alias_value, true, Location))
2551                                             != null)
2552                                                 return new TypeExpr (t);
2553
2554                                         // we have alias value, but it isn't Type, so try if it's namespace
2555                                         return new SimpleName (alias_value, Location);
2556                                 }
2557
2558                                 // No match, maybe our parent can compose us
2559                                 // into something meaningful.
2560                                 //
2561                                 return this;
2562                         }
2563
2564                         // Step 2, continues here.
2565                         if (e is TypeExpr)
2566                                 return e;
2567
2568                         if (e is FieldExpr){
2569                                 FieldExpr fe = (FieldExpr) e;
2570                                 
2571                                 if (!fe.FieldInfo.IsStatic){
2572                                         This t = new This (Location.Null);
2573
2574                                         fe.InstanceExpression = t.DoResolve (ec);
2575                                 }
2576
2577                                 FieldInfo fi = fe.FieldInfo;
2578                                 
2579                                 if (fi is FieldBuilder) {
2580                                         Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
2581                                         
2582                                         if (c != null) {
2583                                                 object o = c.LookupConstantValue (ec);
2584                                                 Expression l = Literalize (o, fi.FieldType);
2585                                                 l = l.Resolve (ec);
2586                                                 return ((Literal) l);
2587                                         }
2588                                 }
2589                         }                               
2590
2591                         if (ec.IsStatic)
2592                                 return MemberStaticCheck (e);
2593                         else
2594                                 return e;
2595                 }
2596
2597                 public override void Emit (EmitContext ec)
2598                 {
2599                         //
2600                         // If this is ever reached, then we failed to
2601                         // find the name as a namespace
2602                         //
2603
2604                         Error (103, Location, "The name `" + Name +
2605                                "' does not exist in the class `" +
2606                                ec.TypeContainer.Name + "'");
2607                 }
2608         }
2609         
2610         /// <summary>
2611         ///   Fully resolved expression that evaluates to a type
2612         /// </summary>
2613         public class TypeExpr : Expression {
2614                 public TypeExpr (Type t)
2615                 {
2616                         Type = t;
2617                         eclass = ExprClass.Type;
2618                 }
2619
2620                 override public Expression DoResolve (EmitContext ec)
2621                 {
2622                         return this;
2623                 }
2624
2625                 override public void Emit (EmitContext ec)
2626                 {
2627                         throw new Exception ("Implement me");
2628                 }
2629         }
2630
2631         /// <summary>
2632         ///   MethodGroup Expression.
2633         ///  
2634         ///   This is a fully resolved expression that evaluates to a type
2635         /// </summary>
2636         public class MethodGroupExpr : Expression {
2637                 public MethodBase [] Methods;
2638                 Expression instance_expression = null;
2639                 
2640                 public MethodGroupExpr (MemberInfo [] mi)
2641                 {
2642                         Methods = new MethodBase [mi.Length];
2643                         mi.CopyTo (Methods, 0);
2644                         eclass = ExprClass.MethodGroup;
2645                 }
2646
2647                 public MethodGroupExpr (ArrayList l)
2648                 {
2649                         Methods = new MethodBase [l.Count];
2650
2651                         l.CopyTo (Methods, 0);
2652                         eclass = ExprClass.MethodGroup;
2653                 }
2654                 
2655                 //
2656                 // `A method group may have associated an instance expression' 
2657                 // 
2658                 public Expression InstanceExpression {
2659                         get {
2660                                 return instance_expression;
2661                         }
2662
2663                         set {
2664                                 instance_expression = value;
2665                         }
2666                 }
2667                 
2668                 override public Expression DoResolve (EmitContext ec)
2669                 {
2670                         return this;
2671                 }
2672
2673                 override public void Emit (EmitContext ec)
2674                 {
2675                         throw new Exception ("This should never be reached");
2676                 }
2677
2678                 bool RemoveMethods (bool keep_static)
2679                 {
2680                         ArrayList smethods = new ArrayList ();
2681                         int top = Methods.Length;
2682                         int i;
2683                         
2684                         for (i = 0; i < top; i++){
2685                                 MethodBase mb = Methods [i];
2686
2687                                 if (mb.IsStatic == keep_static)
2688                                         smethods.Add (mb);
2689                         }
2690
2691                         if (smethods.Count == 0)
2692                                 return false;
2693
2694                         Methods = new MethodBase [smethods.Count];
2695                         smethods.CopyTo (Methods, 0);
2696
2697                         return true;
2698                 }
2699                 
2700                 /// <summary>
2701                 ///   Removes any instance methods from the MethodGroup, returns
2702                 ///   false if the resulting set is empty.
2703                 /// </summary>
2704                 public bool RemoveInstanceMethods ()
2705                 {
2706                         return RemoveMethods (true);
2707                 }
2708
2709                 /// <summary>
2710                 ///   Removes any static methods from the MethodGroup, returns
2711                 ///   false if the resulting set is empty.
2712                 /// </summary>
2713                 public bool RemoveStaticMethods ()
2714                 {
2715                         return RemoveMethods (false);
2716                 }
2717         }
2718
2719         /// <summary>
2720         ///   Fully resolved expression that evaluates to a Field
2721         /// </summary>
2722         public class FieldExpr : Expression, IAssignMethod, IMemoryLocation {
2723                 public readonly FieldInfo FieldInfo;
2724                 public Expression InstanceExpression;
2725                 Location loc;
2726                 
2727                 public FieldExpr (FieldInfo fi, Location l)
2728                 {
2729                         FieldInfo = fi;
2730                         eclass = ExprClass.Variable;
2731                         type = fi.FieldType;
2732                         loc = l;
2733                 }
2734
2735                 override public Expression DoResolve (EmitContext ec)
2736                 {
2737                         if (!FieldInfo.IsStatic){
2738                                 if (InstanceExpression == null){
2739                                         throw new Exception ("non-static FieldExpr without instance var\n" +
2740                                                              "You have to assign the Instance variable\n" +
2741                                                              "Of the FieldExpr to set this\n");
2742                                 }
2743
2744                                 InstanceExpression = InstanceExpression.Resolve (ec);
2745                                 if (InstanceExpression == null)
2746                                         return null;
2747                                 
2748                         }
2749
2750                         return this;
2751                 }
2752
2753                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2754                 {
2755                         Expression e = DoResolve (ec);
2756
2757                         if (e == null)
2758                                 return null;
2759                         
2760                         if (!FieldInfo.IsInitOnly)
2761                                 return this;
2762
2763                         //
2764                         // InitOnly fields can only be assigned in constructors
2765                         //
2766
2767                         if (ec.IsConstructor)
2768                                 return this;
2769
2770                         Report.Error (191, loc,
2771                                       "Readonly field can not be assigned outside " +
2772                                       "of constructor or variable initializer");
2773                         
2774                         return null;
2775                 }
2776
2777                 override public void Emit (EmitContext ec)
2778                 {
2779                         ILGenerator ig = ec.ig;
2780
2781                         if (FieldInfo.IsStatic)
2782                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2783                         else {
2784                                 InstanceExpression.Emit (ec);
2785                                 
2786                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
2787                         }
2788                 }
2789
2790                 public void EmitAssign (EmitContext ec, Expression source)
2791                 {
2792                         bool is_static = FieldInfo.IsStatic;
2793
2794                         if (!is_static){
2795                                 Expression instance = InstanceExpression;
2796
2797                                 if (instance.Type.IsValueType){
2798                                         if (instance is IMemoryLocation){
2799                                                 IMemoryLocation ml = (IMemoryLocation) instance;
2800
2801                                                 ml.AddressOf (ec);
2802                                         } else
2803                                                 throw new Exception ("The " + instance + " of type " + Type+
2804                                                                      "represents a ValueType and does not " +
2805                                                                      "implement IMemoryLocation");
2806                                 } else
2807                                         instance.Emit (ec);
2808                         }
2809                         source.Emit (ec);
2810                         
2811                         if (is_static)
2812                                 ec.ig.Emit (OpCodes.Stsfld, FieldInfo);
2813                         else {
2814                                 ec.ig.Emit (OpCodes.Stfld, FieldInfo);
2815                         }
2816                 }
2817                 
2818                 public void AddressOf (EmitContext ec)
2819                 {
2820                         if (FieldInfo.IsStatic)
2821                                 ec.ig.Emit (OpCodes.Ldsflda, FieldInfo);
2822                         else {
2823                                 InstanceExpression.Emit (ec);
2824                                 ec.ig.Emit (OpCodes.Ldflda, FieldInfo);
2825                         }
2826                 }
2827         }
2828         
2829         /// <summary>
2830         ///   Expression that evaluates to a Property.  The Assign class
2831         ///   might set the `Value' expression if we are in an assignment.
2832         ///
2833         ///   This is not an LValue because we need to re-write the expression, we
2834         ///   can not take data from the stack and store it.  
2835         /// </summary>
2836         public class PropertyExpr : ExpressionStatement, IAssignMethod {
2837                 public readonly PropertyInfo PropertyInfo;
2838                 public readonly bool IsStatic;
2839                 MethodInfo [] Accessors;
2840                 Location loc;
2841                 
2842                 Expression instance_expr;
2843                 
2844                 public PropertyExpr (PropertyInfo pi, Location l)
2845                 {
2846                         PropertyInfo = pi;
2847                         eclass = ExprClass.PropertyAccess;
2848                         IsStatic = false;
2849                         loc = l;
2850                         Accessors = TypeManager.GetAccessors (pi);
2851
2852                         if (Accessors != null)
2853                                 for (int i = 0; i < Accessors.Length; i++){
2854                                         if (Accessors [i] != null)
2855                                                 if (Accessors [i].IsStatic)
2856                                                         IsStatic = true;
2857                                 }
2858                         else
2859                                 Accessors = new MethodInfo [2];
2860                         
2861                         type = pi.PropertyType;
2862                 }
2863
2864                 //
2865                 // The instance expression associated with this expression
2866                 //
2867                 public Expression InstanceExpression {
2868                         set {
2869                                 instance_expr = value;
2870                         }
2871
2872                         get {
2873                                 return instance_expr;
2874                         }
2875                 }
2876
2877                 public bool VerifyAssignable ()
2878                 {
2879                         if (!PropertyInfo.CanWrite){
2880                                 Report.Error (200, loc, 
2881                                               "The property `" + PropertyInfo.Name +
2882                                               "' can not be assigned to, as it has not set accessor");
2883                                 return false;
2884                         }
2885
2886                         return true;
2887                 }
2888
2889                 override public Expression DoResolve (EmitContext ec)
2890                 {
2891                         if (!PropertyInfo.CanRead){
2892                                 Report.Error (154, loc, 
2893                                               "The property `" + PropertyInfo.Name +
2894                                               "' can not be used in " +
2895                                               "this context because it lacks a get accessor");
2896                                 return null;
2897                         }
2898
2899                         type = PropertyInfo.PropertyType;
2900
2901                         return this;
2902                 }
2903
2904                 override public void Emit (EmitContext ec)
2905                 {
2906                         Invocation.EmitCall (ec, IsStatic, instance_expr, Accessors [0], null);
2907                         
2908                 }
2909
2910                 //
2911                 // Implements the IAssignMethod interface for assignments
2912                 //
2913                 public void EmitAssign (EmitContext ec, Expression source)
2914                 {
2915                         Argument arg = new Argument (source, Argument.AType.Expression);
2916                         ArrayList args = new ArrayList ();
2917
2918                         args.Add (arg);
2919                         Invocation.EmitCall (ec, IsStatic, instance_expr, Accessors [1], args);
2920                 }
2921
2922                 override public void EmitStatement (EmitContext ec)
2923                 {
2924                         Emit (ec);
2925                         ec.ig.Emit (OpCodes.Pop);
2926                 }
2927         }
2928
2929         /// <summary>
2930         ///   Fully resolved expression that evaluates to a Expression
2931         /// </summary>
2932         public class EventExpr : Expression {
2933                 public readonly EventInfo EventInfo;
2934                 Location loc;
2935                 public Expression InstanceExpression;
2936
2937                 public readonly bool IsStatic;
2938                 
2939                 public EventExpr (EventInfo ei, Location loc)
2940                 {
2941                         EventInfo = ei;
2942                         this.loc = loc;
2943                         eclass = ExprClass.EventAccess;
2944
2945                         MethodInfo add_accessor = TypeManager.GetAddMethod (ei);
2946                         MethodInfo remove_accessor = TypeManager.GetRemoveMethod (ei);
2947                         
2948                         if (add_accessor != null)
2949                                 if (add_accessor.IsStatic)
2950                                         IsStatic = true;
2951
2952                         if (remove_accessor != null)
2953                                 if (remove_accessor.IsStatic)
2954                                         IsStatic = true;
2955                 }
2956
2957                 override public Expression DoResolve (EmitContext ec)
2958                 {
2959                         // We are born in resolved state.
2960
2961                         Console.WriteLine ("Came here");
2962                         type = EventInfo.EventHandlerType;
2963                         return this;
2964                 }
2965
2966                 override public void Emit (EmitContext ec)
2967                 {
2968                         throw new Exception ("Implement me");
2969                         // FIXME: Implement.
2970                 }
2971         }
2972 }