2005-07-18 Satya Sudha K <ksathyasudha@novell.com>
[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.TypeToCoreType (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                 /// <summary>
2444                 ///   Attemptes to implicityly convert 'target' into 'type', using
2445                 ///   ConvertImplicit.  If there is no implicit conversion, then
2446                 ///   an error is signaled
2447                 /// </summary>
2448                 static public Expression ConvertImplicitRequired (EmitContext ec, Expression source,
2449                                                                   Type target_type, Location loc)
2450                 {
2451                         Expression e;
2452                         
2453                         e = ConvertImplicit (ec, source, target_type, loc);
2454
2455                         if (e != null)
2456                                 return e;
2457
2458
2459                         if (source is DoubleLiteral && target_type == TypeManager.float_type){
2460                                 Report.Error (664, loc,
2461                                               "Double literal cannot be implicitly converted to " +
2462                                               "float type, use F suffix to create a float literal");
2463                         }
2464
2465                         Error_CannotConvertImplicit (loc, source.Type, target_type);
2466
2467                         return null;
2468                 }
2469
2470                 /// <summary>
2471                 ///   Performs the explicit numeric conversions
2472                 /// </summary>
2473                 static Expression ConvertNumericExplicit (EmitContext ec, Expression expr, Type target_type, Location loc)
2474                 {
2475                         Type expr_type = expr.Type;
2476
2477                         //
2478                         // If we have an enumeration, extract the underlying type,
2479                         // use this during the comparison, but wrap around the original
2480                         // target_type
2481                         //
2482                         Type real_target_type = target_type;
2483
2484                         if (TypeManager.IsEnumType (real_target_type))
2485                                 real_target_type = TypeManager.EnumToUnderlying (real_target_type);
2486
2487                         if (StandardConversionExists (expr, real_target_type)){
2488                                 Expression ce = ConvertImplicitStandard (ec, expr, real_target_type, loc);
2489
2490                                 if (real_target_type != target_type)
2491                                         return new EmptyCast (ce, target_type);
2492                                 return ce;
2493                         }
2494                         
2495                         if (expr_type == TypeManager.sbyte_type){
2496                                 //
2497                                 // From sbyte to byte, ushort, uint, ulong, char
2498                                 //
2499                                 if (real_target_type == TypeManager.byte_type)
2500                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U1);
2501                                 if (real_target_type == TypeManager.ushort_type)
2502                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U2);
2503                                 if (real_target_type == TypeManager.uint32_type)
2504                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U4);
2505                                 if (real_target_type == TypeManager.uint64_type)
2506                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I1_U8);
2507                         } else if (expr_type == TypeManager.byte_type){
2508                                 //
2509                                 // From byte to sbyte and char
2510                                 //
2511                                 if (real_target_type == TypeManager.sbyte_type)
2512                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U1_I1);
2513                         } else if (expr_type == TypeManager.short_type){
2514                                 //
2515                                 // From short to sbyte, byte, ushort, uint, ulong, char
2516                                 //
2517                                 if (real_target_type == TypeManager.sbyte_type)
2518                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1);
2519                                 if (real_target_type == TypeManager.byte_type)
2520                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1);
2521                                 if (real_target_type == TypeManager.ushort_type)
2522                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U2);
2523                                 if (real_target_type == TypeManager.uint32_type)
2524                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U4);
2525                                 if (real_target_type == TypeManager.uint64_type)
2526                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U8);
2527                         } else if (expr_type == TypeManager.ushort_type){
2528                                 //
2529                                 // From ushort to sbyte, byte, short, char
2530                                 //
2531                                 if (real_target_type == TypeManager.sbyte_type)
2532                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I1);
2533                                 if (real_target_type == TypeManager.byte_type)
2534                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1);
2535                                 if (real_target_type == TypeManager.short_type)
2536                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_I2);
2537                         } else if (expr_type == TypeManager.int32_type){
2538                                 //
2539                                 // From int to sbyte, byte, short, ushort, uint, ulong, char
2540                                 //
2541                                 if (real_target_type == TypeManager.sbyte_type)
2542                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1);
2543                                 if (real_target_type == TypeManager.byte_type)
2544                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1);
2545                                 if (real_target_type == TypeManager.short_type)
2546                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2);
2547                                 if (real_target_type == TypeManager.ushort_type)
2548                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2);
2549                                 if (real_target_type == TypeManager.uint32_type)
2550                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U4);
2551                                 if (real_target_type == TypeManager.uint64_type)
2552                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U8);
2553                         } else if (expr_type == TypeManager.uint32_type){
2554                                 //
2555                                 // From uint to sbyte, byte, short, ushort, int, char
2556                                 //
2557                                 if (real_target_type == TypeManager.sbyte_type)
2558                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I1);
2559                                 if (real_target_type == TypeManager.byte_type)
2560                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1);
2561                                 if (real_target_type == TypeManager.short_type)
2562                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I2);
2563                                 if (real_target_type == TypeManager.ushort_type)
2564                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2);
2565                                 if (real_target_type == TypeManager.int32_type)
2566                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_I4);
2567                         } else if (expr_type == TypeManager.int64_type){
2568                                 //
2569                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
2570                                 //
2571                                 if (real_target_type == TypeManager.sbyte_type)
2572                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1);
2573                                 if (real_target_type == TypeManager.byte_type)
2574                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1);
2575                                 if (real_target_type == TypeManager.short_type)
2576                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2);
2577                                 if (real_target_type == TypeManager.ushort_type)
2578                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2);
2579                                 if (real_target_type == TypeManager.int32_type)
2580                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4);
2581                                 if (real_target_type == TypeManager.uint32_type)
2582                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4);
2583                                 if (real_target_type == TypeManager.uint64_type)
2584                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U8);
2585                         } else if (expr_type == TypeManager.uint64_type){
2586                                 //
2587                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
2588                                 //
2589                                 if (real_target_type == TypeManager.sbyte_type)
2590                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I1);
2591                                 if (real_target_type == TypeManager.byte_type)
2592                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1);
2593                                 if (real_target_type == TypeManager.short_type)
2594                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I2);
2595                                 if (real_target_type == TypeManager.ushort_type)
2596                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2);
2597                                 if (real_target_type == TypeManager.int32_type)
2598                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4);
2599                                 if (real_target_type == TypeManager.uint32_type)
2600                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U4);
2601                                 if (real_target_type == TypeManager.int64_type)
2602                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I8);
2603                         } else if (expr_type == TypeManager.float_type){
2604                                 //
2605                                 // From float to sbyte, byte, short,
2606                                 // ushort, int, uint, long, ulong, char
2607                                 // or decimal
2608                                 //
2609                                 Expression rounded_expr = RTConversionExpression(ec, "System.Math",".Round" , expr, loc);
2610                                 if (real_target_type == TypeManager.sbyte_type)
2611                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I1);
2612                                 if (real_target_type == TypeManager.byte_type)
2613                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U1);
2614                                 if (real_target_type == TypeManager.short_type)
2615                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I2);
2616                                 if (real_target_type == TypeManager.ushort_type)
2617                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U2);
2618                                 if (real_target_type == TypeManager.int32_type)
2619                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I4);
2620                                 if (real_target_type == TypeManager.uint32_type)
2621                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U4);
2622                                 if (real_target_type == TypeManager.int64_type)
2623                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8);
2624                                 if (real_target_type == TypeManager.uint64_type)
2625                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8);
2626                         } else if (expr_type == TypeManager.double_type){
2627                                 //
2628                                 // From double to byte, byte, short,
2629                                 // ushort, int, uint, long, ulong,
2630                                 // char, float or decimal
2631                                 //
2632                                 Expression rounded_expr = RTConversionExpression(ec, "System.Math",".Round" , expr, loc);
2633                                 if (real_target_type == TypeManager.sbyte_type)
2634                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I1);
2635                                 if (real_target_type == TypeManager.byte_type)
2636                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U1);
2637                                 if (real_target_type == TypeManager.short_type)
2638                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I2);
2639                                 if (real_target_type == TypeManager.ushort_type)
2640                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U2);
2641                                 if (real_target_type == TypeManager.int32_type)
2642                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I4);
2643                                 if (real_target_type == TypeManager.uint32_type)
2644                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U4);
2645                                 if (real_target_type == TypeManager.int64_type)
2646                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8);
2647                                 if (real_target_type == TypeManager.uint64_type)
2648                                         return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8);
2649                                 if (real_target_type == TypeManager.float_type)
2650                                         return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4);
2651                         } 
2652
2653                         // decimal is taken care of by the op_Explicit methods.
2654
2655                         return null;
2656                 }
2657
2658                 /// <summary>
2659                 ///  Returns whether an explicit reference conversion can be performed
2660                 ///  from source_type to target_type
2661                 /// </summary>
2662                 public static bool ExplicitReferenceConversionExists (Type source_type, Type target_type)
2663                 {
2664                         bool target_is_value_type = target_type.IsValueType;
2665                         
2666                         if (source_type == target_type)
2667                                 return true;
2668                         
2669                         //
2670                         // From object to any reference type
2671                         //
2672                         if (source_type == TypeManager.object_type && !target_is_value_type)
2673                                 return true;
2674                                         
2675                         //
2676                         // From any class S to any class-type T, provided S is a base class of T
2677                         //
2678                         if (target_type.IsSubclassOf (source_type))
2679                                 return true;
2680
2681                         //
2682                         // From any interface type S to any interface T provided S is not derived from T
2683                         //
2684                         if (source_type.IsInterface && target_type.IsInterface){
2685                                 if (!target_type.IsSubclassOf (source_type))
2686                                         return true;
2687                         }
2688                             
2689                         //
2690                         // From any class type S to any interface T, provided S is not sealed
2691                         // and provided S does not implement T.
2692                         //
2693                         if (target_type.IsInterface && !source_type.IsSealed &&
2694                             !TypeManager.ImplementsInterface (source_type, target_type))
2695                                 return true;
2696
2697                         //
2698                         // From any interface-type S to to any class type T, provided T is not
2699                         // sealed, or provided T implements S.
2700                         //
2701                         if (source_type.IsInterface &&
2702                             (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type)))
2703                                 return true;
2704                         
2705                         
2706                         // From an array type S with an element type Se to an array type T with an 
2707                         // element type Te provided all the following are true:
2708                         //     * S and T differe only in element type, in other words, S and T
2709                         //       have the same number of dimensions.
2710                         //     * Both Se and Te are reference types
2711                         //     * An explicit referenc conversions exist from Se to Te
2712                         //
2713                         if (source_type.IsArray && target_type.IsArray) {
2714                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
2715                                         
2716                                         Type source_element_type = source_type.GetElementType ();
2717                                         Type target_element_type = target_type.GetElementType ();
2718                                         
2719                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
2720                                                 if (ExplicitReferenceConversionExists (source_element_type,
2721                                                                                        target_element_type))
2722                                                         return true;
2723                                 }
2724                         }
2725                         
2726
2727                         // From System.Array to any array-type
2728                         if (source_type == TypeManager.array_type &&
2729                             target_type.IsArray){
2730                                 return true;
2731                         }
2732
2733                         //
2734                         // From System delegate to any delegate-type
2735                         //
2736                         if (source_type == TypeManager.delegate_type &&
2737                             target_type.IsSubclassOf (TypeManager.delegate_type))
2738                                 return true;
2739
2740                         //
2741                         // From ICloneable to Array or Delegate types
2742                         //
2743                         if (source_type == TypeManager.icloneable_type &&
2744                             (target_type == TypeManager.array_type ||
2745                              target_type == TypeManager.delegate_type))
2746                                 return true;
2747                         
2748                         return false;
2749                 }
2750
2751                 /// <summary>
2752                 ///   Implements Explicit Reference conversions
2753                 /// </summary>
2754                 static Expression ConvertReferenceExplicit (Expression source, Type target_type)
2755                 {
2756                         Type source_type = source.Type;
2757                         bool target_is_value_type = target_type.IsValueType;
2758
2759                         //
2760                         // From object to any reference type
2761                         //
2762                         if (source_type == TypeManager.object_type && !target_is_value_type)
2763                                 return new ClassCast (source, target_type);
2764
2765
2766                         //
2767                         // From any class S to any class-type T, provided S is a base class of T
2768                         //
2769                         if (target_type.IsSubclassOf (source_type))
2770                                 return new ClassCast (source, target_type);
2771
2772                         //
2773                         // From any interface type S to any interface T provided S is not derived from T
2774                         //
2775                         if (source_type.IsInterface && target_type.IsInterface){
2776                                 if (TypeManager.ImplementsInterface (source_type, target_type))
2777                                         return null;
2778                                 else
2779                                         return new ClassCast (source, target_type);
2780                         }
2781                             
2782                         //
2783                         // From any class type S to any interface T, provides S is not sealed
2784                         // and provided S does not implement T.
2785                         //
2786                         if (target_type.IsInterface && !source_type.IsSealed) {
2787                                 if (TypeManager.ImplementsInterface (source_type, target_type))
2788                                         return null;
2789                                 else
2790                                         return new ClassCast (source, target_type);
2791                                 
2792                         }
2793
2794                         //
2795                         // From any interface-type S to to any class type T, provided T is not
2796                         // sealed, or provided T implements S.
2797                         //
2798                         if (source_type.IsInterface) {
2799                                 if (!target_type.IsSealed || TypeManager.ImplementsInterface (target_type, source_type))
2800                                         return new ClassCast (source, target_type);
2801                                 else
2802                                         return null;
2803                         }
2804                         
2805                         // From an array type S with an element type Se to an array type T with an 
2806                         // element type Te provided all the following are true:
2807                         //     * S and T differe only in element type, in other words, S and T
2808                         //       have the same number of dimensions.
2809                         //     * Both Se and Te are reference types
2810                         //     * An explicit referenc conversions exist from Se to Te
2811                         //
2812                         if (source_type.IsArray && target_type.IsArray) {
2813                                 if (source_type.GetArrayRank () == target_type.GetArrayRank ()) {
2814                                         
2815                                         Type source_element_type = source_type.GetElementType ();
2816                                         Type target_element_type = target_type.GetElementType ();
2817                                         
2818                                         if (!source_element_type.IsValueType && !target_element_type.IsValueType)
2819                                                 if (ExplicitReferenceConversionExists (source_element_type,
2820                                                                                        target_element_type))
2821                                                         return new ClassCast (source, target_type);
2822                                 }
2823                         }
2824                         
2825
2826                         // From System.Array to any array-type
2827                         if (source_type == TypeManager.array_type &&
2828                             target_type.IsArray) {
2829                                 return new ClassCast (source, target_type);
2830                         }
2831
2832                         //
2833                         // From System delegate to any delegate-type
2834                         //
2835                         if (source_type == TypeManager.delegate_type &&
2836                             target_type.IsSubclassOf (TypeManager.delegate_type))
2837                                 return new ClassCast (source, target_type);
2838
2839                         //
2840                         // From ICloneable to Array or Delegate types
2841                         //
2842                         if (source_type == TypeManager.icloneable_type &&
2843                             (target_type == TypeManager.array_type ||
2844                              target_type == TypeManager.delegate_type))
2845                                 return new ClassCast (source, target_type);
2846                         
2847                         return null;
2848                 }
2849                 
2850                 /// <summary>
2851                 ///   Performs an explicit conversion of the expression 'expr' whose
2852                 ///   type is expr.Type to 'target_type'.
2853                 /// </summary>
2854                 static public Expression ConvertExplicit (EmitContext ec, Expression expr,
2855                                                           Type target_type, bool runtimeconv, Location loc)
2856                 {
2857                         Type expr_type = expr.Type;
2858                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, loc);
2859
2860                         if (ne != null)
2861                                 return ne;
2862
2863                         ne = ConvertNumericExplicit (ec, expr, target_type, loc);
2864                         if (ne != null)
2865                                 return ne;
2866
2867                         //
2868                         // Unboxing conversion.
2869                         //
2870                         if (expr_type == TypeManager.object_type && target_type.IsValueType)
2871                                 return new UnboxCast (expr, target_type);
2872
2873                         //
2874                         // Enum types
2875                         //
2876                         if (expr_type.IsSubclassOf (TypeManager.enum_type)) {
2877                                 Expression e;
2878
2879                                 //
2880                                 // FIXME: Is there any reason we should have EnumConstant
2881                                 // dealt with here instead of just using always the
2882                                 // UnderlyingSystemType to wrap the type?
2883                                 //
2884                                 if (expr is EnumConstant)
2885                                         e = ((EnumConstant) expr).Child;
2886                                 else {
2887                                         e = new EmptyCast (expr, TypeManager.EnumToUnderlying (expr_type));
2888                                 }
2889                                 
2890                                 Expression t = ConvertImplicit (ec, e, target_type, loc);
2891                                 if (t != null)
2892                                         return t;
2893                                 
2894                                 t = ConvertNumericExplicit (ec, e, target_type, loc);
2895                                 if (t != null)
2896                                         return t;
2897                                 
2898                                 t = NarrowingConversion (ec, e, target_type, loc);
2899                                 if (t != null)
2900                                         return t;       
2901                                                                 
2902                                 Error_CannotConvertType (loc, expr_type, target_type);
2903                                 return null;
2904                         }
2905                         
2906                         ne = ConvertReferenceExplicit (expr, target_type);
2907                         if (ne != null)
2908                                 return ne;
2909
2910                         if (ec.InUnsafe){
2911                                 if (target_type.IsPointer){
2912                                         if (expr_type.IsPointer)
2913                                                 return new EmptyCast (expr, target_type);
2914                                         
2915                                         if (expr_type == TypeManager.sbyte_type ||
2916                                             expr_type == TypeManager.byte_type ||
2917                                             expr_type == TypeManager.short_type ||
2918                                             expr_type == TypeManager.ushort_type ||
2919                                             expr_type == TypeManager.int32_type ||
2920                                             expr_type == TypeManager.uint32_type ||
2921                                             expr_type == TypeManager.uint64_type ||
2922                                             expr_type == TypeManager.int64_type)
2923                                                 return new OpcodeCast (expr, target_type, OpCodes.Conv_U);
2924                                 }
2925                                 if (expr_type.IsPointer){
2926                                         if (target_type == TypeManager.sbyte_type ||
2927                                             target_type == TypeManager.byte_type ||
2928                                             target_type == TypeManager.short_type ||
2929                                             target_type == TypeManager.ushort_type ||
2930                                             target_type == TypeManager.int32_type ||
2931                                             target_type == TypeManager.uint32_type ||
2932                                             target_type == TypeManager.uint64_type ||
2933                                             target_type == TypeManager.int64_type){
2934                                                 Expression e = new EmptyCast (expr, TypeManager.uint32_type);
2935                                                 Expression ci, ce;
2936
2937                                                 ci = ConvertImplicitStandard (ec, e, target_type, loc);
2938
2939                                                 if (ci != null)
2940                                                         return ci;
2941
2942                                                 ce = ConvertNumericExplicit (ec, e, target_type, loc);
2943                                                 if (ce != null)
2944                                                         return ce;
2945                                                 //
2946                                                 // We should always be able to go from an uint32
2947                                                 // implicitly or explicitly to the other integral
2948                                                 // types
2949                                                 //
2950                                                 throw new Exception ("Internal compiler error");
2951                                         }
2952                                 }
2953                         }
2954                         
2955                         ne = ExplicitUserConversion (ec, expr, target_type, loc);
2956                         if (ne != null)
2957                                 return ne;
2958
2959                         if (!(runtimeconv))     {
2960                                 ne = NarrowingConversion (ec, expr, target_type, loc);
2961                                 if (ne != null)
2962                                         return ne;
2963                                 
2964                                 Error_CannotConvertType (loc, expr_type, target_type);
2965                         }
2966                         return null;
2967                 }
2968
2969                 /// <summary>
2970                 ///   Same as ConvertExplicit, only it doesn't include user defined conversions
2971                 /// </summary>
2972                 static public Expression ConvertExplicitStandard (EmitContext ec, Expression expr,
2973                                                                   Type target_type, Location l)
2974                 {
2975                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, l);
2976
2977                         if (ne != null)
2978                                 return ne;
2979
2980                         ne = ConvertNumericExplicit (ec, expr, target_type, l);
2981                         if (ne != null)
2982                                 return ne;
2983
2984                         ne = ConvertReferenceExplicit (expr, target_type);
2985                         if (ne != null)
2986                                 return ne;
2987
2988                         ne = NarrowingConversion (ec, expr, target_type, l);
2989                         if (ne != null)
2990                                 return ne;                              
2991
2992                         Error_CannotConvertType (l, expr.Type, target_type);
2993                         return null;
2994                 }
2995
2996                 static string ExprClassName (ExprClass c)
2997                 {
2998                         switch (c){
2999                         case ExprClass.Invalid:
3000                                 return "Invalid";
3001                         case ExprClass.Value:
3002                                 return "value";
3003                         case ExprClass.Variable:
3004                                 return "variable";
3005                         case ExprClass.Namespace:
3006                                 return "namespace";
3007                         case ExprClass.Type:
3008                                 return "type";
3009                         case ExprClass.MethodGroup:
3010                                 return "method group";
3011                         case ExprClass.PropertyAccess:
3012                                 return "property access";
3013                         case ExprClass.EventAccess:
3014                                 return "event access";
3015                         case ExprClass.IndexerAccess:
3016                                 return "indexer access";
3017                         case ExprClass.Nothing:
3018                                 return "null";
3019                         }
3020                         throw new Exception ("Should not happen");
3021                 }
3022                 
3023                 /// <summary>
3024                 ///   Reports that we were expecting 'expr' to be of class 'expected'
3025                 /// </summary>
3026                 public void Error118 (string expected)
3027                 {
3028                         string kind = "Unknown";
3029                         
3030                         kind = ExprClassName (eclass);
3031
3032                         Error (118, "Expression denotes a '" + kind +
3033                                "' where a '" + expected + "' was expected");
3034                 }
3035
3036                 public void Error118 (ResolveFlags flags)
3037                 {
3038                         ArrayList valid = new ArrayList (10);
3039
3040                         if ((flags & ResolveFlags.VariableOrValue) != 0) {
3041                                 valid.Add ("variable");
3042                                 valid.Add ("value");
3043                         }
3044
3045                         if ((flags & ResolveFlags.Type) != 0)
3046                                 valid.Add ("type");
3047
3048                         if ((flags & ResolveFlags.MethodGroup) != 0)
3049                                 valid.Add ("method group");
3050
3051                         if ((flags & ResolveFlags.SimpleName) != 0)
3052                                 valid.Add ("simple name");
3053
3054                         if (valid.Count == 0)
3055                                 valid.Add ("unknown");
3056
3057                         StringBuilder sb = new StringBuilder ();
3058                         for (int i = 0; i < valid.Count; i++) {
3059                                 if (i > 0)
3060                                         sb.Append (", ");
3061                                 else if (i == valid.Count)
3062                                         sb.Append (" or ");
3063                                 sb.Append (valid [i]);
3064                         }
3065
3066                         string kind = ExprClassName (eclass);
3067
3068                         Error (119, "Expression denotes a '" + kind + "' where " +
3069                                "a '" + sb.ToString () + "' was expected");
3070                 }
3071                 
3072                 static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t)
3073                 {
3074                         Report.Error (30439, l, "Constant value '" + val + "' not representable in type " +
3075                                       TypeManager.MonoBASIC_Name (t));
3076                 }
3077
3078                 public static void UnsafeError (Location loc)
3079                 {
3080                         Report.Error (214, loc, "Pointers may only be used in an unsafe context");
3081                 }
3082                 
3083                 /// <summary>
3084                 ///   Converts the IntConstant, UIntConstant, LongConstant or
3085                 ///   ULongConstant,Double into the integral target_type.   Notice
3086                 ///   that we do not return an 'Expression' we do return
3087                 ///   a boxed integral type.
3088                 ///
3089                 ///   FIXME: Since I added the new constants, we need to
3090                 ///   also support conversions from CharConstant, ByteConstant,
3091                 ///   SByteConstant, UShortConstant, ShortConstant
3092                 ///
3093                 ///   This is used by the switch statement, so the domain
3094                 ///   of work is restricted to the literals above, and the
3095                 ///   targets are int32, uint32, char, byte, sbyte, ushort,
3096                 ///   short, uint64 and int64
3097                 /// </summary>
3098                 public static object ConvertIntLiteral (Constant c, Type target_type, Location loc)
3099                 {
3100                         string s = "";
3101
3102                         if (c.Type == target_type)
3103                                 return ((Constant) c).GetValue ();
3104
3105                         //
3106                         // Make into one of the literals we handle, we dont really care
3107                         // about this value as we will just return a few limited types
3108                         // 
3109                         if (c is EnumConstant)
3110                                 c = ((EnumConstant)c).WidenToCompilerConstant ();
3111
3112                         if (c is IntConstant){
3113                                 int v = ((IntConstant) c).Value;
3114                                 
3115                                 if (target_type == TypeManager.uint32_type){
3116                                         if (v >= 0)
3117                                                 return (uint) v;
3118                                 } else if (target_type == TypeManager.byte_type){
3119                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3120                                                 return (byte) v;
3121                                 } else if (target_type == TypeManager.sbyte_type){
3122                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3123                                                 return (sbyte) v;
3124                                 } else if (target_type == TypeManager.short_type){
3125                                         if (v >= Int16.MinValue && v <= UInt16.MaxValue)
3126                                                 return (short) v;
3127                                 } else if (target_type == TypeManager.ushort_type){
3128                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
3129                                                 return (ushort) v;
3130                                 } else if (target_type == TypeManager.int64_type)
3131                                         return (long) v;
3132                                 else if (target_type == TypeManager.uint64_type){
3133                                         if (v > 0)
3134                                                 return (ulong) v;
3135                                 }
3136
3137                                 s = v.ToString ();
3138                         } else if (c is UIntConstant){
3139                                 uint v = ((UIntConstant) c).Value;
3140
3141                                 if (target_type == TypeManager.int32_type){
3142                                         if (v <= Int32.MaxValue)
3143                                                 return (int) v;
3144                                 } else if (target_type == TypeManager.byte_type){
3145                                         if (v <= Byte.MaxValue)
3146                                                 return (byte) v;
3147                                 } else if (target_type == TypeManager.sbyte_type){
3148                                         if (v <= SByte.MaxValue)
3149                                                 return (sbyte) v;
3150                                 } else if (target_type == TypeManager.short_type){
3151                                         if (v <= UInt16.MaxValue)
3152                                                 return (short) v;
3153                                 } else if (target_type == TypeManager.ushort_type){
3154                                         if (v <= UInt16.MaxValue)
3155                                                 return (ushort) v;
3156                                 } else if (target_type == TypeManager.int64_type)
3157                                         return (long) v;
3158                                 else if (target_type == TypeManager.uint64_type)
3159                                         return (ulong) v;
3160                                 s = v.ToString ();
3161                         } else if (c is LongConstant){ 
3162                                 long v = ((LongConstant) c).Value;
3163
3164                                 if (target_type == TypeManager.int32_type){
3165                                         if (v >= UInt32.MinValue && v <= UInt32.MaxValue)
3166                                                 return (int) v;
3167                                 } else if (target_type == TypeManager.uint32_type){
3168                                         if (v >= 0 && v <= UInt32.MaxValue)
3169                                                 return (uint) v;
3170                                 } else if (target_type == TypeManager.byte_type){
3171                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3172                                                 return (byte) v;
3173                                 } else if (target_type == TypeManager.sbyte_type){
3174                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3175                                                 return (sbyte) v;
3176                                 } else if (target_type == TypeManager.short_type){
3177                                         if (v >= Int16.MinValue && v <= UInt16.MaxValue)
3178                                                 return (short) v;
3179                                 } else if (target_type == TypeManager.ushort_type){
3180                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
3181                                                 return (ushort) v;
3182                                 } else if (target_type == TypeManager.uint64_type){
3183                                         if (v > 0)
3184                                                 return (ulong) v;
3185                                 }
3186                                 s = v.ToString ();
3187                         } else if (c is ULongConstant){
3188                                 ulong v = ((ULongConstant) c).Value;
3189
3190                                 if (target_type == TypeManager.int32_type){
3191                                         if (v <= Int32.MaxValue)
3192                                                 return (int) v;
3193                                 } else if (target_type == TypeManager.uint32_type){
3194                                         if (v <= UInt32.MaxValue)
3195                                                 return (uint) v;
3196                                 } else if (target_type == TypeManager.byte_type){
3197                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3198                                                 return (byte) v;
3199                                 } else if (target_type == TypeManager.sbyte_type){
3200                                         if (v <= (int) SByte.MaxValue)
3201                                                 return (sbyte) v;
3202                                 } else if (target_type == TypeManager.short_type){
3203                                         if (v <= UInt16.MaxValue)
3204                                                 return (short) v;
3205                                 } else if (target_type == TypeManager.ushort_type){
3206                                         if (v <= UInt16.MaxValue)
3207                                                 return (ushort) v;
3208                                 } else if (target_type == TypeManager.int64_type){
3209                                         if (v <= Int64.MaxValue)
3210                                                 return (long) v;
3211                                 }
3212                                 s = v.ToString ();
3213                         } else if (c is ByteConstant){
3214                                 byte v = ((ByteConstant) c).Value;
3215                                 
3216                                 if (target_type == TypeManager.int32_type)
3217                                         return (int) v;
3218                                 else if (target_type == TypeManager.uint32_type)
3219                                         return (uint) v;
3220                                 else if (target_type == TypeManager.sbyte_type){
3221                                         if (v <= SByte.MaxValue)
3222                                                 return (sbyte) v;
3223                                 } else if (target_type == TypeManager.short_type)
3224                                         return (short) v;
3225                                 else if (target_type == TypeManager.ushort_type)
3226                                         return (ushort) v;
3227                                 else if (target_type == TypeManager.int64_type)
3228                                         return (long) v;
3229                                 else if (target_type == TypeManager.uint64_type)
3230                                         return (ulong) v;
3231                                 s = v.ToString ();
3232                         } else if (c is SByteConstant){
3233                                 sbyte v = ((SByteConstant) c).Value;
3234                                 
3235                                 if (target_type == TypeManager.int32_type)
3236                                         return (int) v;
3237                                 else if (target_type == TypeManager.uint32_type){
3238                                         if (v >= 0)
3239                                                 return (uint) v;
3240                                 } else if (target_type == TypeManager.byte_type){
3241                                         if (v >= 0)
3242                                                 return (byte) v;
3243                                 } else if (target_type == TypeManager.short_type)
3244                                         return (short) v;
3245                                 else if (target_type == TypeManager.ushort_type){
3246                                         if (v >= 0)
3247                                                 return (ushort) v;
3248                                 } else if (target_type == TypeManager.int64_type)
3249                                         return (long) v;
3250                                 else if (target_type == TypeManager.uint64_type){
3251                                         if (v >= 0)
3252                                                 return (ulong) v;
3253                                 }
3254                                 s = v.ToString ();
3255                         } else if (c is ShortConstant){
3256                                 short v = ((ShortConstant) c).Value;
3257                                 
3258                                 if (target_type == TypeManager.int32_type){
3259                                         return (int) v;
3260                                 } else if (target_type == TypeManager.uint32_type){
3261                                         if (v >= 0)
3262                                                 return (uint) v;
3263                                 } else if (target_type == TypeManager.byte_type){
3264                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3265                                                 return (byte) v;
3266                                 } else if (target_type == TypeManager.sbyte_type){
3267                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3268                                                 return (sbyte) v;
3269                                 } else if (target_type == TypeManager.ushort_type){
3270                                         if (v >= 0)
3271                                                 return (ushort) v;
3272                                 } else if (target_type == TypeManager.int64_type)
3273                                         return (long) v;
3274                                 else if (target_type == TypeManager.uint64_type)
3275                                         return (ulong) v;
3276
3277                                 s = v.ToString ();
3278                         } else if (c is UShortConstant){
3279                                 ushort v = ((UShortConstant) c).Value;
3280                                 
3281                                 if (target_type == TypeManager.int32_type)
3282                                         return (int) v;
3283                                 else if (target_type == TypeManager.uint32_type)
3284                                         return (uint) v;
3285                                 else if (target_type == TypeManager.byte_type){
3286                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3287                                                 return (byte) v;
3288                                 } else if (target_type == TypeManager.sbyte_type){
3289                                         if (v <= SByte.MaxValue)
3290                                                 return (byte) v;
3291                                 } else if (target_type == TypeManager.short_type){
3292                                         if (v <= Int16.MaxValue)
3293                                                 return (short) v;
3294                                 } else if (target_type == TypeManager.int64_type)
3295                                         return (long) v;
3296                                 else if (target_type == TypeManager.uint64_type)
3297                                         return (ulong) v;
3298
3299                                 s = v.ToString ();
3300                         } else if (c is CharConstant){
3301                                 char v = ((CharConstant) c).Value;
3302                                 
3303                                 if (target_type == TypeManager.int32_type)
3304                                         return (int) v;
3305                                 else if (target_type == TypeManager.uint32_type)
3306                                         return (uint) v;
3307                                 else if (target_type == TypeManager.byte_type){
3308                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3309                                                 return (byte) v;
3310                                 } else if (target_type == TypeManager.sbyte_type){
3311                                         if (v <= SByte.MaxValue)
3312                                                 return (sbyte) v;
3313                                 } else if (target_type == TypeManager.short_type){
3314                                         if (v <= Int16.MaxValue)
3315                                                 return (short) v;
3316                                 } else if (target_type == TypeManager.ushort_type)
3317                                         return (short) v;
3318                                 else if (target_type == TypeManager.int64_type)
3319                                         return (long) v;
3320                                 else if (target_type == TypeManager.uint64_type)
3321                                         return (ulong) v;
3322
3323                                 s = v.ToString ();
3324
3325                          } else if (c is DoubleConstant){
3326                                 double v = ((DoubleConstant) c).Value;
3327
3328                                 if (target_type == TypeManager.sbyte_type){
3329                                         if (v >= SByte.MinValue && v <= SByte.MaxValue)
3330                                                 return new SByteConstant ((sbyte) System.Math.Round (v));
3331                                 } else if (target_type == TypeManager.byte_type){
3332                                         if (v >= Byte.MinValue && v <= Byte.MaxValue)
3333                                                 return new ByteConstant ((byte) System.Math.Round (v));
3334                                 } else if (target_type == TypeManager.short_type){
3335                                         if (v >= Int16.MinValue && v <= Int16.MaxValue)
3336                                                 return new ShortConstant ((short) System.Math.Round (v));
3337                                 } else if (target_type == TypeManager.ushort_type){
3338                                         if (v >= UInt16.MinValue && v <= UInt16.MaxValue)
3339                                                  return new UShortConstant ((ushort) System.Math.Round (v));
3340                                 } else if (target_type == TypeManager.int32_type){
3341                                         if (v >= Int32.MinValue && v <= Int32.MaxValue)
3342                                                 return new IntConstant ((int) System.Math.Round (v));
3343                                 } else if (target_type == TypeManager.uint32_type){
3344                                         if (v >= 0 && v <= UInt32.MaxValue)
3345                                                 return new UIntConstant ((uint) System.Math.Round (v));
3346                                 } else if (target_type == TypeManager.uint64_type){
3347                                         if (v > 0)
3348                                                 return new ULongConstant ((ulong) System.Math.Round (v));
3349                                 }
3350                                 s = v.ToString ();
3351                         }
3352
3353                         Error_ConstantValueCannotBeConverted (loc, s, target_type);
3354                         return null;
3355                 }
3356
3357                 //
3358                 // Load the object from the pointer.  
3359                 //
3360                 public static void LoadFromPtr (ILGenerator ig, Type t)
3361                 {
3362                         if (t == TypeManager.int32_type)
3363                                 ig.Emit (OpCodes.Ldind_I4);
3364                         else if (t == TypeManager.uint32_type)
3365                                 ig.Emit (OpCodes.Ldind_U4);
3366                         else if (t == TypeManager.short_type)
3367                                 ig.Emit (OpCodes.Ldind_I2);
3368                         else if (t == TypeManager.ushort_type)
3369                                 ig.Emit (OpCodes.Ldind_U2);
3370                         else if (t == TypeManager.char_type)
3371                                 ig.Emit (OpCodes.Ldind_U2);
3372                         else if (t == TypeManager.byte_type)
3373                                 ig.Emit (OpCodes.Ldind_U1);
3374                         else if (t == TypeManager.sbyte_type)
3375                                 ig.Emit (OpCodes.Ldind_I1);
3376                         else if (t == TypeManager.uint64_type)
3377                                 ig.Emit (OpCodes.Ldind_I8);
3378                         else if (t == TypeManager.int64_type)
3379                                 ig.Emit (OpCodes.Ldind_I8);
3380                         else if (t == TypeManager.float_type)
3381                                 ig.Emit (OpCodes.Ldind_R4);
3382                         else if (t == TypeManager.double_type)
3383                                 ig.Emit (OpCodes.Ldind_R8);
3384                         else if (t == TypeManager.bool_type)
3385                                 ig.Emit (OpCodes.Ldind_I1);
3386                         else if (t == TypeManager.intptr_type)
3387                                 ig.Emit (OpCodes.Ldind_I);
3388                         else if (TypeManager.IsEnumType (t)) {
3389                                 if (t == TypeManager.enum_type)
3390                                         ig.Emit (OpCodes.Ldind_Ref);
3391                                 else
3392                                         LoadFromPtr (ig, TypeManager.EnumToUnderlying (t));
3393                         } else if (t.IsValueType)
3394                                 ig.Emit (OpCodes.Ldobj, t);
3395                         else
3396                                 ig.Emit (OpCodes.Ldind_Ref);
3397                 }
3398
3399                 //
3400                 // The stack contains the pointer and the value of type 'type'
3401                 //
3402                 public static void StoreFromPtr (ILGenerator ig, Type type)
3403                 {
3404                         if (TypeManager.IsEnumType (type))
3405                                 type = TypeManager.EnumToUnderlying (type);
3406                         if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
3407                                 ig.Emit (OpCodes.Stind_I4);
3408                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
3409                                 ig.Emit (OpCodes.Stind_I8);
3410                         else if (type == TypeManager.char_type || type == TypeManager.short_type ||
3411                                  type == TypeManager.ushort_type)
3412                                 ig.Emit (OpCodes.Stind_I2);
3413                         else if (type == TypeManager.float_type)
3414                                 ig.Emit (OpCodes.Stind_R4);
3415                         else if (type == TypeManager.double_type)
3416                                 ig.Emit (OpCodes.Stind_R8);
3417                         else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type ||
3418                                  type == TypeManager.bool_type)
3419                                 ig.Emit (OpCodes.Stind_I1);
3420                         else if (type == TypeManager.intptr_type)
3421                                 ig.Emit (OpCodes.Stind_I);
3422                         else if (type.IsValueType)
3423                                 ig.Emit (OpCodes.Stobj, type);
3424                         else
3425                                 ig.Emit (OpCodes.Stind_Ref);
3426                 }
3427                 
3428                 //
3429                 // Returns the size of type 't' if known, otherwise, 0
3430                 //
3431                 public static int GetTypeSize (Type t)
3432                 {
3433                         t = TypeManager.TypeToCoreType (t);
3434                         if (t == TypeManager.int32_type ||
3435                             t == TypeManager.uint32_type ||
3436                             t == TypeManager.float_type)
3437                                 return 4;
3438                         else if (t == TypeManager.int64_type ||
3439                                  t == TypeManager.uint64_type ||
3440                                  t == TypeManager.double_type)
3441                                 return 8;
3442                         else if (t == TypeManager.byte_type ||
3443                                  t == TypeManager.sbyte_type ||
3444                                  t == TypeManager.bool_type)    
3445                                 return 1;
3446                         else if (t == TypeManager.short_type ||
3447                                  t == TypeManager.char_type ||
3448                                  t == TypeManager.ushort_type)
3449                                 return 2;
3450                         else if (t == TypeManager.decimal_type)
3451                                 return 16;
3452                         else
3453                                 return 0;
3454                 }
3455
3456                 //
3457                 // Default implementation of IAssignMethod.CacheTemporaries
3458                 //
3459                 public void CacheTemporaries (EmitContext ec)
3460                 {
3461                 }
3462
3463                 static void Error_NegativeArrayIndex (Location loc)
3464                 {
3465                         Report.Error (284, loc, "Can not create array with a negative size");
3466                 }
3467                 
3468                 //
3469                 // Converts 'source' to an int, uint, long or ulong.
3470                 //
3471                 public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc)
3472                 {
3473                         Expression target;
3474                         
3475                         bool old_checked = ec.CheckState;
3476                         ec.CheckState = true;
3477                         
3478                         target = ConvertImplicit (ec, source, TypeManager.int32_type, loc);
3479                         if (target == null){
3480                                 target = ConvertImplicit (ec, source, TypeManager.uint32_type, loc);
3481                                 if (target == null){
3482                                         target = ConvertImplicit (ec, source, TypeManager.int64_type, loc);
3483                                         if (target == null){
3484                                                 target = ConvertImplicit (ec, source, TypeManager.uint64_type, loc);
3485                                                 if (target == null)
3486                                                         Expression.Error_CannotConvertImplicit (loc, source.Type, TypeManager.int32_type);
3487                                         }
3488                                 }
3489                         } 
3490                         ec.CheckState = old_checked;
3491
3492                         //
3493                         // Only positive constants are allowed at compile time
3494                         //
3495                         if (target is Constant){
3496                                 if (target is IntConstant){
3497                                         if (((IntConstant) target).Value < 0){
3498                                                 Error_NegativeArrayIndex (loc);
3499                                                 return null;
3500                                         }
3501                                 }
3502
3503                                 if (target is LongConstant){
3504                                         if (((LongConstant) target).Value < 0){
3505                                                 Error_NegativeArrayIndex (loc);
3506                                                 return null;
3507                                         }
3508                                 }
3509                                 
3510                         }
3511
3512                         return target;
3513                 }
3514                 
3515         }
3516
3517         /// <summary>
3518         ///   This is just a base class for expressions that can
3519         ///   appear on statements (invocations, object creation,
3520         ///   assignments, post/pre increment and decrement).  The idea
3521         ///   being that they would support an extra Emition interface that
3522         ///   does not leave a result on the stack.
3523         /// </summary>
3524         public abstract class ExpressionStatement : Expression {
3525
3526                 /// <summary>
3527                 ///   Requests the expression to be emitted in a 'statement'
3528                 ///   context.  This means that no new value is left on the
3529                 ///   stack after invoking this method (constrasted with
3530                 ///   Emit that will always leave a value on the stack).
3531                 /// </summary>
3532                 public abstract void EmitStatement (EmitContext ec);
3533         }
3534
3535         /// <summary>
3536         ///   This kind of cast is used to encapsulate the child
3537         ///   whose type is child.Type into an expression that is
3538         ///   reported to return "return_type".  This is used to encapsulate
3539         ///   expressions which have compatible types, but need to be dealt
3540         ///   at higher levels with.
3541         ///
3542         ///   For example, a "byte" expression could be encapsulated in one
3543         ///   of these as an "unsigned int".  The type for the expression
3544         ///   would be "unsigned int".
3545         ///
3546         /// </summary>
3547         public class EmptyCast : Expression {
3548                 protected Expression child;
3549
3550                 public EmptyCast (Expression child, Type return_type)
3551                 {
3552                         eclass = child.eclass;
3553                         type = return_type;
3554                         this.child = child;
3555                 }
3556
3557                 public override Expression DoResolve (EmitContext ec)
3558                 {
3559                         // This should never be invoked, we are born in fully
3560                         // initialized state.
3561
3562                         return this;
3563                 }
3564
3565                 public override void Emit (EmitContext ec)
3566                 {
3567                         child.Emit (ec);
3568                 }
3569         }
3570
3571         /// <summary>
3572         ///  This class is used to wrap literals which belong inside Enums
3573         /// </summary>
3574         public class EnumConstant : Constant {
3575                 public Constant Child;
3576
3577                 public EnumConstant (Constant child, Type enum_type)
3578                 {
3579                         eclass = child.eclass;
3580                         this.Child = child;
3581                         type = enum_type;
3582                 }
3583                 
3584                 public override Expression DoResolve (EmitContext ec)
3585                 {
3586                         // This should never be invoked, we are born in fully
3587                         // initialized state.
3588
3589                         return this;
3590                 }
3591
3592                 public override void Emit (EmitContext ec)
3593                 {
3594                         Child.Emit (ec);
3595                 }
3596
3597                 public override object GetValue ()
3598                 {
3599                         return Child.GetValue ();
3600                 }
3601
3602                 //
3603                 // Converts from one of the valid underlying types for an enumeration
3604                 // (int32, uint32, int64, uint64, short, ushort, byte, sbyte) to
3605                 // one of the internal compiler literals: Int/UInt/Long/ULong Literals.
3606                 //
3607                 public Constant WidenToCompilerConstant ()
3608                 {
3609                         Type t = TypeManager.EnumToUnderlying (Child.Type);
3610                         object v = ((Constant) Child).GetValue ();;
3611                         
3612                         if (t == TypeManager.int32_type)
3613                                 return new IntConstant ((int) v);
3614                         if (t == TypeManager.uint32_type)
3615                                 return new UIntConstant ((uint) v);
3616                         if (t == TypeManager.int64_type)
3617                                 return new LongConstant ((long) v);
3618                         if (t == TypeManager.uint64_type)
3619                                 return new ULongConstant ((ulong) v);
3620                         if (t == TypeManager.short_type)
3621                                 return new ShortConstant ((short) v);
3622                         if (t == TypeManager.ushort_type)
3623                                 return new UShortConstant ((ushort) v);
3624                         if (t == TypeManager.byte_type)
3625                                 return new ByteConstant ((byte) v);
3626                         if (t == TypeManager.sbyte_type)
3627                                 return new SByteConstant ((sbyte) v);
3628
3629                         throw new Exception ("Invalid enumeration underlying type: " + t);
3630                 }
3631
3632                 //
3633                 // Extracts the value in the enumeration on its native representation
3634                 //
3635                 public object GetPlainValue ()
3636                 {
3637                         Type t = TypeManager.EnumToUnderlying (Child.Type);
3638                         object v = ((Constant) Child).GetValue ();;
3639                         
3640                         if (t == TypeManager.int32_type)
3641                                 return (int) v;
3642                         if (t == TypeManager.uint32_type)
3643                                 return (uint) v;
3644                         if (t == TypeManager.int64_type)
3645                                 return (long) v;
3646                         if (t == TypeManager.uint64_type)
3647                                 return (ulong) v;
3648                         if (t == TypeManager.short_type)
3649                                 return (short) v;
3650                         if (t == TypeManager.ushort_type)
3651                                 return (ushort) v;
3652                         if (t == TypeManager.byte_type)
3653                                 return (byte) v;
3654                         if (t == TypeManager.sbyte_type)
3655                                 return (sbyte) v;
3656
3657                         return null;
3658                 }
3659                 
3660                 public override string AsString ()
3661                 {
3662                         return Child.AsString ();
3663                 }
3664
3665                 public override DoubleConstant ConvertToDouble ()
3666                 {
3667                         return Child.ConvertToDouble ();
3668                 }
3669
3670                 public override FloatConstant ConvertToFloat ()
3671                 {
3672                         return Child.ConvertToFloat ();
3673                 }
3674
3675                 public override ULongConstant ConvertToULong ()
3676                 {
3677                         return Child.ConvertToULong ();
3678                 }
3679
3680                 public override LongConstant ConvertToLong ()
3681                 {
3682                         return Child.ConvertToLong ();
3683                 }
3684
3685                 public override UIntConstant ConvertToUInt ()
3686                 {
3687                         return Child.ConvertToUInt ();
3688                 }
3689
3690                 public override IntConstant ConvertToInt ()
3691                 {
3692                         return Child.ConvertToInt ();
3693                 }
3694         }
3695
3696         /// <summary>
3697         ///   This kind of cast is used to encapsulate Value Types in objects.
3698         ///
3699         ///   The effect of it is to box the value type emitted by the previous
3700         ///   operation.
3701         /// </summary>
3702         public class BoxedCast : EmptyCast {
3703
3704                 public BoxedCast (Expression expr)
3705                         : base (expr, TypeManager.object_type)
3706                 {
3707                 }
3708
3709                 public override Expression DoResolve (EmitContext ec)
3710                 {
3711                         // This should never be invoked, we are born in fully
3712                         // initialized state.
3713
3714                         return this;
3715                 }
3716
3717                 public override void Emit (EmitContext ec)
3718                 {
3719                         base.Emit (ec);
3720                         
3721                         ec.ig.Emit (OpCodes.Box, child.Type);
3722                 }
3723         }
3724
3725         public class UnboxCast : EmptyCast {
3726                 public UnboxCast (Expression expr, Type return_type)
3727                         : base (expr, return_type)
3728                 {
3729                 }
3730
3731                 public override Expression DoResolve (EmitContext ec)
3732                 {
3733                         // This should never be invoked, we are born in fully
3734                         // initialized state.
3735
3736                         return this;
3737                 }
3738
3739                 public override void Emit (EmitContext ec)
3740                 {
3741                         Type t = type;
3742                         ILGenerator ig = ec.ig;
3743                         
3744                         base.Emit (ec);
3745                         ig.Emit (OpCodes.Unbox, t);
3746
3747                         LoadFromPtr (ig, t);
3748                 }
3749         }
3750         
3751         /// <summary>
3752         ///   This is used to perform explicit numeric conversions.
3753         ///
3754         ///   Explicit numeric conversions might trigger exceptions in a checked
3755         ///   context, so they should generate the conv.ovf opcodes instead of
3756         ///   conv opcodes.
3757         /// </summary>
3758         public class ConvCast : EmptyCast {
3759                 public enum Mode : byte {
3760                         I1_U1, I1_U2, I1_U4, I1_U8, I1_CH,
3761                         U1_I1, U1_CH,
3762                         I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH,
3763                         U2_I1, U2_U1, U2_I2, U2_CH,
3764                         I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH,
3765                         U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH,
3766                         I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH,
3767                         U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH,
3768                         CH_I1, CH_U1, CH_I2,
3769                         R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH,
3770                         R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4
3771                 }
3772
3773                 Mode mode;
3774                 bool checked_state;
3775                 
3776                 public ConvCast (EmitContext ec, Expression child, Type return_type, Mode m)
3777                         : base (child, return_type)
3778                 {
3779                         checked_state = ec.CheckState;
3780                         mode = m;
3781                 }
3782
3783                 public override Expression DoResolve (EmitContext ec)
3784                 {
3785                         // This should never be invoked, we are born in fully
3786                         // initialized state.
3787
3788                         return this;
3789                 }
3790
3791                 public override void Emit (EmitContext ec)
3792                 {
3793                         ILGenerator ig = ec.ig;
3794                         
3795                         base.Emit (ec);
3796
3797                         if (checked_state){
3798                                 switch (mode){
3799                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3800                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3801                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3802                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3803                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3804
3805                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3806                                 case Mode.U1_CH: /* nothing */ break;
3807
3808                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3809                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3810                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3811                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3812                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3813                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3814
3815                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3816                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3817                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3818                                 case Mode.U2_CH: /* nothing */ break;
3819
3820                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3821                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3822                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3823                                 case Mode.I4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3824                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3825                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3826                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3827
3828                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3829                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3830                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3831                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3832                                 case Mode.U4_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
3833                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3834
3835                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3836                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3837                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3838                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3839                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
3840                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3841                                 case Mode.I8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3842                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3843
3844                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3845                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3846                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3847                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3848                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_Ovf_I4_Un); break;
3849                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_Ovf_U4_Un); break;
3850                                 case Mode.U8_I8: ig.Emit (OpCodes.Conv_Ovf_I8_Un); break;
3851                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_Ovf_U2_Un); break;
3852
3853                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_Ovf_I1_Un); break;
3854                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_Ovf_U1_Un); break;
3855                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_Ovf_I2_Un); break;
3856
3857                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3858                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3859                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3860                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3861                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
3862                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3863                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
3864                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3865                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3866
3867                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_Ovf_I1); break;
3868                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_Ovf_U1); break;
3869                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_Ovf_I2); break;
3870                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3871                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_Ovf_I4); break;
3872                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_Ovf_U4); break;
3873                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_Ovf_I8); break;
3874                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_Ovf_U8); break;
3875                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_Ovf_U2); break;
3876                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
3877                                 }
3878                         } else {
3879                                 switch (mode){
3880                                 case Mode.I1_U1: ig.Emit (OpCodes.Conv_U1); break;
3881                                 case Mode.I1_U2: ig.Emit (OpCodes.Conv_U2); break;
3882                                 case Mode.I1_U4: ig.Emit (OpCodes.Conv_U4); break;
3883                                 case Mode.I1_U8: ig.Emit (OpCodes.Conv_I8); break;
3884                                 case Mode.I1_CH: ig.Emit (OpCodes.Conv_U2); break;
3885
3886                                 case Mode.U1_I1: ig.Emit (OpCodes.Conv_I1); break;
3887                                 case Mode.U1_CH: ig.Emit (OpCodes.Conv_U2); break;
3888
3889                                 case Mode.I2_I1: ig.Emit (OpCodes.Conv_I1); break;
3890                                 case Mode.I2_U1: ig.Emit (OpCodes.Conv_U1); break;
3891                                 case Mode.I2_U2: ig.Emit (OpCodes.Conv_U2); break;
3892                                 case Mode.I2_U4: ig.Emit (OpCodes.Conv_U4); break;
3893                                 case Mode.I2_U8: ig.Emit (OpCodes.Conv_I8); break;
3894                                 case Mode.I2_CH: ig.Emit (OpCodes.Conv_U2); break;
3895
3896                                 case Mode.U2_I1: ig.Emit (OpCodes.Conv_I1); break;
3897                                 case Mode.U2_U1: ig.Emit (OpCodes.Conv_U1); break;
3898                                 case Mode.U2_I2: ig.Emit (OpCodes.Conv_I2); break;
3899                                 case Mode.U2_CH: /* nothing */ break;
3900
3901                                 case Mode.I4_I1: ig.Emit (OpCodes.Conv_I1); break;
3902                                 case Mode.I4_U1: ig.Emit (OpCodes.Conv_U1); break;
3903                                 case Mode.I4_I2: ig.Emit (OpCodes.Conv_I2); break;
3904                                 case Mode.I4_U4: /* nothing */ break;
3905                                 case Mode.I4_U2: ig.Emit (OpCodes.Conv_U2); break;
3906                                 case Mode.I4_U8: ig.Emit (OpCodes.Conv_I8); break;
3907                                 case Mode.I4_CH: ig.Emit (OpCodes.Conv_U2); break;
3908
3909                                 case Mode.U4_I1: ig.Emit (OpCodes.Conv_I1); break;
3910                                 case Mode.U4_U1: ig.Emit (OpCodes.Conv_U1); break;
3911                                 case Mode.U4_I2: ig.Emit (OpCodes.Conv_I2); break;
3912                                 case Mode.U4_U2: ig.Emit (OpCodes.Conv_U2); break;
3913                                 case Mode.U4_I4: /* nothing */ break;
3914                                 case Mode.U4_CH: ig.Emit (OpCodes.Conv_U2); break;
3915
3916                                 case Mode.I8_I1: ig.Emit (OpCodes.Conv_I1); break;
3917                                 case Mode.I8_U1: ig.Emit (OpCodes.Conv_U1); break;
3918                                 case Mode.I8_I2: ig.Emit (OpCodes.Conv_I2); break;
3919                                 case Mode.I8_U2: ig.Emit (OpCodes.Conv_U2); break;
3920                                 case Mode.I8_I4: ig.Emit (OpCodes.Conv_I4); break;
3921                                 case Mode.I8_U4: ig.Emit (OpCodes.Conv_U4); break;
3922                                 case Mode.I8_U8: /* nothing */ break;
3923                                 case Mode.I8_CH: ig.Emit (OpCodes.Conv_U2); break;
3924
3925                                 case Mode.U8_I1: ig.Emit (OpCodes.Conv_I1); break;
3926                                 case Mode.U8_U1: ig.Emit (OpCodes.Conv_U1); break;
3927                                 case Mode.U8_I2: ig.Emit (OpCodes.Conv_I2); break;
3928                                 case Mode.U8_U2: ig.Emit (OpCodes.Conv_U2); break;
3929                                 case Mode.U8_I4: ig.Emit (OpCodes.Conv_I4); break;
3930                                 case Mode.U8_U4: ig.Emit (OpCodes.Conv_U4); break;
3931                                 case Mode.U8_I8: /* nothing */ break;
3932                                 case Mode.U8_CH: ig.Emit (OpCodes.Conv_U2); break;
3933
3934                                 case Mode.CH_I1: ig.Emit (OpCodes.Conv_I1); break;
3935                                 case Mode.CH_U1: ig.Emit (OpCodes.Conv_U1); break;
3936                                 case Mode.CH_I2: ig.Emit (OpCodes.Conv_I2); break;
3937
3938                                 case Mode.R4_I1: ig.Emit (OpCodes.Conv_I1); break;
3939                                 case Mode.R4_U1: ig.Emit (OpCodes.Conv_U1); break;
3940                                 case Mode.R4_I2: ig.Emit (OpCodes.Conv_I2); break;
3941                                 case Mode.R4_U2: ig.Emit (OpCodes.Conv_U2); break;
3942                                 case Mode.R4_I4: ig.Emit (OpCodes.Conv_I4); break;
3943                                 case Mode.R4_U4: ig.Emit (OpCodes.Conv_U4); break;
3944                                 case Mode.R4_I8: ig.Emit (OpCodes.Conv_I8); break;
3945                                 case Mode.R4_U8: ig.Emit (OpCodes.Conv_U8); break;
3946                                 case Mode.R4_CH: ig.Emit (OpCodes.Conv_U2); break;
3947
3948                                 case Mode.R8_I1: ig.Emit (OpCodes.Conv_I1); break;
3949                                 case Mode.R8_U1: ig.Emit (OpCodes.Conv_U1); break;
3950                                 case Mode.R8_I2: ig.Emit (OpCodes.Conv_I2); break;
3951                                 case Mode.R8_U2: ig.Emit (OpCodes.Conv_U2); break;
3952                                 case Mode.R8_I4: ig.Emit (OpCodes.Conv_I4); break;
3953                                 case Mode.R8_U4: ig.Emit (OpCodes.Conv_U4); break;
3954                                 case Mode.R8_I8: ig.Emit (OpCodes.Conv_I8); break;
3955                                 case Mode.R8_U8: ig.Emit (OpCodes.Conv_U8); break;
3956                                 case Mode.R8_CH: ig.Emit (OpCodes.Conv_U2); break;
3957                                 case Mode.R8_R4: ig.Emit (OpCodes.Conv_R4); break;
3958                                 }
3959                         }
3960                 }
3961         }
3962         
3963         public class OpcodeCast : EmptyCast {
3964                 OpCode op, op2;
3965                 bool second_valid;
3966                 
3967                 public OpcodeCast (Expression child, Type return_type, OpCode op)
3968                         : base (child, return_type)
3969                         
3970                 {
3971                         this.op = op;
3972                         second_valid = false;
3973                 }
3974
3975                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
3976                         : base (child, return_type)
3977                         
3978                 {
3979                         this.op = op;
3980                         this.op2 = op2;
3981                         second_valid = true;
3982                 }
3983
3984                 public override Expression DoResolve (EmitContext ec)
3985                 {
3986                         // This should never be invoked, we are born in fully
3987                         // initialized state.
3988
3989                         return this;
3990                 }
3991
3992                 public override void Emit (EmitContext ec)
3993                 {
3994                         base.Emit (ec);
3995                         ec.ig.Emit (op);
3996
3997                         if (second_valid)
3998                                 ec.ig.Emit (op2);
3999                 }                       
4000         }
4001
4002
4003         public class NumericToBoolCast : EmptyCast 
4004         {
4005                 Type src_type;
4006                 
4007                 public NumericToBoolCast (Expression src, Type src_type)
4008                         : base (src, TypeManager.bool_type)
4009                         
4010                 {
4011                         this.src_type = src_type;
4012                 }
4013
4014                 public override Expression DoResolve (EmitContext ec)
4015                 {
4016                         return this;
4017                 }
4018
4019                 public override void Emit (EmitContext ec)
4020                 {
4021                         base.Emit (ec);
4022
4023                         if (src_type == TypeManager.byte_type ||
4024                                 src_type == TypeManager.short_type ||
4025                                 src_type == TypeManager.int32_type) {
4026                                 
4027                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
4028                                 ec.ig.Emit (OpCodes.Cgt_Un);
4029                                 return;
4030                         } 
4031
4032                         if (src_type == TypeManager.int64_type) {
4033                                 ec.ig.Emit (OpCodes.Ldc_I8, (long) 0);
4034                                 ec.ig.Emit (OpCodes.Cgt_Un);
4035                                 return;
4036                         } 
4037
4038                         if (src_type == TypeManager.float_type) {
4039                                 ec.ig.Emit (OpCodes.Ldc_R4, (float) 0);
4040                                 ec.ig.Emit (OpCodes.Ceq);
4041                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
4042                                 ec.ig.Emit (OpCodes.Ceq);
4043                                 return;
4044                         } 
4045
4046                         if (src_type == TypeManager.double_type) {
4047                                 ec.ig.Emit (OpCodes.Ldc_R8, (double) 0);
4048                                 ec.ig.Emit (OpCodes.Ceq);
4049                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
4050                                 ec.ig.Emit (OpCodes.Ceq);
4051                                 return;
4052                         }
4053                 }                       
4054         }
4055
4056         public class BoolToNumericCast : EmptyCast 
4057         {
4058                 Type target_type;
4059                 OpCode conv;
4060                 
4061                 public BoolToNumericCast (Expression src, Type target_type)
4062                         : base (src, target_type)
4063                         
4064                 {
4065                         this.target_type = target_type;
4066                 }
4067
4068                 public override Expression DoResolve (EmitContext ec)
4069                 {
4070                         return this;
4071                 }
4072
4073                 public override void Emit (EmitContext ec)
4074                 {
4075                         base.Emit (ec);
4076
4077                         if (target_type == TypeManager.byte_type) {
4078                                 conv = OpCodes.Conv_U1;
4079                         } else if (target_type == TypeManager.short_type) {
4080                                 conv = OpCodes.Conv_I2;
4081                         } else if (target_type == TypeManager.int32_type) {
4082                                 conv = OpCodes.Conv_I4;
4083                         } else if (target_type == TypeManager.int64_type) {
4084                                 conv = OpCodes.Conv_I8;
4085                         } else if (target_type == TypeManager.float_type) {
4086                                 conv = OpCodes.Conv_R4;
4087                         } else if (target_type == TypeManager.double_type) {
4088                                 conv = OpCodes.Conv_R8;
4089                         }
4090
4091                         ec.ig.Emit (OpCodes.Ldc_I4_0);
4092                         ec.ig.Emit (OpCodes.Cgt_Un);
4093                         ec.ig.Emit (OpCodes.Neg);
4094                         ec.ig.Emit (conv);
4095                         return;
4096                 }                       
4097         }
4098
4099         /// <summary>
4100         ///   This kind of cast is used to encapsulate a child and cast it
4101         ///   to the class requested
4102         /// </summary>
4103         public class ClassCast : EmptyCast {
4104                 public ClassCast (Expression child, Type return_type)
4105                         : base (child, return_type)
4106                         
4107                 {
4108                 }
4109
4110                 public override Expression DoResolve (EmitContext ec)
4111                 {
4112                         // This should never be invoked, we are born in fully
4113                         // initialized state.
4114
4115                         return this;
4116                 }
4117
4118                 public override void Emit (EmitContext ec)
4119                 {
4120                         base.Emit (ec);
4121
4122                         ec.ig.Emit (OpCodes.Castclass, type);
4123                 }                       
4124                 
4125         }
4126         
4127         /// <summary>
4128         ///   SimpleName expressions are initially formed of a single
4129         ///   word and it only happens at the beginning of the expression.
4130         /// </summary>
4131         ///
4132         /// <remarks>
4133         ///   The expression will try to be bound to a Field, a Method
4134         ///   group or a Property.  If those fail we pass the name to our
4135         ///   caller and the SimpleName is compounded to perform a type
4136         ///   lookup.  The idea behind this process is that we want to avoid
4137         ///   creating a namespace map from the assemblies, as that requires
4138         ///   the GetExportedTypes function to be called and a hashtable to
4139         ///   be constructed which reduces startup time.  If later we find
4140         ///   that this is slower, we should create a 'NamespaceExpr' expression
4141         ///   that fully participates in the resolution process. 
4142         ///   
4143         ///   For example 'System.Console.WriteLine' is decomposed into
4144         ///   MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
4145         ///   
4146         ///   The first SimpleName wont produce a match on its own, so it will
4147         ///   be turned into:
4148         ///   MemberAccess (SimpleName ("System.Console"), "WriteLine").
4149         ///   
4150         ///   System.Console will produce a TypeExpr match.
4151         ///   
4152         ///   The downside of this is that we might be hitting 'LookupType' too many
4153         ///   times with this scheme.
4154         /// </remarks>
4155         public class SimpleName : Expression, ITypeExpression {
4156                 public readonly string Name;
4157                 bool is_invocation = false;
4158
4159                 public bool IsInvocation {
4160                         set {
4161                                 is_invocation = value;
4162                         }
4163                 }
4164                 
4165                 public SimpleName (string name, Location l)
4166                 {
4167                         Name = name;
4168                         loc = l;
4169                 }
4170
4171                 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
4172                 {
4173                         if (ec.IsFieldInitializer)
4174                                 Report.Error (
4175                                         236, l,
4176                                         "A field initializer cannot reference the non-static field, " +
4177                                         "method or property '"+name+"'");
4178                         else
4179                                 Report.Error (
4180                                         120, l,
4181                                         "An object reference is required " +
4182                                         "for the non-static field '"+name+"'");
4183                 }
4184                 
4185                 //
4186                 // Checks whether we are trying to access an instance
4187                 // property, method or field from a static body.
4188                 //
4189                 Expression MemberStaticCheck (EmitContext ec, Expression e)
4190                 {
4191                         if (e is IMemberExpr){
4192                                 IMemberExpr member = (IMemberExpr) e;
4193                                 
4194                                 if (!member.IsStatic){
4195                                         Error_ObjectRefRequired (ec, loc, Name);
4196                                         return null;
4197                                 }
4198                         }
4199
4200                         return e;
4201                 }
4202                 
4203                 public override Expression DoResolve (EmitContext ec)
4204                 {
4205                         return SimpleNameResolve (ec, null, false);
4206                 }
4207
4208                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
4209                 {
4210                         return SimpleNameResolve (ec, right_side, false);
4211                 }
4212                 
4213
4214                 public Expression DoResolveAllowStatic (EmitContext ec)
4215                 {
4216                         return SimpleNameResolve (ec, null, true);
4217                 }
4218
4219                 public Expression DoResolveType (EmitContext ec)
4220                 {
4221                         //
4222                         // Stage 3: Lookup symbol in the various namespaces. 
4223                         //
4224                         DeclSpace ds = ec.DeclSpace;
4225                         Type t;
4226                         string alias_value;
4227
4228                         if (ec.ResolvingTypeTree){
4229                                 int errors = Report.Errors;
4230                                 Type dt = ec.DeclSpace.FindType (loc, Name);
4231                                 if (Report.Errors != errors)
4232                                         return null;
4233                                 
4234                                 if (dt != null)
4235                                         return new TypeExpr (dt, loc);
4236                         }
4237
4238                         if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
4239                                 return new TypeExpr (t, loc);
4240                                 
4241
4242                         //
4243                         // Stage 2 part b: Lookup up if we are an alias to a type
4244                         // or a namespace.
4245                         //
4246                         // Since we are cheating: we only do the Alias lookup for
4247                         // namespaces if the name does not include any dots in it
4248                         //
4249                                 
4250                         alias_value = ec.DeclSpace.LookupAlias (Name);
4251                                 
4252                         if (Name.IndexOf ('.') == -1 && alias_value != null) {
4253                                 if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
4254                                         return new TypeExpr (t, loc);
4255                                         
4256                                 // we have alias value, but it isn't Type, so try if it's namespace
4257                                 return new SimpleName (alias_value, loc);
4258                         }
4259                                 
4260                         // No match, maybe our parent can compose us
4261                         // into something meaningful.
4262                         return this;
4263                 }
4264
4265                 /// <remarks>
4266                 ///   7.5.2: Simple Names. 
4267                 ///
4268                 ///   Local Variables and Parameters are handled at
4269                 ///   parse time, so they never occur as SimpleNames.
4270                 ///
4271                 ///   The 'allow_static' flag is used by MemberAccess only
4272                 ///   and it is used to inform us that it is ok for us to 
4273                 ///   avoid the static check, because MemberAccess might end
4274                 ///   up resolving the Name as a Type name and the access as
4275                 ///   a static type access.
4276                 ///
4277                 ///   ie: Type Type; .... { Type.GetType (""); }
4278                 ///
4279                 ///   Type is both an instance variable and a Type;  Type.GetType
4280                 ///   is the static method not an instance method of type.
4281                 /// </remarks>
4282                 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static)
4283                 {
4284                         Expression e = null;
4285                         
4286                         //
4287                         // Stage 1: Performed by the parser (binding to locals or parameters).
4288                         //
4289                         Block current_block = ec.CurrentBlock;
4290                         if (ec.InvokingOwnOverload == false && current_block != null && current_block.IsVariableDefined (Name)){
4291                                 LocalVariableReference var;
4292
4293                                 var = new LocalVariableReference (current_block, Name, loc);
4294
4295                                 if (right_side != null)
4296                                         return var.ResolveLValue (ec, right_side);
4297                                 else
4298                                         return var.Resolve (ec);
4299                         }
4300
4301                         if (current_block != null){
4302                                 int idx = -1;
4303                                 Parameter par = null;
4304                                 Parameters pars = current_block.Parameters;
4305                                 if (pars != null)
4306                                         par = pars.GetParameterByName (Name, out idx);
4307
4308                                 if (par != null) {
4309                                         ParameterReference param;
4310                                         
4311                                         param = new ParameterReference (pars, idx, Name, loc);
4312
4313                                         if (right_side != null)
4314                                                 return param.ResolveLValue (ec, right_side);
4315                                         else
4316                                                 return param.Resolve (ec);
4317                                 }
4318                         }
4319
4320                         //
4321                         // Stage 2: Lookup members 
4322                         //
4323
4324                         //
4325                         // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
4326                         // Hence we have two different cases
4327                         //
4328
4329                         DeclSpace lookup_ds = ec.DeclSpace;
4330                         do {
4331                                 if (lookup_ds.TypeBuilder == null)
4332                                         break;
4333
4334                                 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
4335                                 if (e != null)
4336                                         break;
4337
4338                                 //
4339                                 // Classes/structs keep looking, enums break
4340                                 //
4341                                 if (lookup_ds is TypeContainer)
4342                                         lookup_ds = ((TypeContainer) lookup_ds).Parent;
4343                                 else
4344                                         break;
4345                         } while (lookup_ds != null);
4346                                 
4347                         if (e == null && ec.ContainerType != null)
4348                                 e = MemberLookup (ec, ec.ContainerType, Name, loc);
4349
4350 // #52067 - Start - Trying to solve
4351
4352                         if (e == null) {
4353                                 ArrayList lookups = new ArrayList();
4354                                 ArrayList typelookups = new ArrayList();
4355                                 
4356                                 int split = Name.LastIndexOf('.');
4357                                 if (split != -1) {
4358                                         String nameSpacePart = Name.Substring(0, split);
4359                                         String memberNamePart = Name.Substring(split + 1);
4360                                         foreach(Type type in TypeManager.GetPertinentStandardModules(nameSpacePart)) {
4361                                                 e = MemberLookup(ec, type, memberNamePart, loc);
4362                                                 if (e != null) {
4363                                                         lookups.Add(e);
4364                                                         typelookups.Add(type);
4365                                                 }
4366                                         }
4367                                 }
4368                                 
4369                                 string[] NamespacesInScope = RootContext.SourceBeingCompiled.GetNamespacesInScope(ec.DeclSpace.Namespace.Name);
4370                                 foreach(Type type in TypeManager.GetPertinentStandardModules(NamespacesInScope)) {
4371                                         e = MemberLookup(ec, type, Name, loc);
4372                                         if (e != null) {
4373                                                 lookups.Add(e);
4374                                                 typelookups.Add(type);
4375                                         }
4376                                 }
4377                                 if (lookups.Count == 1) { 
4378                                         e = (Expression)lookups[0];
4379                                 } else {
4380                                         if (lookups.Count > 1) {
4381                                                 StringBuilder sb = new StringBuilder();
4382                                                 foreach(Type type in typelookups)
4383                                                         sb.Append("'" + type.FullName + "'");                                           
4384                                                 Error (-1, "The name '" + Name + "' can be resolved to a member of more than one standard module: " + sb.ToString() + ". Please fully qualify it.");
4385                                                 return null;
4386                                         }
4387                                 }
4388                         }
4389
4390 // #52067 - End
4391
4392                         if (e == null) {
4393                         
4394                 /* preparing to support automatic definition of variables on first usage with Option Explicit Off
4395                         
4396                         Isn't good enough to enable just now (tries to define some internal links and breaks on emit)
4397                         
4398                                 if (Name.IndexOf ('.') == -1 && current_block != null && !Mono.MonoBASIC.Parser.OptionExplicit) {
4399                                 
4400                                         // while looking for a real solution
4401                                         if (Name != "anything")
4402                                                 return DoResolveType (ec);
4403                                                 
4404                                         Console.WriteLine("Implicitly adding a variable named '{0}'", Name);
4405                                         
4406                                         // TODO: look at type-suffixes to correct name and type
4407                                         Expression type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", loc);
4408                                         
4409                                         current_block.AddVariable(ec, type, Name, loc);
4410                                 
4411                                         LocalVariableReference var = new LocalVariableReference (current_block, Name, loc);
4412                                         if (right_side != null)
4413                                                 return var.ResolveLValue (ec, right_side);
4414                                         else
4415                                                 return var.Resolve (ec);
4416                                 } else
4417                 */
4418                                         return DoResolveType (ec);
4419                         }
4420                         
4421                         if (e is TypeExpr)
4422                                 return e;
4423
4424                         if (e is IMemberExpr) {
4425                                 e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
4426                                 if (e == null)
4427                                         return null;
4428
4429                                 if (e is PropertyGroupExpr && is_invocation) // We dont know the arguments yet
4430                                         return e;
4431
4432                                 IMemberExpr me = e as IMemberExpr;
4433                                 if (me == null)
4434                                         return e;
4435
4436                                 // This fails if ResolveMemberAccess() was unable to decide whether
4437                                 // it's a field or a type of the same name.
4438                                 if (!me.IsStatic && (me.InstanceExpression == null))
4439                                         return e;
4440
4441 /* FIXME    If this is not commented out, it seems that it's not possible to reach class members in mBas.
4442             Maybe a grammar-related problem?
4443
4444                                 if (!me.IsStatic &&
4445                                     TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) {
4446                                         Error (38, "Cannot access nonstatic member '" + me.Name + "' of " +
4447                                                "outer type '" + me.DeclaringType + "' via nested type '" +
4448                                                me.InstanceExpression.Type + "'");
4449                                         return null;
4450                                 }
4451 */
4452                                 bool isPropertyGroup = (e is PropertyGroupExpr);
4453                                 if (right_side != null)
4454                                         e = e.DoResolveLValue (ec, right_side);
4455                                 else
4456                                         e = e.DoResolve (ec);
4457
4458                                 if (e == null && isPropertyGroup && !is_invocation)
4459                                          Error (30057, "Property '" + Name + "' cannot be invoked with given arguments");
4460                                          
4461                                 return e;
4462                         }
4463
4464                         if (ec.IsStatic || ec.IsFieldInitializer) {
4465                                 if (allow_static)
4466                                         return e;
4467
4468                                 return MemberStaticCheck (ec, e);
4469                         }
4470
4471                         return e;
4472                 }
4473                 
4474                 public override void Emit (EmitContext ec)
4475                 {
4476                         //
4477                         // If this is ever reached, then we failed to
4478                         // find the name as a namespace
4479                         //
4480
4481                         Error (30451, "The name '" + Name +
4482                                "' does not exist in the class '" +
4483                                ec.DeclSpace.Name + "'");
4484                 }
4485
4486                 public override string ToString ()
4487                 {
4488                         return Name;
4489                 }
4490         }
4491         
4492         /// <summary>
4493         ///   Fully resolved expression that evaluates to a type
4494         /// </summary>
4495         public class TypeExpr : Expression, ITypeExpression {
4496                 public TypeExpr (Type t, Location l)
4497                 {
4498                         Type = t;
4499                         eclass = ExprClass.Type;
4500                         loc = l;
4501                 }
4502
4503                 public virtual Expression DoResolveType (EmitContext ec)
4504                 {
4505                         return this;
4506                 }
4507
4508                 override public Expression DoResolve (EmitContext ec)
4509                 {
4510                         return this;
4511                 }
4512
4513                 override public void Emit (EmitContext ec)
4514                 {
4515                         throw new Exception ("Should never be called");
4516                 }
4517
4518                 public override string ToString ()
4519                 {
4520                         return Type.ToString ();
4521                 }
4522         }
4523
4524         /// <summary>
4525         ///   Used to create types from a fully qualified name.  These are just used
4526         ///   by the parser to setup the core types.  A TypeLookupExpression is always
4527         ///   classified as a type.
4528         /// </summary>
4529         public class TypeLookupExpression : TypeExpr {
4530                 string name;
4531                 
4532                 public TypeLookupExpression (string name) : base (null, Location.Null)
4533                 {
4534                         this.name = name;
4535                 }
4536
4537                 public override Expression DoResolveType (EmitContext ec)
4538                 {
4539                         if (type == null)
4540                                 type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
4541                         return this;
4542                 }
4543
4544                 public override Expression DoResolve (EmitContext ec)
4545                 {
4546                         return DoResolveType (ec);
4547                 }
4548
4549                 public override void Emit (EmitContext ec)
4550                 {
4551                         throw new Exception ("Should never be called");
4552                 }
4553
4554                 public override string ToString ()
4555                 {
4556                         return name;
4557                 }
4558         }
4559
4560         /// <summary>
4561         ///   MethodGroup Expression.
4562         ///  
4563         ///   This is a fully resolved expression that evaluates to a type
4564         /// </summary>
4565         public class MethodGroupExpr : Expression, IMemberExpr {
4566                 public MethodBase [] Methods;
4567                 Expression instance_expression = null;
4568                 bool is_explicit_impl = false;
4569                 
4570                 public MethodGroupExpr (MemberInfo [] mi, Location l)
4571                 {
4572                         Methods = new MethodBase [mi.Length];
4573                         mi.CopyTo (Methods, 0);
4574                         eclass = ExprClass.MethodGroup;
4575                         type = TypeManager.object_type;
4576                         loc = l;
4577                 }
4578
4579                 public MethodGroupExpr (ArrayList list, Location l)
4580                 {
4581                         Methods = new MethodBase [list.Count];
4582
4583                         try {
4584                                 list.CopyTo (Methods, 0);
4585                         } catch {
4586                                 foreach (MemberInfo m in list){
4587                                         if (!(m is MethodBase)){
4588                                                 Console.WriteLine ("Name " + m.Name);
4589                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4590                                         }
4591                                 }
4592                                 throw;
4593                         }
4594                         loc = l;
4595                         eclass = ExprClass.MethodGroup;
4596                         type = TypeManager.object_type;
4597                 }
4598
4599                 public Type DeclaringType {
4600                         get {
4601                                 return Methods [0].DeclaringType;
4602                         }
4603                 }
4604                 
4605                 //
4606                 // 'A method group may have associated an instance expression' 
4607                 // 
4608                 public Expression InstanceExpression {
4609                         get {
4610                                 return instance_expression;
4611                         }
4612
4613                         set {
4614                                 instance_expression = value;
4615                         }
4616                 }
4617
4618                 public bool IsExplicitImpl {
4619                         get {
4620                                 return is_explicit_impl;
4621                         }
4622
4623                         set {
4624                                 is_explicit_impl = value;
4625                         }
4626                 }
4627
4628                 public string Name {
4629                         get {
4630                                 return Methods [0].Name;
4631                         }
4632                 }
4633
4634                 public bool IsInstance {
4635                         get {
4636                                 foreach (MethodBase mb in Methods)
4637                                         if (!mb.IsStatic)
4638                                                 return true;
4639
4640                                 return false;
4641                         }
4642                 }
4643
4644                 public bool IsStatic {
4645                         get {
4646                                 foreach (MethodBase mb in Methods)
4647                                         if (mb.IsStatic)
4648                                                 return true;
4649
4650                                 return false;
4651                         }
4652                 }
4653                 
4654                 override public Expression DoResolve (EmitContext ec)
4655                 {
4656                         if (instance_expression != null) {
4657                                 instance_expression = instance_expression.DoResolve (ec);
4658                                 if (instance_expression == null)
4659                                         return null;
4660                         }
4661
4662                         return this;
4663                 }
4664
4665                 public void ReportUsageError ()
4666                 {
4667                         Report.Error (654, loc, "Method '" + Methods [0].DeclaringType + "." +
4668                                       Methods [0].Name + "()' is referenced without parentheses");
4669                 }
4670
4671                 override public void Emit (EmitContext ec)
4672                 {
4673                         ReportUsageError ();
4674                 }
4675
4676                 bool RemoveMethods (bool keep_static)
4677                 {
4678                         ArrayList smethods = new ArrayList ();
4679
4680                         foreach (MethodBase mb in Methods){
4681                                 if (mb.IsStatic == keep_static)
4682                                         smethods.Add (mb);
4683                         }
4684
4685                         if (smethods.Count == 0)
4686                                 return false;
4687
4688                         Methods = new MethodBase [smethods.Count];
4689                         smethods.CopyTo (Methods, 0);
4690
4691                         return true;
4692                 }
4693                 
4694                 /// <summary>
4695                 ///   Removes any instance methods from the MethodGroup, returns
4696                 ///   false if the resulting set is empty.
4697                 /// </summary>
4698                 public bool RemoveInstanceMethods ()
4699                 {
4700                         return RemoveMethods (true);
4701                 }
4702
4703                 /// <summary>
4704                 ///   Removes any static methods from the MethodGroup, returns
4705                 ///   false if the resulting set is empty.
4706                 /// </summary>
4707                 public bool RemoveStaticMethods ()
4708                 {
4709                         return RemoveMethods (false);
4710                 }
4711         }
4712
4713         /// <summary>
4714         ///   Property Group Expression.
4715         ///  
4716         /// </summary>
4717         public class PropertyGroupExpr : ExpressionStatement, IMemberExpr {
4718                 public PropertyInfo [] Properties;
4719                 Expression instance_expression = null;
4720                 bool is_explicit_impl = false;
4721                 MethodBase method = null;
4722                 bool indexer_access_req = false;
4723                 ArrayList arguments = null;
4724                 
4725                 public PropertyGroupExpr (MemberInfo [] mi, Location l)
4726                 {
4727                         Properties = new PropertyInfo [mi.Length];
4728                         mi.CopyTo (Properties, 0);
4729                         eclass = ExprClass.PropertyAccess;
4730                         type = TypeManager.object_type;
4731                         loc = l;
4732                 }
4733
4734                 public PropertyGroupExpr (MemberInfo [] mi, ArrayList args, Expression expr, Location l)
4735                         : this (mi, l)
4736                 {
4737                         arguments = args;
4738                         instance_expression = expr;
4739                 }
4740
4741                 public PropertyGroupExpr (ArrayList list, Location l)
4742                 {
4743                         Properties = new PropertyInfo [list.Count];
4744
4745                         try {
4746                                 list.CopyTo (Properties, 0);
4747                         } catch {
4748                                 foreach (MemberInfo m in list){
4749                                         if (!(m is PropertyInfo)){
4750                                                 Console.WriteLine ("Name " + m.Name);
4751                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4752                                         }
4753                                 }
4754                                 throw;
4755                         }
4756                         loc = l;
4757                         eclass = ExprClass.PropertyAccess;
4758                         type = TypeManager.object_type;
4759                 }
4760
4761                 public ArrayList Arguments {
4762                         get {
4763                                 return arguments;
4764                         }
4765                         set {
4766                                 arguments = value;
4767                         }
4768                 }
4769
4770                 public Type DeclaringType {
4771                         get {
4772                                 return Properties [0].DeclaringType;
4773                         }
4774                 }
4775
4776                 public bool IndexerAccessRequired {
4777                         get {
4778                                 return indexer_access_req;
4779                         }
4780                 }
4781
4782                 //
4783                 // 'A method group may have associated an instance expression' 
4784                 // 
4785                 public Expression InstanceExpression {
4786                         get {
4787                                 return instance_expression;
4788                         }
4789
4790                         set {
4791                                 instance_expression = value;
4792                         }
4793                 }
4794
4795                 public bool IsExplicitImpl {
4796                         get {
4797                                 return is_explicit_impl;
4798                         }
4799
4800                         set {
4801                                 is_explicit_impl = value;
4802                         }
4803                 }
4804
4805                 public string Name {
4806                         get {
4807                                 return Properties [0].Name;
4808                         }
4809                 }
4810
4811                 public bool IsInstance {
4812                         get {
4813                                 foreach (PropertyInfo pi in Properties) {
4814                                         MethodInfo mi = pi.GetGetMethod ();
4815                                         if (mi != null && !mi.IsStatic)
4816                                                 return true;
4817                                         mi = pi.GetSetMethod ();
4818                                         if (mi != null && !mi.IsStatic)
4819                                                 return true;
4820                                 }               
4821                                 return false;
4822                         }
4823                 }
4824
4825                 public bool IsStatic {
4826                         get {
4827                                 return (!IsInstance);
4828                         }
4829                 }
4830                 
4831                 public ArrayList GetAccessors () {
4832                         ArrayList GetAccessors = new ArrayList ();
4833                         foreach (PropertyInfo pi in Properties) {
4834                                 if (pi.GetGetMethod () != null)
4835                                         GetAccessors.Add (pi.GetGetMethod ());
4836                         }
4837                         return GetAccessors;
4838                 }
4839                 
4840                 public ArrayList SetAccessors () {
4841                         ArrayList SetAccessors = new ArrayList ();
4842                         foreach (PropertyInfo pi in Properties) {
4843                                 if (pi.GetSetMethod () != null)
4844                                         SetAccessors.Add (pi.GetSetMethod ());
4845                         }
4846                         return SetAccessors;
4847                 }
4848
4849                 override public Expression DoResolve (EmitContext ec)
4850                 {
4851                         if (instance_expression != null) {
4852                                 instance_expression = instance_expression.DoResolve (ec);
4853                                 if (instance_expression == null)
4854                                         return null;
4855                         }
4856
4857                         ArrayList members = GetAccessors ();
4858                         if (members == null || members.Count == 0) {
4859                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'get' accesor");
4860                                 return null;
4861                         }
4862
4863                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4864                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4865                         if ((method as MethodInfo) != null) {
4866                                 MethodInfo mi = method as MethodInfo;
4867                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
4868                                 indexer_access_req = false;
4869                                 eclass = ExprClass.Value;
4870                                 return this;
4871                         } else {
4872                                 // find a get method that doesnt take any arguments. Check the return type of
4873                                 // that method to find out if indexer access is required. Leave the rest to
4874                                 // 'Invocation's Resolve'
4875                                 method = Invocation.OverloadResolve (ec, m_expr, null, loc);
4876                                 if (method != null) {
4877                                         MethodInfo mi = method as MethodInfo;
4878                                         Type ret_type = mi.ReturnType;
4879                                         if (ret_type.IsArray)
4880                                                 indexer_access_req = true;
4881                                         else {
4882                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, ret_type, loc);
4883                                                 if (list != null && list.getters.Count > 0)
4884                                                         indexer_access_req = true;
4885                                                 else 
4886                                                         return null;
4887                                         }
4888                                         Arguments = null;
4889                                         type = mi.ReturnType;
4890                                         return this;
4891                                 }
4892                         }
4893
4894                         return null;
4895                 }
4896
4897                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side) {
4898                         if (instance_expression != null) {
4899                                 instance_expression = instance_expression.DoResolve (ec);
4900                                 if (instance_expression == null)
4901                                         return null;
4902                         }
4903
4904                         ArrayList members = SetAccessors ();
4905                         if (members == null || members.Count == 0) {
4906                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'set' accesor");
4907                                 return null;
4908                         }
4909
4910                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4911                         if (arguments == null)
4912                                 arguments = new ArrayList ();
4913                         arguments.Add (new Argument (right_side, Argument.AType.Expression));
4914                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4915                         if (method != null) {
4916                                 //MethodInfo mi = method as MethodInfo;
4917                                 type = TypeManager.void_type; //TypeManager.TypeToCoreType (mi.ReturnType);
4918                                 eclass = ExprClass.Value;
4919                                 indexer_access_req = false;
4920                                 return this;
4921                         } else {
4922                                 // Look for properties that do not take any arguments.
4923                                 // Check if the return type has any indexers
4924                                 arguments = null;
4925                                 DoResolve (ec);
4926                                 if (method != null) {
4927                                         MethodInfo mi = method as MethodInfo;
4928                                         Type ret_type = mi.ReturnType;
4929                                         if (ret_type.IsArray)
4930                                                 indexer_access_req = true;
4931                                         else {
4932
4933                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, 
4934                                                                         ret_type, loc);
4935                                                 if (list != null && list.setters.Count > 0)
4936                                                         indexer_access_req = true;
4937                                                 else 
4938                                                         return null;
4939                                         }
4940                                         type = mi.ReturnType;
4941                                         return this;
4942                                 }
4943                         }
4944
4945                         return null;
4946                 }
4947
4948                 override public void Emit (EmitContext ec)
4949                 {
4950                         if (Arguments == null)
4951                                 Arguments = new ArrayList ();
4952                         Invocation.EmitCall (ec, false, IsStatic, instance_expression, method, null, Arguments, loc);
4953                 }
4954
4955                 override public void EmitStatement (EmitContext ec) 
4956                 {
4957                         Emit (ec);
4958                 }
4959
4960         }
4961
4962         /// <summary>
4963         ///   Fully resolved expression that evaluates to a Field
4964         /// </summary>
4965         public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr {
4966                 public readonly FieldInfo FieldInfo;
4967                 Expression instance_expr;
4968                 
4969                 public FieldExpr (FieldInfo fi, Location l)
4970                 {
4971                         FieldInfo = fi;
4972                         eclass = ExprClass.Variable;
4973                         type = fi.FieldType;
4974                         loc = l;
4975                 }
4976
4977                 public string Name {
4978                         get {
4979                                 return FieldInfo.Name;
4980                         }
4981                 }
4982
4983                 public bool IsInstance {
4984                         get {
4985                                 return !FieldInfo.IsStatic;
4986                         }
4987                 }
4988
4989                 public bool IsStatic {
4990                         get {
4991                                 return FieldInfo.IsStatic;
4992                         }
4993                 }
4994
4995                 public Type DeclaringType {
4996                         get {
4997                                 return FieldInfo.DeclaringType;
4998                         }
4999                 }
5000
5001                 public Expression InstanceExpression {
5002                         get {
5003                                 return instance_expr;
5004                         }
5005
5006                         set {
5007                                 instance_expr = value;
5008                         }
5009                 }
5010
5011                 override public Expression DoResolve (EmitContext ec)
5012                 {
5013                         if (!FieldInfo.IsStatic){
5014                                 if (instance_expr == null){
5015                                         throw new Exception ("non-static FieldExpr without instance var\n" +
5016                                                              "You have to assign the Instance variable\n" +
5017                                                              "Of the FieldExpr to set this\n");
5018                                 }
5019
5020                                 // Resolve the field's instance expression while flow analysis is turned
5021                                 // off: when accessing a field "a.b", we must check whether the field
5022                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
5023                                 instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
5024                                                                        ResolveFlags.DisableFlowAnalysis);
5025                                 if (instance_expr == null)
5026                                         return null;
5027                         }
5028
5029                         // If the instance expression is a local variable or parameter.
5030                         IVariable var = instance_expr as IVariable;
5031                         if ((var != null) && !var.IsFieldAssigned (ec, FieldInfo.Name, loc))
5032                                 return null;
5033
5034                         return this;
5035                 }
5036
5037                 void Report_AssignToReadonly (bool is_instance)
5038                 {
5039                         string msg;
5040                         
5041                         if (is_instance)
5042                                 msg = "Readonly field can not be assigned outside " +
5043                                 "of constructor or variable initializer";
5044                         else
5045                                 msg = "A static readonly field can only be assigned in " +
5046                                 "a static constructor";
5047
5048                         Report.Error (is_instance ? 191 : 198, loc, msg);
5049                 }
5050                 
5051                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5052                 {
5053                         IVariable var = instance_expr as IVariable;
5054                         if (var != null)
5055                                 var.SetFieldAssigned (ec, FieldInfo.Name);
5056
5057                         Expression e = DoResolve (ec);
5058
5059                         if (e == null)
5060                                 return null;
5061                         
5062                         if (!FieldInfo.IsInitOnly)
5063                                 return this;
5064
5065                         //
5066                         // InitOnly fields can only be assigned in constructors
5067                         //
5068
5069                         if (ec.IsConstructor)
5070                                 return this;
5071
5072                         Report_AssignToReadonly (true);
5073                         
5074                         return null;
5075                 }
5076
5077                 override public void Emit (EmitContext ec)
5078                 {
5079                         ILGenerator ig = ec.ig;
5080                         bool is_volatile = false;
5081
5082                         if (FieldInfo is FieldBuilder){
5083                                 FieldBase f = TypeManager.GetField (FieldInfo);
5084
5085                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5086                                         is_volatile = true;
5087                                 
5088                                 f.status |= Field.Status.USED;
5089                         }
5090                         
5091                         if (FieldInfo.IsStatic){
5092                                 if (is_volatile)
5093                                         ig.Emit (OpCodes.Volatile);
5094                                 
5095                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
5096                         } else {
5097                                 if (instance_expr.Type.IsValueType){
5098                                         IMemoryLocation ml;
5099                                         LocalTemporary tempo = null;
5100                                         
5101                                         if (!(instance_expr is IMemoryLocation)){
5102                                                 tempo = new LocalTemporary (
5103                                                         ec, instance_expr.Type);
5104
5105                                                 InstanceExpression.Emit (ec);
5106                                                 tempo.Store (ec);
5107                                                 ml = tempo;
5108                                         } else
5109                                                 ml = (IMemoryLocation) instance_expr;
5110
5111                                         ml.AddressOf (ec, AddressOp.Load);
5112                                 } else 
5113                                         instance_expr.Emit (ec);
5114
5115                                 if (is_volatile)
5116                                         ig.Emit (OpCodes.Volatile);
5117                                 
5118                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
5119                         }
5120                 }
5121
5122                 public void EmitAssign (EmitContext ec, Expression source)
5123                 {
5124                         FieldAttributes fa = FieldInfo.Attributes;
5125                         bool is_static = (fa & FieldAttributes.Static) != 0;
5126                         bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
5127                         ILGenerator ig = ec.ig;
5128
5129                         if (is_readonly && !ec.IsConstructor){
5130                                 Report_AssignToReadonly (!is_static);
5131                                 return;
5132                         }
5133                         
5134                         if (!is_static){
5135                                 Expression instance = instance_expr;
5136
5137                                 if (instance.Type.IsValueType){
5138                                         if (instance is IMemoryLocation){
5139                                                 IMemoryLocation ml = (IMemoryLocation) instance;
5140
5141                                                 ml.AddressOf (ec, AddressOp.Store);
5142                                         } else
5143                                                 throw new Exception ("The " + instance + " of type " +
5144                                                                      instance.Type +
5145                                                                      " represents a ValueType and does " +
5146                                                                      "not implement IMemoryLocation");
5147                                 } else
5148                                         instance.Emit (ec);
5149                         }
5150                         source.Emit (ec);
5151
5152                         if (FieldInfo is FieldBuilder){
5153                                 FieldBase f = TypeManager.GetField (FieldInfo);
5154                                 
5155                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5156                                         ig.Emit (OpCodes.Volatile);
5157                         }
5158                         
5159                         if (is_static)
5160                                 ig.Emit (OpCodes.Stsfld, FieldInfo);
5161                         else 
5162                                 ig.Emit (OpCodes.Stfld, FieldInfo);
5163
5164                         if (FieldInfo is FieldBuilder){
5165                                 FieldBase f = TypeManager.GetField (FieldInfo);
5166
5167                                 f.status |= Field.Status.ASSIGNED;
5168                         }
5169                 }
5170                 
5171                 public void AddressOf (EmitContext ec, AddressOp mode)
5172                 {
5173                         ILGenerator ig = ec.ig;
5174                         
5175                         if (FieldInfo is FieldBuilder){
5176                                 FieldBase f = TypeManager.GetField (FieldInfo);
5177                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5178                                         ig.Emit (OpCodes.Volatile);
5179                         }
5180
5181                         if (FieldInfo is FieldBuilder){
5182                                 FieldBase f = TypeManager.GetField (FieldInfo);
5183
5184                                 if ((mode & AddressOp.Store) != 0)
5185                                         f.status |= Field.Status.ASSIGNED;
5186                                 if ((mode & AddressOp.Load) != 0)
5187                                         f.status |= Field.Status.USED;
5188                         }
5189
5190                         //
5191                         // Handle initonly fields specially: make a copy and then
5192                         // get the address of the copy.
5193                         //
5194                         if (FieldInfo.IsInitOnly && !ec.IsConstructor){
5195                                 LocalBuilder local;
5196                                 
5197                                 Emit (ec);
5198                                 local = ig.DeclareLocal (type);
5199                                 ig.Emit (OpCodes.Stloc, local);
5200                                 ig.Emit (OpCodes.Ldloca, local);
5201                                 return;
5202                         }
5203
5204                         if (FieldInfo.IsStatic)
5205                                 ig.Emit (OpCodes.Ldsflda, FieldInfo);
5206                         else {
5207                                 if (instance_expr is IMemoryLocation)
5208                                         ((IMemoryLocation)instance_expr).AddressOf (ec, AddressOp.LoadStore);
5209                                 else
5210                                         instance_expr.Emit (ec);
5211                                 ig.Emit (OpCodes.Ldflda, FieldInfo);
5212                         }
5213                 }
5214         }
5215         
5216         /// <summary>
5217         ///   Expression that evaluates to a Property.  The Assign class
5218         ///   might set the 'Value' expression if we are in an assignment.
5219         ///
5220         ///   This is not an LValue because we need to re-write the expression, we
5221         ///   can not take data from the stack and store it.  
5222         /// </summary>
5223         public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
5224                 public readonly PropertyInfo PropertyInfo;
5225                 public bool IsBase;
5226                 MethodInfo getter, setter;
5227                 bool is_static;
5228                 public ArrayList PropertyArgs;
5229
5230                 Expression instance_expr;
5231
5232                 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
5233                 {
5234                         PropertyInfo = pi;
5235                         eclass = ExprClass.PropertyAccess;
5236                         PropertyArgs = null;
5237                         is_static = false;
5238                         loc = l;
5239
5240                         type = TypeManager.TypeToCoreType (pi.PropertyType);
5241
5242                         ResolveAccessors (ec);
5243                 }
5244
5245                 public string Name {
5246                         get {
5247                                 return PropertyInfo.Name;
5248                         }
5249                 }
5250
5251                 public bool IsInstance {
5252                         get {
5253                                 return !is_static;
5254                         }
5255                 }
5256
5257                 public bool IsStatic {
5258                         get {
5259                                 return is_static;
5260                         }
5261                 }
5262                 
5263                 public Type DeclaringType {
5264                         get {
5265                                 return PropertyInfo.DeclaringType;
5266                         }
5267                 }
5268
5269                 //
5270                 // The instance expression associated with this expression
5271                 //
5272                 public Expression InstanceExpression {
5273                         set {
5274                                 instance_expr = value;
5275                         }
5276
5277                         get {
5278                                 return instance_expr;
5279                         }
5280                 }
5281
5282                 public bool VerifyAssignable ()
5283                 {
5284                         if (!PropertyInfo.CanWrite){
5285                                 Report.Error (200, loc, 
5286                                               "The property '" + PropertyInfo.Name +
5287                                               "' can not be assigned to, as it has not set accessor");
5288                                 return false;
5289                         }
5290
5291                         return true;
5292                 }
5293
5294                 void ResolveAccessors (EmitContext ec)
5295                 {
5296                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
5297                         MemberInfo [] group;
5298                         
5299                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5300                                                               MemberTypes.Method, flags, "get_" + PropertyInfo.Name);
5301
5302                         //
5303                         // The first method is the closest to us
5304                         //
5305                         if (group != null && group.Length > 0){
5306                                 getter = (MethodInfo) group [0];
5307
5308                                 if (getter.IsStatic)
5309                                         is_static = true;
5310                         }                       
5311
5312                         //
5313                         // The first method is the closest to us
5314                         //
5315                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5316                                                           MemberTypes.Method, flags, "set_" + PropertyInfo.Name);
5317                         if (group != null && group.Length > 0){
5318                                 setter = (MethodInfo) group [0];
5319                                 if (setter.IsStatic)
5320                                         is_static = true;
5321                         }
5322                 }
5323
5324                 override public Expression DoResolve (EmitContext ec)
5325                 {
5326                         if (getter == null){
5327                                 Report.Error (30524, loc, 
5328                                               "The property '" + PropertyInfo.Name +
5329                                               "' can not be used in " +
5330                                               "this context because it lacks a get accessor");
5331                                 return null;
5332                         }
5333
5334                         if ((instance_expr == null) && ec.IsStatic && !is_static) {
5335                                 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
5336                                 return null;
5337                         }
5338
5339                         if (instance_expr != null) {
5340                                 instance_expr = instance_expr.DoResolve (ec);
5341                                 if (instance_expr == null)
5342                                         return null;
5343                         }
5344
5345                         return this;
5346                 }
5347
5348                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5349                 {
5350                         if (setter == null){
5351                                 Report.Error (30526, loc, 
5352                                               "The property '" + PropertyInfo.Name +
5353                                               "' can not be used in " +
5354                                               "this context because it lacks a set accessor");
5355                                 return null;
5356                         }
5357
5358                         if (instance_expr != null) {
5359                                 instance_expr = instance_expr.DoResolve (ec);
5360                                 if (instance_expr == null)
5361                                         return null;
5362                         }
5363
5364                         return this;
5365                 }
5366
5367                 override public void Emit (EmitContext ec)
5368                 {
5369                         //
5370                         // Special case: length of single dimension array property is turned into ldlen
5371                         //
5372                         if ((getter == TypeManager.system_int_array_get_length) ||
5373                             (getter == TypeManager.int_array_get_length)){
5374                                 Type iet = instance_expr.Type;
5375
5376                                 //
5377                                 // System.Array.Length can be called, but the Type does not
5378                                 // support invoking GetArrayRank, so test for that case first
5379                                 //
5380                                 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
5381                                         instance_expr.Emit (ec);
5382                                         ec.ig.Emit (OpCodes.Ldlen);
5383                                         return;
5384                                 }
5385                         }
5386                         if (PropertyArgs == null)
5387                                 PropertyArgs = new ArrayList ();
5388                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, PropertyArgs, loc);
5389                 }
5390
5391                 //
5392                 // Implements the IAssignMethod interface for assignments
5393                 //
5394                 public void EmitAssign (EmitContext ec, Expression source)
5395                 {
5396                         Argument arg = new Argument (source, Argument.AType.Expression);
5397                         ArrayList args = new ArrayList ();
5398 //HERE
5399                         args.Add (arg);
5400                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, PropertyArgs,loc);
5401                 }
5402
5403                 override public void EmitStatement (EmitContext ec)
5404                 {
5405                         Emit (ec);
5406                         ec.ig.Emit (OpCodes.Pop);
5407                 }
5408         }
5409
5410         /// <summary>
5411         ///   Fully resolved expression that evaluates to an Event
5412         /// </summary>
5413         public class EventExpr : Expression, IMemberExpr {
5414                 public readonly EventInfo EventInfo;
5415                 public Expression instance_expr;
5416
5417                 bool is_static;
5418                 MethodInfo add_accessor, remove_accessor;
5419                 
5420                 public EventExpr (EventInfo ei, Location loc)
5421                 {
5422                         EventInfo = ei;
5423                         this.loc = loc;
5424                         eclass = ExprClass.EventAccess;
5425
5426                         add_accessor = TypeManager.GetAddMethod (ei);
5427                         remove_accessor = TypeManager.GetRemoveMethod (ei);
5428                         
5429                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
5430                                 is_static = true;
5431
5432                         if (EventInfo is MyEventBuilder)
5433                                 type = ((MyEventBuilder) EventInfo).EventType;
5434                         else
5435                                 type = EventInfo.EventHandlerType;
5436                 }
5437
5438                 public string Name {
5439                         get {
5440                                 return EventInfo.Name;
5441                         }
5442                 }
5443
5444                 public bool IsInstance {
5445                         get {
5446                                 return !is_static;
5447                         }
5448                 }
5449
5450                 public bool IsStatic {
5451                         get {
5452                                 return is_static;
5453                         }
5454                 }
5455
5456                 public Type DeclaringType {
5457                         get {
5458                                 return EventInfo.DeclaringType;
5459                         }
5460                 }
5461
5462                 public Expression InstanceExpression {
5463                         get {
5464                                 return instance_expr;
5465                         }
5466
5467                         set {
5468                                 instance_expr = value;
5469                         }
5470                 }
5471
5472                 Expression field_expr = null;
5473
5474                 public override Expression DoResolve (EmitContext ec)
5475                 {
5476                         if (instance_expr != null) {
5477                                 instance_expr = instance_expr.DoResolve (ec);
5478                                 if (instance_expr == null)
5479                                         return null;
5480                         }
5481
5482                         if (this.DeclaringType == ec.ContainerType)     {
5483                                 MemberInfo mi = GetFieldFromEvent (this);
5484                                 if (mi == null)
5485                                         return null;
5486                                 field_expr = ExprClassFromMemberInfo (ec, mi, loc);
5487                                 ((FieldExpr) field_expr).InstanceExpression = instance_expr;
5488                                 field_expr = field_expr.DoResolve (ec);
5489                                 if (field_expr == null)
5490                                         return null;
5491                         }
5492
5493                         return this;
5494                 }
5495
5496                 public override void Emit (EmitContext ec)
5497                 {
5498                         if (field_expr != null)
5499                                 field_expr.Emit (ec);
5500                 }
5501
5502                 public void EmitAddOrRemove (EmitContext ec, Expression source)
5503                 {
5504                         Expression handler = ((Binary) source).Right;
5505                         
5506                         Argument arg = new Argument (handler, Argument.AType.Expression);
5507                         ArrayList args = new ArrayList ();
5508                                 
5509                         args.Add (arg);
5510                         
5511                         if (((Binary) source).Oper == Binary.Operator.Addition)
5512                                 Invocation.EmitCall (
5513                                         ec, false, IsStatic, instance_expr, add_accessor, args, loc);
5514                         else
5515                                 Invocation.EmitCall (
5516                                         ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
5517                 }
5518         }
5519 }