svn path=/trunk/mcs/; revision=60765
[mono.git] / mcs / mbas / 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 //   Manjula GHM (mmanjula@novell.com)
7 //
8 // (C) 2001 Ximian, Inc.
9 //
10 //
11
12 namespace Mono.MonoBASIC {
13         using System;
14         using System.Collections;
15         using System.Diagnostics;
16         using System.Reflection;
17         using System.Reflection.Emit;
18         using System.Text;
19
20         /// <remarks>
21         ///   The ExprClass class contains the is used to pass the 
22         ///   classification of an expression (value, variable, namespace,
23         ///   type, method group, property access, event access, indexer access,
24         ///   nothing).
25         /// </remarks>
26         public enum ExprClass : byte {
27                 Invalid,
28                 
29                 Value,
30                 Variable,
31                 Namespace,
32                 Type,
33                 MethodGroup,
34                 PropertyAccess,
35                 EventAccess,
36                 IndexerAccess,
37                 Nothing, 
38         }
39
40         /// <remarks>
41         ///   This is used to tell Resolve in which types of expressions we're
42         ///   interested.
43         /// </remarks>
44         [Flags]
45         public enum ResolveFlags {
46                 // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess.
47                 VariableOrValue         = 1,
48
49                 // Returns a type expression.
50                 Type                    = 2,
51
52                 // Returns a method group.
53                 MethodGroup             = 4,
54
55                 // Allows SimpleNames to be returned.
56                 // This is used by MemberAccess to construct long names that can not be
57                 // partially resolved (namespace-qualified names for example).
58                 SimpleName              = 8,
59
60                 // Mask of all the expression class flags.
61                 MaskExprClass           = 15,
62
63                 // Disable control flow analysis while resolving the expression.
64                 // This is used when resolving the instance expression of a field expression.
65                 DisableFlowAnalysis     = 16
66         }
67
68         //
69         // This is just as a hint to AddressOf of what will be done with the
70         // address.
71         [Flags]
72         public enum AddressOp {
73                 Store = 1,
74                 Load  = 2,
75                 LoadStore = 3
76         };
77         
78         /// <summary>
79         ///   This interface is implemented by variables
80         /// </summary>
81         public interface IMemoryLocation {
82                 /// <summary>
83                 ///   The AddressOf method should generate code that loads
84                 ///   the address of the object and leaves it on the stack.
85                 ///
86                 ///   The 'mode' argument is used to notify the expression
87                 ///   of whether this will be used to read from the address or
88                 ///   write to the address.
89                 ///
90                 ///   This is just a hint that can be used to provide good error
91                 ///   reporting, and should have no other side effects. 
92                 /// </summary>
93                 void AddressOf (EmitContext ec, AddressOp mode);
94         }
95
96         /// <summary>
97         ///   This interface is implemented by variables
98         /// </summary>
99         public interface IVariable {
100                 /// <summary>
101                 ///   Checks whether the variable has already been assigned at
102                 ///   the current position of the method's control flow and
103                 ///   reports an appropriate error message if not.
104                 ///
105                 ///   If the variable is a struct, then this call checks whether
106                 ///   all of its fields (including all private ones) have been
107                 ///   assigned.
108                 /// </summary>
109                 bool IsAssigned (EmitContext ec, Location loc);
110
111                 /// <summary>
112                 ///   Checks whether field 'name' in this struct has been assigned.
113                 /// </summary>
114                 bool IsFieldAssigned (EmitContext ec, string name, Location loc);
115
116                 /// <summary>
117                 ///   Tells the flow analysis code that the variable has already
118                 ///   been assigned at the current code position.
119                 ///
120                 ///   If the variable is a struct, this call marks all its fields
121                 ///   (including private fields) as being assigned.
122                 /// </summary>
123                 void SetAssigned (EmitContext ec);
124
125                 /// <summary>
126                 ///   Tells the flow analysis code that field 'name' in this struct
127                 ///   has already been assigned atthe current code position.
128                 /// </summary>
129                 void SetFieldAssigned (EmitContext ec, string name);
130         }
131
132         /// <summary>
133         ///   This interface denotes an expression which evaluates to a member
134         ///   of a struct or a class.
135         /// </summary>
136         public interface IMemberExpr
137         {
138                 /// <summary>
139                 ///   The name of this member.
140                 /// </summary>
141                 string Name {
142                         get;
143                 }
144
145                 /// <summary>
146                 ///   Whether this is an instance member.
147                 /// </summary>
148                 bool IsInstance {
149                         get;
150                 }
151
152                 /// <summary>
153                 ///   Whether this is a static member.
154                 /// </summary>
155                 bool IsStatic {
156                         get;
157                 }
158
159                 /// <summary>
160                 ///   The type which declares this member.
161                 /// </summary>
162                 Type DeclaringType {
163                         get;
164                 }
165
166                 /// <summary>
167                 ///   The instance expression associated with this member, if it's a
168                 ///   non-static member.
169                 /// </summary>
170                 Expression InstanceExpression {
171                         get; set;
172                 }
173         }
174
175         /// <summary>
176         ///   Expression which resolves to a type.
177         /// </summary>
178         public interface ITypeExpression
179         {
180                 /// <summary>
181                 ///   Resolve the expression, but only lookup types.
182                 /// </summary>
183                 Expression DoResolveType (EmitContext ec);
184         }
185
186         /// <remarks>
187         ///   Base class for expressions
188         /// </remarks>
189         public abstract class Expression {
190                 public ExprClass eclass;
191                 protected Type type;
192                 protected Location loc;
193                 
194                 public Type Type {
195                         get {
196                                 return type;
197                         }
198
199                         set {
200                                 type = value;
201                         }
202                 }
203
204                 public Location Location {
205                         get {
206                                 return loc;
207                         }
208                 }
209
210                 /// <summary>
211                 ///   Utility wrapper routine for Error, just to beautify the code
212                 /// </summary>
213                 public void Error (int error, string s)
214                 {
215                         if (!Location.IsNull (loc))
216                                 Report.Error (error, loc, s);
217                         else
218                                 Report.Error (error, s);
219                 }
220
221                 /// <summary>
222                 ///   Utility wrapper routine for Warning, just to beautify the code
223                 /// </summary>
224                 public void Warning (int warning, string s)
225                 {
226                         if (!Location.IsNull (loc))
227                                 Report.Warning (warning, loc, s);
228                         else
229                                 Report.Warning (warning, s);
230                 }
231
232                 /// <summary>
233                 ///   Utility wrapper routine for Warning, only prints the warning if
234                 ///   warnings of level 'level' are enabled.
235                 /// </summary>
236                 public void Warning (int warning, int level, string s)
237                 {
238                         if (level <= RootContext.WarningLevel)
239                                 Warning (warning, s);
240                 }
241
242                 static public void Error_CannotConvertType (Location loc, Type source, Type target)
243                 {
244                         Report.Error (30, loc, "Cannot convert type '" +
245                                       TypeManager.MonoBASIC_Name (source) + "' to '" +
246                                       TypeManager.MonoBASIC_Name (target) + "'");
247                 }
248
249                 /// <summary>
250                 ///   Performs semantic analysis on the Expression
251                 /// </summary>
252                 ///
253                 /// <remarks>
254                 ///   The Resolve method is invoked to perform the semantic analysis
255                 ///   on the node.
256                 ///
257                 ///   The return value is an expression (it can be the
258                 ///   same expression in some cases) or a new
259                 ///   expression that better represents this node.
260                 ///   
261                 ///   For example, optimizations of Unary (LiteralInt)
262                 ///   would return a new LiteralInt with a negated
263                 ///   value.
264                 ///   
265                 ///   If there is an error during semantic analysis,
266                 ///   then an error should be reported (using Report)
267                 ///   and a null value should be returned.
268                 ///   
269                 ///   There are two side effects expected from calling
270                 ///   Resolve(): the the field variable "eclass" should
271                 ///   be set to any value of the enumeration
272                 ///   'ExprClass' and the type variable should be set
273                 ///   to a valid type (this is the type of the
274                 ///   expression).
275                 /// </remarks>
276                 public abstract Expression DoResolve (EmitContext ec);
277
278                 public virtual Expression DoResolveLValue (EmitContext ec, Expression right_side)
279                 {
280                         return DoResolve (ec);
281                 }
282                 
283                 /// <summary>
284                 ///   Resolves an expression and performs semantic analysis on it.
285                 /// </summary>
286                 ///
287                 /// <remarks>
288                 ///   Currently Resolve wraps DoResolve to perform sanity
289                 ///   checking and assertion checking on what we expect from Resolve.
290                 /// </remarks>
291                 public Expression Resolve (EmitContext ec, ResolveFlags flags)
292                 {
293                         // Are we doing a types-only search ?
294                         if ((flags & ResolveFlags.MaskExprClass) == ResolveFlags.Type) {
295                                 ITypeExpression type_expr = this as ITypeExpression;
296
297                                 if (type_expr == null)
298                                         return null;
299
300                                 return type_expr.DoResolveType (ec);
301                         }
302
303                         bool old_do_flow_analysis = ec.DoFlowAnalysis;
304                         if ((flags & ResolveFlags.DisableFlowAnalysis) != 0)
305                                 ec.DoFlowAnalysis = false;
306                         
307                         Expression e;
308                         try {
309                                 if (this is SimpleName)
310                                         e = ((SimpleName) this).DoResolveAllowStatic (ec);
311                                 else 
312                                         e = DoResolve (ec);
313                         } finally {
314                                 ec.DoFlowAnalysis = old_do_flow_analysis;
315                         }
316
317                         if (e == null)
318                                 return null;
319
320                         if (e is SimpleName){
321                                 SimpleName s = (SimpleName) e;
322
323                                 if ((flags & ResolveFlags.SimpleName) == 0) {
324
325                                         object lookup = TypeManager.MemberLookup (
326                                                 ec.ContainerType, ec.ContainerType, AllMemberTypes,
327                                                 AllBindingFlags | BindingFlags.NonPublic, s.Name);
328                                         if (lookup != null)
329                                                 Error (30390, "'" + s.Name + "' " +
330                                                        "is inaccessible because of its protection level");
331                                         else
332                                                 Error (30451, "The name '" + s.Name + "' could not be " +
333                                                        "found in '" + ec.DeclSpace.Name + "'");
334                                         return null;
335                                 }
336
337                                 return s;
338                         }
339                         
340                         if ((e is TypeExpr) || (e is ComposedCast)) {
341                                 if ((flags & ResolveFlags.Type) == 0) {
342                                         e.Error118 (flags);
343                                         return null;
344                                 }
345
346                                 return e;
347                         }
348
349                         switch (e.eclass) {
350                         case ExprClass.Type:
351                                 if ((flags & ResolveFlags.VariableOrValue) == 0) {
352                                         e.Error118 (flags);
353                                         return null;
354                                 }
355                                 break;
356
357                         case ExprClass.MethodGroup:
358                                 if ((flags & ResolveFlags.MethodGroup) == 0) {
359                                         MethodGroupExpr mg = (MethodGroupExpr) e;
360                                         Invocation i = new Invocation (mg, new ArrayList(), Location.Null);
361                                         Expression te = i.Resolve(ec);
362                                         //((MethodGroupExpr) e).ReportUsageError ();
363                                         //return null;
364                                         return te;
365                                 }
366                                 break;
367
368                         case ExprClass.Value:
369                         case ExprClass.Variable:
370                         case ExprClass.PropertyAccess:
371                         case ExprClass.EventAccess:
372                         case ExprClass.IndexerAccess:
373                                 if ((flags & ResolveFlags.VariableOrValue) == 0) {
374                                         e.Error118 (flags);
375                                         return null;
376                                 }
377                                 break;
378
379                         default:
380                                 throw new Exception ("Expression " + e.GetType () +
381                                                      " ExprClass is Invalid after resolve");
382                         }
383
384                         if (e.type == null)
385                                 throw new Exception (
386                                         "Expression " + e.GetType () +
387                                         " did not set its type after Resolve\n" +
388                                         "called from: " + this.GetType ());
389
390                         return e;
391                 }
392
393                 /// <summary>
394                 ///   Resolves an expression and performs semantic analysis on it.
395                 /// </summary>
396                 public Expression Resolve (EmitContext ec)
397                 {
398                         return Resolve (ec, ResolveFlags.VariableOrValue);
399                 }
400
401                 /// <summary>
402                 ///   Resolves an expression for LValue assignment
403                 /// </summary>
404                 ///
405                 /// <remarks>
406                 ///   Currently ResolveLValue wraps DoResolveLValue to perform sanity
407                 ///   checking and assertion checking on what we expect from Resolve
408                 /// </remarks>
409                 public Expression ResolveLValue (EmitContext ec, Expression right_side)
410                 {
411                         Expression e = DoResolveLValue (ec, right_side);
412
413                         if (e != null){
414                                 if (e is SimpleName){
415                                         SimpleName s = (SimpleName) e;
416
417                                         Report.Error (
418                                                 30451, loc,
419                                                 "The name '" + s.Name + "' could not be found in '" +
420                                                 ec.DeclSpace.Name + "'");
421                                         return null;
422                                 }
423
424                                 if (e.eclass == ExprClass.Invalid)
425                                         throw new Exception ("Expression " + e +
426                                                              " ExprClass is Invalid after resolve");
427
428                                 if (e.eclass == ExprClass.MethodGroup) {
429                                         MethodGroupExpr mg = (MethodGroupExpr) e;
430                                         Invocation i = new Invocation (mg, new ArrayList(), Location.Null);
431                                         Expression te = i.Resolve(ec);
432                                         return te;
433                                         //((MethodGroupExpr) e).ReportUsageError ();
434                                         //return null;
435                                 }
436
437                                 if (e.type == null)
438                                         throw new Exception ("Expression " + e +
439                                                              " did not set its type after Resolve");
440                         }
441
442                         return e;
443                 }
444                 
445                 /// <summary>
446                 ///   Emits the code for the expression
447                 /// </summary>
448                 ///
449                 /// <remarks>
450                 ///   The Emit method is invoked to generate the code
451                 ///   for the expression.  
452                 /// </remarks>
453                 public abstract void Emit (EmitContext ec);
454
455                 /// <summary>
456                 ///   Protected constructor.  Only derivate types should
457                 ///   be able to be created
458                 /// </summary>
459
460                 protected Expression ()
461                 {
462                         eclass = ExprClass.Invalid;
463                         type = null;
464                 }
465
466                 /// <summary>
467                 ///   Returns a literalized version of a literal FieldInfo
468                 /// </summary>
469                 ///
470                 /// <remarks>
471                 ///   The possible return values are:
472                 ///      IntConstant, UIntConstant
473                 ///      LongLiteral, ULongConstant
474                 ///      FloatConstant, DoubleConstant
475                 ///      StringConstant
476                 ///
477                 ///   The value returned is already resolved.
478                 /// </remarks>
479                 public static Constant Constantify (object v, Type t)
480                 {
481                         if (t == TypeManager.int32_type)
482                                 return new IntConstant ((int) v);
483                         else if (t == TypeManager.uint32_type)
484                                 return new UIntConstant ((uint) v);
485                         else if (t == TypeManager.int64_type)
486                                 return new LongConstant ((long) v);
487                         else if (t == TypeManager.uint64_type)
488                                 return new ULongConstant ((ulong) v);
489                         else if (t == TypeManager.float_type)
490                                 return new FloatConstant ((float) v);
491                         else if (t == TypeManager.double_type)
492                                 return new DoubleConstant ((double) v);
493                         else if (t == TypeManager.string_type)
494                                 return new StringConstant ((string) v);
495                         else if (t == TypeManager.short_type)
496                                 return new ShortConstant ((short)v);
497                         else if (t == TypeManager.ushort_type)
498                                 return new UShortConstant ((ushort)v);
499                         else if (t == TypeManager.sbyte_type)
500                                 return new SByteConstant (((sbyte)v));
501                         else if (t == TypeManager.byte_type)
502                                 return new ByteConstant ((byte)v);
503                         else if (t == TypeManager.char_type)
504                                 return new CharConstant ((char)v);
505                         else if (t == TypeManager.bool_type)
506                                 return new BoolConstant ((bool) v);
507                         else if (t == TypeManager.decimal_type)
508                                 return new DecimalConstant ((decimal)v);
509                         else if (TypeManager.IsEnumType (t)){
510                                 Constant e = Constantify (v, TypeManager.EnumToUnderlying (v.GetType ()));
511
512                                 return new EnumConstant (e, t);
513                         } else
514                                 throw new Exception ("Unknown type for constant (" + t +
515                                                      "), details: " + v);
516                 }
517
518                 /// <summary>
519                 ///   Returns a fully formed expression after a MemberLookup
520                 /// </summary>
521                 public static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
522                 {
523                         if (mi is EventInfo)
524                                 return new EventExpr ((EventInfo) mi, loc);
525                         else if (mi is FieldInfo)
526                                 return new FieldExpr ((FieldInfo) mi, loc);
527                         else if (mi is PropertyInfo)
528                                 return new PropertyExpr (ec, (PropertyInfo) mi, loc);
529                         else if (mi is Type){
530                                 return new TypeExpr ((System.Type) mi, loc);
531                         }
532
533                         return null;
534                 }
535
536                 //
537                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
538                 //
539                 // This code could use some optimizations, but we need to do some
540                 // measurements.  For example, we could use a delegate to 'flag' when
541                 // something can not any longer be a method-group (because it is something
542                 // else).
543                 //
544                 // Return values:
545                 //     If the return value is an Array, then it is an array of
546                 //     MethodBases
547                 //   
548                 //     If the return value is an MemberInfo, it is anything, but a Method
549                 //
550                 //     null on error.
551                 //
552                 // FIXME: When calling MemberLookup inside an 'Invocation', we should pass
553                 // the arguments here and have MemberLookup return only the methods that
554                 // match the argument count/type, unlike we are doing now (we delay this
555                 // decision).
556                 //
557                 // This is so we can catch correctly attempts to invoke instance methods
558                 // from a static body (scan for error 120 in ResolveSimpleName).
559                 //
560                 //
561                 // FIXME: Potential optimization, have a static ArrayList
562                 //
563
564                 public static Expression MemberLookup (EmitContext ec, Type t, string name,
565                                                        MemberTypes mt, BindingFlags bf, Location loc)
566                 {
567                         return MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc);
568                 }
569
570                 //
571                 // Lookup type 't' for code in class 'invocation_type'.  Note that it's important
572                 // to set 'invocation_type' correctly since this method also checks whether the
573                 // invoking class is allowed to access the member in class 't'.  When you want to
574                 // explicitly do a lookup in the base class, you must set both 't' and 'invocation_type'
575                 // to the base class (although a derived class can access protected members of its base
576                 // class it cannot do so through an instance of the base class (error CS1540)).
577                 // 
578
579                 public static Expression MemberLookup (EmitContext ec, Type invocation_type, Type t,
580                                                        string name, MemberTypes mt, BindingFlags bf,
581                                                        Location loc)
582                 {
583                         MemberInfo [] mi = TypeManager.MemberLookup (invocation_type, t, mt, bf, name);
584
585                         if (mi == null)
586                                 return null;
587
588                         int count = mi.Length;
589
590                         if (mi [0] is MethodBase)
591                                 return new MethodGroupExpr (mi, loc);
592
593                         if (mi [0] is PropertyInfo)
594                                 return new PropertyGroupExpr (mi, loc);
595
596                         if (count > 1)
597                                 return null;
598
599                         return ExprClassFromMemberInfo (ec, mi [0], loc);
600                 }
601
602                 public const MemberTypes AllMemberTypes =
603                         MemberTypes.Constructor |
604                         MemberTypes.Event       |
605                         MemberTypes.Field       |
606                         MemberTypes.Method      |
607                         MemberTypes.NestedType  |
608                         MemberTypes.Property;
609                 
610                 public const BindingFlags AllBindingFlags =
611                         BindingFlags.Public |
612                         BindingFlags.Static |
613                         BindingFlags.Instance |
614                         BindingFlags.IgnoreCase;
615
616                 public static Expression MemberLookup (EmitContext ec, Type t, string name, Location loc)
617                 {
618                         return MemberLookup (ec, ec.ContainerType, t, name, AllMemberTypes, AllBindingFlags, loc);
619                 }
620
621                 public static Expression MethodLookup (EmitContext ec, Type t, string name, Location loc)
622                 {
623                         return MemberLookup (ec, ec.ContainerType, t, name,
624                                              MemberTypes.Method, AllBindingFlags, loc);
625                 }
626
627                 /// <summary>
628                 ///   This is a wrapper for MemberLookup that is not used to "probe", but
629                 ///   to find a final definition.  If the final definition is not found, we
630                 ///   look for private members and display a useful debugging message if we
631                 ///   find it.
632                 /// </summary>
633                 public static Expression MemberLookupFinal (EmitContext ec, Type t, string name, 
634                                                             Location loc)
635                 {
636                         return MemberLookupFinal (ec, t, name, MemberTypes.Method, AllBindingFlags, loc);
637                 }
638
639                 public static Expression MemberLookupFinal (EmitContext ec, Type t, string name,
640                                                             MemberTypes mt, BindingFlags bf, Location loc)
641                 {
642                         Expression e;
643
644                         int errors = Report.Errors;
645
646                         e = MemberLookup (ec, ec.ContainerType, t, name, mt, bf, loc);
647
648                         if (e != null)
649                                 return e;
650
651                         // Error has already been reported.
652                         if (errors < Report.Errors)
653                                 return null;
654                         
655                         e = MemberLookup (ec, t, name, AllMemberTypes,
656                                           AllBindingFlags | BindingFlags.NonPublic, loc);
657                         if (e == null){
658                                 Report.Error (
659                                         30456, loc, "'" + t + "' does not contain a definition " +
660                                         "for '" + name + "'");
661                         } else {
662                                         Report.Error (
663                                                 30390, loc, "'" + t + "." + name +
664                                                 "' is inaccessible due to its protection level");
665                         }
666                         
667                         return null;
668                 }
669
670                 static public MemberInfo GetFieldFromEvent (EventExpr event_expr)
671                 {
672                         EventInfo ei = event_expr.EventInfo;
673
674                         return TypeManager.GetPrivateFieldOfEvent (ei);
675                 }
676                 
677                 static EmptyExpression MyEmptyExpr;
678                 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
679                 {
680                         Type expr_type = expr.Type;
681
682                         if (expr_type == null && expr.eclass == ExprClass.MethodGroup){
683                                 // if we are a method group, emit a warning
684
685                                 expr.Emit (null);
686                         }
687
688                         //
689                         // notice that it is possible to write "ValueType v = 1", the ValueType here
690                         // is an abstract class, and not really a value type, so we apply the same rules.
691                         //
692                         if (target_type == TypeManager.object_type || target_type == TypeManager.value_type) {
693                                 //
694                                 // A pointer type cannot be converted to object
695                                 // 
696                                 if (expr_type.IsPointer)
697                                         return null;
698
699                                 if (expr_type.IsValueType)
700                                         return new BoxedCast (expr);
701                                 if (expr_type.IsClass || expr_type.IsInterface)
702                                         return new EmptyCast (expr, target_type);
703                         } else if (expr_type.IsSubclassOf (target_type)) {
704                                 //
705                                 // Special case: enumeration to System.Enum.
706                                 // System.Enum is not a value type, it is a class, so we need
707                                 // a boxing conversion
708                                 //
709                                 if (expr_type.IsEnum)
710                                         return new BoxedCast (expr);
711                         
712                                 return new EmptyCast (expr, target_type);
713                         } else {
714
715                                 // This code is kind of mirrored inside StandardConversionExists
716                                 // with the small distinction that we only probe there
717                                 //
718                                 // Always ensure that the code here and there is in sync
719                                 
720                                 // from the null type to any reference-type.
721                                 if (expr is NullLiteral && !target_type.IsValueType)
722                                         return new EmptyCast (expr, target_type);
723
724                                 // from any class-type S to any interface-type T.
725                                 if (target_type.IsInterface) {
726                                         if (TypeManager.ImplementsInterface (expr_type, target_type)){
727                                                 if (expr_type.IsClass)
728                                                         return new EmptyCast (expr, target_type);
729                                                 else if (expr_type.IsValueType)
730                                                         return new BoxedCast (expr);
731                                         }
732                                 }
733
734                                 // from any interface type S to interface-type T.
735                                 if (expr_type.IsInterface && target_type.IsInterface) {
736                                         if (TypeManager.ImplementsInterface (expr_type, target_type))
737                                                 return new EmptyCast (expr, target_type);
738                                         else
739                                                 return null;
740                                 }
741                                 
742                                 // from an array-type S to an array-type of type T
743                                 if (expr_type.IsArray && target_type.IsArray) {
744                                         if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
745
746                                                 Type expr_element_type = expr_type.GetElementType ();
747
748                                                 if (MyEmptyExpr == null)
749                                                         MyEmptyExpr = new EmptyExpression ();
750                                                 
751                                                 MyEmptyExpr.SetType (expr_element_type);
752                                                 Type target_element_type = target_type.GetElementType ();
753
754                                                 if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
755                                                         if (StandardConversionExists (MyEmptyExpr,
756                                                                                       target_element_type))
757                                                                 return new EmptyCast (expr, target_type);
758                                         }
759                                 }
760                                 
761                                 
762                                 // from an array-type to System.Array
763                                 if (expr_type.IsArray && target_type == TypeManager.array_type)
764                                         return new EmptyCast (expr, target_type);
765                                 
766                                 // from any delegate type to System.Delegate
767                                 if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
768                                     target_type == TypeManager.delegate_type)
769                                         return new EmptyCast (expr, target_type);
770                                         
771                                 // from any array-type or delegate type into System.ICloneable.
772                                 if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
773                                         if (target_type == TypeManager.icloneable_type)
774                                                 return new EmptyCast (expr, target_type);
775                                 
776                                 return null;
777
778                         }
779                         
780                         return null;
781                 }
782
783                 /// <summary>
784                 ///   Implicit Numeric Conversions.
785                 ///
786                 ///   expr is the expression to convert, returns a new expression of type
787                 ///   target_type or null if an implicit conversion is not possible.
788                 /// </summary>
789                 static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
790                                                                     Type target_type, Location loc)
791                 {
792                         Type expr_type = expr.Type;
793                         
794                         //
795                         // Attempt to do the implicit constant expression conversions
796
797                         if (expr is BoolConstant || expr is IntConstant || expr is LongConstant || expr is DoubleConstant || expr is FloatConstant){
798                                 Expression e;
799                                 
800                                 e = TryImplicitNumericConversion (target_type, (Constant) expr);
801
802                                 if (e != null)
803                                         return e;
804                                 if (target_type == TypeManager.byte_type || 
805                                     target_type == TypeManager.short_type ||
806                                     target_type == TypeManager.int32_type ||
807                                     target_type == TypeManager.int64_type ||
808                                     target_type == TypeManager.float_type) {
809                                         
810                                         string val = null;
811                                         if (expr is IntConstant)
812                                                 val = ((IntConstant) expr).Value.ToString();
813                                         if (expr is LongConstant)
814                                                 val = ((LongConstant) expr).Value.ToString();
815                                         if (expr is FloatConstant)
816                                                 val = ((FloatConstant) expr).Value.ToString();
817                                         if (expr is DoubleConstant)
818                                                 val = ((DoubleConstant) expr).Value.ToString();
819                                         Error_ConstantValueCannotBeConverted(loc, val, target_type);
820                                         return null;
821                                 }
822                         } else if (expr is LongConstant && target_type == TypeManager.uint64_type) {
823                                 //
824                                 // Try the implicit constant expression conversion
825                                 // from long to ulong, instead of a nice routine,
826                                 // we just inline it
827                                 //
828                                 long v = ((LongConstant) expr).Value;
829                                 if (v > 0)
830                                         return new ULongConstant ((ulong) v);
831                         }
832
833                         Type real_target_type = target_type;
834
835                         if (target_type == TypeManager.bool_type) {
836
837                                 if (expr_type == TypeManager.decimal_type) {
838                                         return RTConversionExpression (ec, "System.Convert",".ToBoolean" , expr, loc);
839                                 }
840
841                                 if ((expr_type != TypeManager.char_type) && 
842                                     (expr_type != TypeManager.string_type) &&
843                                     (expr_type != TypeManager.object_type))
844                                         return new NumericToBoolCast (expr, expr.Type);
845                         }
846
847                         if (expr_type == TypeManager.bool_type){
848                                 //
849                                 if (real_target_type == TypeManager.sbyte_type)
850                                         return new BoolToNumericCast (expr, target_type);
851                                 if (real_target_type == TypeManager.byte_type) 
852                                         return new BoolToNumericCast (expr, target_type);
853                                 if (real_target_type == TypeManager.int32_type)
854                                         return new BoolToNumericCast (expr, target_type);
855                                 if (real_target_type == TypeManager.int64_type)
856                                         return new BoolToNumericCast (expr, target_type);
857                                 if (real_target_type == TypeManager.double_type)
858                                         return new BoolToNumericCast (expr, target_type);
859                                 if (real_target_type == TypeManager.float_type)
860                                         return new BoolToNumericCast (expr, target_type);
861                                 if (real_target_type == TypeManager.short_type)
862                                         return new BoolToNumericCast (expr, target_type);
863                                 if (real_target_type == TypeManager.decimal_type)
864                                         return RTConversionExpression(ec, "DecimalType.FromBoolean", expr, loc);
865                         } else if (expr_type == TypeManager.sbyte_type){
866                                 //
867                                 // From sbyte to short, int, long, float, double.
868                                 //
869                                 if (real_target_type == TypeManager.int32_type)
870                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
871                                 if (real_target_type == TypeManager.int64_type)
872                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
873                                 if (real_target_type == TypeManager.double_type)
874                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
875                                 if (real_target_type == TypeManager.float_type)
876                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
877                                 if (real_target_type == TypeManager.short_type)
878                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
879                         } else if (expr_type == TypeManager.byte_type){
880                                 //
881                                 // From byte to short, ushort, int, uint, long, ulong, float, double
882                                 // 
883                                 if ((real_target_type == TypeManager.short_type) ||
884                                     (real_target_type == TypeManager.ushort_type) ||
885                                     (real_target_type == TypeManager.int32_type) ||
886                                     (real_target_type == TypeManager.uint32_type))
887                                         return new EmptyCast (expr, target_type);
888
889                                 if (real_target_type == TypeManager.uint64_type)
890                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
891                                 if (real_target_type == TypeManager.int64_type)
892                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
893                                 if (real_target_type == TypeManager.float_type)
894                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
895                                 if (real_target_type == TypeManager.double_type)
896                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
897                         } else if (expr_type == TypeManager.short_type){
898                                 //
899                                 // From short to int, long, float, double
900                                 // 
901                                 if (real_target_type == TypeManager.int32_type)
902                                         return new EmptyCast (expr, target_type);
903                                 if (real_target_type == TypeManager.int64_type)
904                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
905                                 if (real_target_type == TypeManager.double_type)
906                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
907                                 if (real_target_type == TypeManager.float_type)
908                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
909                         } else if (expr_type == TypeManager.ushort_type){
910                                 //
911                                 // From ushort to int, uint, long, ulong, float, double
912                                 //
913                                 if (real_target_type == TypeManager.uint32_type)
914                                         return new EmptyCast (expr, target_type);
915
916                                 if (real_target_type == TypeManager.uint64_type)
917                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
918                                 if (real_target_type == TypeManager.int32_type)
919                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
920                                 if (real_target_type == TypeManager.int64_type)
921                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
922                                 if (real_target_type == TypeManager.double_type)
923                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
924                                 if (real_target_type == TypeManager.float_type)
925                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
926                         } else if (expr_type == TypeManager.int32_type){
927                                 //
928                                 // From int to long, float, double
929                                 //
930                                 if (real_target_type == TypeManager.int64_type)
931                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
932                                 if (real_target_type == TypeManager.double_type)
933                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
934                                 if (real_target_type == TypeManager.float_type)
935                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
936                         } else if (expr_type == TypeManager.uint32_type){
937                                 //
938                                 // From uint to long, ulong, float, double
939                                 //
940                                 if (real_target_type == TypeManager.int64_type)
941                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
942                                 if (real_target_type == TypeManager.uint64_type)
943                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
944                                 if (real_target_type == TypeManager.double_type)
945                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
946                                                                OpCodes.Conv_R8);
947                                 if (real_target_type == TypeManager.float_type)
948                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
949                                                                OpCodes.Conv_R4);
950                         } else if (expr_type == TypeManager.int64_type){
951                                 //
952                                 // From long/ulong to float, double
953                                 //
954                                 if (real_target_type == TypeManager.double_type)
955                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
956                                 if (real_target_type == TypeManager.float_type)
957                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);     
958                         } else if (expr_type == TypeManager.uint64_type){
959                                 //
960                                 // From ulong to float, double
961                                 //
962                                 if (real_target_type == TypeManager.double_type)
963                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
964                                                                OpCodes.Conv_R8);
965                                 if (real_target_type == TypeManager.float_type)
966                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
967                                                                OpCodes.Conv_R4);        
968                         } else if (expr_type == TypeManager.string_type){
969
970                                 if (real_target_type == TypeManager.bool_type)
971                                         return RTConversionExpression (ec, "BooleanType.FromString" , expr, loc);
972                                 if (real_target_type == TypeManager.decimal_type)
973                                         return RTConversionExpression (ec, "DecimalType.FromString" , expr, loc);
974                                 if (real_target_type == TypeManager.float_type)
975                                         return RTConversionExpression (ec, "SingleType.FromString" , expr, loc);
976                                 if (real_target_type == TypeManager.short_type)
977                                         return RTConversionExpression (ec, "ShortType.FromString" , expr, loc);
978                                 if (real_target_type == TypeManager.int64_type)
979                                         return RTConversionExpression (ec, "LongType.FromString" , expr, loc);
980                                 if (real_target_type == TypeManager.int32_type)
981                                         return RTConversionExpression (ec, "IntegerType.FromString" , expr, loc);
982                                 if (real_target_type == TypeManager.double_type)
983                                         return RTConversionExpression (ec, "DoubleType.FromString" , expr, loc);
984                                 if (real_target_type == TypeManager.byte_type)
985                                         return RTConversionExpression (ec, "ByteType.FromString" , expr, loc);
986                         } else if (expr_type == TypeManager.float_type){
987                                 //
988                                 // float to double
989                                 //
990                                 if (real_target_type == TypeManager.decimal_type)
991                                         return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc);
992                                 if (real_target_type == TypeManager.double_type)
993                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
994
995                         } else if (expr_type == TypeManager.double_type){
996
997                                 if (real_target_type == TypeManager.decimal_type)
998                                         return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc);
999                         } else if (expr_type == TypeManager.decimal_type){
1000
1001                                 if (real_target_type == TypeManager.bool_type)
1002                                         return RTConversionExpression (ec, "BooleanType.FromDecimal" , expr, loc);
1003                                 if (real_target_type == TypeManager.short_type)
1004                                         return RTConversionExpression(ec, "System.Convert", ".ToInt16", expr, loc);
1005                                 if (real_target_type == TypeManager.byte_type)
1006                                         return RTConversionExpression(ec, "System.Convert", ".ToByte", expr, loc);
1007                                 if (real_target_type == TypeManager.int32_type)
1008                                         return RTConversionExpression(ec, "System.Convert", ".ToInt32", expr, loc);
1009                                 if (real_target_type == TypeManager.int64_type)
1010                                         return RTConversionExpression(ec, "System.Convert", ".ToInt64", expr, loc);
1011                                 if (real_target_type == TypeManager.float_type)
1012                                         return RTConversionExpression(ec, "System.Convert", ".ToSingle", expr, loc);
1013                                 if (real_target_type == TypeManager.double_type)
1014                                         return RTConversionExpression(ec, "System.Convert", ".ToDouble", expr, loc);
1015                         }
1016
1017                         return null;
1018                 }
1019
1020                 //
1021                 // Tests whether an implicit reference conversion exists between expr_type
1022                 // and target_type
1023                 //
1024                 public static bool ImplicitReferenceConversionExists (Expression expr, Type expr_type, Type target_type)
1025                 {
1026                         //
1027                         // This is the boxed case.
1028                         //
1029                         if (target_type == TypeManager.object_type) {
1030                                 if ((expr_type.IsClass) ||
1031                                     (expr_type.IsValueType) ||
1032                                     (expr_type.IsInterface))
1033                                         return true;
1034                                 
1035                         } else if (expr_type.IsSubclassOf (target_type)) {
1036                                 return true;
1037                         } else {
1038                                 // Please remember that all code below actually comes
1039                                 // from ImplicitReferenceConversion so make sure code remains in sync
1040                                 
1041                                 // from any class-type S to any interface-type T.
1042                                 if (target_type.IsInterface) {
1043                                         if (TypeManager.ImplementsInterface (expr_type, target_type))
1044                                                 return true;
1045                                 }
1046                                 
1047                                 // from any interface type S to interface-type T.
1048                                 if (expr_type.IsInterface && target_type.IsInterface)
1049                                         if (TypeManager.ImplementsInterface (expr_type, target_type))
1050                                                 return true;
1051                                 
1052                                 // from an array-type S to an array-type of type T
1053                                 if (expr_type.IsArray && target_type.IsArray) {
1054                                         if (expr_type.GetArrayRank () == target_type.GetArrayRank ()) {
1055                                                 
1056                                                 Type expr_element_type = expr_type.GetElementType ();
1057
1058                                                 if (MyEmptyExpr == null)
1059                                                         MyEmptyExpr = new EmptyExpression ();
1060                                                 
1061                                                 MyEmptyExpr.SetType (expr_element_type);
1062                                                 Type target_element_type = target_type.GetElementType ();
1063                                                 
1064                                                 if (!expr_element_type.IsValueType && !target_element_type.IsValueType)
1065                                                         if (StandardConversionExists (MyEmptyExpr,
1066                                                                                       target_element_type))
1067                                                                 return true;
1068                                         }
1069                                 }
1070                                 
1071                                 // from an array-type to System.Array
1072                                 if (expr_type.IsArray && (target_type == TypeManager.array_type))
1073                                         return true;
1074                                 
1075                                 // from any delegate type to System.Delegate
1076                                 if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
1077                                     target_type == TypeManager.delegate_type)
1078                                         if (target_type.IsAssignableFrom (expr_type))
1079                                                 return true;
1080                                         
1081                                 // from any array-type or delegate type into System.ICloneable.
1082                                 if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
1083                                         if (target_type == TypeManager.icloneable_type)
1084                                                 return true;
1085                                 
1086                                 // from the null type to any reference-type.
1087                                 if (expr is NullLiteral && !target_type.IsValueType &&
1088                                     !TypeManager.IsEnumType (target_type))
1089                                         return true;
1090                                 
1091                         }
1092
1093                         return false;
1094                 }
1095
1096                 /// <summary>
1097                 ///  Same as StandardConversionExists except that it also looks at
1098                 ///  implicit user defined conversions - needed for overload resolution
1099                 /// </summary>
1100                 public static bool ImplicitConversionExists (EmitContext ec, Expression expr, Type target_type)
1101                 {
1102                         if (StandardConversionExists (expr, target_type) == true)
1103                                 return true;
1104
1105 #if false
1106                         Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null);
1107
1108                         if (dummy != null)
1109                                 return true;
1110 #endif
1111
1112                         return false;
1113                 }
1114
1115                 /// <summary>
1116                 ///  Determines if a standard implicit conversion exists from
1117                 ///  expr_type to target_type
1118                 /// </summary>
1119                 public static bool StandardConversionExists (Expression expr, Type target_type)
1120                 {
1121                         return WideningConversionExists (expr, expr.type, target_type);
1122                 }
1123
1124                 public static bool WideningConversionExists (Type expr_type, Type target_type)
1125                 {
1126                         return WideningConversionExists (null, expr_type, target_type);
1127                 }
1128
1129                 public static bool WideningConversionExists (Expression expr, Type target_type)
1130                 {
1131                         return WideningConversionExists (expr, expr.Type, target_type);
1132                 }
1133
1134                 public static bool WideningConversionExists (Expression expr, Type expr_type, Type target_type)
1135                 {
1136
1137                         if (expr_type == null || expr_type == TypeManager.void_type)
1138                                 return false;
1139                         
1140                         if (expr_type == target_type)
1141                                 return true;
1142
1143                         // Conversions from enum to underlying type are widening.
1144                         if (expr_type.IsSubclassOf (TypeManager.enum_type))
1145                                 expr_type = TypeManager.EnumToUnderlying (expr_type);
1146
1147                         if (expr_type == target_type)
1148                                 return true;
1149
1150                         // First numeric conversions 
1151                         
1152                         if (expr_type == TypeManager.sbyte_type){
1153                                 //
1154                                 // From sbyte to short, int, long, float, double.
1155                                 //
1156                                 if ((target_type == TypeManager.int32_type) || 
1157                                     (target_type == TypeManager.int64_type) ||
1158                                     (target_type == TypeManager.double_type) ||
1159                                     (target_type == TypeManager.float_type)  ||
1160                                     (target_type == TypeManager.short_type) ||
1161                                     (target_type == TypeManager.decimal_type))
1162                                         return true;
1163                                 
1164                         } else if (expr_type == TypeManager.byte_type){
1165                                 //
1166                                 // From byte to short, ushort, int, uint, long, ulong, float, double
1167                                 // 
1168                                 if ((target_type == TypeManager.short_type) ||
1169                                     (target_type == TypeManager.bool_type) ||
1170                                     (target_type == TypeManager.ushort_type) ||
1171                                     (target_type == TypeManager.int32_type) ||
1172                                     (target_type == TypeManager.uint32_type) ||
1173                                     (target_type == TypeManager.uint64_type) ||
1174                                     (target_type == TypeManager.int64_type) ||
1175                                     (target_type == TypeManager.float_type) ||
1176                                     (target_type == TypeManager.double_type) ||
1177                                     (target_type == TypeManager.decimal_type))
1178                                         return true;
1179         
1180                         } else if (expr_type == TypeManager.short_type){
1181                                 //
1182                                 // From short to int, long, float, double
1183                                 // 
1184                                 if ((target_type == TypeManager.int32_type) ||
1185                                     (target_type == TypeManager.bool_type) ||
1186                                     (target_type == TypeManager.int64_type) ||
1187                                     (target_type == TypeManager.double_type) ||
1188                                     (target_type == TypeManager.float_type) ||
1189                                     (target_type == TypeManager.decimal_type))
1190                                         return true;
1191                                         
1192                         } else if (expr_type == TypeManager.ushort_type){
1193                                 //
1194                                 // From ushort to int, uint, long, ulong, float, double
1195                                 //
1196                                 if ((target_type == TypeManager.uint32_type) ||
1197                                     (target_type == TypeManager.uint64_type) ||
1198                                     (target_type == TypeManager.int32_type) ||
1199                                     (target_type == TypeManager.int64_type) ||
1200                                     (target_type == TypeManager.double_type) ||
1201                                     (target_type == TypeManager.float_type) ||
1202                                     (target_type == TypeManager.decimal_type))
1203                                         return true;
1204                                     
1205                         } else if (expr_type == TypeManager.int32_type){
1206                                 //
1207                                 // From int to long, float, double
1208                                 //
1209                                 if ((target_type == TypeManager.int64_type) ||
1210                                     (target_type == TypeManager.bool_type) ||
1211                                     (target_type == TypeManager.double_type) ||
1212                                     (target_type == TypeManager.float_type) ||
1213                                     (target_type == TypeManager.decimal_type))
1214                                         return true;
1215                                         
1216                         } else if (expr_type == TypeManager.uint32_type){
1217                                 //
1218                                 // From uint to long, ulong, float, double
1219                                 //
1220                                 if ((target_type == TypeManager.int64_type) ||
1221                                     (target_type == TypeManager.bool_type) ||
1222                                     (target_type == TypeManager.uint64_type) ||
1223                                     (target_type == TypeManager.double_type) ||
1224                                     (target_type == TypeManager.float_type) ||
1225                                     (target_type == TypeManager.decimal_type))
1226                                         return true;
1227                                         
1228                         } else if ((expr_type == TypeManager.uint64_type) ||
1229                                    (expr_type == TypeManager.int64_type)) {
1230                                 //
1231                                 // From long/ulong to float, double
1232                                 //
1233                                 if ((target_type == TypeManager.double_type) ||
1234                                     (target_type == TypeManager.bool_type) ||
1235                                     (target_type == TypeManager.float_type) ||
1236                                     (target_type == TypeManager.decimal_type))
1237                                         return true;
1238                                     
1239                         } else if (expr_type == TypeManager.decimal_type) {
1240                                 if (target_type == TypeManager.float_type ||
1241                                     target_type == TypeManager.double_type)
1242                                         return true;
1243                         } else if (expr_type == TypeManager.float_type){
1244                                 //
1245                                 // float to double, decimal
1246                                 //
1247                                 if (target_type == TypeManager.double_type)
1248                                         return true;
1249                         } else if (expr_type == TypeManager.double_type){
1250
1251                                 if ((target_type == TypeManager.bool_type))
1252                                         return true;
1253                         }               
1254                         
1255                         if (ImplicitReferenceConversionExists (expr, expr_type, target_type))
1256                                 return true;
1257                         
1258 /*
1259                         if (expr is IntConstant){
1260                                 int value = ((IntConstant) expr).Value;
1261
1262                                 if (target_type == TypeManager.sbyte_type){
1263                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
1264                                                 return true;
1265                                 } else if (target_type == TypeManager.byte_type){
1266                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
1267                                                 return true;
1268                                 } else if (target_type == TypeManager.short_type){
1269                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
1270                                                 return true;
1271                                 } else if (target_type == TypeManager.ushort_type){
1272                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1273                                                 return true;
1274                                 } else if (target_type == TypeManager.uint32_type){
1275                                         if (value >= 0)
1276                                                 return true;
1277                                 } else if (target_type == TypeManager.uint64_type){
1278                                          //
1279                                          // we can optimize this case: a positive int32
1280                                          // always fits on a uint64.  But we need an opcode
1281                                          // to do it.
1282                                          //
1283                                         if (value >= 0)
1284                                                 return true;
1285                                 }
1286                                 
1287                                 if (value == 0 && expr is IntLiteral && TypeManager.IsEnumType (target_type))
1288                                         return true;
1289                         }
1290
1291                         if (expr is LongConstant && target_type == TypeManager.uint64_type){
1292                                 //
1293                                 // Try the implicit constant expression conversion
1294                                 // from long to ulong, instead of a nice routine,
1295                                 // we just inline it
1296                                 //
1297                                 long v = ((LongConstant) expr).Value;
1298                                 if (v > 0)
1299                                         return true;
1300                         }
1301 */
1302                         
1303                         if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
1304                                 IntLiteral i = (IntLiteral) expr;
1305
1306                                 if (i.Value == 0)
1307                                         return true;
1308                         }
1309
1310                         if (target_type == TypeManager.void_ptr_type && expr_type.IsPointer)
1311                                 return true;
1312
1313                         return false;
1314                 }
1315
1316                 //
1317                 // Used internally by FindMostEncompassedType, this is used
1318                 // to avoid creating lots of objects in the tight loop inside
1319                 // FindMostEncompassedType
1320                 //
1321                 static EmptyExpression priv_fmet_param;
1322                 
1323                 /// <summary>
1324                 ///  Finds "most encompassed type" according to the spec (13.4.2)
1325                 ///  amongst the methods in the MethodGroupExpr
1326                 /// </summary>
1327                 static Type FindMostEncompassedType (ArrayList types)
1328                 {
1329                         Type best = null;
1330
1331                         if (priv_fmet_param == null)
1332                                 priv_fmet_param = new EmptyExpression ();
1333
1334                         foreach (Type t in types){
1335                                 priv_fmet_param.SetType (t);
1336                                 
1337                                 if (best == null) {
1338                                         best = t;
1339                                         continue;
1340                                 }
1341                                 
1342                                 if (StandardConversionExists (priv_fmet_param, best))
1343                                         best = t;
1344                         }
1345
1346                         return best;
1347                 }
1348
1349                 //
1350                 // Used internally by FindMostEncompassingType, this is used
1351                 // to avoid creating lots of objects in the tight loop inside
1352                 // FindMostEncompassingType
1353                 //
1354                 static EmptyExpression priv_fmee_ret;
1355                 
1356                 /// <summary>
1357                 ///  Finds "most encompassing type" according to the spec (13.4.2)
1358                 ///  amongst the types in the given set
1359                 /// </summary>
1360                 static Type FindMostEncompassingType (ArrayList types)
1361                 {
1362                         Type best = null;
1363
1364                         if (priv_fmee_ret == null)
1365                                 priv_fmee_ret = new EmptyExpression ();
1366
1367                         foreach (Type t in types){
1368                                 priv_fmee_ret.SetType (best);
1369
1370                                 if (best == null) {
1371                                         best = t;
1372                                         continue;
1373                                 }
1374
1375                                 if (StandardConversionExists (priv_fmee_ret, t))
1376                                         best = t;
1377                         }
1378                         
1379                         return best;
1380                 }
1381
1382                 //
1383                 // Used to avoid creating too many objects
1384                 //
1385                 static EmptyExpression priv_fms_expr;
1386                 
1387                 /// <summary>
1388                 ///   Finds the most specific source Sx according to the rules of the spec (13.4.4)
1389                 ///   by making use of FindMostEncomp* methods. Applies the correct rules separately
1390                 ///   for explicit and implicit conversion operators.
1391                 /// </summary>
1392                 static public Type FindMostSpecificSource (MethodGroupExpr me, Expression source,
1393                                                            bool apply_explicit_conv_rules,
1394                                                            Location loc)
1395                 {
1396                         ArrayList src_types_set = new ArrayList ();
1397                         
1398                         if (priv_fms_expr == null)
1399                                 priv_fms_expr = new EmptyExpression ();
1400
1401                         //
1402                         // If any operator converts from S then Sx = S
1403                         //
1404                         Type source_type= source.Type;
1405                         foreach (MethodBase mb in me.Methods){
1406                                 ParameterData pd = Invocation.GetParameterData (mb);
1407                                 Type param_type = pd.ParameterType (0);
1408
1409                                 if (param_type == source_type)
1410                                         return param_type;
1411
1412                                 if (apply_explicit_conv_rules) {
1413                                         //
1414                                         // From the spec :
1415                                         // Find the set of applicable user-defined conversion operators, U.  This set
1416                                         // consists of the
1417                                         // user-defined implicit or explicit conversion operators declared by
1418                                         // the classes or structs in D that convert from a type encompassing
1419                                         // or encompassed by S to a type encompassing or encompassed by T
1420                                         //
1421                                         priv_fms_expr.SetType (param_type);
1422                                         if (StandardConversionExists (priv_fms_expr, source_type))
1423                                                 src_types_set.Add (param_type);
1424                                         else {
1425                                                 if (StandardConversionExists (source, param_type))
1426                                                         src_types_set.Add (param_type);
1427                                         }
1428                                 } else {
1429                                         //
1430                                         // Only if S is encompassed by param_type
1431                                         //
1432                                         if (StandardConversionExists (source, param_type))
1433                                                 src_types_set.Add (param_type);
1434                                 }
1435                         }
1436                         
1437                         //
1438                         // Explicit Conv rules
1439                         //
1440                         if (apply_explicit_conv_rules) {
1441                                 ArrayList candidate_set = new ArrayList ();
1442
1443                                 foreach (Type param_type in src_types_set){
1444                                         if (StandardConversionExists (source, param_type))
1445                                                 candidate_set.Add (param_type);
1446                                 }
1447
1448                                 if (candidate_set.Count != 0)
1449                                         return FindMostEncompassedType (candidate_set);
1450                         }
1451
1452                         //
1453                         // Final case
1454                         //
1455                         if (apply_explicit_conv_rules)
1456                                 return FindMostEncompassingType (src_types_set);
1457                         else
1458                                 return FindMostEncompassedType (src_types_set);
1459                 }
1460
1461                 //
1462                 // Useful in avoiding proliferation of objects
1463                 //
1464                 static EmptyExpression priv_fmt_expr;
1465                 
1466                 /// <summary>
1467                 ///  Finds the most specific target Tx according to section 13.4.4
1468                 /// </summary>
1469                 static public Type FindMostSpecificTarget (MethodGroupExpr me, Type target,
1470                                                            bool apply_explicit_conv_rules,
1471                                                            Location loc)
1472                 {
1473                         ArrayList tgt_types_set = new ArrayList ();
1474                         
1475                         if (priv_fmt_expr == null)
1476                                 priv_fmt_expr = new EmptyExpression ();
1477                         
1478                         //
1479                         // If any operator converts to T then Tx = T
1480                         //
1481                         foreach (MethodInfo mi in me.Methods){
1482                                 Type ret_type = mi.ReturnType;
1483
1484                                 if (ret_type == target)
1485                                         return ret_type;
1486
1487                                 if (apply_explicit_conv_rules) {
1488                                         //
1489                                         // From the spec :
1490                                         // Find the set of applicable user-defined conversion operators, U.
1491                                         //
1492                                         // This set consists of the
1493                                         // user-defined implicit or explicit conversion operators declared by
1494                                         // the classes or structs in D that convert from a type encompassing
1495                                         // or encompassed by S to a type encompassing or encompassed by T
1496                                         //
1497                                         priv_fms_expr.SetType (ret_type);
1498                                         if (StandardConversionExists (priv_fms_expr, target))
1499                                                 tgt_types_set.Add (ret_type);
1500                                         else {
1501                                                 priv_fms_expr.SetType (target);
1502                                                 if (StandardConversionExists (priv_fms_expr, ret_type))
1503                                                         tgt_types_set.Add (ret_type);
1504                                         }
1505                                 } else {
1506                                         //
1507                                         // Only if T is encompassed by param_type
1508                                         //
1509                                         priv_fms_expr.SetType (ret_type);
1510                                         if (StandardConversionExists (priv_fms_expr, target))
1511                                                 tgt_types_set.Add (ret_type);
1512                                 }
1513                         }
1514
1515                         //
1516                         // Explicit conv rules
1517                         //
1518                         if (apply_explicit_conv_rules) {
1519                                 ArrayList candidate_set = new ArrayList ();
1520
1521                                 foreach (Type ret_type in tgt_types_set){
1522                                         priv_fmt_expr.SetType (ret_type);
1523                                         
1524                                         if (StandardConversionExists (priv_fmt_expr, target))
1525                                                 candidate_set.Add (ret_type);
1526                                 }
1527
1528                                 if (candidate_set.Count != 0)
1529                                         return FindMostEncompassingType (candidate_set);
1530                         }
1531                         
1532                         //
1533                         // Okay, final case !
1534                         //
1535                         if (apply_explicit_conv_rules)
1536                                 return FindMostEncompassedType (tgt_types_set);
1537                         else 
1538                                 return FindMostEncompassingType (tgt_types_set);
1539                 }
1540                 
1541                 /// <summary>
1542                 ///  User-defined Implicit conversions
1543                 /// </summary>
1544                 static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
1545                                                                  Type target, Location loc)
1546                 {
1547                         return UserDefinedConversion (ec, source, target, loc, false);
1548                 }
1549
1550                 /// <summary>
1551                 ///  User-defined Explicit conversions
1552                 /// </summary>
1553                 static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
1554                                                                  Type target, Location loc)
1555                 {
1556                         return UserDefinedConversion (ec, source, target, loc, true);
1557                 }
1558
1559                 /// <summary>
1560                 ///   Computes the MethodGroup for the user-defined conversion
1561                 ///   operators from source_type to target_type.  'look_for_explicit'
1562                 ///   controls whether we should also include the list of explicit
1563                 ///   operators
1564                 /// </summary>
1565                 static MethodGroupExpr GetConversionOperators (EmitContext ec,
1566                                                                Type source_type, Type target_type,
1567                                                                Location loc, bool look_for_explicit)
1568                 {
1569                         Expression mg1 = null, mg2 = null;
1570                         Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
1571                         string op_name;
1572
1573                         //
1574                         // FIXME : How does the False operator come into the picture ?
1575                         // This doesn't look complete and very correct !
1576                         //
1577                         if (target_type == TypeManager.bool_type && !look_for_explicit)
1578                                 op_name = "op_True";
1579                         else
1580                                 op_name = "op_Implicit";
1581
1582                         MethodGroupExpr union3;
1583                         
1584                         mg1 = MethodLookup (ec, source_type, op_name, loc);
1585                         if (source_type.BaseType != null)
1586                                 mg2 = MethodLookup (ec, source_type.BaseType, op_name, loc);
1587
1588                         if (mg1 == null)
1589                                 union3 = (MethodGroupExpr) mg2;
1590                         else if (mg2 == null)
1591                                 union3 = (MethodGroupExpr) mg1;
1592                         else
1593                                 union3 = Invocation.MakeUnionSet (mg1, mg2, loc);
1594
1595                         mg1 = MethodLookup (ec, target_type, op_name, loc);
1596                         if (mg1 != null){
1597                                 if (union3 != null)
1598                                         union3 = Invocation.MakeUnionSet (union3, mg1, loc);
1599                                 else
1600                                         union3 = (MethodGroupExpr) mg1;
1601                         }
1602
1603                         if (target_type.BaseType != null)
1604                                 mg1 = MethodLookup (ec, target_type.BaseType, op_name, loc);
1605                         
1606                         if (mg1 != null){
1607                                 if (union3 != null)
1608                                         union3 = Invocation.MakeUnionSet (union3, mg1, loc);
1609                                 else
1610                                         union3 = (MethodGroupExpr) mg1;
1611                         }
1612
1613                         MethodGroupExpr union4 = null;
1614
1615                         if (look_for_explicit) {
1616                                 op_name = "op_Explicit";
1617
1618                                 mg5 = MemberLookup (ec, source_type, op_name, loc);
1619                                 if (source_type.BaseType != null)
1620                                         mg6 = MethodLookup (ec, source_type.BaseType, op_name, loc);
1621                                 
1622                                 mg7 = MemberLookup (ec, target_type, op_name, loc);
1623                                 if (target_type.BaseType != null)
1624                                         mg8 = MethodLookup (ec, target_type.BaseType, op_name, loc);
1625                                 
1626                                 MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6, loc);
1627                                 MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8, loc);
1628
1629                                 union4 = Invocation.MakeUnionSet (union5, union6, loc);
1630                         }
1631                         
1632                         return Invocation.MakeUnionSet (union3, union4, loc);
1633                 }
1634                 
1635                 /// <summary>
1636                 ///   User-defined conversions
1637                 /// </summary>
1638                 static public Expression UserDefinedConversion (EmitContext ec, Expression source,
1639                                                                 Type target, Location loc,
1640                                                                 bool look_for_explicit)
1641                 {
1642                         MethodGroupExpr union;
1643                         Type source_type = source.Type;
1644                         MethodBase method = null;
1645                         
1646                         union = GetConversionOperators (ec, source_type, target, loc, look_for_explicit);
1647                         if (union == null)
1648                                 return null;
1649                         
1650                         Type most_specific_source, most_specific_target;
1651
1652 #if BLAH
1653                         foreach (MethodBase m in union.Methods){
1654                                 Console.WriteLine ("Name: " + m.Name);
1655                                 Console.WriteLine ("    : " + ((MethodInfo)m).ReturnType);
1656                         }
1657 #endif
1658                         
1659                         most_specific_source = FindMostSpecificSource (union, source, look_for_explicit, loc);
1660                         if (most_specific_source == null)
1661                                 return null;
1662
1663                         most_specific_target = FindMostSpecificTarget (union, target, look_for_explicit, loc);
1664                         if (most_specific_target == null) 
1665                                 return null;
1666
1667                         int count = 0;
1668
1669                         foreach (MethodBase mb in union.Methods){
1670                                 ParameterData pd = Invocation.GetParameterData (mb);
1671                                 MethodInfo mi = (MethodInfo) mb;
1672                                 
1673                                 if (pd.ParameterType (0) == most_specific_source &&
1674                                     mi.ReturnType == most_specific_target) {
1675                                         method = mb;
1676                                         count++;
1677                                 }
1678                         }
1679                         
1680                         if (method == null || count > 1)
1681                                 return null;
1682                         
1683                         
1684                         //
1685                         // This will do the conversion to the best match that we
1686                         // found.  Now we need to perform an implict standard conversion
1687                         // if the best match was not the type that we were requested
1688                         // by target.
1689                         //
1690                         if (look_for_explicit)
1691                                 source = ConvertExplicitStandard (ec, source, most_specific_source, loc);
1692                         else
1693                                 source = ConvertImplicitStandard (ec, source, most_specific_source, loc);
1694
1695                         if (source == null)
1696                                 return null;
1697
1698                         Expression e;
1699                         e =  new UserCast ((MethodInfo) method, source, loc);
1700                         if (e.Type != target){
1701                                 if (!look_for_explicit)
1702                                         e = ConvertImplicitStandard (ec, e, target, loc);
1703                                 else
1704                                         e = ConvertExplicitStandard (ec, e, target, loc);
1705                         } 
1706                         return e;
1707                 }
1708                 
1709                 /// <summary>
1710                 ///   Converts implicitly the resolved expression 'expr' into the
1711                 ///   'target_type'.  It returns a new expression that can be used
1712                 ///   in a context that expects a 'target_type'. 
1713                 /// </summary>
1714                 static public Expression ConvertImplicit (EmitContext ec, Expression expr,
1715                                                           Type target_type, Location loc)
1716                 {
1717                         Type expr_type = expr.Type;
1718                         Expression e;
1719
1720
1721                         if (expr_type == target_type)
1722                                 return expr;
1723
1724                         if (target_type == null)
1725                                 throw new Exception ("Target type is null");
1726
1727                         e = ConvertImplicitStandard (ec, expr, target_type, loc);
1728                         if (e != null)
1729                                 return e;
1730                                         
1731                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1732                         
1733                         if (e != null)
1734                                 return e;
1735
1736                         e = NarrowingConversion (ec, expr, target_type, loc);
1737                         if (e != null)
1738                                 return e;                               
1739
1740                         return null;
1741                 }
1742
1743                 /// <summary>
1744                 ///   Converts the resolved expression 'expr' into the
1745                 ///   'target_type' using the Microsoft.VisualBasic runtime.
1746                 ///   It returns a new expression that can be used
1747                 ///   in a context that expects a 'target_type'. 
1748                 /// </summary>
1749                 static private Expression RTConversionExpression (EmitContext ec, string s, Expression expr, Location loc)
1750                 {
1751                         Expression etmp, e;
1752                         ArrayList args;
1753                         Argument arg;
1754                         
1755                         etmp = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices." + s, loc);
1756                         args = new ArrayList();
1757                         arg = new Argument (expr, Argument.AType.Expression);
1758                         args.Add (arg);
1759                         e = (Expression) new Invocation (etmp, args, loc);
1760                         e = e.Resolve(ec);      
1761                         return (e);             
1762                 }
1763
1764                 static private Expression RTConversionExpression (EmitContext ec, string ns, string method, Expression expr, Location loc)
1765                 {
1766                         Expression etmp, e;
1767                         ArrayList args;
1768                         Argument arg;
1769                         
1770                         etmp = Mono.MonoBASIC.Parser.DecomposeQI(ns+method, loc);
1771                         args = new ArrayList();
1772                         arg = new Argument (expr, Argument.AType.Expression);
1773                         args.Add (arg);
1774                         e = (Expression) new Invocation (etmp, args, loc);
1775                         e = e.Resolve(ec);      
1776                         return (e);             
1777                 }
1778
1779                 
1780                 static public bool NarrowingConversionExists (EmitContext ec, Expression expr, Type target_type)
1781                 {
1782                         Type expr_type = expr.Type;
1783                         if (expr_type.IsSubclassOf (TypeManager.enum_type))
1784                                 expr_type = TypeManager.EnumToUnderlying (expr_type);
1785         
1786                         if (target_type.IsSubclassOf (TypeManager.enum_type))
1787                                 target_type = TypeManager.EnumToUnderlying (target_type);
1788
1789
1790                         if (expr_type == target_type)
1791                                 return true;
1792
1793                         if (target_type == TypeManager.sbyte_type){
1794                                 //
1795                                 // To sbyte from short, int, long, float, double.
1796                                 //
1797                                 if ((expr_type == TypeManager.int32_type) || 
1798                                     (expr_type == TypeManager.int64_type) ||
1799                                     (expr_type == TypeManager.double_type) ||
1800                                     (expr_type == TypeManager.float_type)  ||
1801                                     (expr_type == TypeManager.short_type) ||
1802                                     (expr_type == TypeManager.decimal_type))
1803                                         return true;
1804                                 
1805                         } else if (target_type == TypeManager.byte_type){
1806                                 //
1807                                 // To byte from short, ushort, int, uint, long, ulong, float, double
1808                                 // 
1809                                 if ((expr_type == TypeManager.short_type) ||
1810                                     (expr_type == TypeManager.ushort_type) ||
1811                                     (expr_type == TypeManager.int32_type) ||
1812                                     (expr_type == TypeManager.uint32_type) ||
1813                                     (expr_type == TypeManager.uint64_type) ||
1814                                     (expr_type == TypeManager.int64_type) ||
1815                                     (expr_type == TypeManager.float_type) ||
1816                                     (expr_type == TypeManager.double_type) ||
1817                                     (expr_type == TypeManager.decimal_type))
1818                                         return true;
1819         
1820                         } else if (target_type == TypeManager.short_type){
1821                                 //
1822                                 // To short from int, long, float, double
1823                                 // 
1824                                 if ((expr_type == TypeManager.int32_type) ||
1825                                     (expr_type == TypeManager.int64_type) ||
1826                                     (expr_type == TypeManager.double_type) ||
1827                                     (expr_type == TypeManager.float_type) ||
1828                                     (expr_type == TypeManager.decimal_type))
1829                                         return true;
1830                                         
1831                         } else if (target_type == TypeManager.ushort_type){
1832                                 //
1833                                 // To ushort from int, uint, long, ulong, float, double
1834                                 //
1835                                 if ((expr_type == TypeManager.uint32_type) ||
1836                                     (expr_type == TypeManager.uint64_type) ||
1837                                     (expr_type == TypeManager.int32_type) ||
1838                                     (expr_type == TypeManager.int64_type) ||
1839                                     (expr_type == TypeManager.double_type) ||
1840                                     (expr_type == TypeManager.float_type) ||
1841                                     (expr_type == TypeManager.decimal_type))
1842                                         return true;
1843                                     
1844                         } else if (target_type == TypeManager.int32_type){
1845                                 //
1846                                 // To int from long, float, double
1847                                 //
1848                                 if ((expr_type == TypeManager.int64_type) ||
1849                                     (expr_type == TypeManager.double_type) ||
1850                                     (expr_type == TypeManager.float_type) ||
1851                                     (expr_type == TypeManager.decimal_type))
1852                                         return true;
1853                                         
1854                         } else if (target_type == TypeManager.uint32_type){
1855                                 //
1856                                 // To uint from long, ulong, float, double
1857                                 //
1858                                 if ((expr_type == TypeManager.int64_type) ||
1859                                     (expr_type == TypeManager.uint64_type) ||
1860                                     (expr_type == TypeManager.double_type) ||
1861                                     (expr_type == TypeManager.float_type) ||
1862                                     (expr_type == TypeManager.decimal_type))
1863                                         return true;
1864                                         
1865                         } else if ((target_type == TypeManager.uint64_type) ||
1866                                    (target_type == TypeManager.int64_type)) {
1867                                 //
1868                                 // To long/ulong from float, double
1869                                 //
1870                                 if ((expr_type == TypeManager.double_type) ||
1871                                     (expr_type == TypeManager.float_type) ||
1872                                     (expr_type == TypeManager.decimal_type))
1873                                         return true;
1874                                     
1875                         } else if (target_type == TypeManager.decimal_type){
1876                                 if (expr_type == TypeManager.float_type ||
1877                                     expr_type == TypeManager.double_type)
1878                                         return true;
1879                         } else if (target_type == TypeManager.float_type){
1880                                 //
1881                                 // To float from double
1882                                 //
1883                                 if (expr_type == TypeManager.double_type)
1884                                         return true;
1885                         }       
1886
1887                         return (NarrowingConversion (ec, expr, target_type,Location.Null)) != null;     
1888                 }
1889                 
1890                 static public Expression NarrowingConversion (EmitContext ec, Expression expr,
1891                                                                 Type target_type, Location loc)
1892                 {
1893                         Type expr_type = expr.Type;
1894
1895                         if (expr_type.IsSubclassOf (TypeManager.enum_type))
1896                                 expr_type = TypeManager.EnumToUnderlying (expr_type);
1897         
1898                         if (target_type.IsSubclassOf (TypeManager.enum_type))
1899                                 target_type = TypeManager.EnumToUnderlying (target_type);
1900
1901                         if (expr_type == target_type)
1902                                 return expr;
1903
1904                         if (target_type == TypeManager.sbyte_type){
1905                                 //
1906                                 // To sbyte from short, int, long, float, double.
1907                                 //
1908                                 if (expr_type == TypeManager.int32_type) 
1909                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
1910                                 if (expr_type == TypeManager.int64_type)
1911                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
1912                                 if (expr_type == TypeManager.short_type)
1913                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
1914
1915                                 if (expr_type == TypeManager.float_type) {
1916                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1917                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I1);
1918                                 }
1919                                 if (expr_type == TypeManager.double_type) {
1920                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1921                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I1);
1922                                 }
1923                                 
1924                         } else if (target_type == TypeManager.byte_type){
1925                                 //
1926                                 // To byte from short, ushort, int, uint, long, ulong, float, double
1927                                 // 
1928                                 if (expr_type == TypeManager.short_type) 
1929                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
1930                                 if (expr_type == TypeManager.ushort_type) 
1931                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
1932                                 if (expr_type == TypeManager.int32_type) 
1933                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
1934                                 if (expr_type == TypeManager.uint32_type)
1935                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
1936                                 if (expr_type == TypeManager.uint64_type)
1937                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
1938                                 if (expr_type == TypeManager.int64_type) 
1939                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
1940
1941                                 if (expr_type == TypeManager.float_type) {
1942                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1943                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U1);
1944                                 }
1945                                 if (expr_type == TypeManager.double_type) {
1946                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1947                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U1);
1948                                 }
1949         
1950                         } else if (target_type == TypeManager.short_type) {
1951                                 //
1952                                 // To short from int, long, float, double
1953                                 // 
1954                                 if (expr_type == TypeManager.int32_type) 
1955                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
1956                                 if (expr_type == TypeManager.int64_type) 
1957                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
1958
1959                                 if (expr_type == TypeManager.float_type) {
1960                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1961                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I2);
1962                                 }
1963                                 if (expr_type == TypeManager.double_type) {
1964                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1965                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I2);
1966                                 }
1967                                         
1968                         } else if (target_type == TypeManager.ushort_type) {
1969                                 //
1970                                 // To ushort from int, uint, long, ulong, float, double
1971                                 //
1972                                 if (expr_type == TypeManager.uint32_type) 
1973                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
1974                                 if (expr_type == TypeManager.uint64_type)
1975                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
1976                                 if (expr_type == TypeManager.int32_type)
1977                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
1978                                 if (expr_type == TypeManager.int64_type)
1979                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
1980
1981                                 if (expr_type == TypeManager.float_type) {
1982                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1983                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U2);
1984                                 }
1985
1986                                 if (expr_type == TypeManager.double_type) {
1987                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
1988                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U2);
1989                                 }
1990                                     
1991                         } else if (target_type == TypeManager.int32_type){
1992                                 //
1993                                 // To int from long, float, double
1994                                 //
1995                                 if (expr_type == TypeManager.int64_type)
1996                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
1997
1998                                 if (expr_type == TypeManager.float_type) {
1999                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2000                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I4);
2001                                 }
2002                                 if (expr_type == TypeManager.double_type) {
2003                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2004                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I4);
2005                                 }
2006                                         
2007                         } else if (target_type == TypeManager.uint32_type){
2008                                 //
2009                                 // To uint from long, ulong, float, double
2010                                 //
2011                                 if (expr_type == TypeManager.int64_type) 
2012                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
2013                                 if (expr_type == TypeManager.uint64_type)
2014                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
2015                                 if (expr_type == TypeManager.float_type) {
2016                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2017                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U4);
2018                                 }
2019                                 if (expr_type == TypeManager.double_type) {
2020                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2021                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U4);
2022                                 }
2023                                         
2024                         } else if (target_type == TypeManager.uint64_type) {
2025                                 //
2026                                 // To long/ulong from float, double
2027                                 //
2028                                 if (expr_type == TypeManager.float_type) {
2029                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2030                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8);
2031                                 }
2032                                 if (expr_type == TypeManager.double_type) {
2033                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2034                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8);
2035                                 }
2036                                     
2037                         } else if (target_type == TypeManager.int64_type) {
2038                                 //
2039                                 // To long/ulong from float, double
2040                                 //
2041                                 if (expr_type == TypeManager.float_type) {
2042                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2043                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8);
2044                                 }
2045                                 if (expr_type == TypeManager.double_type) {
2046                                         Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc);
2047                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8);
2048                                 }
2049
2050                         } else if (target_type == TypeManager.float_type){
2051                                 //
2052                                 // To float from double
2053                                 //
2054                                 if (expr_type == TypeManager.double_type)
2055                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
2056                         }       
2057
2058                         TypeCode dest_type = Type.GetTypeCode (target_type);
2059                         TypeCode src_type = Type.GetTypeCode (expr_type);
2060                         Expression e = null;
2061
2062                         switch (dest_type) {
2063                                 case TypeCode.String:
2064                                         switch (src_type) {
2065                                                 case TypeCode.SByte:                                            
2066                                                 case TypeCode.Byte:
2067                                                         e = RTConversionExpression(ec, "StringType.FromByte", expr, loc);
2068                                                         break;  
2069                                                 case TypeCode.UInt16:
2070                                                 case TypeCode.Int16:
2071                                                         e = RTConversionExpression(ec, "StringType.FromShort", expr, loc);
2072                                                         break;          
2073                                                 case TypeCode.UInt32:                                   
2074                                                 case TypeCode.Int32:
2075                                                         e = RTConversionExpression(ec, "StringType.FromInteger", expr, loc);
2076                                                         break;                                                  
2077                                                 case TypeCode.UInt64:   
2078                                                 case TypeCode.Int64:
2079                                                         e = RTConversionExpression(ec, "StringType.FromLong", expr, loc);
2080                                                         break;                                                  
2081                                                 case TypeCode.Char:
2082                                                         e = RTConversionExpression(ec, "StringType.FromChar", expr, loc);
2083                                                         break;                                                          
2084                                                 case TypeCode.Single:
2085                                                         e = RTConversionExpression(ec, "StringType.FromSingle", expr, loc);
2086                                                         break;          
2087                                                 case TypeCode.Double:
2088                                                         e = RTConversionExpression(ec, "StringType.FromDouble", expr, loc);
2089                                                         break;                                                                                                                                                  
2090                                                 case TypeCode.Boolean:
2091                                                         e = RTConversionExpression(ec, "StringType.FromBoolean", expr, loc);
2092                                                         break;  
2093                                                 case TypeCode.DateTime:
2094                                                         e = RTConversionExpression(ec, "StringType.FromDate", expr, loc);
2095                                                         break;          
2096                                                 case TypeCode.Decimal:
2097                                                         e = RTConversionExpression(ec, "StringType.FromDecimal", expr, loc);
2098                                                         break;          
2099                                                 case TypeCode.Object:
2100                                                         e = RTConversionExpression(ec, "StringType.FromObject", expr, loc);
2101                                                         break;                                                                                                                                                                                                                          
2102                                         }
2103                                         break;
2104                                         
2105                                 case TypeCode.Double:
2106                                         switch (src_type) {                                             
2107                                                 case TypeCode.String:                           
2108                                                         e = RTConversionExpression(ec, "DoubleType.FromString", expr, loc);
2109                                                         break;          
2110                                                 case TypeCode.Object:                           
2111                                                         e = RTConversionExpression(ec, "DoubleType.FromObject", expr, loc);
2112                                                         break;                                                                                  
2113                                         }
2114                                         break;  
2115                                         
2116                                 case TypeCode.Single:
2117                                         switch (src_type) {                                             
2118                                                 case TypeCode.String:                           
2119                                                         e = RTConversionExpression(ec, "SingleType.FromString", expr, loc);
2120                                                         break;          
2121                                                 case TypeCode.Object:                           
2122                                                         e = RTConversionExpression(ec, "SingleType.FromObject", expr, loc);
2123                                                         break;                                                                                  
2124                                         }
2125                                         break;  
2126                                         
2127                                 case TypeCode.Decimal:
2128                                         switch (src_type) {                                             
2129                                                 case TypeCode.String:                           
2130                                                         e = RTConversionExpression(ec, "DecimalType.FromString", expr, loc);
2131                                                         break;          
2132                                                 case TypeCode.Object:                           
2133                                                         e = RTConversionExpression(ec, "DecimalType.FromObject", expr, loc);
2134                                                         break;                                                                                  
2135                                         }
2136                                         break;  
2137                                         
2138                                 case TypeCode.Int64:
2139                                 case TypeCode.UInt64:   
2140                                         switch (src_type) {                                             
2141                                                 case TypeCode.String:                           
2142                                                         e = RTConversionExpression(ec, "LongType.FromString", expr, loc);
2143                                                         break;          
2144                                                 case TypeCode.Object:                           
2145                                                         e = RTConversionExpression(ec, "LongType.FromObject", expr, loc);
2146                                                         break;                                                                                  
2147                                         }
2148                                         break;  
2149                                 case TypeCode.Int32:
2150                                 case TypeCode.UInt32:   
2151                                         switch (src_type) {                                             
2152                                                 case TypeCode.String:                           
2153                                                         e = RTConversionExpression(ec, "IntegerType.FromString", expr, loc);
2154                                                         break;          
2155                                                 case TypeCode.Object:                           
2156                                                         e = RTConversionExpression(ec, "IntegerType.FromObject", expr, loc);
2157                                                         break;                                                                                  
2158                                         }
2159                                         break;  
2160
2161                                 case TypeCode.Int16:
2162                                 case TypeCode.UInt16:   
2163                                         switch (src_type) {                                             
2164                                                 case TypeCode.String:                           
2165                                                         e = RTConversionExpression(ec, "ShortType.FromString", expr, loc);
2166                                                         break;          
2167                                                 case TypeCode.Object:                           
2168                                                         e = RTConversionExpression(ec, "ShortType.FromObject", expr, loc);
2169                                                         break;                                                                                  
2170                                         }
2171                                         break;  
2172                                 case TypeCode.Byte:
2173                                         
2174                                         switch (src_type) {                                             
2175                                                 case TypeCode.String:                           
2176                                                         e = RTConversionExpression(ec, "BooleanType.FromString", expr, loc);
2177                                                         break;          
2178                                                 case TypeCode.Object:                           
2179                                                         e = RTConversionExpression(ec, "ByteType.FromObject", expr, loc);
2180                                                         break;  
2181                                         }
2182                                         break;
2183                                 case TypeCode.Boolean:  
2184                                         switch (src_type) {                                             
2185                                                 case TypeCode.String:                           
2186                                                         e = RTConversionExpression(ec, "BooleanType.FromString", expr, loc);
2187                                                         break;          
2188                                                 case TypeCode.Object:                           
2189                                                         e = RTConversionExpression(ec, "BooleanType.FromObject", expr, loc);
2190                                                         break;                                                                                  
2191                                         }
2192                                         break;
2193                                 case TypeCode.DateTime: 
2194                                         switch (src_type) {                                             
2195                                                 case TypeCode.String:                           
2196                                                         e = RTConversionExpression(ec, "DateType.FromString", expr, loc);
2197                                                         break;          
2198                                                 case TypeCode.Object:                           
2199                                                         e = RTConversionExpression(ec, "DateType.FromObject", expr, loc);
2200                                                         break;                                                                                  
2201                                         }
2202                                         break;
2203                                 case TypeCode.Char:
2204                                         switch (src_type) {
2205
2206                                                 case TypeCode.String:
2207                                                         e = RTConversionExpression(ec, "CharType.FromString", expr, loc);
2208                                                         break;                  
2209                                         
2210                                 }       
2211                                 break;                                                                                                          
2212                         }
2213                         
2214                         // We must examine separately some types that
2215                         // don't have a TypeCode but are supported 
2216                         // in the runtime
2217                         if (expr_type == typeof(System.String) && target_type == typeof (System.Char[])) {
2218                                 e = RTConversionExpression(ec, "CharArrayType.FromString", expr, loc);
2219                         }
2220                         if (e != null)  
2221                                 return e;
2222                         // VB.NET Objects can be converted to anything by default
2223                         // unless, that is, an exception at runtime blows it all
2224                         if (src_type == TypeCode.Object) {
2225                                 Expression cast_type = Mono.MonoBASIC.Parser.DecomposeQI(target_type.ToString(), loc);
2226                                 Cast ce = new Cast (cast_type, expr, loc);
2227                                 ce.IsRuntimeCast = true;
2228                                 return ce.Resolve (ec);
2229                         }
2230                       return null;
2231                 }
2232
2233                 static public Expression ConvertNothingToDefaultValues (EmitContext ec, Expression expr,
2234                                                                         Type target_type, Location loc)
2235                 {
2236                         switch (Type.GetTypeCode (target_type)) {
2237                         case TypeCode.Boolean  :
2238                                 return new BoolConstant (false);
2239                         case TypeCode.Byte  :
2240                                 return new ByteConstant (0);
2241                         case TypeCode.Char  :
2242                                 return new CharConstant ((char)0);
2243                         case TypeCode.SByte :
2244                                 return new SByteConstant (0);
2245                         case TypeCode.Int16 :
2246                                 return new ShortConstant (0);
2247                         case TypeCode.Int32 :
2248                                 return new IntConstant (0);
2249                         case TypeCode.Int64 :
2250                                 return new LongConstant (0);
2251                         case TypeCode.Decimal :
2252                                 return new DecimalConstant (System.Decimal.Zero);
2253                         case TypeCode.Single :
2254                                 return new FloatConstant (0.0F);
2255                         case TypeCode.Double :
2256                                 return new DoubleConstant (0.0);
2257                         }
2258
2259                         return null;
2260                 }
2261                                                                                                 
2262                 /// <summary>
2263                 ///   Attempts to apply the 'Standard Implicit
2264                 ///   Conversion' rules to the expression 'expr' into
2265                 ///   the 'target_type'.  It returns a new expression
2266                 ///   that can be used in a context that expects a
2267                 ///   'target_type'.
2268                 ///
2269                 ///   This is different from 'ConvertImplicit' in that the
2270                 ///   user defined implicit conversions are excluded. 
2271                 /// </summary>
2272                 static public Expression ConvertImplicitStandard (EmitContext ec, Expression expr,
2273                                                                   Type target_type, Location loc)
2274                 {
2275                         Type expr_type = expr.Type;
2276
2277                         if (expr_type.IsSubclassOf (TypeManager.enum_type))
2278                                 expr_type = TypeManager.EnumToUnderlying (expr_type);
2279
2280                         Expression e;
2281
2282                         if (expr is NullLiteral) {
2283                                 if (target_type == TypeManager.string_type)
2284                                         return expr;
2285                                 e = ConvertNothingToDefaultValues (ec, expr, target_type, loc);
2286                                 if (e != null)
2287                                         return e;
2288                         }
2289
2290                         if (expr_type == target_type)
2291                                 return expr;
2292
2293                         e = ImplicitNumericConversion (ec, expr, target_type, loc);
2294
2295                         if (e != null)
2296                                 return e;
2297
2298                         if (expr is StringConstant && target_type == TypeManager.char_type)
2299                                 return new CharConstant (((StringConstant) expr).Value [0]);
2300
2301                         if (expr is CharConstant && target_type == TypeManager.string_type)
2302                                 return new StringConstant (((CharConstant) expr).Value.ToString ());
2303
2304                         e = ImplicitReferenceConversion (expr, target_type);
2305                         if (e != null)
2306                                 return e;
2307
2308                         if (expr.Type.IsSubclassOf (TypeManager.enum_type)) {
2309                                 expr_type = TypeManager.EnumToUnderlying (expr.Type);
2310                                 expr = new EmptyCast (expr, expr_type);
2311                                 if (expr_type == target_type)
2312                                         return expr;
2313                                 e = ImplicitNumericConversion (ec, expr, target_type, loc);
2314                                 if (e != null)
2315                                         return e;
2316                         }
2317
2318                         if (ec.InUnsafe) {
2319                                 if (expr_type.IsPointer){
2320                                         if (target_type == TypeManager.void_ptr_type)
2321                                                 return new EmptyCast (expr, target_type);
2322
2323                                         //
2324                                         // yep, comparing pointer types cant be done with
2325                                         // t1 == t2, we have to compare their element types.
2326                                         //
2327                                         if (target_type.IsPointer){
2328                                                 if (target_type.GetElementType()==expr_type.GetElementType())
2329                                                         return expr;
2330                                         }
2331                                 }
2332                                 
2333                                 if (target_type.IsPointer){
2334                                         if (expr is NullLiteral)
2335                                                 return new EmptyCast (expr, target_type);
2336                                 }
2337                         }
2338
2339                         return null;
2340                 }
2341
2342                 /// <summary>
2343                 ///   Attemps to perform an implict constant conversion of the any Numeric Constant
2344                 ///   into a different data type using casts (See Implicit Constant
2345                 ///   Expression Conversions)
2346                 /// </summary>
2347                 static protected Expression TryImplicitNumericConversion (Type target_type, Constant ic)
2348                 {
2349                         double value = 0;
2350                         if (ic is BoolConstant) {
2351                                 bool val = (bool) ((BoolConstant)ic).Value;
2352                                 if (val) {
2353                                         if (target_type == TypeManager.byte_type)
2354                                                 value = Byte.MaxValue;
2355                                         else 
2356                                                 value = -1;
2357                                 }
2358                         }
2359                         if (ic is IntConstant) 
2360                                 value = (double)((IntConstant)ic).Value;
2361                         
2362                         if (ic is LongConstant) 
2363                                 value = (double) ((LongConstant)ic).Value;
2364
2365                         if (ic is FloatConstant) {
2366                                 value = (double) ((FloatConstant)ic).Value;
2367                         }
2368
2369                         if (ic is DoubleConstant) {
2370                                 value = ((DoubleConstant)ic).Value;
2371                         }
2372
2373                         //
2374                         // FIXME: This could return constants instead of EmptyCasts
2375                         //
2376                         if (target_type == TypeManager.bool_type){
2377                                 if (value != 0)
2378                                         return new BoolConstant (true);
2379                                 return new BoolConstant (false);
2380                         } else if (target_type == TypeManager.sbyte_type){
2381                                 if (value >= SByte.MinValue && value <= SByte.MaxValue)
2382                                         return new SByteConstant ((sbyte) System.Math.Round (value));
2383                         } else if (target_type == TypeManager.byte_type){
2384                                 if (value >= Byte.MinValue && value <= Byte.MaxValue)
2385                                         return new ByteConstant ((byte) System.Math.Round (value));
2386                         } else if (target_type == TypeManager.short_type){
2387                                 if (value >= Int16.MinValue && value <= Int16.MaxValue)
2388                                         return new ShortConstant ((short) System.Math.Round (value));
2389                         } else if (target_type == TypeManager.ushort_type){
2390                                 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
2391                                         return new UShortConstant ((ushort) System.Math.Round (value));
2392                         } else if (target_type == TypeManager.int32_type){
2393                                 if (value >= Int32.MinValue && value <= Int32.MaxValue)
2394                                         return new IntConstant ((int) System.Math.Round (value));
2395                         } else if (target_type == TypeManager.uint32_type){
2396                                 if (value >= 0)
2397                                         return new UIntConstant ((uint) System.Math.Round (value));
2398                         } else if (target_type == TypeManager.int64_type){
2399                                         return new LongConstant ((long) System.Math.Round (value));
2400                         } else if (target_type == TypeManager.uint64_type){
2401                                 //
2402                                 // we can optimize this case: a positive int32
2403                                 // always fits on a uint64.  But we need an opcode
2404                                 // to do it.
2405                                 //
2406                                 if (value >= 0)
2407                                         return new ULongConstant ((ulong)System.Math.Round ( value));
2408                         } else if (target_type == TypeManager.float_type){
2409                                         return new FloatConstant ((float) value);
2410                         } else if (target_type == TypeManager.double_type){
2411                                         return new DoubleConstant ((double) value);
2412                         }
2413                         
2414                         if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){
2415                                 Type underlying = TypeManager.EnumToUnderlying (target_type);
2416                                 Constant e = (Constant) ic;
2417                                 
2418                                 //
2419                                 // Possibly, we need to create a different 0 literal before passing
2420                                 // to EnumConstant
2421                                 //n
2422                                 if (underlying == TypeManager.int64_type)
2423                                         e = new LongLiteral (0);
2424                                 else if (underlying == TypeManager.uint64_type)
2425                                         e = new ULongLiteral (0);
2426
2427                                 return new EnumConstant (e, target_type);
2428                         }
2429                         return null;
2430                 }
2431
2432                 static public void Error_CannotConvertImplicit (Location loc, Type source, Type target)
2433                 {
2434                         string msg = "Cannot convert implicitly from '"+
2435                                 TypeManager.MonoBASIC_Name (source) + "' to '" +
2436                                 TypeManager.MonoBASIC_Name (target) + "'";
2437
2438                         throw new Exception (msg);
2439
2440                         // Report.Error (30512, loc, msg);
2441                 }
2442
2443                 static public void Error_CannotConvertTypeStrict (Type source, Type target, Location loc)
2444                 {
2445                         Report.Error (
2446                                 30512, loc, "Cannot convert implicitly from '" +
2447                                 TypeManager.MonoBASIC_Name (source) + "' to '" +
2448                                 TypeManager.MonoBASIC_Name (target) + "' with Option Strict On.");
2449                 }               
2450
2451                 /// <summary>
2452                 ///   Attemptes to implicityly convert 'target' into 'type', using
2453                 ///   ConvertImplicit.  If there is no implicit conversion, then
2454                 ///   an error is signaled
2455                 /// </summary>
2456                 static public Expression ConvertImplicitRequired (EmitContext ec, Expression source,
2457                                                                   Type target_type, Location loc)
2458                 {
2459                         Expression e;
2460                         
2461                         e = ConvertImplicit (ec, source, target_type, loc);
2462
2463                         if (e != null)
2464                                 return e;
2465
2466
2467                         if (source is DoubleLiteral && target_type == TypeManager.float_type){
2468                                 Report.Error (664, loc,
2469                                               "Double literal cannot be implicitly converted to " +
2470                                               "float type, use F suffix to create a float literal");
2471                         }
2472
2473                         Error_CannotConvertImplicit (loc, source.Type, target_type);
2474
2475                         return null;
2476                 }
2477
2478                 /// <summary>
2479                 ///   Performs the explicit numeric conversions
2480                 /// </summary>
2481                 static Expression ConvertNumericExplicit (EmitContext ec, Expression expr, Type target_type, Location loc)
2482                 {
2483                         Type expr_type = expr.Type;
2484
2485                         //
2486                         // If we have an enumeration, extract the underlying type,
2487                         // use this during the comparison, but wrap around the original
2488                         // target_type
2489                         //
2490                         Type real_target_type = target_type;
2491
2492                         if (TypeManager.IsEnumType (real_target_type))
2493                                 real_target_type = TypeManager.EnumToUnderlying (real_target_type);
2494
2495                         if (StandardConversionExists (expr, real_target_type)){
2496                                 Expression ce = ConvertImplicitStandard (ec, expr, real_target_type, loc);
2497
2498                                 if (real_target_type != target_type)
2499                                         return new EmptyCast (ce, target_type);
2500                                 return ce;
2501                         }
2502                         
2503                         if (expr_type == TypeManager.sbyte_type){
2504                                 //
2505                                 // From sbyte to byte, ushort, uint, ulong, char
2506                                 //
2507                                 if (real_target_type == TypeManager.byte_type)
2508                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U1);
2509                                 if (real_target_type == TypeManager.ushort_type)
2510                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U2);
2511                                 if (real_target_type == TypeManager.uint32_type)
2512                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
2513                                 if (real_target_type == TypeManager.uint64_type)
2514                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
2515                         } else if (expr_type == TypeManager.byte_type){
2516                                 //
2517                                 // From byte to sbyte and char
2518                                 //
2519                                 if (real_target_type == TypeManager.sbyte_type)
2520                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
2521                         } else if (expr_type == TypeManager.short_type){
2522                                 //
2523                                 // From short to sbyte, byte, ushort, uint, ulong, char
2524                                 //
2525                                 if (real_target_type == TypeManager.sbyte_type)
2526                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
2527                                 if (real_target_type == TypeManager.byte_type)
2528                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
2529                                 if (real_target_type == TypeManager.ushort_type)
2530                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U2);
2531                                 if (real_target_type == TypeManager.uint32_type)
2532                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
2533                                 if (real_target_type == TypeManager.uint64_type)
2534                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
2535                         } else if (expr_type == TypeManager.ushort_type){
2536                                 //
2537                                 // From ushort to sbyte, byte, short, char
2538                                 //
2539                                 if (real_target_type == TypeManager.sbyte_type)
2540                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I1);
2541                                 if (real_target_type == TypeManager.byte_type)
2542                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
2543                                 if (real_target_type == TypeManager.short_type)
2544                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
2545                         } else if (expr_type == TypeManager.int32_type){
2546                                 //
2547                                 // From int to sbyte, byte, short, ushort, uint, ulong, char
2548                                 //
2549                                 if (real_target_type == TypeManager.sbyte_type)
2550                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
2551                                 if (real_target_type == TypeManager.byte_type)
2552                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
2553                                 if (real_target_type == TypeManager.short_type)
2554                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
2555                                 if (real_target_type == TypeManager.ushort_type)
2556                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
2557                                 if (real_target_type == TypeManager.uint32_type)
2558                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
2559                                 if (real_target_type == TypeManager.uint64_type)
2560                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
2561                         } else if (expr_type == TypeManager.uint32_type){
2562                                 //
2563                                 // From uint to sbyte, byte, short, ushort, int, char
2564                                 //
2565                                 if (real_target_type == TypeManager.sbyte_type)
2566                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I1);
2567                                 if (real_target_type == TypeManager.byte_type)
2568                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
2569                                 if (real_target_type == TypeManager.short_type)
2570                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I2);
2571                                 if (real_target_type == TypeManager.ushort_type)
2572                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
2573                                 if (real_target_type == TypeManager.int32_type)
2574                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
2575                         } else if (expr_type == TypeManager.int64_type){
2576                                 //
2577                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
2578                                 //
2579                                 if (real_target_type == TypeManager.sbyte_type)
2580                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
2581                                 if (real_target_type == TypeManager.byte_type)
2582                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
2583                                 if (real_target_type == TypeManager.short_type)
2584                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
2585                                 if (real_target_type == TypeManager.ushort_type)
2586                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
2587                                 if (real_target_type == TypeManager.int32_type)
2588                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
2589                                 if (real_target_type == TypeManager.uint32_type)
2590                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
2591                                 if (real_target_type == TypeManager.uint64_type)
2592                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
2593                         } else if (expr_type == TypeManager.uint64_type){
2594                                 //
2595                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
2596                                 //
2597                                 if (real_target_type == TypeManager.sbyte_type)
2598                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I1);
2599                                 if (real_target_type == TypeManager.byte_type)
2600                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
2601                                 if (real_target_type == TypeManager.short_type)
2602                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I2);
2603                                 if (real_target_type == TypeManager.ushort_type)
2604                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
2605                                 if (real_target_type == TypeManager.int32_type)
2606                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
2607                                 if (real_target_type == TypeManager.uint32_type)
2608                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
2609                                 if (real_target_type == TypeManager.int64_type)
2610                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
2611                         } else if (expr_type == TypeManager.float_type){
2612                                 //
2613                                 // From float to sbyte, byte, short,
2614                                 // ushort, int, uint, long, ulong, char
2615                                 // or decimal
2616                                 //
2617                                 Expression rounded_expr = RTConversionExpression(ec, "System.Math",".Round" , expr, loc);
2618                                 if (real_target_type == TypeManager.sbyte_type)
2619                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I1);
2620                                 if (real_target_type == TypeManager.byte_type)
2621                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U1);
2622                                 if (real_target_type == TypeManager.short_type)
2623                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I2);
2624                                 if (real_target_type == TypeManager.ushort_type)
2625                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U2);
2626                                 if (real_target_type == TypeManager.int32_type)
2627                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I4);
2628                                 if (real_target_type == TypeManager.uint32_type)
2629                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U4);
2630                                 if (real_target_type == TypeManager.int64_type)
2631                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8);
2632                                 if (real_target_type == TypeManager.uint64_type)
2633                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8);
2634                         } else if (expr_type == TypeManager.double_type){
2635                                 //
2636                                 // From double to byte, byte, short,
2637                                 // ushort, int, uint, long, ulong,
2638                                 // char, float or decimal
2639                                 //
2640                                 Expression rounded_expr = RTConversionExpression(ec, "System.Math",".Round" , expr, loc);
2641                                 if (real_target_type == TypeManager.sbyte_type)
2642                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I1);
2643                                 if (real_target_type == TypeManager.byte_type)
2644                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U1);
2645                                 if (real_target_type == TypeManager.short_type)
2646                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I2);
2647                                 if (real_target_type == TypeManager.ushort_type)
2648                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U2);
2649                                 if (real_target_type == TypeManager.int32_type)
2650                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I4);
2651                                 if (real_target_type == TypeManager.uint32_type)
2652                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U4);
2653                                 if (real_target_type == TypeManager.int64_type)
2654                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8);
2655                                 if (real_target_type == TypeManager.uint64_type)
2656                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8);
2657                                 if (real_target_type == TypeManager.float_type)
2658                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
2659                         } 
2660
2661                         // decimal is taken care of by the op_Explicit methods.
2662
2663                         return null;
2664                 }
2665
2666                 /// <summary>
2667                 ///  Returns whether an explicit reference conversion can be performed
2668                 ///  from source_type to target_type
2669                 /// </summary>
2670                 public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
2671                 {
2672                         bool target_is_value_type = target_type.IsValueType;
2673                         
2674                         if (source_type == target_type)
2675                                 return true;
2676                         
2677                         //
2678                         // From object to any reference type
2679                         //
2680                         if (source_type == TypeManager.object_type && !target_is_value_type)
2681                                 return true;
2682                                         
2683                         //
2684                         // From any class S to any class-type T, provided S is a base class of T
2685                         //
2686                         if (target_type.IsSubclassOf (source_type))
2687                                 return true;
2688
2689                         //
2690                         // From any interface type S to any interface T provided S is not derived from T
2691                         //
2692                         if (source_type.IsInterface && target_type.IsInterface){
2693                                 if (!target_type.IsSubclassOf (source_type))
2694                                         return true;
2695                         }
2696                             
2697                         //
2698                         // From any class type S to any interface T, provided S is not sealed
2699                         // and provided S does not implement T.
2700                         //
2701                         if (target_type.IsInterface && !source_type.IsSealed &&
2702                             !TypeManager.ImplementsInterface (source_type, target_type))
2703                                 return true;
2704
2705                         //
2706                         // From any interface-type S to to any class type T, provided T is not
2707                         // sealed, or provided T implements S.
2708                         //
2709                         if (source_type.IsInterface &&
2710                             (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
2711                                 return true;
2712                         
2713                         
2714                         // From an array type S with an element type Se to an array type T with an 
2715                         // element type Te provided all the following are true:
2716                         //     * S and T differe only in element type, in other words, S and T
2717                         //       have the same number of dimensions.
2718                         //     * Both Se and Te are reference types
2719                         //     * An explicit referenc conversions exist from Se to Te
2720                         //
2721                         if (source_type.IsArray && target_type.IsArray) {
2722                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
2723                                         
2724                                         Type source_element_type = source_type.GetElementType ();
2725                                         Type target_element_type = target_type.GetElementType ();
2726                                         
2727                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
2728                                                 if (ExplicitReferenceConversionExists (source_element_type,
2729                                                                                        target_element_type))
2730                                                         return true;
2731                                 }
2732                         }
2733                         
2734
2735                         // From System.Array to any array-type
2736                         if (source_type == TypeManager.array_type &&
2737                             target_type.IsArray){
2738                                 return true;
2739                         }
2740
2741                         //
2742                         // From System delegate to any delegate-type
2743                         //
2744                         if (source_type == TypeManager.delegate_type &&
2745                             target_type.IsSubclassOf (TypeManager.delegate_type))
2746                                 return true;
2747
2748                         //
2749                         // From ICloneable to Array or Delegate types
2750                         //
2751                         if (source_type == TypeManager.icloneable_type &&
2752                             (target_type == TypeManager.array_type ||
2753                              target_type == TypeManager.delegate_type))
2754                                 return true;
2755                         
2756                         return false;
2757                 }
2758
2759                 /// <summary>
2760                 ///   Implements Explicit Reference conversions
2761                 /// </summary>
2762                 static Expression ConvertReferenceExplicit (Expression source, Type target_type)
2763                 {
2764                         Type source_type = source.Type;
2765                         bool target_is_value_type = target_type.IsValueType;
2766
2767                         //
2768                         // From object to any reference type
2769                         //
2770                         if (source_type == TypeManager.object_type && !target_is_value_type)
2771                                 return new ClassCast (source, target_type);
2772
2773
2774                         //
2775                         // From any class S to any class-type T, provided S is a base class of T
2776                         //
2777                         if (target_type.IsSubclassOf (source_type))
2778                                 return new ClassCast (source, target_type);
2779
2780                         //
2781                         // From any interface type S to any interface T provided S is not derived from T
2782                         //
2783                         if (source_type.IsInterface && target_type.IsInterface){
2784                                 if (TypeManager.ImplementsInterface (source_type, target_type))
2785                                         return null;
2786                                 else
2787                                         return new ClassCast (source, target_type);
2788                         }
2789                             
2790                         //
2791                         // From any class type S to any interface T, provides S is not sealed
2792                         // and provided S does not implement T.
2793                         //
2794                         if (target_type.IsInterface && !source_type.IsSealed) {
2795                                 if (TypeManager.ImplementsInterface (source_type, target_type))
2796                                         return null;
2797                                 else
2798                                         return new ClassCast (source, target_type);
2799                                 
2800                         }
2801
2802                         //
2803                         // From any interface-type S to to any class type T, provided T is not
2804                         // sealed, or provided T implements S.
2805                         //
2806                         if (source_type.IsInterface) {
2807                                 if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type))
2808                                         return new ClassCast (source, target_type);
2809                                 else
2810                                         return null;
2811                         }
2812                         
2813                         // From an array type S with an element type Se to an array type T with an 
2814                         // element type Te provided all the following are true:
2815                         //     * S and T differe only in element type, in other words, S and T
2816                         //       have the same number of dimensions.
2817                         //     * Both Se and Te are reference types
2818                         //     * An explicit referenc conversions exist from Se to Te
2819                         //
2820                         if (source_type.IsArray && target_type.IsArray) {
2821                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
2822                                         
2823                                         Type source_element_type = source_type.GetElementType ();
2824                                         Type target_element_type = target_type.GetElementType ();
2825                                         
2826                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
2827                                                 if (ExplicitReferenceConversionExists (source_element_type,
2828                                                                                        target_element_type))
2829                                                         return new ClassCast (source, target_type);
2830                                 }
2831                         }
2832                         
2833
2834                         // From System.Array to any array-type
2835                         if (source_type == TypeManager.array_type &&
2836                             target_type.IsArray) {
2837                                 return new ClassCast (source, target_type);
2838                         }
2839
2840                         //
2841                         // From System delegate to any delegate-type
2842                         //
2843                         if (source_type == TypeManager.delegate_type &&
2844                             target_type.IsSubclassOf (TypeManager.delegate_type))
2845                                 return new ClassCast (source, target_type);
2846
2847                         //
2848                         // From ICloneable to Array or Delegate types
2849                         //
2850                         if (source_type == TypeManager.icloneable_type &&
2851                             (target_type == TypeManager.array_type ||
2852                              target_type == TypeManager.delegate_type))
2853                                 return new ClassCast (source, target_type);
2854                         
2855                         return null;
2856                 }
2857                 
2858                 /// <summary>
2859                 ///   Performs an explicit conversion of the expression 'expr' whose
2860                 ///   type is expr.Type to 'target_type'.
2861                 /// </summary>
2862                 static public Expression ConvertExplicit (EmitContext ec, Expression expr,
2863                                                           Type target_type, bool runtimeconv, Location loc)
2864                 {
2865                         Type expr_type = expr.Type;
2866                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, loc);
2867
2868                         if (ne != null)
2869                                 return ne;
2870
2871                         ne = ConvertNumericExplicit (ec, expr, target_type, loc);
2872                         if (ne != null)
2873                                 return ne;
2874
2875                         //
2876                         // Unboxing conversion.
2877                         //
2878                         if (expr_type == TypeManager.object_type && target_type.IsValueType)
2879                                 return new UnboxCast (expr, target_type);
2880
2881                         //
2882                         // Enum types
2883                         //
2884                         if (expr_type.IsSubclassOf (TypeManager.enum_type)) {
2885                                 Expression e;
2886
2887                                 //
2888                                 // FIXME: Is there any reason we should have EnumConstant
2889                                 // dealt with here instead of just using always the
2890                                 // UnderlyingSystemType to wrap the type?
2891                                 //
2892                                 if (expr is EnumConstant)
2893                                         e = ((EnumConstant) expr).Child;
2894                                 else {
2895                                         e = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
2896                                 }
2897                                 
2898                                 Expression t = ConvertImplicit (ec, e, target_type, loc);
2899                                 if (t != null)
2900                                         return t;
2901                                 
2902                                 t = ConvertNumericExplicit (ec, e, target_type, loc);
2903                                 if (t != null)
2904                                         return t;
2905                                 
2906                                 t = NarrowingConversion (ec, e, target_type, loc);
2907                                 if (t != null)
2908                                         return t;       
2909                                                                 
2910                                 Error_CannotConvertType (loc, expr_type, target_type);
2911                                 return null;
2912                         }
2913                         
2914                         ne = ConvertReferenceExplicit (expr, target_type);
2915                         if (ne != null)
2916                                 return ne;
2917
2918                         if (ec.InUnsafe){
2919                                 if (target_type.IsPointer){
2920                                         if (expr_type.IsPointer)
2921                                                 return new EmptyCast (expr, target_type);
2922                                         
2923                                         if (expr_type == TypeManager.sbyte_type ||
2924                                             expr_type == TypeManager.byte_type ||
2925                                             expr_type == TypeManager.short_type ||
2926                                             expr_type == TypeManager.ushort_type ||
2927                                             expr_type == TypeManager.int32_type ||
2928                                             expr_type == TypeManager.uint32_type ||
2929                                             expr_type == TypeManager.uint64_type ||
2930                                             expr_type == TypeManager.int64_type)
2931                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2932                                 }
2933                                 if (expr_type.IsPointer){
2934                                         if (target_type == TypeManager.sbyte_type ||
2935                                             target_type == TypeManager.byte_type ||
2936                                             target_type == TypeManager.short_type ||
2937                                             target_type == TypeManager.ushort_type ||
2938                                             target_type == TypeManager.int32_type ||
2939                                             target_type == TypeManager.uint32_type ||
2940                                             target_type == TypeManager.uint64_type ||
2941                                             target_type == TypeManager.int64_type){
2942                                                 Expression e = new EmptyCast (expr, TypeManager.uint32_type);
2943                                                 Expression ci, ce;
2944
2945                                                 ci = ConvertImplicitStandard (ec, e, target_type, loc);
2946
2947                                                 if (ci != null)
2948                                                         return ci;
2949
2950                                                 ce = ConvertNumericExplicit (ec, e, target_type, loc);
2951                                                 if (ce != null)
2952                                                         return ce;
2953                                                 //
2954                                                 // We should always be able to go from an uint32
2955                                                 // implicitly or explicitly to the other integral
2956                                                 // types
2957                                                 //
2958                                                 throw new Exception ("Internal compiler error");
2959                                         }
2960                                 }
2961                         }
2962                         
2963                         ne = ExplicitUserConversion (ec, expr, target_type, loc);
2964                         if (ne != null)
2965                                 return ne;
2966
2967                         if (!(runtimeconv))     {
2968                                 ne = NarrowingConversion (ec, expr, target_type, loc);
2969                                 if (ne != null)
2970                                         return ne;
2971                                 
2972                                 Error_CannotConvertType (loc, expr_type, target_type);
2973                         }
2974                         return null;
2975                 }
2976
2977                 /// <summary>
2978                 ///   Same as ConvertExplicit, only it doesn't include user defined conversions
2979                 /// </summary>
2980                 static public Expression ConvertExplicitStandard (EmitContext ec, Expression expr,
2981                                                                   Type target_type, Location l)
2982                 {
2983                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, l);
2984
2985                         if (ne != null)
2986                                 return ne;
2987
2988                         ne = ConvertNumericExplicit (ec, expr, target_type, l);
2989                         if (ne != null)
2990                                 return ne;
2991
2992                         ne = ConvertReferenceExplicit (expr, target_type);
2993                         if (ne != null)
2994                                 return ne;
2995
2996                         ne = NarrowingConversion (ec, expr, target_type, l);
2997                         if (ne != null)
2998                                 return ne;                              
2999
3000                         Error_CannotConvertType (l, expr.Type, target_type);
3001                         return null;
3002                 }
3003
3004                 static string ExprClassName (ExprClass c)
3005                 {
3006                         switch (c){
3007                         case ExprClass.Invalid:
3008                                 return "Invalid";
3009                         case ExprClass.Value:
3010                                 return "value";
3011                         case ExprClass.Variable:
3012                                 return "variable";
3013                         case ExprClass.Namespace:
3014                                 return "namespace";
3015                         case ExprClass.Type:
3016                                 return "type";
3017                         case ExprClass.MethodGroup:
3018                                 return "method group";
3019                         case ExprClass.PropertyAccess:
3020                                 return "property access";
3021                         case ExprClass.EventAccess:
3022                                 return "event access";
3023                         case ExprClass.IndexerAccess:
3024                                 return "indexer access";
3025                         case ExprClass.Nothing:
3026                                 return "null";
3027                         }
3028                         throw new Exception ("Should not happen");
3029                 }
3030                 
3031                 /// <summary>
3032                 ///   Reports that we were expecting 'expr' to be of class 'expected'
3033                 /// </summary>
3034                 public void Error118 (string expected)
3035                 {
3036                         string kind = "Unknown";
3037                         
3038                         kind = ExprClassName (eclass);
3039
3040                         Error (118, "Expression denotes a '" + kind +
3041                                "' where a '" + expected + "' was expected");
3042                 }
3043
3044                 public void Error118 (ResolveFlags flags)
3045                 {
3046                         ArrayList valid = new ArrayList (10);
3047
3048                         if ((flags & ResolveFlags.VariableOrValue) != 0) {
3049                                 valid.Add ("variable");
3050                                 valid.Add ("value");
3051                         }
3052
3053                         if ((flags & ResolveFlags.Type) != 0)
3054                                 valid.Add ("type");
3055
3056                         if ((flags & ResolveFlags.MethodGroup) != 0)
3057                                 valid.Add ("method group");
3058
3059                         if ((flags & ResolveFlags.SimpleName) != 0)
3060                                 valid.Add ("simple name");
3061
3062                         if (valid.Count == 0)
3063                                 valid.Add ("unknown");
3064
3065                         StringBuilder sb = new StringBuilder ();
3066                         for (int i = 0; i < valid.Count; i++) {
3067                                 if (i > 0)
3068                                         sb.Append (", ");
3069                                 else if (i == valid.Count)
3070                                         sb.Append (" or ");
3071                                 sb.Append (valid [i]);
3072                         }
3073
3074                         string kind = ExprClassName (eclass);
3075
3076                         Error (119, "Expression denotes a '" + kind + "' where " +
3077                                "a '" + sb.ToString () + "' was expected");
3078                 }
3079                 
3080                 static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
3081                 {
3082                         Report.Error (30439, l, "Constant value '" + val + "' not representable in type " +
3083                                       TypeManager.MonoBASIC_Name (t));
3084                 }
3085
3086                 public static void UnsafeError (Location loc)
3087                 {
3088                         Report.Error (214, loc, "Pointers may only be used in an unsafe context");
3089                 }
3090                 
3091                 /// <summary>
3092                 ///   Converts the IntConstant, UIntConstant, LongConstant or
3093                 ///   ULongConstant,Double into the integral target_type.   Notice
3094                 ///   that we do not return an 'Expression' we do return
3095                 ///   a boxed integral type.
3096                 ///
3097                 ///   FIXME: Since I added the new constants, we need to
3098                 ///   also support conversions from CharConstant, ByteConstant,
3099                 ///   SByteConstant, UShortConstant, ShortConstant
3100                 ///
3101                 ///   This is used by the switch statement, so the domain
3102                 ///   of work is restricted to the literals above, and the
3103                 ///   targets are int32, uint32, char, byte, sbyte, ushort,
3104                 ///   short, uint64 and int64
3105                 /// </summary>
3106                 public static object ConvertIntLiteral (Constant c, Type target_type, Location loc)
3107                 {
3108                         string s = "";
3109
3110                         if (c.Type == target_type)
3111                                 return ((Constant) c).GetValue ();
3112
3113                         //
3114                         // Make into one of the literals we handle, we dont really care
3115                         // about this value as we will just return a few limited types
3116                         // 
3117                         if (c is EnumConstant)
3118                                 c = ((EnumConstant)c).WidenToCompilerConstant ();
3119
3120                         if (c is IntConstant){
3121                                 int v = ((IntConstant) c).Value;
3122                                 
3123                                 if (target_type == TypeManager.uint32_type){
3124                                         if (v >= 0)
3125                                                 return (uint) v;
3126                                 } else if (target_type == TypeManager.byte_type){
3127                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3128                                                 return (byte) v;
3129                                 } else if (target_type == TypeManager.sbyte_type){
3130                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3131                                                 return (sbyte) v;
3132                                 } else if (target_type == TypeManager.short_type){
3133                                         if (v >= Int16.MinValue && v <= UInt16.MaxValue)
3134                                                 return (short) v;
3135                                 } else if (target_type == TypeManager.ushort_type){
3136                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
3137                                                 return (ushort) v;
3138                                 } else if (target_type == TypeManager.int64_type)
3139                                         return (long) v;
3140                                 else if (target_type == TypeManager.uint64_type){
3141                                         if (v > 0)
3142                                                 return (ulong) v;
3143                                 }
3144
3145                                 s = v.ToString ();
3146                         } else if (c is UIntConstant){
3147                                 uint v = ((UIntConstant) c).Value;
3148
3149                                 if (target_type == TypeManager.int32_type){
3150                                         if (v <= Int32.MaxValue)
3151                                                 return (int) v;
3152                                 } else if (target_type == TypeManager.byte_type){
3153                                         if (v <= Byte.MaxValue)
3154                                                 return (byte) v;
3155                                 } else if (target_type == TypeManager.sbyte_type){
3156                                         if (v <= SByte.MaxValue)
3157                                                 return (sbyte) v;
3158                                 } else if (target_type == TypeManager.short_type){
3159                                         if (v <= UInt16.MaxValue)
3160                                                 return (short) v;
3161                                 } else if (target_type == TypeManager.ushort_type){
3162                                         if (v <= UInt16.MaxValue)
3163                                                 return (ushort) v;
3164                                 } else if (target_type == TypeManager.int64_type)
3165                                         return (long) v;
3166                                 else if (target_type == TypeManager.uint64_type)
3167                                         return (ulong) v;
3168                                 s = v.ToString ();
3169                         } else if (c is LongConstant){ 
3170                                 long v = ((LongConstant) c).Value;
3171
3172                                 if (target_type == TypeManager.int32_type){
3173                                         if (v >= UInt32.MinValue && v <= UInt32.MaxValue)
3174                                                 return (int) v;
3175                                 } else if (target_type == TypeManager.uint32_type){
3176                                         if (v >= 0 && v <= UInt32.MaxValue)
3177                                                 return (uint) v;
3178                                 } else if (target_type == TypeManager.byte_type){
3179                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3180                                                 return (byte) v;
3181                                 } else if (target_type == TypeManager.sbyte_type){
3182                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3183                                                 return (sbyte) v;
3184                                 } else if (target_type == TypeManager.short_type){
3185                                         if (v >= Int16.MinValue && v <= UInt16.MaxValue)
3186                                                 return (short) v;
3187                                 } else if (target_type == TypeManager.ushort_type){
3188                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
3189                                                 return (ushort) v;
3190                                 } else if (target_type == TypeManager.uint64_type){
3191                                         if (v > 0)
3192                                                 return (ulong) v;
3193                                 }
3194                                 s = v.ToString ();
3195                         } else if (c is ULongConstant){
3196                                 ulong v = ((ULongConstant) c).Value;
3197
3198                                 if (target_type == TypeManager.int32_type){
3199                                         if (v <= Int32.MaxValue)
3200                                                 return (int) v;
3201                                 } else if (target_type == TypeManager.uint32_type){
3202                                         if (v <= UInt32.MaxValue)
3203                                                 return (uint) v;
3204                                 } else if (target_type == TypeManager.byte_type){
3205                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3206                                                 return (byte) v;
3207                                 } else if (target_type == TypeManager.sbyte_type){
3208                                         if (v <= (int) SByte.MaxValue)
3209                                                 return (sbyte) v;
3210                                 } else if (target_type == TypeManager.short_type){
3211                                         if (v <= UInt16.MaxValue)
3212                                                 return (short) v;
3213                                 } else if (target_type == TypeManager.ushort_type){
3214                                         if (v <= UInt16.MaxValue)
3215                                                 return (ushort) v;
3216                                 } else if (target_type == TypeManager.int64_type){
3217                                         if (v <= Int64.MaxValue)
3218                                                 return (long) v;
3219                                 }
3220                                 s = v.ToString ();
3221                         } else if (c is ByteConstant){
3222                                 byte v = ((ByteConstant) c).Value;
3223                                 
3224                                 if (target_type == TypeManager.int32_type)
3225                                         return (int) v;
3226                                 else if (target_type == TypeManager.uint32_type)
3227                                         return (uint) v;
3228                                 else if (target_type == TypeManager.sbyte_type){
3229                                         if (v <= SByte.MaxValue)
3230                                                 return (sbyte) v;
3231                                 } else if (target_type == TypeManager.short_type)
3232                                         return (short) v;
3233                                 else if (target_type == TypeManager.ushort_type)
3234                                         return (ushort) v;
3235                                 else if (target_type == TypeManager.int64_type)
3236                                         return (long) v;
3237                                 else if (target_type == TypeManager.uint64_type)
3238                                         return (ulong) v;
3239                                 s = v.ToString ();
3240                         } else if (c is SByteConstant){
3241                                 sbyte v = ((SByteConstant) c).Value;
3242                                 
3243                                 if (target_type == TypeManager.int32_type)
3244                                         return (int) v;
3245                                 else if (target_type == TypeManager.uint32_type){
3246                                         if (v >= 0)
3247                                                 return (uint) v;
3248                                 } else if (target_type == TypeManager.byte_type){
3249                                         if (v >= 0)
3250                                                 return (byte) v;
3251                                 } else if (target_type == TypeManager.short_type)
3252                                         return (short) v;
3253                                 else if (target_type == TypeManager.ushort_type){
3254                                         if (v >= 0)
3255                                                 return (ushort) v;
3256                                 } else if (target_type == TypeManager.int64_type)
3257                                         return (long) v;
3258                                 else if (target_type == TypeManager.uint64_type){
3259                                         if (v >= 0)
3260                                                 return (ulong) v;
3261                                 }
3262                                 s = v.ToString ();
3263                         } else if (c is ShortConstant){
3264                                 short v = ((ShortConstant) c).Value;
3265                                 
3266                                 if (target_type == TypeManager.int32_type){
3267                                         return (int) v;
3268                                 } else if (target_type == TypeManager.uint32_type){
3269                                         if (v >= 0)
3270                                                 return (uint) v;
3271                                 } else if (target_type == TypeManager.byte_type){
3272                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3273                                                 return (byte) v;
3274                                 } else if (target_type == TypeManager.sbyte_type){
3275                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3276                                                 return (sbyte) v;
3277                                 } else if (target_type == TypeManager.ushort_type){
3278                                         if (v >= 0)
3279                                                 return (ushort) v;
3280                                 } else if (target_type == TypeManager.int64_type)
3281                                         return (long) v;
3282                                 else if (target_type == TypeManager.uint64_type)
3283                                         return (ulong) v;
3284
3285                                 s = v.ToString ();
3286                         } else if (c is UShortConstant){
3287                                 ushort v = ((UShortConstant) c).Value;
3288                                 
3289                                 if (target_type == TypeManager.int32_type)
3290                                         return (int) v;
3291                                 else if (target_type == TypeManager.uint32_type)
3292                                         return (uint) v;
3293                                 else if (target_type == TypeManager.byte_type){
3294                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3295                                                 return (byte) v;
3296                                 } else if (target_type == TypeManager.sbyte_type){
3297                                         if (v <= SByte.MaxValue)
3298                                                 return (byte) v;
3299                                 } else if (target_type == TypeManager.short_type){
3300                                         if (v <= Int16.MaxValue)
3301                                                 return (short) v;
3302                                 } else if (target_type == TypeManager.int64_type)
3303                                         return (long) v;
3304                                 else if (target_type == TypeManager.uint64_type)
3305                                         return (ulong) v;
3306
3307                                 s = v.ToString ();
3308                         } else if (c is CharConstant){
3309                                 char v = ((CharConstant) c).Value;
3310                                 
3311                                 if (target_type == TypeManager.int32_type)
3312                                         return (int) v;
3313                                 else if (target_type == TypeManager.uint32_type)
3314                                         return (uint) v;
3315                                 else if (target_type == TypeManager.byte_type){
3316                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3317                                                 return (byte) v;
3318                                 } else if (target_type == TypeManager.sbyte_type){
3319                                         if (v <= SByte.MaxValue)
3320                                                 return (sbyte) v;
3321                                 } else if (target_type == TypeManager.short_type){
3322                                         if (v <= Int16.MaxValue)
3323                                                 return (short) v;
3324                                 } else if (target_type == TypeManager.ushort_type)
3325                                         return (short) v;
3326                                 else if (target_type == TypeManager.int64_type)
3327                                         return (long) v;
3328                                 else if (target_type == TypeManager.uint64_type)
3329                                         return (ulong) v;
3330
3331                                 s = v.ToString ();
3332
3333                          } else if (c is DoubleConstant){
3334                                 double v = ((DoubleConstant) c).Value;
3335
3336                                 if (target_type == TypeManager.sbyte_type){
3337                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3338                                                 return new SByteConstant ((sbyte) System.Math.Round (v));
3339                                 } else if (target_type == TypeManager.byte_type){
3340                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3341                                                 return new ByteConstant ((byte) System.Math.Round (v));
3342                                 } else if (target_type == TypeManager.short_type){
3343                                         if (v >= Int16.MinValue && v <= Int16.MaxValue)
3344                                                 return new ShortConstant ((short) System.Math.Round (v));
3345                                 } else if (target_type == TypeManager.ushort_type){
3346                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
3347                                                  return new UShortConstant ((ushort) System.Math.Round (v));
3348                                 } else if (target_type == TypeManager.int32_type){
3349                                         if (v >= Int32.MinValue && v <= Int32.MaxValue)
3350                                                 return new IntConstant ((int) System.Math.Round (v));
3351                                 } else if (target_type == TypeManager.uint32_type){
3352                                         if (v >= 0 && v <= UInt32.MaxValue)
3353                                                 return new UIntConstant ((uint) System.Math.Round (v));
3354                                 } else if (target_type == TypeManager.uint64_type){
3355                                         if (v > 0)
3356                                                 return new ULongConstant ((ulong) System.Math.Round (v));
3357                                 }
3358                                 s = v.ToString ();
3359                         }
3360
3361                         Error_ConstantValueCannotBeConverted (loc, s, target_type);
3362                         return null;
3363                 }
3364
3365                 //
3366                 // Load the object from the pointer.  
3367                 //
3368                 public static void LoadFromPtr (ILGenerator ig, Type t)
3369                 {
3370                         if (t == TypeManager.int32_type)
3371                                 ig.Emit (OpCodes.Ldind_I4);
3372                         else if (t == TypeManager.uint32_type)
3373                                 ig.Emit (OpCodes.Ldind_U4);
3374                         else if (t == TypeManager.short_type)
3375                                 ig.Emit (OpCodes.Ldind_I2);
3376                         else if (t == TypeManager.ushort_type)
3377                                 ig.Emit (OpCodes.Ldind_U2);
3378                         else if (t == TypeManager.char_type)
3379                                 ig.Emit (OpCodes.Ldind_U2);
3380                         else if (t == TypeManager.byte_type)
3381                                 ig.Emit (OpCodes.Ldind_U1);
3382                         else if (t == TypeManager.sbyte_type)
3383                                 ig.Emit (OpCodes.Ldind_I1);
3384                         else if (t == TypeManager.uint64_type)
3385                                 ig.Emit (OpCodes.Ldind_I8);
3386                         else if (t == TypeManager.int64_type)
3387                                 ig.Emit (OpCodes.Ldind_I8);
3388                         else if (t == TypeManager.float_type)
3389                                 ig.Emit (OpCodes.Ldind_R4);
3390                         else if (t == TypeManager.double_type)
3391                                 ig.Emit (OpCodes.Ldind_R8);
3392                         else if (t == TypeManager.bool_type)
3393                                 ig.Emit (OpCodes.Ldind_I1);
3394                         else if (t == TypeManager.intptr_type)
3395                                 ig.Emit (OpCodes.Ldind_I);
3396                         else if (TypeManager.IsEnumType (t)) {
3397                                 if (t == TypeManager.enum_type)
3398                                         ig.Emit (OpCodes.Ldind_Ref);
3399                                 else
3400                                         LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
3401                         } else if (t.IsValueType)
3402                                 ig.Emit (OpCodes.Ldobj, t);
3403                         else
3404                                 ig.Emit (OpCodes.Ldind_Ref);
3405                 }
3406
3407                 //
3408                 // The stack contains the pointer and the value of type 'type'
3409                 //
3410                 public static void StoreFromPtr (ILGenerator ig, Type type)
3411                 {
3412                         if (TypeManager.IsEnumType (type))
3413                                 type = TypeManager.EnumToUnderlying (type);
3414                         if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
3415                                 ig.Emit (OpCodes.Stind_I4);
3416                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
3417                                 ig.Emit (OpCodes.Stind_I8);
3418                         else if (type == TypeManager.char_type || type == TypeManager.short_type ||
3419                                  type == TypeManager.ushort_type)
3420                                 ig.Emit (OpCodes.Stind_I2);
3421                         else if (type == TypeManager.float_type)
3422                                 ig.Emit (OpCodes.Stind_R4);
3423                         else if (type == TypeManager.double_type)
3424                                 ig.Emit (OpCodes.Stind_R8);
3425                         else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
3426                                  type == TypeManager.bool_type)
3427                                 ig.Emit (OpCodes.Stind_I1);
3428                         else if (type == TypeManager.intptr_type)
3429                                 ig.Emit (OpCodes.Stind_I);
3430                         else if (type.IsValueType)
3431                                 ig.Emit (OpCodes.Stobj, type);
3432                         else
3433                                 ig.Emit (OpCodes.Stind_Ref);
3434                 }
3435                 
3436                 //
3437                 // Returns the size of type 't' if known, otherwise, 0
3438                 //
3439                 public static int GetTypeSize (Type t)
3440                 {
3441                         t = TypeManager.TypeToCoreType (t);
3442                         if (t == TypeManager.int32_type ||
3443                             t == TypeManager.uint32_type ||
3444                             t == TypeManager.float_type)
3445                                 return 4;
3446                         else if (t == TypeManager.int64_type ||
3447                                  t == TypeManager.uint64_type ||
3448                                  t == TypeManager.double_type)
3449                                 return 8;
3450                         else if (t == TypeManager.byte_type ||
3451                                  t == TypeManager.sbyte_type ||
3452                                  t == TypeManager.bool_type)    
3453                                 return 1;
3454                         else if (t == TypeManager.short_type ||
3455                                  t == TypeManager.char_type ||
3456                                  t == TypeManager.ushort_type)
3457                                 return 2;
3458                         else if (t == TypeManager.decimal_type)
3459                                 return 16;
3460                         else
3461                                 return 0;
3462                 }
3463
3464                 //
3465                 // Default implementation of IAssignMethod.CacheTemporaries
3466                 //
3467                 public void CacheTemporaries (EmitContext ec)
3468                 {
3469                 }
3470
3471                 static void Error_NegativeArrayIndex (Location loc)
3472                 {
3473                         Report.Error (284, loc, "Can not create array with a negative size");
3474                 }
3475                 
3476                 //
3477                 // Converts 'source' to an int, uint, long or ulong.
3478                 //
3479                 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
3480                 {
3481                         Expression target;
3482                         
3483                         bool old_checked = ec.CheckState;
3484                         ec.CheckState = true;
3485                         
3486                         target = ConvertImplicit (ec, source, TypeManager.int32_type, loc);
3487                         if (target == null){
3488                                 target = ConvertImplicit (ec, source, TypeManager.uint32_type, loc);
3489                                 if (target == null){
3490                                         target = ConvertImplicit (ec, source, TypeManager.int64_type, loc);
3491                                         if (target == null){
3492                                                 target = ConvertImplicit (ec, source, TypeManager.uint64_type, loc);
3493                                                 if (target == null)
3494                                                         Expression.Error_CannotConvertImplicit (loc, source.Type, TypeManager.int32_type);
3495                                         }
3496                                 }
3497                         } 
3498                         ec.CheckState = old_checked;
3499
3500                         //
3501                         // Only positive constants are allowed at compile time
3502                         //
3503                         if (target is Constant){
3504                                 if (target is IntConstant){
3505                                         if (((IntConstant) target).Value < 0){
3506                                                 Error_NegativeArrayIndex (loc);
3507                                                 return null;
3508                                         }
3509                                 }
3510
3511                                 if (target is LongConstant){
3512                                         if (((LongConstant) target).Value < 0){
3513                                                 Error_NegativeArrayIndex (loc);
3514                                                 return null;
3515                                         }
3516                                 }
3517                                 
3518                         }
3519
3520                         return target;
3521                 }
3522                 
3523         }
3524
3525         /// <summary>
3526         ///   This is just a base class for expressions that can
3527         ///   appear on statements (invocations, object creation,
3528         ///   assignments, post/pre increment and decrement).  The idea
3529         ///   being that they would support an extra Emition interface that
3530         ///   does not leave a result on the stack.
3531         /// </summary>
3532         public abstract class ExpressionStatement : Expression {
3533
3534                 /// <summary>
3535                 ///   Requests the expression to be emitted in a 'statement'
3536                 ///   context.  This means that no new value is left on the
3537                 ///   stack after invoking this method (constrasted with
3538                 ///   Emit that will always leave a value on the stack).
3539                 /// </summary>
3540                 public abstract void EmitStatement (EmitContext ec);
3541         }
3542
3543         /// <summary>
3544         ///   This kind of cast is used to encapsulate the child
3545         ///   whose type is child.Type into an expression that is
3546         ///   reported to return "return_type".  This is used to encapsulate
3547         ///   expressions which have compatible types, but need to be dealt
3548         ///   at higher levels with.
3549         ///
3550         ///   For example, a "byte" expression could be encapsulated in one
3551         ///   of these as an "unsigned int".  The type for the expression
3552         ///   would be "unsigned int".
3553         ///
3554         /// </summary>
3555         public class EmptyCast : Expression {
3556                 protected Expression child;
3557
3558                 public EmptyCast (Expression child, Type return_type)
3559                 {
3560                         eclass = child.eclass;
3561                         type = return_type;
3562                         this.child = child;
3563                 }
3564
3565                 public override Expression DoResolve (EmitContext ec)
3566                 {
3567                         // This should never be invoked, we are born in fully
3568                         // initialized state.
3569
3570                         return this;
3571                 }
3572
3573                 public override void Emit (EmitContext ec)
3574                 {
3575                         child.Emit (ec);
3576                 }
3577         }
3578
3579         /// <summary>
3580         ///  This class is used to wrap literals which belong inside Enums
3581         /// </summary>
3582         public class EnumConstant : Constant {
3583                 public Constant Child;
3584
3585                 public EnumConstant (Constant child, Type enum_type)
3586                 {
3587                         eclass = child.eclass;
3588                         this.Child = child;
3589                         type = enum_type;
3590                 }
3591                 
3592                 public override Expression DoResolve (EmitContext ec)
3593                 {
3594                         // This should never be invoked, we are born in fully
3595                         // initialized state.
3596
3597                         return this;
3598                 }
3599
3600                 public override void Emit (EmitContext ec)
3601                 {
3602                         Child.Emit (ec);
3603                 }
3604
3605                 public override object GetValue ()
3606                 {
3607                         return Child.GetValue ();
3608                 }
3609
3610                 //
3611                 // Converts from one of the valid underlying types for an enumeration
3612                 // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to
3613                 // one of the internal compiler literals: Int/UInt/Long/ULong Literals.
3614                 //
3615                 public Constant WidenToCompilerConstant ()
3616                 {
3617                         Type t = TypeManager.EnumToUnderlying (Child.Type);
3618                         object v = ((Constant) Child).GetValue ();;
3619                         
3620                         if (t == TypeManager.int32_type)
3621                                 return new IntConstant ((int) v);
3622                         if (t == TypeManager.uint32_type)
3623                                 return new UIntConstant ((uint) v);
3624                         if (t == TypeManager.int64_type)
3625                                 return new LongConstant ((long) v);
3626                         if (t == TypeManager.uint64_type)
3627                                 return new ULongConstant ((ulong) v);
3628                         if (t == TypeManager.short_type)
3629                                 return new ShortConstant ((short) v);
3630                         if (t == TypeManager.ushort_type)
3631                                 return new UShortConstant ((ushort) v);
3632                         if (t == TypeManager.byte_type)
3633                                 return new ByteConstant ((byte) v);
3634                         if (t == TypeManager.sbyte_type)
3635                                 return new SByteConstant ((sbyte) v);
3636
3637                         throw new Exception ("Invalid enumeration underlying type: " + t);
3638                 }
3639
3640                 //
3641                 // Extracts the value in the enumeration on its native representation
3642                 //
3643                 public object GetPlainValue ()
3644                 {
3645                         Type t = TypeManager.EnumToUnderlying (Child.Type);
3646                         object v = ((Constant) Child).GetValue ();;
3647                         
3648                         if (t == TypeManager.int32_type)
3649                                 return (int) v;
3650                         if (t == TypeManager.uint32_type)
3651                                 return (uint) v;
3652                         if (t == TypeManager.int64_type)
3653                                 return (long) v;
3654                         if (t == TypeManager.uint64_type)
3655                                 return (ulong) v;
3656                         if (t == TypeManager.short_type)
3657                                 return (short) v;
3658                         if (t == TypeManager.ushort_type)
3659                                 return (ushort) v;
3660                         if (t == TypeManager.byte_type)
3661                                 return (byte) v;
3662                         if (t == TypeManager.sbyte_type)
3663                                 return (sbyte) v;
3664
3665                         return null;
3666                 }
3667                 
3668                 public override string AsString ()
3669                 {
3670                         return Child.AsString ();
3671                 }
3672
3673                 public override DoubleConstant ConvertToDouble ()
3674                 {
3675                         return Child.ConvertToDouble ();
3676                 }
3677
3678                 public override FloatConstant ConvertToFloat ()
3679                 {
3680                         return Child.ConvertToFloat ();
3681                 }
3682
3683                 public override ULongConstant ConvertToULong ()
3684                 {
3685                         return Child.ConvertToULong ();
3686                 }
3687
3688                 public override LongConstant ConvertToLong ()
3689                 {
3690                         return Child.ConvertToLong ();
3691                 }
3692
3693                 public override UIntConstant ConvertToUInt ()
3694                 {
3695                         return Child.ConvertToUInt ();
3696                 }
3697
3698                 public override IntConstant ConvertToInt ()
3699                 {
3700                         return Child.ConvertToInt ();
3701                 }
3702         }
3703
3704         /// <summary>
3705         ///   This kind of cast is used to encapsulate Value Types in objects.
3706         ///
3707         ///   The effect of it is to box the value type emitted by the previous
3708         ///   operation.
3709         /// </summary>
3710         public class BoxedCast : EmptyCast {
3711
3712                 public BoxedCast (Expression expr)
3713                         : base (expr, TypeManager.object_type)
3714                 {
3715                 }
3716
3717                 public override Expression DoResolve (EmitContext ec)
3718                 {
3719                         // This should never be invoked, we are born in fully
3720                         // initialized state.
3721
3722                         return this;
3723                 }
3724
3725                 public override void Emit (EmitContext ec)
3726                 {
3727                         base.Emit (ec);
3728                         
3729                         ec.ig.Emit (OpCodes.Box, child.Type);
3730                 }
3731         }
3732
3733         public class UnboxCast : EmptyCast {
3734                 public UnboxCast (Expression expr, Type return_type)
3735                         : base (expr, return_type)
3736                 {
3737                 }
3738
3739                 public override Expression DoResolve (EmitContext ec)
3740                 {
3741                         // This should never be invoked, we are born in fully
3742                         // initialized state.
3743
3744                         return this;
3745                 }
3746
3747                 public override void Emit (EmitContext ec)
3748                 {
3749                         Type t = type;
3750                         ILGenerator ig = ec.ig;
3751                         
3752                         base.Emit (ec);
3753                         
3754                         ig.Emit (OpCodes.Dup);
3755                         Label unbox = ig.DefineLabel ();
3756                         ig.Emit (OpCodes.Brtrue, unbox);
3757                         ig.Emit (OpCodes.Pop);
3758                         ig.Emit (OpCodes.Ldtoken, t);
3759                         ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
3760                         MethodInfo createInst =  Type.GetType("System.Activator").GetMethod ("CreateInstance", new Type[]{Type.GetType("System.Type")} );
3761                         ig.Emit (OpCodes.Call, createInst );
3762                         
3763                         ig.MarkLabel (unbox);           
3764                         ig.Emit (OpCodes.Unbox, t);
3765
3766                         LoadFromPtr (ig, t);
3767                 }
3768         }
3769         
3770         /// <summary>
3771         ///   This is used to perform explicit numeric conversions.
3772         ///
3773         ///   Explicit numeric conversions might trigger exceptions in a checked
3774         ///   context, so they should generate the conv.ovf opcodes instead of
3775         ///   conv opcodes.
3776         /// </summary>
3777         public class ConvCast : EmptyCast {
3778                 public enum Mode : byte {
3779                         I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
3780                         U1_I1, U1_CH,
3781                         I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
3782                         U2_I1, U2_U1, U2_I2, U2_CH,
3783                         I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
3784                         U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
3785                         I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
3786                         U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
3787                         CH_I1, CH_U1, CH_I2,
3788                         R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
3789                         R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
3790                 }
3791
3792                 Mode mode;
3793                 bool checked_state;
3794                 
3795                 public ConvCast (EmitContext ec, Expression child, Type return_type, Mode m)
3796                         : base (child, return_type)
3797                 {
3798                         checked_state = ec.CheckState;
3799                         mode = m;
3800                 }
3801
3802                 public override Expression DoResolve (EmitContext ec)
3803                 {
3804                         // This should never be invoked, we are born in fully
3805                         // initialized state.
3806
3807                         return this;
3808                 }
3809
3810                 public override void Emit (EmitContext ec)
3811                 {
3812                         ILGenerator ig = ec.ig;
3813                         
3814                         base.Emit (ec);
3815
3816                         if (checked_state){
3817                                 switch (mode){
3818                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3819                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3820                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3821                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3822                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3823
3824                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3825                                 case Mode.U1_CH: /* nothing */ break;
3826
3827                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3828                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3829                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3830                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3831                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3832                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3833
3834                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3835                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3836                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3837                                 case Mode.U2_CH: /* nothing */ break;
3838
3839                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3840                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3841                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3842                                 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3843                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3844                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3845                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3846
3847                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3848                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3849                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3850                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3851                                 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
3852                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3853
3854                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3855                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3856                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3857                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3858                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
3859                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3860                                 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3861                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3862
3863                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3864                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3865                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3866                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3867                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
3868                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
3869                                 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
3870                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3871
3872                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3873                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3874                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3875
3876                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3877                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3878                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3879                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3880                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
3881                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3882                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
3883                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3884                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3885
3886                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3887                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3888                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3889                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3890                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
3891                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3892                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
3893                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3894                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3895                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
3896                                 }
3897                         } else {
3898                                 switch (mode){
3899                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
3900                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
3901                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
3902                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
3903                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
3904
3905                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
3906                                 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
3907
3908                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
3909                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
3910                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
3911                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
3912                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
3913                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
3914
3915                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
3916                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
3917                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
3918                                 case Mode.U2_CH: /* nothing */ break;
3919
3920                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
3921                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
3922                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
3923                                 case Mode.I4_U4: /* nothing */ break;
3924                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
3925                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
3926                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
3927
3928                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
3929                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
3930                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
3931                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
3932                                 case Mode.U4_I4: /* nothing */ break;
3933                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
3934
3935                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
3936                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
3937                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
3938                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
3939                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
3940                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
3941                                 case Mode.I8_U8: /* nothing */ break;
3942                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
3943
3944                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
3945                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
3946                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
3947                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
3948                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
3949                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
3950                                 case Mode.U8_I8: /* nothing */ break;
3951                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
3952
3953                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
3954                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
3955                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
3956
3957                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
3958                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
3959                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
3960                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
3961                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
3962                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
3963                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
3964                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
3965                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
3966
3967                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
3968                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
3969                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
3970                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
3971                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
3972                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
3973                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
3974                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
3975                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
3976                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
3977                                 }
3978                         }
3979                 }
3980         }
3981         
3982         public class OpcodeCast : EmptyCast {
3983                 OpCode op, op2;
3984                 bool second_valid;
3985                 
3986                 public OpcodeCast (Expression child, Type return_type, OpCode op)
3987                         : base (child, return_type)
3988                         
3989                 {
3990                         this.op = op;
3991                         second_valid = false;
3992                 }
3993
3994                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
3995                         : base (child, return_type)
3996                         
3997                 {
3998                         this.op = op;
3999                         this.op2 = op2;
4000                         second_valid = true;
4001                 }
4002
4003                 public override Expression DoResolve (EmitContext ec)
4004                 {
4005                         // This should never be invoked, we are born in fully
4006                         // initialized state.
4007
4008                         return this;
4009                 }
4010
4011                 public override void Emit (EmitContext ec)
4012                 {
4013                         base.Emit (ec);
4014                         ec.ig.Emit (op);
4015
4016                         if (second_valid)
4017                                 ec.ig.Emit (op2);
4018                 }                       
4019         }
4020
4021
4022         public class NumericToBoolCast : EmptyCast 
4023         {
4024                 Type src_type;
4025                 
4026                 public NumericToBoolCast (Expression src, Type src_type)
4027                         : base (src, TypeManager.bool_type)
4028                         
4029                 {
4030                         this.src_type = src_type;
4031                 }
4032
4033                 public override Expression DoResolve (EmitContext ec)
4034                 {
4035                         return this;
4036                 }
4037
4038                 public override void Emit (EmitContext ec)
4039                 {
4040                         base.Emit (ec);
4041
4042                         if (src_type == TypeManager.byte_type ||
4043                                 src_type == TypeManager.short_type ||
4044                                 src_type == TypeManager.int32_type) {
4045                                 
4046                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
4047                                 ec.ig.Emit (OpCodes.Cgt_Un);
4048                                 return;
4049                         } 
4050
4051                         if (src_type == TypeManager.int64_type) {
4052                                 ec.ig.Emit (OpCodes.Ldc_I8, (long) 0);
4053                                 ec.ig.Emit (OpCodes.Cgt_Un);
4054                                 return;
4055                         } 
4056
4057                         if (src_type == TypeManager.float_type) {
4058                                 ec.ig.Emit (OpCodes.Ldc_R4, (float) 0);
4059                                 ec.ig.Emit (OpCodes.Ceq);
4060                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
4061                                 ec.ig.Emit (OpCodes.Ceq);
4062                                 return;
4063                         } 
4064
4065                         if (src_type == TypeManager.double_type) {
4066                                 ec.ig.Emit (OpCodes.Ldc_R8, (double) 0);
4067                                 ec.ig.Emit (OpCodes.Ceq);
4068                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
4069                                 ec.ig.Emit (OpCodes.Ceq);
4070                                 return;
4071                         }
4072                 }                       
4073         }
4074
4075         public class BoolToNumericCast : EmptyCast 
4076         {
4077                 Type target_type;
4078                 OpCode conv;
4079                 
4080                 public BoolToNumericCast (Expression src, Type target_type)
4081                         : base (src, target_type)
4082                         
4083                 {
4084                         this.target_type = target_type;
4085                 }
4086
4087                 public override Expression DoResolve (EmitContext ec)
4088                 {
4089                         return this;
4090                 }
4091
4092                 public override void Emit (EmitContext ec)
4093                 {
4094                         base.Emit (ec);
4095
4096                         if (target_type == TypeManager.byte_type) {
4097                                 conv = OpCodes.Conv_U1;
4098                         } else if (target_type == TypeManager.short_type) {
4099                                 conv = OpCodes.Conv_I2;
4100                         } else if (target_type == TypeManager.int32_type) {
4101                                 conv = OpCodes.Conv_I4;
4102                         } else if (target_type == TypeManager.int64_type) {
4103                                 conv = OpCodes.Conv_I8;
4104                         } else if (target_type == TypeManager.float_type) {
4105                                 conv = OpCodes.Conv_R4;
4106                         } else if (target_type == TypeManager.double_type) {
4107                                 conv = OpCodes.Conv_R8;
4108                         }
4109
4110                         ec.ig.Emit (OpCodes.Ldc_I4_0);
4111                         ec.ig.Emit (OpCodes.Cgt_Un);
4112                         ec.ig.Emit (OpCodes.Neg);
4113                         ec.ig.Emit (conv);
4114                         return;
4115                 }                       
4116         }
4117
4118         /// <summary>
4119         ///   This kind of cast is used to encapsulate a child and cast it
4120         ///   to the class requested
4121         /// </summary>
4122         public class ClassCast : EmptyCast {
4123                 public ClassCast (Expression child, Type return_type)
4124                         : base (child, return_type)
4125                         
4126                 {
4127                 }
4128
4129                 public override Expression DoResolve (EmitContext ec)
4130                 {
4131                         // This should never be invoked, we are born in fully
4132                         // initialized state.
4133
4134                         return this;
4135                 }
4136
4137                 public override void Emit (EmitContext ec)
4138                 {
4139                         base.Emit (ec);
4140
4141                         ec.ig.Emit (OpCodes.Castclass, type);
4142                 }                       
4143                 
4144         }
4145         
4146         /// <summary>
4147         ///   SimpleName expressions are initially formed of a single
4148         ///   word and it only happens at the beginning of the expression.
4149         /// </summary>
4150         ///
4151         /// <remarks>
4152         ///   The expression will try to be bound to a Field, a Method
4153         ///   group or a Property.  If those fail we pass the name to our
4154         ///   caller and the SimpleName is compounded to perform a type
4155         ///   lookup.  The idea behind this process is that we want to avoid
4156         ///   creating a namespace map from the assemblies, as that requires
4157         ///   the GetExportedTypes function to be called and a hashtable to
4158         ///   be constructed which reduces startup time.  If later we find
4159         ///   that this is slower, we should create a 'NamespaceExpr' expression
4160         ///   that fully participates in the resolution process. 
4161         ///   
4162         ///   For example 'System.Console.WriteLine' is decomposed into
4163         ///   MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
4164         ///   
4165         ///   The first SimpleName wont produce a match on its own, so it will
4166         ///   be turned into:
4167         ///   MemberAccess (SimpleName ("System.Console"), "WriteLine").
4168         ///   
4169         ///   System.Console will produce a TypeExpr match.
4170         ///   
4171         ///   The downside of this is that we might be hitting 'LookupType' too many
4172         ///   times with this scheme.
4173         /// </remarks>
4174         public class SimpleName : Expression, ITypeExpression {
4175                 public readonly string Name;
4176                 bool is_invocation = false;
4177                 bool is_addressof = false;
4178
4179                 public bool IsInvocation {
4180                         set {
4181                                 is_invocation = value;
4182                         }
4183                 }
4184
4185                 public bool IsAddressOf {
4186                         set {
4187                                 is_addressof = value;
4188                         }
4189                 }
4190                 
4191                 public SimpleName (string name, Location l)
4192                 {
4193                         Name = name;
4194                         loc = l;
4195                 }
4196
4197                 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
4198                 {
4199                         if (ec.IsFieldInitializer)
4200                                 Report.Error (
4201                                         236, l,
4202                                         "A field initializer cannot reference the non-static field, " +
4203                                         "method or property '"+name+"'");
4204                         else
4205                                 Report.Error (
4206                                         120, l,
4207                                         "An object reference is required " +
4208                                         "for the non-static field '"+name+"'");
4209                 }
4210                 
4211                 //
4212                 // Checks whether we are trying to access an instance
4213                 // property, method or field from a static body.
4214                 //
4215                 Expression MemberStaticCheck (EmitContext ec, Expression e)
4216                 {
4217                         if (e is IMemberExpr){
4218                                 IMemberExpr member = (IMemberExpr) e;
4219                                 
4220                                 if (!member.IsStatic){
4221                                         Error_ObjectRefRequired (ec, loc, Name);
4222                                         return null;
4223                                 }
4224                         }
4225
4226                         return e;
4227                 }
4228                 
4229                 public override Expression DoResolve (EmitContext ec)
4230                 {
4231                         return SimpleNameResolve (ec, null, false);
4232                 }
4233
4234                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
4235                 {
4236                         return SimpleNameResolve (ec, right_side, false);
4237                 }
4238                 
4239
4240                 public Expression DoResolveAllowStatic (EmitContext ec)
4241                 {
4242                         return SimpleNameResolve (ec, null, true);
4243                 }
4244
4245                 public Expression DoResolveType (EmitContext ec)
4246                 {
4247                         //
4248                         // Stage 3: Lookup symbol in the various namespaces. 
4249                         //
4250                         DeclSpace ds = ec.DeclSpace;
4251                         Type t;
4252                         string alias_value;
4253
4254                         if (ec.ResolvingTypeTree){
4255                                 int errors = Report.Errors;
4256                                 Type dt = ec.DeclSpace.FindType (loc, Name);
4257                                 if (Report.Errors != errors)
4258                                         return null;
4259                                 
4260                                 if (dt != null)
4261                                         return new TypeExpr (dt, loc);
4262                         }
4263
4264                         if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
4265                                 return new TypeExpr (t, loc);
4266                                 
4267
4268                         //
4269                         // Stage 2 part b: Lookup up if we are an alias to a type
4270                         // or a namespace.
4271                         //
4272                         // Since we are cheating: we only do the Alias lookup for
4273                         // namespaces if the name does not include any dots in it
4274                         //
4275                                 
4276                         alias_value = ec.DeclSpace.LookupAlias (Name);
4277                                 
4278                         if (Name.IndexOf ('.') == -1 && alias_value != null) {
4279                                 if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
4280                                         return new TypeExpr (t, loc);
4281                                         
4282                                 // we have alias value, but it isn't Type, so try if it's namespace
4283                                 return new SimpleName (alias_value, loc);
4284                         }
4285                                 
4286                         // No match, maybe our parent can compose us
4287                         // into something meaningful.
4288                         return this;
4289                 }
4290
4291                 /// <remarks>
4292                 ///   7.5.2: Simple Names. 
4293                 ///
4294                 ///   Local Variables and Parameters are handled at
4295                 ///   parse time, so they never occur as SimpleNames.
4296                 ///
4297                 ///   The 'allow_static' flag is used by MemberAccess only
4298                 ///   and it is used to inform us that it is ok for us to 
4299                 ///   avoid the static check, because MemberAccess might end
4300                 ///   up resolving the Name as a Type name and the access as
4301                 ///   a static type access.
4302                 ///
4303                 ///   ie: Type Type; .... { Type.GetType (""); }
4304                 ///
4305                 ///   Type is both an instance variable and a Type;  Type.GetType
4306                 ///   is the static method not an instance method of type.
4307                 /// </remarks>
4308                 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static)
4309                 {
4310                         Expression e = null;
4311                         
4312                         //
4313                         // Stage 1: Performed by the parser (binding to locals or parameters).
4314                         //
4315                         Block current_block = ec.CurrentBlock;
4316                         if (ec.InvokingOwnOverload == false && current_block != null && current_block.IsVariableDefined (Name)){
4317                                 LocalVariableReference var;
4318
4319                                 var = new LocalVariableReference (current_block, Name, loc);
4320
4321                                 if (right_side != null)
4322                                         return var.ResolveLValue (ec, right_side);
4323                                 else
4324                                         return var.Resolve (ec);
4325                         }
4326
4327                         if (current_block != null){
4328                                 int idx = -1;
4329                                 Parameter par = null;
4330                                 Parameters pars = current_block.Parameters;
4331                                 if (pars != null)
4332                                         par = pars.GetParameterByName (Name, out idx);
4333
4334                                 if (par != null) {
4335                                         ParameterReference param;
4336                                         
4337                                         param = new ParameterReference (pars, idx, Name, loc);
4338
4339                                         if (right_side != null)
4340                                                 return param.ResolveLValue (ec, right_side);
4341                                         else
4342                                                 return param.Resolve (ec);
4343                                 }
4344                         }
4345
4346                         //
4347                         // Stage 2: Lookup members 
4348                         //
4349
4350                         //
4351                         // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
4352                         // Hence we have two different cases
4353                         //
4354
4355                         DeclSpace lookup_ds = ec.DeclSpace;
4356                         do {
4357                                 if (lookup_ds.TypeBuilder == null)
4358                                         break;
4359
4360                                 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
4361                                 if (e != null)
4362                                         break;
4363
4364                                 //
4365                                 // Classes/structs keep looking, enums break
4366                                 //
4367                                 if (lookup_ds is TypeContainer)
4368                                         lookup_ds = ((TypeContainer) lookup_ds).Parent;
4369                                 else
4370                                         break;
4371                         } while (lookup_ds != null);
4372                                 
4373                         if (e == null && ec.ContainerType != null)
4374                                 e = MemberLookup (ec, ec.ContainerType, Name, loc);
4375
4376 // #52067 - Start - Trying to solve
4377
4378                         if (e == null) {
4379                                 ArrayList lookups = new ArrayList();
4380                                 ArrayList typelookups = new ArrayList();
4381                                 
4382                                 int split = Name.LastIndexOf('.');
4383                                 if (split != -1) {
4384                                         String nameSpacePart = Name.Substring(0, split);
4385                                         String memberNamePart = Name.Substring(split + 1);
4386                                         foreach(Type type in TypeManager.GetPertinentStandardModules(nameSpacePart)) {
4387                                                 e = MemberLookup(ec, type, memberNamePart, loc);
4388                                                 if (e != null) {
4389                                                         lookups.Add(e);
4390                                                         typelookups.Add(type);
4391                                                 }
4392                                         }
4393                                 }
4394                                 
4395                                 string[] NamespacesInScope = RootContext.SourceBeingCompiled.GetNamespacesInScope(ec.DeclSpace.Namespace.Name);
4396                                 foreach(Type type in TypeManager.GetPertinentStandardModules(NamespacesInScope)) {
4397                                         e = MemberLookup(ec, type, Name, loc);
4398                                         if (e != null) {
4399                                                 lookups.Add(e);
4400                                                 typelookups.Add(type);
4401                                         }
4402                                 }
4403                                 if (lookups.Count == 1) { 
4404                                         e = (Expression)lookups[0];
4405                                 } else {
4406                                         if (lookups.Count > 1) {
4407                                                 StringBuilder sb = new StringBuilder();
4408                                                 foreach(Type type in typelookups)
4409                                                         sb.Append("'" + type.FullName + "'");                                           
4410                                                 Error (-1, "The name '" + Name + "' can be resolved to a member of more than one standard module: " + sb.ToString() + ". Please fully qualify it.");
4411                                                 return null;
4412                                         }
4413                                 }
4414                         }
4415
4416 // #52067 - End
4417
4418                         if (e == null) {
4419                         
4420                 /* preparing to support automatic definition of variables on first usage with Option Explicit Off
4421                         
4422                         Isn't good enough to enable just now (tries to define some internal links and breaks on emit)
4423                         
4424                                 if (Name.IndexOf ('.') == -1 && current_block != null && !Mono.MonoBASIC.Parser.OptionExplicit) {
4425                                 
4426                                         // while looking for a real solution
4427                                         if (Name != "anything")
4428                                                 return DoResolveType (ec);
4429                                                 
4430                                         Console.WriteLine("Implicitly adding a variable named '{0}'", Name);
4431                                         
4432                                         // TODO: look at type-suffixes to correct name and type
4433                                         Expression type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", loc);
4434                                         
4435                                         current_block.AddVariable(ec, type, Name, loc);
4436                                 
4437                                         LocalVariableReference var = new LocalVariableReference (current_block, Name, loc);
4438                                         if (right_side != null)
4439                                                 return var.ResolveLValue (ec, right_side);
4440                                         else
4441                                                 return var.Resolve (ec);
4442                                 } else
4443                 */
4444                                         return DoResolveType (ec);
4445                         }
4446                         
4447                         if (e is TypeExpr)
4448                                 return e;
4449
4450                         if (e is IMemberExpr) {
4451                                 if ((e is MethodGroupExpr) && !is_invocation && !is_addressof) {
4452                                         Expression inv = new Invocation (this, new ArrayList (), loc);
4453                                         return inv.Resolve (ec);
4454                                 }
4455                                 e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
4456                                 if (e == null)
4457                                         return null;
4458
4459                                 if (e is PropertyGroupExpr && is_invocation) // We dont know the arguments yet
4460                                         return e;
4461
4462                                 IMemberExpr me = e as IMemberExpr;
4463                                 if (me == null)
4464                                         return e;
4465
4466                                 // This fails if ResolveMemberAccess() was unable to decide whether
4467                                 // it's a field or a type of the same name.
4468                                 if (!me.IsStatic && (me.InstanceExpression == null))
4469                                         return e;
4470
4471 /* FIXME    If this is not commented out, it seems that it's not possible to reach class members in mBas.
4472             Maybe a grammar-related problem?
4473
4474                                 if (!me.IsStatic &&
4475                                     TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) {
4476                                         Error (38, "Cannot access nonstatic member '" + me.Name + "' of " +
4477                                                "outer type '" + me.DeclaringType + "' via nested type '" +
4478                                                me.InstanceExpression.Type + "'");
4479                                         return null;
4480                                 }
4481 */
4482                                 bool isPropertyGroup = (e is PropertyGroupExpr);
4483                                 if (right_side != null)
4484                                         e = e.DoResolveLValue (ec, right_side);
4485                                 else
4486                                         e = e.DoResolve (ec);
4487
4488                                 if (e == null && isPropertyGroup && !is_invocation)
4489                                          Error (30057, "Property '" + Name + "' cannot be invoked with given arguments");
4490                                          
4491                                 return e;
4492                         }
4493
4494                         if (ec.IsStatic || ec.IsFieldInitializer) {
4495                                 if (allow_static)
4496                                         return e;
4497
4498                                 return MemberStaticCheck (ec, e);
4499                         }
4500
4501                         return e;
4502                 }
4503                 
4504                 public override void Emit (EmitContext ec)
4505                 {
4506                         //
4507                         // If this is ever reached, then we failed to
4508                         // find the name as a namespace
4509                         //
4510
4511                         Error (30451, "The name '" + Name +
4512                                "' does not exist in the class '" +
4513                                ec.DeclSpace.Name + "'");
4514                 }
4515
4516                 public override string ToString ()
4517                 {
4518                         return Name;
4519                 }
4520         }
4521
4522         public class DecoratedIdentifier : Expression {
4523                 Expression id;
4524                 Type decoration;
4525
4526                 public Expression Id
4527                 {
4528                         get
4529                         {
4530                                 return this.id;
4531                         }
4532                 }
4533                 
4534                 public DecoratedIdentifier (Expression id, Type decoration)
4535                 {
4536                         this.id = id;
4537                         this.decoration = decoration;
4538                 }
4539
4540                 override public Expression DoResolve (EmitContext ec)
4541                 {
4542                         if (id == null || decoration == null)
4543                                 return null;
4544                         
4545                         Expression ret = id.DoResolve (ec);
4546                         if (ret.Type != TypeManager.TypeToCoreType (decoration)) {
4547                                 Report.Error (30277, id.Location, "Type character '" + decoration + "' does not match declared type '" + ret.Type  + "'."); 
4548                                 return null;
4549                         }
4550
4551                         return ret;
4552                 }
4553                 
4554                 override public void Emit (EmitContext ec)
4555                 {
4556                         throw new InternalErrorException ("Should never be called");
4557                 }
4558         }
4559         
4560         /// <summary>
4561         ///   Fully resolved expression that evaluates to a type
4562         /// </summary>
4563         public class TypeExpr : Expression, ITypeExpression {
4564                 public TypeExpr (Type t, Location l)
4565                 {
4566                         Type = t;
4567                         eclass = ExprClass.Type;
4568                         loc = l;
4569                 }
4570
4571                 public virtual Expression DoResolveType (EmitContext ec)
4572                 {
4573                         return this;
4574                 }
4575
4576                 override public Expression DoResolve (EmitContext ec)
4577                 {
4578                         return this;
4579                 }
4580
4581                 override public void Emit (EmitContext ec)
4582                 {
4583                         throw new Exception ("Should never be called");
4584                 }
4585
4586                 public override string ToString ()
4587                 {
4588                         return Type.ToString ();
4589                 }
4590         }
4591
4592         /// <summary>
4593         ///   Used to create types from a fully qualified name.  These are just used
4594         ///   by the parser to setup the core types.  A TypeLookupExpression is always
4595         ///   classified as a type.
4596         /// </summary>
4597         public class TypeLookupExpression : TypeExpr {
4598                 string name;
4599                 
4600                 public TypeLookupExpression (string name) : base (null, Location.Null)
4601                 {
4602                         this.name = name;
4603                 }
4604
4605                 public override Expression DoResolveType (EmitContext ec)
4606                 {
4607                         if (type == null)
4608                                 type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
4609                         return this;
4610                 }
4611
4612                 public override Expression DoResolve (EmitContext ec)
4613                 {
4614                         return DoResolveType (ec);
4615                 }
4616
4617                 public override void Emit (EmitContext ec)
4618                 {
4619                         throw new Exception ("Should never be called");
4620                 }
4621
4622                 public override string ToString ()
4623                 {
4624                         return name;
4625                 }
4626         }
4627
4628         /// <summary>
4629         ///   MethodGroup Expression.
4630         ///  
4631         ///   This is a fully resolved expression that evaluates to a type
4632         /// </summary>
4633         public class MethodGroupExpr : Expression, IMemberExpr {
4634                 public MethodBase [] Methods;
4635                 Expression instance_expression = null;
4636                 bool is_explicit_impl = false;
4637                 
4638                 public MethodGroupExpr (MemberInfo [] mi, Location l)
4639                 {
4640                         Methods = new MethodBase [mi.Length];
4641                         mi.CopyTo (Methods, 0);
4642                         eclass = ExprClass.MethodGroup;
4643                         type = TypeManager.object_type;
4644                         loc = l;
4645                 }
4646
4647                 public MethodGroupExpr (ArrayList list, Location l)
4648                 {
4649                         Methods = new MethodBase [list.Count];
4650
4651                         try {
4652                                 list.CopyTo (Methods, 0);
4653                         } catch {
4654                                 foreach (MemberInfo m in list){
4655                                         if (!(m is MethodBase)){
4656                                                 Console.WriteLine ("Name " + m.Name);
4657                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4658                                         }
4659                                 }
4660                                 throw;
4661                         }
4662                         loc = l;
4663                         eclass = ExprClass.MethodGroup;
4664                         type = TypeManager.object_type;
4665                 }
4666
4667                 public Type DeclaringType {
4668                         get {
4669                                 return Methods [0].DeclaringType;
4670                         }
4671                 }
4672                 
4673                 //
4674                 // 'A method group may have associated an instance expression' 
4675                 // 
4676                 public Expression InstanceExpression {
4677                         get {
4678                                 return instance_expression;
4679                         }
4680
4681                         set {
4682                                 instance_expression = value;
4683                         }
4684                 }
4685
4686                 public bool IsExplicitImpl {
4687                         get {
4688                                 return is_explicit_impl;
4689                         }
4690
4691                         set {
4692                                 is_explicit_impl = value;
4693                         }
4694                 }
4695
4696                 public string Name {
4697                         get {
4698                                 return Methods [0].Name;
4699                         }
4700                 }
4701
4702                 public bool IsInstance {
4703                         get {
4704                                 foreach (MethodBase mb in Methods)
4705                                         if (!mb.IsStatic)
4706                                                 return true;
4707
4708                                 return false;
4709                         }
4710                 }
4711
4712                 public bool IsStatic {
4713                         get {
4714                                 foreach (MethodBase mb in Methods)
4715                                         if (mb.IsStatic)
4716                                                 return true;
4717
4718                                 return false;
4719                         }
4720                 }
4721                 
4722                 override public Expression DoResolve (EmitContext ec)
4723                 {
4724                         if (instance_expression != null) {
4725                                 instance_expression = instance_expression.DoResolve (ec);
4726                                 if (instance_expression == null)
4727                                         return null;
4728                         }
4729
4730                         return this;
4731                 }
4732
4733                 public void ReportUsageError ()
4734                 {
4735                         Report.Error (654, loc, "Method '" + Methods [0].DeclaringType + "." +
4736                                       Methods [0].Name + "()' is referenced without parentheses");
4737                 }
4738
4739                 override public void Emit (EmitContext ec)
4740                 {
4741                         ReportUsageError ();
4742                 }
4743
4744                 bool RemoveMethods (bool keep_static)
4745                 {
4746                         ArrayList smethods = new ArrayList ();
4747
4748                         foreach (MethodBase mb in Methods){
4749                                 if (mb.IsStatic == keep_static)
4750                                         smethods.Add (mb);
4751                         }
4752
4753                         if (smethods.Count == 0)
4754                                 return false;
4755
4756                         Methods = new MethodBase [smethods.Count];
4757                         smethods.CopyTo (Methods, 0);
4758
4759                         return true;
4760                 }
4761                 
4762                 /// <summary>
4763                 ///   Removes any instance methods from the MethodGroup, returns
4764                 ///   false if the resulting set is empty.
4765                 /// </summary>
4766                 public bool RemoveInstanceMethods ()
4767                 {
4768                         return RemoveMethods (true);
4769                 }
4770
4771                 /// <summary>
4772                 ///   Removes any static methods from the MethodGroup, returns
4773                 ///   false if the resulting set is empty.
4774                 /// </summary>
4775                 public bool RemoveStaticMethods ()
4776                 {
4777                         return RemoveMethods (false);
4778                 }
4779         }
4780
4781         /// <summary>
4782         ///   Property Group Expression.
4783         ///  
4784         /// </summary>
4785         public class PropertyGroupExpr : ExpressionStatement, IMemberExpr {
4786                 public PropertyInfo [] Properties;
4787                 Expression instance_expression = null;
4788                 bool is_explicit_impl = false;
4789                 MethodBase method = null;
4790                 bool indexer_access_req = false;
4791                 ArrayList arguments = null;
4792                 
4793                 public PropertyGroupExpr (MemberInfo [] mi, Location l)
4794                 {
4795                         Properties = new PropertyInfo [mi.Length];
4796                         mi.CopyTo (Properties, 0);
4797                         eclass = ExprClass.PropertyAccess;
4798                         type = TypeManager.object_type;
4799                         loc = l;
4800                 }
4801
4802                 public PropertyGroupExpr (MemberInfo [] mi, ArrayList args, Expression expr, Location l)
4803                         : this (mi, l)
4804                 {
4805                         arguments = args;
4806                         instance_expression = expr;
4807                 }
4808
4809                 public PropertyGroupExpr (ArrayList list, Location l)
4810                 {
4811                         Properties = new PropertyInfo [list.Count];
4812
4813                         try {
4814                                 list.CopyTo (Properties, 0);
4815                         } catch {
4816                                 foreach (MemberInfo m in list){
4817                                         if (!(m is PropertyInfo)){
4818                                                 Console.WriteLine ("Name " + m.Name);
4819                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4820                                         }
4821                                 }
4822                                 throw;
4823                         }
4824                         loc = l;
4825                         eclass = ExprClass.PropertyAccess;
4826                         type = TypeManager.object_type;
4827                 }
4828
4829                 public ArrayList Arguments {
4830                         get {
4831                                 return arguments;
4832                         }
4833                         set {
4834                                 arguments = value;
4835                         }
4836                 }
4837
4838                 public Type DeclaringType {
4839                         get {
4840                                 return Properties [0].DeclaringType;
4841                         }
4842                 }
4843
4844                 public bool IndexerAccessRequired {
4845                         get {
4846                                 return indexer_access_req;
4847                         }
4848                 }
4849
4850                 //
4851                 // 'A method group may have associated an instance expression' 
4852                 // 
4853                 public Expression InstanceExpression {
4854                         get {
4855                                 return instance_expression;
4856                         }
4857
4858                         set {
4859                                 instance_expression = value;
4860                         }
4861                 }
4862
4863                 public bool IsExplicitImpl {
4864                         get {
4865                                 return is_explicit_impl;
4866                         }
4867
4868                         set {
4869                                 is_explicit_impl = value;
4870                         }
4871                 }
4872
4873                 public string Name {
4874                         get {
4875                                 return Properties [0].Name;
4876                         }
4877                 }
4878
4879                 public bool IsInstance {
4880                         get {
4881                                 foreach (PropertyInfo pi in Properties) {
4882                                         MethodInfo mi = pi.GetGetMethod ();
4883                                         if (mi != null && !mi.IsStatic)
4884                                                 return true;
4885                                         mi = pi.GetSetMethod ();
4886                                         if (mi != null && !mi.IsStatic)
4887                                                 return true;
4888                                 }               
4889                                 return false;
4890                         }
4891                 }
4892
4893                 public bool IsStatic {
4894                         get {
4895                                 return (!IsInstance);
4896                         }
4897                 }
4898                 
4899                 public ArrayList GetAccessors () {
4900                         ArrayList GetAccessors = new ArrayList ();
4901                         foreach (PropertyInfo pi in Properties) {
4902                                 if (pi.GetGetMethod () != null)
4903                                         GetAccessors.Add (pi.GetGetMethod ());
4904 /*
4905                                 else if (pi.GetGetMethod (true) != null)
4906                                         GetAccessors.Add (pi.GetGetMethod (true));
4907 */
4908                                         
4909                         }
4910                         return GetAccessors;
4911                 }
4912                 
4913                 public ArrayList SetAccessors () {
4914                         ArrayList SetAccessors = new ArrayList ();
4915                         foreach (PropertyInfo pi in Properties) {
4916                                 if (pi.GetSetMethod () != null)
4917                                         SetAccessors.Add (pi.GetSetMethod ());
4918 /*
4919                                 else if (pi.GetSetMethod (true) != null)
4920                                         SetAccessors.Add (pi.GetSetMethod (true));
4921 */
4922                         }
4923                         return SetAccessors;
4924                 }
4925
4926                 override public Expression DoResolve (EmitContext ec)
4927                 {
4928                         if (instance_expression != null) {
4929                                 instance_expression = instance_expression.DoResolve (ec);
4930                                 if (instance_expression == null)
4931                                         return null;
4932                         }
4933
4934                         ArrayList members = GetAccessors ();
4935                         if (members == null || members.Count == 0) {
4936                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'get' accesor");
4937                                 return null;
4938                         }
4939
4940                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4941                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4942                         if ((method as MethodInfo) != null) {
4943                                 MethodInfo mi = method as MethodInfo;
4944                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
4945                                 indexer_access_req = false;
4946                                 eclass = ExprClass.Value;
4947                                 return this;
4948                         } else {
4949                                 // find a get method that doesnt take any arguments. Check the return type of
4950                                 // that method to find out if indexer access is required. Leave the rest to
4951                                 // 'Invocation's Resolve'
4952                                 method = Invocation.OverloadResolve (ec, m_expr, null, loc);
4953                                 if (method != null) {
4954                                         MethodInfo mi = method as MethodInfo;
4955                                         Type ret_type = mi.ReturnType;
4956                                         if (ret_type.IsArray)
4957                                                 indexer_access_req = true;
4958                                         else {
4959                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, ret_type, loc);
4960                                                 if (list != null && list.getters.Count > 0)
4961                                                         indexer_access_req = true;
4962                                                 else 
4963                                                         return null;
4964                                         }
4965                                         Arguments = null;
4966                                         type = mi.ReturnType;
4967                                         return this;
4968                                 }
4969                         }
4970
4971                         return null;
4972                 }
4973
4974                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side) {
4975                         if (instance_expression != null) {
4976                                 instance_expression = instance_expression.DoResolve (ec);
4977                                 if (instance_expression == null)
4978                                         return null;
4979                         }
4980
4981                         ArrayList members = SetAccessors ();
4982                         if (members == null || members.Count == 0) {
4983                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'set' accesor");
4984                                 return null;
4985                         }
4986
4987                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4988                         if (arguments == null)
4989                                 arguments = new ArrayList ();
4990                         arguments.Add (new Argument (right_side, Argument.AType.Expression));
4991                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4992                         if (method != null) {
4993                                 //MethodInfo mi = method as MethodInfo;
4994                                 type = TypeManager.void_type; //TypeManager.TypeToCoreType (mi.ReturnType);
4995                                 eclass = ExprClass.Value;
4996                                 indexer_access_req = false;
4997                                 return this;
4998                         } else {
4999                                 // Look for properties that do not take any arguments.
5000                                 // Check if the return type has any indexers
5001                                 arguments = null;
5002                                 DoResolve (ec);
5003                                 if (method != null) {
5004                                         MethodInfo mi = method as MethodInfo;
5005                                         Type ret_type = mi.ReturnType;
5006                                         if (ret_type.IsArray)
5007                                                 indexer_access_req = true;
5008                                         else {
5009
5010                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, 
5011                                                                         ret_type, loc);
5012                                                 if (list != null && list.setters.Count > 0)
5013                                                         indexer_access_req = true;
5014                                                 else 
5015                                                         return null;
5016                                         }
5017                                         type = mi.ReturnType;
5018                                         return this;
5019                                 }
5020                         }
5021
5022                         return null;
5023                 }
5024
5025                 override public void Emit (EmitContext ec)
5026                 {
5027                         if (Arguments == null)
5028                                 Arguments = new ArrayList ();
5029                         Invocation.EmitCall (ec, false, IsStatic, instance_expression, method, null, Arguments, loc);
5030                 }
5031
5032                 override public void EmitStatement (EmitContext ec) 
5033                 {
5034                         Emit (ec);
5035                 }
5036
5037         }
5038
5039         /// <summary>
5040         ///   Fully resolved expression that evaluates to a Field
5041         /// </summary>
5042         public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr {
5043                 public readonly FieldInfo FieldInfo;
5044                 Expression instance_expr;
5045                 
5046                 public FieldExpr (FieldInfo fi, Location l)
5047                 {
5048                         FieldInfo = fi;
5049                         eclass = ExprClass.Variable;
5050                         type = fi.FieldType;
5051                         loc = l;
5052                 }
5053
5054                 public string Name {
5055                         get {
5056                                 return FieldInfo.Name;
5057                         }
5058                 }
5059
5060                 public bool IsInstance {
5061                         get {
5062                                 return !FieldInfo.IsStatic;
5063                         }
5064                 }
5065
5066                 public bool IsStatic {
5067                         get {
5068                                 return FieldInfo.IsStatic;
5069                         }
5070                 }
5071
5072                 public Type DeclaringType {
5073                         get {
5074                                 return FieldInfo.DeclaringType;
5075                         }
5076                 }
5077
5078                 public Expression InstanceExpression {
5079                         get {
5080                                 return instance_expr;
5081                         }
5082
5083                         set {
5084                                 instance_expr = value;
5085                         }
5086                 }
5087
5088                 override public Expression DoResolve (EmitContext ec)
5089                 {
5090                         if (!FieldInfo.IsStatic){
5091                                 if (instance_expr == null){
5092                                         throw new Exception ("non-static FieldExpr without instance var\n" +
5093                                                              "You have to assign the Instance variable\n" +
5094                                                              "Of the FieldExpr to set this\n");
5095                                 }
5096
5097                                 // Resolve the field's instance expression while flow analysis is turned
5098                                 // off: when accessing a field "a.b", we must check whether the field
5099                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
5100                                 instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
5101                                                                        ResolveFlags.DisableFlowAnalysis);
5102                                 if (instance_expr == null)
5103                                         return null;
5104                         }
5105
5106                         // If the instance expression is a local variable or parameter.
5107                         IVariable var = instance_expr as IVariable;
5108                         if ((var != null) && !var.IsFieldAssigned (ec, FieldInfo.Name, loc))
5109                                 return null;
5110
5111                         return this;
5112                 }
5113
5114                 void Report_AssignToReadonly (bool is_instance)
5115                 {
5116                         string msg;
5117                         
5118                         if (is_instance)
5119                                 msg = "Readonly field can not be assigned outside " +
5120                                 "of constructor or variable initializer";
5121                         else
5122                                 msg = "A static readonly field can only be assigned in " +
5123                                 "a static constructor";
5124
5125                         Report.Error (is_instance ? 191 : 198, loc, msg);
5126                 }
5127                 
5128                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5129                 {
5130                         IVariable var = instance_expr as IVariable;
5131                         if (var != null)
5132                                 var.SetFieldAssigned (ec, FieldInfo.Name);
5133
5134                         Expression e = DoResolve (ec);
5135
5136                         if (e == null)
5137                                 return null;
5138                         
5139                         if (!FieldInfo.IsInitOnly)
5140                                 return this;
5141
5142                         //
5143                         // InitOnly fields can only be assigned in constructors
5144                         //
5145
5146                         if (ec.IsConstructor)
5147                                 return this;
5148
5149                         Report_AssignToReadonly (true);
5150                         
5151                         return null;
5152                 }
5153
5154                 override public void Emit (EmitContext ec)
5155                 {
5156                         ILGenerator ig = ec.ig;
5157                         bool is_volatile = false;
5158
5159                         if (FieldInfo is FieldBuilder){
5160                                 FieldBase f = TypeManager.GetField (FieldInfo);
5161
5162                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5163                                         is_volatile = true;
5164                                 
5165                                 f.status |= Field.Status.USED;
5166                         }
5167                         
5168                         if (FieldInfo.IsStatic){
5169                                 if (is_volatile)
5170                                         ig.Emit (OpCodes.Volatile);
5171                                 
5172                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
5173                         } else {
5174                                 if (instance_expr.Type.IsValueType){
5175                                         IMemoryLocation ml;
5176                                         LocalTemporary tempo = null;
5177                                         
5178                                         if (!(instance_expr is IMemoryLocation)){
5179                                                 tempo = new LocalTemporary (
5180                                                         ec, instance_expr.Type);
5181
5182                                                 InstanceExpression.Emit (ec);
5183                                                 tempo.Store (ec);
5184                                                 ml = tempo;
5185                                         } else
5186                                                 ml = (IMemoryLocation) instance_expr;
5187
5188                                         ml.AddressOf (ec, AddressOp.Load);
5189                                 } else 
5190                                         instance_expr.Emit (ec);
5191
5192                                 if (is_volatile)
5193                                         ig.Emit (OpCodes.Volatile);
5194                                 
5195                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
5196                         }
5197                 }
5198
5199                 public void EmitAssign (EmitContext ec, Expression source)
5200                 {
5201                         FieldAttributes fa = FieldInfo.Attributes;
5202                         bool is_static = (fa & FieldAttributes.Static) != 0;
5203                         bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
5204                         ILGenerator ig = ec.ig;
5205
5206                         if (is_readonly && !ec.IsConstructor){
5207                                 Report_AssignToReadonly (!is_static);
5208                                 return;
5209                         }
5210                         
5211                         if (!is_static){
5212                                 Expression instance = instance_expr;
5213
5214                                 if (instance.Type.IsValueType){
5215                                         if (instance is IMemoryLocation){
5216                                                 IMemoryLocation ml = (IMemoryLocation) instance;
5217
5218                                                 ml.AddressOf (ec, AddressOp.Store);
5219                                         } else
5220                                                 throw new Exception ("The " + instance + " of type " +
5221                                                                      instance.Type +
5222                                                                      " represents a ValueType and does " +
5223                                                                      "not implement IMemoryLocation");
5224                                 } else
5225                                         instance.Emit (ec);
5226                         }
5227                         source.Emit (ec);
5228
5229                         if (FieldInfo is FieldBuilder){
5230                                 FieldBase f = TypeManager.GetField (FieldInfo);
5231                                 
5232                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5233                                         ig.Emit (OpCodes.Volatile);
5234                         }
5235                         
5236                         if (is_static)
5237                                 ig.Emit (OpCodes.Stsfld, FieldInfo);
5238                         else 
5239                                 ig.Emit (OpCodes.Stfld, FieldInfo);
5240
5241                         if (FieldInfo is FieldBuilder){
5242                                 FieldBase f = TypeManager.GetField (FieldInfo);
5243
5244                                 f.status |= Field.Status.ASSIGNED;
5245                         }
5246                 }
5247                 
5248                 public void AddressOf (EmitContext ec, AddressOp mode)
5249                 {
5250                         ILGenerator ig = ec.ig;
5251                         
5252                         if (FieldInfo is FieldBuilder){
5253                                 FieldBase f = TypeManager.GetField (FieldInfo);
5254                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5255                                         ig.Emit (OpCodes.Volatile);
5256                         }
5257
5258                         if (FieldInfo is FieldBuilder){
5259                                 FieldBase f = TypeManager.GetField (FieldInfo);
5260
5261                                 if ((mode & AddressOp.Store) != 0)
5262                                         f.status |= Field.Status.ASSIGNED;
5263                                 if ((mode & AddressOp.Load) != 0)
5264                                         f.status |= Field.Status.USED;
5265                         }
5266
5267                         //
5268                         // Handle initonly fields specially: make a copy and then
5269                         // get the address of the copy.
5270                         //
5271                         if (FieldInfo.IsInitOnly && !ec.IsConstructor){
5272                                 LocalBuilder local;
5273                                 
5274                                 Emit (ec);
5275                                 local = ig.DeclareLocal (type);
5276                                 ig.Emit (OpCodes.Stloc, local);
5277                                 ig.Emit (OpCodes.Ldloca, local);
5278                                 return;
5279                         }
5280
5281                         if (FieldInfo.IsStatic)
5282                                 ig.Emit (OpCodes.Ldsflda, FieldInfo);
5283                         else {
5284                                 if (instance_expr is IMemoryLocation)
5285                                         ((IMemoryLocation)instance_expr).AddressOf (ec, AddressOp.LoadStore);
5286                                 else
5287                                         instance_expr.Emit (ec);
5288                                 ig.Emit (OpCodes.Ldflda, FieldInfo);
5289                         }
5290                 }
5291         }
5292         
5293         /// <summary>
5294         ///   Expression that evaluates to a Property.  The Assign class
5295         ///   might set the 'Value' expression if we are in an assignment.
5296         ///
5297         ///   This is not an LValue because we need to re-write the expression, we
5298         ///   can not take data from the stack and store it.  
5299         /// </summary>
5300         public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
5301                 public readonly PropertyInfo PropertyInfo;
5302                 public bool IsBase;
5303                 MethodInfo getter, setter;
5304                 bool is_static;
5305                 public ArrayList PropertyArgs;
5306
5307                 Expression instance_expr;
5308
5309                 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
5310                 {
5311                         PropertyInfo = pi;
5312                         eclass = ExprClass.PropertyAccess;
5313                         PropertyArgs = null;
5314                         is_static = false;
5315                         loc = l;
5316
5317                         type = TypeManager.TypeToCoreType (pi.PropertyType);
5318
5319                         ResolveAccessors (ec);
5320                 }
5321
5322                 public string Name {
5323                         get {
5324                                 return PropertyInfo.Name;
5325                         }
5326                 }
5327
5328                 public bool IsInstance {
5329                         get {
5330                                 return !is_static;
5331                         }
5332                 }
5333
5334                 public bool IsStatic {
5335                         get {
5336                                 return is_static;
5337                         }
5338                 }
5339                 
5340                 public Type DeclaringType {
5341                         get {
5342                                 return PropertyInfo.DeclaringType;
5343                         }
5344                 }
5345
5346                 //
5347                 // The instance expression associated with this expression
5348                 //
5349                 public Expression InstanceExpression {
5350                         set {
5351                                 instance_expr = value;
5352                         }
5353
5354                         get {
5355                                 return instance_expr;
5356                         }
5357                 }
5358
5359                 public bool VerifyAssignable ()
5360                 {
5361                         if (!PropertyInfo.CanWrite){
5362                                 Report.Error (200, loc, 
5363                                               "The property '" + PropertyInfo.Name +
5364                                               "' can not be assigned to, as it has not set accessor");
5365                                 return false;
5366                         }
5367
5368                         return true;
5369                 }
5370
5371                 void ResolveAccessors (EmitContext ec)
5372                 {
5373                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
5374                         MemberInfo [] group;
5375                         
5376                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5377                                                               MemberTypes.Method, flags, "get_" + PropertyInfo.Name);
5378
5379                         //
5380                         // The first method is the closest to us
5381                         //
5382                         if (group != null && group.Length > 0){
5383                                 getter = (MethodInfo) group [0];
5384
5385                                 if (getter.IsStatic)
5386                                         is_static = true;
5387                         }                       
5388
5389                         //
5390                         // The first method is the closest to us
5391                         //
5392                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5393                                                           MemberTypes.Method, flags, "set_" + PropertyInfo.Name);
5394                         if (group != null && group.Length > 0){
5395                                 setter = (MethodInfo) group [0];
5396                                 if (setter.IsStatic)
5397                                         is_static = true;
5398                         }
5399                 }
5400
5401                 override public Expression DoResolve (EmitContext ec)
5402                 {
5403                         if (getter == null){
5404                                 Report.Error (30524, loc, 
5405                                               "The property '" + PropertyInfo.Name +
5406                                               "' can not be used in " +
5407                                               "this context because it lacks a get accessor");
5408                                 return null;
5409                         }
5410
5411                         if ((instance_expr == null) && ec.IsStatic && !is_static) {
5412                                 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
5413                                 return null;
5414                         }
5415
5416                         if (instance_expr != null) {
5417                                 instance_expr = instance_expr.DoResolve (ec);
5418                                 if (instance_expr == null)
5419                                         return null;
5420                         }
5421
5422                         return this;
5423                 }
5424
5425                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5426                 {
5427                         if (setter == null){
5428                                 Report.Error (30526, loc, 
5429                                               "The property '" + PropertyInfo.Name +
5430                                               "' can not be used in " +
5431                                               "this context because it lacks a set accessor");
5432                                 return null;
5433                         }
5434
5435                         if (instance_expr != null) {
5436                                 instance_expr = instance_expr.DoResolve (ec);
5437                                 if (instance_expr == null)
5438                                         return null;
5439                         }
5440
5441                         return this;
5442                 }
5443
5444                 override public void Emit (EmitContext ec)
5445                 {
5446                         //
5447                         // Special case: length of single dimension array property is turned into ldlen
5448                         //
5449                         if ((getter == TypeManager.system_int_array_get_length) ||
5450                             (getter == TypeManager.int_array_get_length)){
5451                                 Type iet = instance_expr.Type;
5452
5453                                 //
5454                                 // System.Array.Length can be called, but the Type does not
5455                                 // support invoking GetArrayRank, so test for that case first
5456                                 //
5457                                 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
5458                                         instance_expr.Emit (ec);
5459                                         ec.ig.Emit (OpCodes.Ldlen);
5460                                         return;
5461                                 }
5462                         }
5463                         if (PropertyArgs == null)
5464                                 PropertyArgs = new ArrayList ();
5465                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, PropertyArgs, loc);
5466                 }
5467
5468                 //
5469                 // Implements the IAssignMethod interface for assignments
5470                 //
5471                 public void EmitAssign (EmitContext ec, Expression source)
5472                 {
5473                         Argument arg = new Argument (source, Argument.AType.Expression);
5474                         ArrayList args = new ArrayList ();
5475 //HERE
5476                         args.Add (arg);
5477                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, PropertyArgs,loc);
5478                 }
5479
5480                 override public void EmitStatement (EmitContext ec)
5481                 {
5482                         Emit (ec);
5483                         ec.ig.Emit (OpCodes.Pop);
5484                 }
5485         }
5486
5487         /// <summary>
5488         ///   Fully resolved expression that evaluates to an Event
5489         /// </summary>
5490         public class EventExpr : Expression, IMemberExpr {
5491                 public readonly EventInfo EventInfo;
5492                 public Expression instance_expr;
5493
5494                 bool is_static;
5495                 MethodInfo add_accessor, remove_accessor;
5496                 
5497                 public EventExpr (EventInfo ei, Location loc)
5498                 {
5499                         EventInfo = ei;
5500                         this.loc = loc;
5501                         eclass = ExprClass.EventAccess;
5502
5503                         add_accessor = TypeManager.GetAddMethod (ei);
5504                         remove_accessor = TypeManager.GetRemoveMethod (ei);
5505                         
5506                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
5507                                 is_static = true;
5508
5509                         if (EventInfo is MyEventBuilder)
5510                                 type = ((MyEventBuilder) EventInfo).EventType;
5511                         else
5512                                 type = EventInfo.EventHandlerType;
5513                 }
5514
5515                 public string Name {
5516                         get {
5517                                 return EventInfo.Name;
5518                         }
5519                 }
5520
5521                 public bool IsInstance {
5522                         get {
5523                                 return !is_static;
5524                         }
5525                 }
5526
5527                 public bool IsStatic {
5528                         get {
5529                                 return is_static;
5530                         }
5531                 }
5532
5533                 public Type DeclaringType {
5534                         get {
5535                                 return EventInfo.DeclaringType;
5536                         }
5537                 }
5538
5539                 public Expression InstanceExpression {
5540                         get {
5541                                 return instance_expr;
5542                         }
5543
5544                         set {
5545                                 instance_expr = value;
5546                         }
5547                 }
5548
5549                 Expression field_expr = null;
5550
5551                 public override Expression DoResolve (EmitContext ec)
5552                 {
5553                         if (instance_expr != null) {
5554                                 instance_expr = instance_expr.DoResolve (ec);
5555                                 if (instance_expr == null)
5556                                         return null;
5557                         }
5558
5559                         if (this.DeclaringType == ec.ContainerType)     {
5560                                 MemberInfo mi = GetFieldFromEvent (this);
5561                                 if (mi == null)
5562                                         return null;
5563                                 field_expr = ExprClassFromMemberInfo (ec, mi, loc);
5564                                 ((FieldExpr) field_expr).InstanceExpression = instance_expr;
5565                                 field_expr = field_expr.DoResolve (ec);
5566                                 if (field_expr == null)
5567                                         return null;
5568                         }
5569
5570                         return this;
5571                 }
5572
5573                 public override void Emit (EmitContext ec)
5574                 {
5575                         if (field_expr != null)
5576                                 field_expr.Emit (ec);
5577                 }
5578
5579                 public void EmitAddOrRemove (EmitContext ec, Expression source)
5580                 {
5581                         Expression handler = ((Binary) source).Right;
5582                         
5583                         Argument arg = new Argument (handler, Argument.AType.Expression);
5584                         ArrayList args = new ArrayList ();
5585                                 
5586                         args.Add (arg);
5587                         
5588                         if (((Binary) source).Oper == Binary.Operator.Addition)
5589                                 Invocation.EmitCall (
5590                                         ec, false, IsStatic, instance_expr, add_accessor, args, loc);
5591                         else
5592                                 Invocation.EmitCall (
5593                                         ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
5594                 }
5595         }
5596 }