* profiles/basic.make (do-profile-check): Make the "silent"
[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                 bool is_addressof = false;
4159
4160                 public bool IsInvocation {
4161                         set {
4162                                 is_invocation = value;
4163                         }
4164                 }
4165
4166                 public bool IsAddressOf {
4167                         set {
4168                                 is_addressof = value;
4169                         }
4170                 }
4171                 
4172                 public SimpleName (string name, Location l)
4173                 {
4174                         Name = name;
4175                         loc = l;
4176                 }
4177
4178                 public static void Error_ObjectRefRequired (EmitContext ec, Location l, string name)
4179                 {
4180                         if (ec.IsFieldInitializer)
4181                                 Report.Error (
4182                                         236, l,
4183                                         "A field initializer cannot reference the non-static field, " +
4184                                         "method or property '"+name+"'");
4185                         else
4186                                 Report.Error (
4187                                         120, l,
4188                                         "An object reference is required " +
4189                                         "for the non-static field '"+name+"'");
4190                 }
4191                 
4192                 //
4193                 // Checks whether we are trying to access an instance
4194                 // property, method or field from a static body.
4195                 //
4196                 Expression MemberStaticCheck (EmitContext ec, Expression e)
4197                 {
4198                         if (e is IMemberExpr){
4199                                 IMemberExpr member = (IMemberExpr) e;
4200                                 
4201                                 if (!member.IsStatic){
4202                                         Error_ObjectRefRequired (ec, loc, Name);
4203                                         return null;
4204                                 }
4205                         }
4206
4207                         return e;
4208                 }
4209                 
4210                 public override Expression DoResolve (EmitContext ec)
4211                 {
4212                         return SimpleNameResolve (ec, null, false);
4213                 }
4214
4215                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
4216                 {
4217                         return SimpleNameResolve (ec, right_side, false);
4218                 }
4219                 
4220
4221                 public Expression DoResolveAllowStatic (EmitContext ec)
4222                 {
4223                         return SimpleNameResolve (ec, null, true);
4224                 }
4225
4226                 public Expression DoResolveType (EmitContext ec)
4227                 {
4228                         //
4229                         // Stage 3: Lookup symbol in the various namespaces. 
4230                         //
4231                         DeclSpace ds = ec.DeclSpace;
4232                         Type t;
4233                         string alias_value;
4234
4235                         if (ec.ResolvingTypeTree){
4236                                 int errors = Report.Errors;
4237                                 Type dt = ec.DeclSpace.FindType (loc, Name);
4238                                 if (Report.Errors != errors)
4239                                         return null;
4240                                 
4241                                 if (dt != null)
4242                                         return new TypeExpr (dt, loc);
4243                         }
4244
4245                         if ((t = RootContext.LookupType (ds, Name, true, loc)) != null)
4246                                 return new TypeExpr (t, loc);
4247                                 
4248
4249                         //
4250                         // Stage 2 part b: Lookup up if we are an alias to a type
4251                         // or a namespace.
4252                         //
4253                         // Since we are cheating: we only do the Alias lookup for
4254                         // namespaces if the name does not include any dots in it
4255                         //
4256                                 
4257                         alias_value = ec.DeclSpace.LookupAlias (Name);
4258                                 
4259                         if (Name.IndexOf ('.') == -1 && alias_value != null) {
4260                                 if ((t = RootContext.LookupType (ds, alias_value, true, loc)) != null)
4261                                         return new TypeExpr (t, loc);
4262                                         
4263                                 // we have alias value, but it isn't Type, so try if it's namespace
4264                                 return new SimpleName (alias_value, loc);
4265                         }
4266                                 
4267                         // No match, maybe our parent can compose us
4268                         // into something meaningful.
4269                         return this;
4270                 }
4271
4272                 /// <remarks>
4273                 ///   7.5.2: Simple Names. 
4274                 ///
4275                 ///   Local Variables and Parameters are handled at
4276                 ///   parse time, so they never occur as SimpleNames.
4277                 ///
4278                 ///   The 'allow_static' flag is used by MemberAccess only
4279                 ///   and it is used to inform us that it is ok for us to 
4280                 ///   avoid the static check, because MemberAccess might end
4281                 ///   up resolving the Name as a Type name and the access as
4282                 ///   a static type access.
4283                 ///
4284                 ///   ie: Type Type; .... { Type.GetType (""); }
4285                 ///
4286                 ///   Type is both an instance variable and a Type;  Type.GetType
4287                 ///   is the static method not an instance method of type.
4288                 /// </remarks>
4289                 Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static)
4290                 {
4291                         Expression e = null;
4292                         
4293                         //
4294                         // Stage 1: Performed by the parser (binding to locals or parameters).
4295                         //
4296                         Block current_block = ec.CurrentBlock;
4297                         if (ec.InvokingOwnOverload == false && current_block != null && current_block.IsVariableDefined (Name)){
4298                                 LocalVariableReference var;
4299
4300                                 var = new LocalVariableReference (current_block, Name, loc);
4301
4302                                 if (right_side != null)
4303                                         return var.ResolveLValue (ec, right_side);
4304                                 else
4305                                         return var.Resolve (ec);
4306                         }
4307
4308                         if (current_block != null){
4309                                 int idx = -1;
4310                                 Parameter par = null;
4311                                 Parameters pars = current_block.Parameters;
4312                                 if (pars != null)
4313                                         par = pars.GetParameterByName (Name, out idx);
4314
4315                                 if (par != null) {
4316                                         ParameterReference param;
4317                                         
4318                                         param = new ParameterReference (pars, idx, Name, loc);
4319
4320                                         if (right_side != null)
4321                                                 return param.ResolveLValue (ec, right_side);
4322                                         else
4323                                                 return param.Resolve (ec);
4324                                 }
4325                         }
4326
4327                         //
4328                         // Stage 2: Lookup members 
4329                         //
4330
4331                         //
4332                         // For enums, the TypeBuilder is not ec.DeclSpace.TypeBuilder
4333                         // Hence we have two different cases
4334                         //
4335
4336                         DeclSpace lookup_ds = ec.DeclSpace;
4337                         do {
4338                                 if (lookup_ds.TypeBuilder == null)
4339                                         break;
4340
4341                                 e = MemberLookup (ec, lookup_ds.TypeBuilder, Name, loc);
4342                                 if (e != null)
4343                                         break;
4344
4345                                 //
4346                                 // Classes/structs keep looking, enums break
4347                                 //
4348                                 if (lookup_ds is TypeContainer)
4349                                         lookup_ds = ((TypeContainer) lookup_ds).Parent;
4350                                 else
4351                                         break;
4352                         } while (lookup_ds != null);
4353                                 
4354                         if (e == null && ec.ContainerType != null)
4355                                 e = MemberLookup (ec, ec.ContainerType, Name, loc);
4356
4357 // #52067 - Start - Trying to solve
4358
4359                         if (e == null) {
4360                                 ArrayList lookups = new ArrayList();
4361                                 ArrayList typelookups = new ArrayList();
4362                                 
4363                                 int split = Name.LastIndexOf('.');
4364                                 if (split != -1) {
4365                                         String nameSpacePart = Name.Substring(0, split);
4366                                         String memberNamePart = Name.Substring(split + 1);
4367                                         foreach(Type type in TypeManager.GetPertinentStandardModules(nameSpacePart)) {
4368                                                 e = MemberLookup(ec, type, memberNamePart, loc);
4369                                                 if (e != null) {
4370                                                         lookups.Add(e);
4371                                                         typelookups.Add(type);
4372                                                 }
4373                                         }
4374                                 }
4375                                 
4376                                 string[] NamespacesInScope = RootContext.SourceBeingCompiled.GetNamespacesInScope(ec.DeclSpace.Namespace.Name);
4377                                 foreach(Type type in TypeManager.GetPertinentStandardModules(NamespacesInScope)) {
4378                                         e = MemberLookup(ec, type, Name, loc);
4379                                         if (e != null) {
4380                                                 lookups.Add(e);
4381                                                 typelookups.Add(type);
4382                                         }
4383                                 }
4384                                 if (lookups.Count == 1) { 
4385                                         e = (Expression)lookups[0];
4386                                 } else {
4387                                         if (lookups.Count > 1) {
4388                                                 StringBuilder sb = new StringBuilder();
4389                                                 foreach(Type type in typelookups)
4390                                                         sb.Append("'" + type.FullName + "'");                                           
4391                                                 Error (-1, "The name '" + Name + "' can be resolved to a member of more than one standard module: " + sb.ToString() + ". Please fully qualify it.");
4392                                                 return null;
4393                                         }
4394                                 }
4395                         }
4396
4397 // #52067 - End
4398
4399                         if (e == null) {
4400                         
4401                 /* preparing to support automatic definition of variables on first usage with Option Explicit Off
4402                         
4403                         Isn't good enough to enable just now (tries to define some internal links and breaks on emit)
4404                         
4405                                 if (Name.IndexOf ('.') == -1 && current_block != null && !Mono.MonoBASIC.Parser.OptionExplicit) {
4406                                 
4407                                         // while looking for a real solution
4408                                         if (Name != "anything")
4409                                                 return DoResolveType (ec);
4410                                                 
4411                                         Console.WriteLine("Implicitly adding a variable named '{0}'", Name);
4412                                         
4413                                         // TODO: look at type-suffixes to correct name and type
4414                                         Expression type = Mono.MonoBASIC.Parser.DecomposeQI("System.Object", loc);
4415                                         
4416                                         current_block.AddVariable(ec, type, Name, loc);
4417                                 
4418                                         LocalVariableReference var = new LocalVariableReference (current_block, Name, loc);
4419                                         if (right_side != null)
4420                                                 return var.ResolveLValue (ec, right_side);
4421                                         else
4422                                                 return var.Resolve (ec);
4423                                 } else
4424                 */
4425                                         return DoResolveType (ec);
4426                         }
4427                         
4428                         if (e is TypeExpr)
4429                                 return e;
4430
4431                         if (e is IMemberExpr) {
4432                                 if ((e is MethodGroupExpr) && !is_invocation && !is_addressof) {
4433                                         Expression inv = new Invocation (this, new ArrayList (), loc);
4434                                         return inv.Resolve (ec);
4435                                 }
4436                                 e = MemberAccess.ResolveMemberAccess (ec, e, null, loc, this);
4437                                 if (e == null)
4438                                         return null;
4439
4440                                 if (e is PropertyGroupExpr && is_invocation) // We dont know the arguments yet
4441                                         return e;
4442
4443                                 IMemberExpr me = e as IMemberExpr;
4444                                 if (me == null)
4445                                         return e;
4446
4447                                 // This fails if ResolveMemberAccess() was unable to decide whether
4448                                 // it's a field or a type of the same name.
4449                                 if (!me.IsStatic && (me.InstanceExpression == null))
4450                                         return e;
4451
4452 /* FIXME    If this is not commented out, it seems that it's not possible to reach class members in mBas.
4453             Maybe a grammar-related problem?
4454
4455                                 if (!me.IsStatic &&
4456                                     TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) {
4457                                         Error (38, "Cannot access nonstatic member '" + me.Name + "' of " +
4458                                                "outer type '" + me.DeclaringType + "' via nested type '" +
4459                                                me.InstanceExpression.Type + "'");
4460                                         return null;
4461                                 }
4462 */
4463                                 bool isPropertyGroup = (e is PropertyGroupExpr);
4464                                 if (right_side != null)
4465                                         e = e.DoResolveLValue (ec, right_side);
4466                                 else
4467                                         e = e.DoResolve (ec);
4468
4469                                 if (e == null && isPropertyGroup && !is_invocation)
4470                                          Error (30057, "Property '" + Name + "' cannot be invoked with given arguments");
4471                                          
4472                                 return e;
4473                         }
4474
4475                         if (ec.IsStatic || ec.IsFieldInitializer) {
4476                                 if (allow_static)
4477                                         return e;
4478
4479                                 return MemberStaticCheck (ec, e);
4480                         }
4481
4482                         return e;
4483                 }
4484                 
4485                 public override void Emit (EmitContext ec)
4486                 {
4487                         //
4488                         // If this is ever reached, then we failed to
4489                         // find the name as a namespace
4490                         //
4491
4492                         Error (30451, "The name '" + Name +
4493                                "' does not exist in the class '" +
4494                                ec.DeclSpace.Name + "'");
4495                 }
4496
4497                 public override string ToString ()
4498                 {
4499                         return Name;
4500                 }
4501         }
4502         
4503         /// <summary>
4504         ///   Fully resolved expression that evaluates to a type
4505         /// </summary>
4506         public class TypeExpr : Expression, ITypeExpression {
4507                 public TypeExpr (Type t, Location l)
4508                 {
4509                         Type = t;
4510                         eclass = ExprClass.Type;
4511                         loc = l;
4512                 }
4513
4514                 public virtual Expression DoResolveType (EmitContext ec)
4515                 {
4516                         return this;
4517                 }
4518
4519                 override public Expression DoResolve (EmitContext ec)
4520                 {
4521                         return this;
4522                 }
4523
4524                 override public void Emit (EmitContext ec)
4525                 {
4526                         throw new Exception ("Should never be called");
4527                 }
4528
4529                 public override string ToString ()
4530                 {
4531                         return Type.ToString ();
4532                 }
4533         }
4534
4535         /// <summary>
4536         ///   Used to create types from a fully qualified name.  These are just used
4537         ///   by the parser to setup the core types.  A TypeLookupExpression is always
4538         ///   classified as a type.
4539         /// </summary>
4540         public class TypeLookupExpression : TypeExpr {
4541                 string name;
4542                 
4543                 public TypeLookupExpression (string name) : base (null, Location.Null)
4544                 {
4545                         this.name = name;
4546                 }
4547
4548                 public override Expression DoResolveType (EmitContext ec)
4549                 {
4550                         if (type == null)
4551                                 type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
4552                         return this;
4553                 }
4554
4555                 public override Expression DoResolve (EmitContext ec)
4556                 {
4557                         return DoResolveType (ec);
4558                 }
4559
4560                 public override void Emit (EmitContext ec)
4561                 {
4562                         throw new Exception ("Should never be called");
4563                 }
4564
4565                 public override string ToString ()
4566                 {
4567                         return name;
4568                 }
4569         }
4570
4571         /// <summary>
4572         ///   MethodGroup Expression.
4573         ///  
4574         ///   This is a fully resolved expression that evaluates to a type
4575         /// </summary>
4576         public class MethodGroupExpr : Expression, IMemberExpr {
4577                 public MethodBase [] Methods;
4578                 Expression instance_expression = null;
4579                 bool is_explicit_impl = false;
4580                 
4581                 public MethodGroupExpr (MemberInfo [] mi, Location l)
4582                 {
4583                         Methods = new MethodBase [mi.Length];
4584                         mi.CopyTo (Methods, 0);
4585                         eclass = ExprClass.MethodGroup;
4586                         type = TypeManager.object_type;
4587                         loc = l;
4588                 }
4589
4590                 public MethodGroupExpr (ArrayList list, Location l)
4591                 {
4592                         Methods = new MethodBase [list.Count];
4593
4594                         try {
4595                                 list.CopyTo (Methods, 0);
4596                         } catch {
4597                                 foreach (MemberInfo m in list){
4598                                         if (!(m is MethodBase)){
4599                                                 Console.WriteLine ("Name " + m.Name);
4600                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4601                                         }
4602                                 }
4603                                 throw;
4604                         }
4605                         loc = l;
4606                         eclass = ExprClass.MethodGroup;
4607                         type = TypeManager.object_type;
4608                 }
4609
4610                 public Type DeclaringType {
4611                         get {
4612                                 return Methods [0].DeclaringType;
4613                         }
4614                 }
4615                 
4616                 //
4617                 // 'A method group may have associated an instance expression' 
4618                 // 
4619                 public Expression InstanceExpression {
4620                         get {
4621                                 return instance_expression;
4622                         }
4623
4624                         set {
4625                                 instance_expression = value;
4626                         }
4627                 }
4628
4629                 public bool IsExplicitImpl {
4630                         get {
4631                                 return is_explicit_impl;
4632                         }
4633
4634                         set {
4635                                 is_explicit_impl = value;
4636                         }
4637                 }
4638
4639                 public string Name {
4640                         get {
4641                                 return Methods [0].Name;
4642                         }
4643                 }
4644
4645                 public bool IsInstance {
4646                         get {
4647                                 foreach (MethodBase mb in Methods)
4648                                         if (!mb.IsStatic)
4649                                                 return true;
4650
4651                                 return false;
4652                         }
4653                 }
4654
4655                 public bool IsStatic {
4656                         get {
4657                                 foreach (MethodBase mb in Methods)
4658                                         if (mb.IsStatic)
4659                                                 return true;
4660
4661                                 return false;
4662                         }
4663                 }
4664                 
4665                 override public Expression DoResolve (EmitContext ec)
4666                 {
4667                         if (instance_expression != null) {
4668                                 instance_expression = instance_expression.DoResolve (ec);
4669                                 if (instance_expression == null)
4670                                         return null;
4671                         }
4672
4673                         return this;
4674                 }
4675
4676                 public void ReportUsageError ()
4677                 {
4678                         Report.Error (654, loc, "Method '" + Methods [0].DeclaringType + "." +
4679                                       Methods [0].Name + "()' is referenced without parentheses");
4680                 }
4681
4682                 override public void Emit (EmitContext ec)
4683                 {
4684                         ReportUsageError ();
4685                 }
4686
4687                 bool RemoveMethods (bool keep_static)
4688                 {
4689                         ArrayList smethods = new ArrayList ();
4690
4691                         foreach (MethodBase mb in Methods){
4692                                 if (mb.IsStatic == keep_static)
4693                                         smethods.Add (mb);
4694                         }
4695
4696                         if (smethods.Count == 0)
4697                                 return false;
4698
4699                         Methods = new MethodBase [smethods.Count];
4700                         smethods.CopyTo (Methods, 0);
4701
4702                         return true;
4703                 }
4704                 
4705                 /// <summary>
4706                 ///   Removes any instance methods from the MethodGroup, returns
4707                 ///   false if the resulting set is empty.
4708                 /// </summary>
4709                 public bool RemoveInstanceMethods ()
4710                 {
4711                         return RemoveMethods (true);
4712                 }
4713
4714                 /// <summary>
4715                 ///   Removes any static methods from the MethodGroup, returns
4716                 ///   false if the resulting set is empty.
4717                 /// </summary>
4718                 public bool RemoveStaticMethods ()
4719                 {
4720                         return RemoveMethods (false);
4721                 }
4722         }
4723
4724         /// <summary>
4725         ///   Property Group Expression.
4726         ///  
4727         /// </summary>
4728         public class PropertyGroupExpr : ExpressionStatement, IMemberExpr {
4729                 public PropertyInfo [] Properties;
4730                 Expression instance_expression = null;
4731                 bool is_explicit_impl = false;
4732                 MethodBase method = null;
4733                 bool indexer_access_req = false;
4734                 ArrayList arguments = null;
4735                 
4736                 public PropertyGroupExpr (MemberInfo [] mi, Location l)
4737                 {
4738                         Properties = new PropertyInfo [mi.Length];
4739                         mi.CopyTo (Properties, 0);
4740                         eclass = ExprClass.PropertyAccess;
4741                         type = TypeManager.object_type;
4742                         loc = l;
4743                 }
4744
4745                 public PropertyGroupExpr (MemberInfo [] mi, ArrayList args, Expression expr, Location l)
4746                         : this (mi, l)
4747                 {
4748                         arguments = args;
4749                         instance_expression = expr;
4750                 }
4751
4752                 public PropertyGroupExpr (ArrayList list, Location l)
4753                 {
4754                         Properties = new PropertyInfo [list.Count];
4755
4756                         try {
4757                                 list.CopyTo (Properties, 0);
4758                         } catch {
4759                                 foreach (MemberInfo m in list){
4760                                         if (!(m is PropertyInfo)){
4761                                                 Console.WriteLine ("Name " + m.Name);
4762                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4763                                         }
4764                                 }
4765                                 throw;
4766                         }
4767                         loc = l;
4768                         eclass = ExprClass.PropertyAccess;
4769                         type = TypeManager.object_type;
4770                 }
4771
4772                 public ArrayList Arguments {
4773                         get {
4774                                 return arguments;
4775                         }
4776                         set {
4777                                 arguments = value;
4778                         }
4779                 }
4780
4781                 public Type DeclaringType {
4782                         get {
4783                                 return Properties [0].DeclaringType;
4784                         }
4785                 }
4786
4787                 public bool IndexerAccessRequired {
4788                         get {
4789                                 return indexer_access_req;
4790                         }
4791                 }
4792
4793                 //
4794                 // 'A method group may have associated an instance expression' 
4795                 // 
4796                 public Expression InstanceExpression {
4797                         get {
4798                                 return instance_expression;
4799                         }
4800
4801                         set {
4802                                 instance_expression = value;
4803                         }
4804                 }
4805
4806                 public bool IsExplicitImpl {
4807                         get {
4808                                 return is_explicit_impl;
4809                         }
4810
4811                         set {
4812                                 is_explicit_impl = value;
4813                         }
4814                 }
4815
4816                 public string Name {
4817                         get {
4818                                 return Properties [0].Name;
4819                         }
4820                 }
4821
4822                 public bool IsInstance {
4823                         get {
4824                                 foreach (PropertyInfo pi in Properties) {
4825                                         MethodInfo mi = pi.GetGetMethod ();
4826                                         if (mi != null && !mi.IsStatic)
4827                                                 return true;
4828                                         mi = pi.GetSetMethod ();
4829                                         if (mi != null && !mi.IsStatic)
4830                                                 return true;
4831                                 }               
4832                                 return false;
4833                         }
4834                 }
4835
4836                 public bool IsStatic {
4837                         get {
4838                                 return (!IsInstance);
4839                         }
4840                 }
4841                 
4842                 public ArrayList GetAccessors () {
4843                         ArrayList GetAccessors = new ArrayList ();
4844                         foreach (PropertyInfo pi in Properties) {
4845                                 if (pi.GetGetMethod () != null)
4846                                         GetAccessors.Add (pi.GetGetMethod ());
4847 /*
4848                                 else if (pi.GetGetMethod (true) != null)
4849                                         GetAccessors.Add (pi.GetGetMethod (true));
4850 */
4851                                         
4852                         }
4853                         return GetAccessors;
4854                 }
4855                 
4856                 public ArrayList SetAccessors () {
4857                         ArrayList SetAccessors = new ArrayList ();
4858                         foreach (PropertyInfo pi in Properties) {
4859                                 if (pi.GetSetMethod () != null)
4860                                         SetAccessors.Add (pi.GetSetMethod ());
4861 /*
4862                                 else if (pi.GetSetMethod (true) != null)
4863                                         SetAccessors.Add (pi.GetSetMethod (true));
4864 */
4865                         }
4866                         return SetAccessors;
4867                 }
4868
4869                 override public Expression DoResolve (EmitContext ec)
4870                 {
4871                         if (instance_expression != null) {
4872                                 instance_expression = instance_expression.DoResolve (ec);
4873                                 if (instance_expression == null)
4874                                         return null;
4875                         }
4876
4877                         ArrayList members = GetAccessors ();
4878                         if (members == null || members.Count == 0) {
4879                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'get' accesor");
4880                                 return null;
4881                         }
4882
4883                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4884                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4885                         if ((method as MethodInfo) != null) {
4886                                 MethodInfo mi = method as MethodInfo;
4887                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
4888                                 indexer_access_req = false;
4889                                 eclass = ExprClass.Value;
4890                                 return this;
4891                         } else {
4892                                 // find a get method that doesnt take any arguments. Check the return type of
4893                                 // that method to find out if indexer access is required. Leave the rest to
4894                                 // 'Invocation's Resolve'
4895                                 method = Invocation.OverloadResolve (ec, m_expr, null, loc);
4896                                 if (method != null) {
4897                                         MethodInfo mi = method as MethodInfo;
4898                                         Type ret_type = mi.ReturnType;
4899                                         if (ret_type.IsArray)
4900                                                 indexer_access_req = true;
4901                                         else {
4902                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, ret_type, loc);
4903                                                 if (list != null && list.getters.Count > 0)
4904                                                         indexer_access_req = true;
4905                                                 else 
4906                                                         return null;
4907                                         }
4908                                         Arguments = null;
4909                                         type = mi.ReturnType;
4910                                         return this;
4911                                 }
4912                         }
4913
4914                         return null;
4915                 }
4916
4917                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side) {
4918                         if (instance_expression != null) {
4919                                 instance_expression = instance_expression.DoResolve (ec);
4920                                 if (instance_expression == null)
4921                                         return null;
4922                         }
4923
4924                         ArrayList members = SetAccessors ();
4925                         if (members == null || members.Count == 0) {
4926                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'set' accesor");
4927                                 return null;
4928                         }
4929
4930                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4931                         if (arguments == null)
4932                                 arguments = new ArrayList ();
4933                         arguments.Add (new Argument (right_side, Argument.AType.Expression));
4934                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4935                         if (method != null) {
4936                                 //MethodInfo mi = method as MethodInfo;
4937                                 type = TypeManager.void_type; //TypeManager.TypeToCoreType (mi.ReturnType);
4938                                 eclass = ExprClass.Value;
4939                                 indexer_access_req = false;
4940                                 return this;
4941                         } else {
4942                                 // Look for properties that do not take any arguments.
4943                                 // Check if the return type has any indexers
4944                                 arguments = null;
4945                                 DoResolve (ec);
4946                                 if (method != null) {
4947                                         MethodInfo mi = method as MethodInfo;
4948                                         Type ret_type = mi.ReturnType;
4949                                         if (ret_type.IsArray)
4950                                                 indexer_access_req = true;
4951                                         else {
4952
4953                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, 
4954                                                                         ret_type, loc);
4955                                                 if (list != null && list.setters.Count > 0)
4956                                                         indexer_access_req = true;
4957                                                 else 
4958                                                         return null;
4959                                         }
4960                                         type = mi.ReturnType;
4961                                         return this;
4962                                 }
4963                         }
4964
4965                         return null;
4966                 }
4967
4968                 override public void Emit (EmitContext ec)
4969                 {
4970                         if (Arguments == null)
4971                                 Arguments = new ArrayList ();
4972                         Invocation.EmitCall (ec, false, IsStatic, instance_expression, method, null, Arguments, loc);
4973                 }
4974
4975                 override public void EmitStatement (EmitContext ec) 
4976                 {
4977                         Emit (ec);
4978                 }
4979
4980         }
4981
4982         /// <summary>
4983         ///   Fully resolved expression that evaluates to a Field
4984         /// </summary>
4985         public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr {
4986                 public readonly FieldInfo FieldInfo;
4987                 Expression instance_expr;
4988                 
4989                 public FieldExpr (FieldInfo fi, Location l)
4990                 {
4991                         FieldInfo = fi;
4992                         eclass = ExprClass.Variable;
4993                         type = fi.FieldType;
4994                         loc = l;
4995                 }
4996
4997                 public string Name {
4998                         get {
4999                                 return FieldInfo.Name;
5000                         }
5001                 }
5002
5003                 public bool IsInstance {
5004                         get {
5005                                 return !FieldInfo.IsStatic;
5006                         }
5007                 }
5008
5009                 public bool IsStatic {
5010                         get {
5011                                 return FieldInfo.IsStatic;
5012                         }
5013                 }
5014
5015                 public Type DeclaringType {
5016                         get {
5017                                 return FieldInfo.DeclaringType;
5018                         }
5019                 }
5020
5021                 public Expression InstanceExpression {
5022                         get {
5023                                 return instance_expr;
5024                         }
5025
5026                         set {
5027                                 instance_expr = value;
5028                         }
5029                 }
5030
5031                 override public Expression DoResolve (EmitContext ec)
5032                 {
5033                         if (!FieldInfo.IsStatic){
5034                                 if (instance_expr == null){
5035                                         throw new Exception ("non-static FieldExpr without instance var\n" +
5036                                                              "You have to assign the Instance variable\n" +
5037                                                              "Of the FieldExpr to set this\n");
5038                                 }
5039
5040                                 // Resolve the field's instance expression while flow analysis is turned
5041                                 // off: when accessing a field "a.b", we must check whether the field
5042                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
5043                                 instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
5044                                                                        ResolveFlags.DisableFlowAnalysis);
5045                                 if (instance_expr == null)
5046                                         return null;
5047                         }
5048
5049                         // If the instance expression is a local variable or parameter.
5050                         IVariable var = instance_expr as IVariable;
5051                         if ((var != null) && !var.IsFieldAssigned (ec, FieldInfo.Name, loc))
5052                                 return null;
5053
5054                         return this;
5055                 }
5056
5057                 void Report_AssignToReadonly (bool is_instance)
5058                 {
5059                         string msg;
5060                         
5061                         if (is_instance)
5062                                 msg = "Readonly field can not be assigned outside " +
5063                                 "of constructor or variable initializer";
5064                         else
5065                                 msg = "A static readonly field can only be assigned in " +
5066                                 "a static constructor";
5067
5068                         Report.Error (is_instance ? 191 : 198, loc, msg);
5069                 }
5070                 
5071                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5072                 {
5073                         IVariable var = instance_expr as IVariable;
5074                         if (var != null)
5075                                 var.SetFieldAssigned (ec, FieldInfo.Name);
5076
5077                         Expression e = DoResolve (ec);
5078
5079                         if (e == null)
5080                                 return null;
5081                         
5082                         if (!FieldInfo.IsInitOnly)
5083                                 return this;
5084
5085                         //
5086                         // InitOnly fields can only be assigned in constructors
5087                         //
5088
5089                         if (ec.IsConstructor)
5090                                 return this;
5091
5092                         Report_AssignToReadonly (true);
5093                         
5094                         return null;
5095                 }
5096
5097                 override public void Emit (EmitContext ec)
5098                 {
5099                         ILGenerator ig = ec.ig;
5100                         bool is_volatile = false;
5101
5102                         if (FieldInfo is FieldBuilder){
5103                                 FieldBase f = TypeManager.GetField (FieldInfo);
5104
5105                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5106                                         is_volatile = true;
5107                                 
5108                                 f.status |= Field.Status.USED;
5109                         }
5110                         
5111                         if (FieldInfo.IsStatic){
5112                                 if (is_volatile)
5113                                         ig.Emit (OpCodes.Volatile);
5114                                 
5115                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
5116                         } else {
5117                                 if (instance_expr.Type.IsValueType){
5118                                         IMemoryLocation ml;
5119                                         LocalTemporary tempo = null;
5120                                         
5121                                         if (!(instance_expr is IMemoryLocation)){
5122                                                 tempo = new LocalTemporary (
5123                                                         ec, instance_expr.Type);
5124
5125                                                 InstanceExpression.Emit (ec);
5126                                                 tempo.Store (ec);
5127                                                 ml = tempo;
5128                                         } else
5129                                                 ml = (IMemoryLocation) instance_expr;
5130
5131                                         ml.AddressOf (ec, AddressOp.Load);
5132                                 } else 
5133                                         instance_expr.Emit (ec);
5134
5135                                 if (is_volatile)
5136                                         ig.Emit (OpCodes.Volatile);
5137                                 
5138                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
5139                         }
5140                 }
5141
5142                 public void EmitAssign (EmitContext ec, Expression source)
5143                 {
5144                         FieldAttributes fa = FieldInfo.Attributes;
5145                         bool is_static = (fa & FieldAttributes.Static) != 0;
5146                         bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
5147                         ILGenerator ig = ec.ig;
5148
5149                         if (is_readonly && !ec.IsConstructor){
5150                                 Report_AssignToReadonly (!is_static);
5151                                 return;
5152                         }
5153                         
5154                         if (!is_static){
5155                                 Expression instance = instance_expr;
5156
5157                                 if (instance.Type.IsValueType){
5158                                         if (instance is IMemoryLocation){
5159                                                 IMemoryLocation ml = (IMemoryLocation) instance;
5160
5161                                                 ml.AddressOf (ec, AddressOp.Store);
5162                                         } else
5163                                                 throw new Exception ("The " + instance + " of type " +
5164                                                                      instance.Type +
5165                                                                      " represents a ValueType and does " +
5166                                                                      "not implement IMemoryLocation");
5167                                 } else
5168                                         instance.Emit (ec);
5169                         }
5170                         source.Emit (ec);
5171
5172                         if (FieldInfo is FieldBuilder){
5173                                 FieldBase f = TypeManager.GetField (FieldInfo);
5174                                 
5175                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5176                                         ig.Emit (OpCodes.Volatile);
5177                         }
5178                         
5179                         if (is_static)
5180                                 ig.Emit (OpCodes.Stsfld, FieldInfo);
5181                         else 
5182                                 ig.Emit (OpCodes.Stfld, FieldInfo);
5183
5184                         if (FieldInfo is FieldBuilder){
5185                                 FieldBase f = TypeManager.GetField (FieldInfo);
5186
5187                                 f.status |= Field.Status.ASSIGNED;
5188                         }
5189                 }
5190                 
5191                 public void AddressOf (EmitContext ec, AddressOp mode)
5192                 {
5193                         ILGenerator ig = ec.ig;
5194                         
5195                         if (FieldInfo is FieldBuilder){
5196                                 FieldBase f = TypeManager.GetField (FieldInfo);
5197                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5198                                         ig.Emit (OpCodes.Volatile);
5199                         }
5200
5201                         if (FieldInfo is FieldBuilder){
5202                                 FieldBase f = TypeManager.GetField (FieldInfo);
5203
5204                                 if ((mode & AddressOp.Store) != 0)
5205                                         f.status |= Field.Status.ASSIGNED;
5206                                 if ((mode & AddressOp.Load) != 0)
5207                                         f.status |= Field.Status.USED;
5208                         }
5209
5210                         //
5211                         // Handle initonly fields specially: make a copy and then
5212                         // get the address of the copy.
5213                         //
5214                         if (FieldInfo.IsInitOnly && !ec.IsConstructor){
5215                                 LocalBuilder local;
5216                                 
5217                                 Emit (ec);
5218                                 local = ig.DeclareLocal (type);
5219                                 ig.Emit (OpCodes.Stloc, local);
5220                                 ig.Emit (OpCodes.Ldloca, local);
5221                                 return;
5222                         }
5223
5224                         if (FieldInfo.IsStatic)
5225                                 ig.Emit (OpCodes.Ldsflda, FieldInfo);
5226                         else {
5227                                 if (instance_expr is IMemoryLocation)
5228                                         ((IMemoryLocation)instance_expr).AddressOf (ec, AddressOp.LoadStore);
5229                                 else
5230                                         instance_expr.Emit (ec);
5231                                 ig.Emit (OpCodes.Ldflda, FieldInfo);
5232                         }
5233                 }
5234         }
5235         
5236         /// <summary>
5237         ///   Expression that evaluates to a Property.  The Assign class
5238         ///   might set the 'Value' expression if we are in an assignment.
5239         ///
5240         ///   This is not an LValue because we need to re-write the expression, we
5241         ///   can not take data from the stack and store it.  
5242         /// </summary>
5243         public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
5244                 public readonly PropertyInfo PropertyInfo;
5245                 public bool IsBase;
5246                 MethodInfo getter, setter;
5247                 bool is_static;
5248                 public ArrayList PropertyArgs;
5249
5250                 Expression instance_expr;
5251
5252                 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
5253                 {
5254                         PropertyInfo = pi;
5255                         eclass = ExprClass.PropertyAccess;
5256                         PropertyArgs = null;
5257                         is_static = false;
5258                         loc = l;
5259
5260                         type = TypeManager.TypeToCoreType (pi.PropertyType);
5261
5262                         ResolveAccessors (ec);
5263                 }
5264
5265                 public string Name {
5266                         get {
5267                                 return PropertyInfo.Name;
5268                         }
5269                 }
5270
5271                 public bool IsInstance {
5272                         get {
5273                                 return !is_static;
5274                         }
5275                 }
5276
5277                 public bool IsStatic {
5278                         get {
5279                                 return is_static;
5280                         }
5281                 }
5282                 
5283                 public Type DeclaringType {
5284                         get {
5285                                 return PropertyInfo.DeclaringType;
5286                         }
5287                 }
5288
5289                 //
5290                 // The instance expression associated with this expression
5291                 //
5292                 public Expression InstanceExpression {
5293                         set {
5294                                 instance_expr = value;
5295                         }
5296
5297                         get {
5298                                 return instance_expr;
5299                         }
5300                 }
5301
5302                 public bool VerifyAssignable ()
5303                 {
5304                         if (!PropertyInfo.CanWrite){
5305                                 Report.Error (200, loc, 
5306                                               "The property '" + PropertyInfo.Name +
5307                                               "' can not be assigned to, as it has not set accessor");
5308                                 return false;
5309                         }
5310
5311                         return true;
5312                 }
5313
5314                 void ResolveAccessors (EmitContext ec)
5315                 {
5316                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
5317                         MemberInfo [] group;
5318                         
5319                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5320                                                               MemberTypes.Method, flags, "get_" + PropertyInfo.Name);
5321
5322                         //
5323                         // The first method is the closest to us
5324                         //
5325                         if (group != null && group.Length > 0){
5326                                 getter = (MethodInfo) group [0];
5327
5328                                 if (getter.IsStatic)
5329                                         is_static = true;
5330                         }                       
5331
5332                         //
5333                         // The first method is the closest to us
5334                         //
5335                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5336                                                           MemberTypes.Method, flags, "set_" + PropertyInfo.Name);
5337                         if (group != null && group.Length > 0){
5338                                 setter = (MethodInfo) group [0];
5339                                 if (setter.IsStatic)
5340                                         is_static = true;
5341                         }
5342                 }
5343
5344                 override public Expression DoResolve (EmitContext ec)
5345                 {
5346                         if (getter == null){
5347                                 Report.Error (30524, loc, 
5348                                               "The property '" + PropertyInfo.Name +
5349                                               "' can not be used in " +
5350                                               "this context because it lacks a get accessor");
5351                                 return null;
5352                         }
5353
5354                         if ((instance_expr == null) && ec.IsStatic && !is_static) {
5355                                 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
5356                                 return null;
5357                         }
5358
5359                         if (instance_expr != null) {
5360                                 instance_expr = instance_expr.DoResolve (ec);
5361                                 if (instance_expr == null)
5362                                         return null;
5363                         }
5364
5365                         return this;
5366                 }
5367
5368                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5369                 {
5370                         if (setter == null){
5371                                 Report.Error (30526, loc, 
5372                                               "The property '" + PropertyInfo.Name +
5373                                               "' can not be used in " +
5374                                               "this context because it lacks a set accessor");
5375                                 return null;
5376                         }
5377
5378                         if (instance_expr != null) {
5379                                 instance_expr = instance_expr.DoResolve (ec);
5380                                 if (instance_expr == null)
5381                                         return null;
5382                         }
5383
5384                         return this;
5385                 }
5386
5387                 override public void Emit (EmitContext ec)
5388                 {
5389                         //
5390                         // Special case: length of single dimension array property is turned into ldlen
5391                         //
5392                         if ((getter == TypeManager.system_int_array_get_length) ||
5393                             (getter == TypeManager.int_array_get_length)){
5394                                 Type iet = instance_expr.Type;
5395
5396                                 //
5397                                 // System.Array.Length can be called, but the Type does not
5398                                 // support invoking GetArrayRank, so test for that case first
5399                                 //
5400                                 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
5401                                         instance_expr.Emit (ec);
5402                                         ec.ig.Emit (OpCodes.Ldlen);
5403                                         return;
5404                                 }
5405                         }
5406                         if (PropertyArgs == null)
5407                                 PropertyArgs = new ArrayList ();
5408                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, PropertyArgs, loc);
5409                 }
5410
5411                 //
5412                 // Implements the IAssignMethod interface for assignments
5413                 //
5414                 public void EmitAssign (EmitContext ec, Expression source)
5415                 {
5416                         Argument arg = new Argument (source, Argument.AType.Expression);
5417                         ArrayList args = new ArrayList ();
5418 //HERE
5419                         args.Add (arg);
5420                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, PropertyArgs,loc);
5421                 }
5422
5423                 override public void EmitStatement (EmitContext ec)
5424                 {
5425                         Emit (ec);
5426                         ec.ig.Emit (OpCodes.Pop);
5427                 }
5428         }
5429
5430         /// <summary>
5431         ///   Fully resolved expression that evaluates to an Event
5432         /// </summary>
5433         public class EventExpr : Expression, IMemberExpr {
5434                 public readonly EventInfo EventInfo;
5435                 public Expression instance_expr;
5436
5437                 bool is_static;
5438                 MethodInfo add_accessor, remove_accessor;
5439                 
5440                 public EventExpr (EventInfo ei, Location loc)
5441                 {
5442                         EventInfo = ei;
5443                         this.loc = loc;
5444                         eclass = ExprClass.EventAccess;
5445
5446                         add_accessor = TypeManager.GetAddMethod (ei);
5447                         remove_accessor = TypeManager.GetRemoveMethod (ei);
5448                         
5449                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
5450                                 is_static = true;
5451
5452                         if (EventInfo is MyEventBuilder)
5453                                 type = ((MyEventBuilder) EventInfo).EventType;
5454                         else
5455                                 type = EventInfo.EventHandlerType;
5456                 }
5457
5458                 public string Name {
5459                         get {
5460                                 return EventInfo.Name;
5461                         }
5462                 }
5463
5464                 public bool IsInstance {
5465                         get {
5466                                 return !is_static;
5467                         }
5468                 }
5469
5470                 public bool IsStatic {
5471                         get {
5472                                 return is_static;
5473                         }
5474                 }
5475
5476                 public Type DeclaringType {
5477                         get {
5478                                 return EventInfo.DeclaringType;
5479                         }
5480                 }
5481
5482                 public Expression InstanceExpression {
5483                         get {
5484                                 return instance_expr;
5485                         }
5486
5487                         set {
5488                                 instance_expr = value;
5489                         }
5490                 }
5491
5492                 Expression field_expr = null;
5493
5494                 public override Expression DoResolve (EmitContext ec)
5495                 {
5496                         if (instance_expr != null) {
5497                                 instance_expr = instance_expr.DoResolve (ec);
5498                                 if (instance_expr == null)
5499                                         return null;
5500                         }
5501
5502                         if (this.DeclaringType == ec.ContainerType)     {
5503                                 MemberInfo mi = GetFieldFromEvent (this);
5504                                 if (mi == null)
5505                                         return null;
5506                                 field_expr = ExprClassFromMemberInfo (ec, mi, loc);
5507                                 ((FieldExpr) field_expr).InstanceExpression = instance_expr;
5508                                 field_expr = field_expr.DoResolve (ec);
5509                                 if (field_expr == null)
5510                                         return null;
5511                         }
5512
5513                         return this;
5514                 }
5515
5516                 public override void Emit (EmitContext ec)
5517                 {
5518                         if (field_expr != null)
5519                                 field_expr.Emit (ec);
5520                 }
5521
5522                 public void EmitAddOrRemove (EmitContext ec, Expression source)
5523                 {
5524                         Expression handler = ((Binary) source).Right;
5525                         
5526                         Argument arg = new Argument (handler, Argument.AType.Expression);
5527                         ArrayList args = new ArrayList ();
5528                                 
5529                         args.Add (arg);
5530                         
5531                         if (((Binary) source).Oper == Binary.Operator.Addition)
5532                                 Invocation.EmitCall (
5533                                         ec, false, IsStatic, instance_expr, add_accessor, args, loc);
5534                         else
5535                                 Invocation.EmitCall (
5536                                         ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
5537                 }
5538         }
5539 }