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