fix for different results message
[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         public class DecoratedIdentifier : Expression {
4504                 Expression id;
4505                 Type decoration;
4506
4507                 public DecoratedIdentifier (Expression id, Type decoration)
4508                 {
4509                         this.id = id;
4510                         this.decoration = decoration;
4511                 }
4512
4513                 override public Expression DoResolve (EmitContext ec)
4514                 {
4515                         if (id == null || decoration == null)
4516                                 return null;
4517                         
4518                         Expression ret = id.DoResolve (ec);
4519                         if (ret.Type != TypeManager.TypeToCoreType (decoration)) {
4520                                 Report.Error (30277, id.Location, "Type character '" + decoration + "' does not match declared type '" + ret.Type  + "'."); 
4521                                 return null;
4522                         }
4523
4524                         return ret;
4525                 }
4526                 
4527                 override public void Emit (EmitContext ec)
4528                 {
4529                         throw new InternalErrorException ("Should never be called");
4530                 }
4531         }
4532         
4533         /// <summary>
4534         ///   Fully resolved expression that evaluates to a type
4535         /// </summary>
4536         public class TypeExpr : Expression, ITypeExpression {
4537                 public TypeExpr (Type t, Location l)
4538                 {
4539                         Type = t;
4540                         eclass = ExprClass.Type;
4541                         loc = l;
4542                 }
4543
4544                 public virtual Expression DoResolveType (EmitContext ec)
4545                 {
4546                         return this;
4547                 }
4548
4549                 override public Expression DoResolve (EmitContext ec)
4550                 {
4551                         return this;
4552                 }
4553
4554                 override public void Emit (EmitContext ec)
4555                 {
4556                         throw new Exception ("Should never be called");
4557                 }
4558
4559                 public override string ToString ()
4560                 {
4561                         return Type.ToString ();
4562                 }
4563         }
4564
4565         /// <summary>
4566         ///   Used to create types from a fully qualified name.  These are just used
4567         ///   by the parser to setup the core types.  A TypeLookupExpression is always
4568         ///   classified as a type.
4569         /// </summary>
4570         public class TypeLookupExpression : TypeExpr {
4571                 string name;
4572                 
4573                 public TypeLookupExpression (string name) : base (null, Location.Null)
4574                 {
4575                         this.name = name;
4576                 }
4577
4578                 public override Expression DoResolveType (EmitContext ec)
4579                 {
4580                         if (type == null)
4581                                 type = RootContext.LookupType (ec.DeclSpace, name, false, Location.Null);
4582                         return this;
4583                 }
4584
4585                 public override Expression DoResolve (EmitContext ec)
4586                 {
4587                         return DoResolveType (ec);
4588                 }
4589
4590                 public override void Emit (EmitContext ec)
4591                 {
4592                         throw new Exception ("Should never be called");
4593                 }
4594
4595                 public override string ToString ()
4596                 {
4597                         return name;
4598                 }
4599         }
4600
4601         /// <summary>
4602         ///   MethodGroup Expression.
4603         ///  
4604         ///   This is a fully resolved expression that evaluates to a type
4605         /// </summary>
4606         public class MethodGroupExpr : Expression, IMemberExpr {
4607                 public MethodBase [] Methods;
4608                 Expression instance_expression = null;
4609                 bool is_explicit_impl = false;
4610                 
4611                 public MethodGroupExpr (MemberInfo [] mi, Location l)
4612                 {
4613                         Methods = new MethodBase [mi.Length];
4614                         mi.CopyTo (Methods, 0);
4615                         eclass = ExprClass.MethodGroup;
4616                         type = TypeManager.object_type;
4617                         loc = l;
4618                 }
4619
4620                 public MethodGroupExpr (ArrayList list, Location l)
4621                 {
4622                         Methods = new MethodBase [list.Count];
4623
4624                         try {
4625                                 list.CopyTo (Methods, 0);
4626                         } catch {
4627                                 foreach (MemberInfo m in list){
4628                                         if (!(m is MethodBase)){
4629                                                 Console.WriteLine ("Name " + m.Name);
4630                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4631                                         }
4632                                 }
4633                                 throw;
4634                         }
4635                         loc = l;
4636                         eclass = ExprClass.MethodGroup;
4637                         type = TypeManager.object_type;
4638                 }
4639
4640                 public Type DeclaringType {
4641                         get {
4642                                 return Methods [0].DeclaringType;
4643                         }
4644                 }
4645                 
4646                 //
4647                 // 'A method group may have associated an instance expression' 
4648                 // 
4649                 public Expression InstanceExpression {
4650                         get {
4651                                 return instance_expression;
4652                         }
4653
4654                         set {
4655                                 instance_expression = value;
4656                         }
4657                 }
4658
4659                 public bool IsExplicitImpl {
4660                         get {
4661                                 return is_explicit_impl;
4662                         }
4663
4664                         set {
4665                                 is_explicit_impl = value;
4666                         }
4667                 }
4668
4669                 public string Name {
4670                         get {
4671                                 return Methods [0].Name;
4672                         }
4673                 }
4674
4675                 public bool IsInstance {
4676                         get {
4677                                 foreach (MethodBase mb in Methods)
4678                                         if (!mb.IsStatic)
4679                                                 return true;
4680
4681                                 return false;
4682                         }
4683                 }
4684
4685                 public bool IsStatic {
4686                         get {
4687                                 foreach (MethodBase mb in Methods)
4688                                         if (mb.IsStatic)
4689                                                 return true;
4690
4691                                 return false;
4692                         }
4693                 }
4694                 
4695                 override public Expression DoResolve (EmitContext ec)
4696                 {
4697                         if (instance_expression != null) {
4698                                 instance_expression = instance_expression.DoResolve (ec);
4699                                 if (instance_expression == null)
4700                                         return null;
4701                         }
4702
4703                         return this;
4704                 }
4705
4706                 public void ReportUsageError ()
4707                 {
4708                         Report.Error (654, loc, "Method '" + Methods [0].DeclaringType + "." +
4709                                       Methods [0].Name + "()' is referenced without parentheses");
4710                 }
4711
4712                 override public void Emit (EmitContext ec)
4713                 {
4714                         ReportUsageError ();
4715                 }
4716
4717                 bool RemoveMethods (bool keep_static)
4718                 {
4719                         ArrayList smethods = new ArrayList ();
4720
4721                         foreach (MethodBase mb in Methods){
4722                                 if (mb.IsStatic == keep_static)
4723                                         smethods.Add (mb);
4724                         }
4725
4726                         if (smethods.Count == 0)
4727                                 return false;
4728
4729                         Methods = new MethodBase [smethods.Count];
4730                         smethods.CopyTo (Methods, 0);
4731
4732                         return true;
4733                 }
4734                 
4735                 /// <summary>
4736                 ///   Removes any instance methods from the MethodGroup, returns
4737                 ///   false if the resulting set is empty.
4738                 /// </summary>
4739                 public bool RemoveInstanceMethods ()
4740                 {
4741                         return RemoveMethods (true);
4742                 }
4743
4744                 /// <summary>
4745                 ///   Removes any static methods from the MethodGroup, returns
4746                 ///   false if the resulting set is empty.
4747                 /// </summary>
4748                 public bool RemoveStaticMethods ()
4749                 {
4750                         return RemoveMethods (false);
4751                 }
4752         }
4753
4754         /// <summary>
4755         ///   Property Group Expression.
4756         ///  
4757         /// </summary>
4758         public class PropertyGroupExpr : ExpressionStatement, IMemberExpr {
4759                 public PropertyInfo [] Properties;
4760                 Expression instance_expression = null;
4761                 bool is_explicit_impl = false;
4762                 MethodBase method = null;
4763                 bool indexer_access_req = false;
4764                 ArrayList arguments = null;
4765                 
4766                 public PropertyGroupExpr (MemberInfo [] mi, Location l)
4767                 {
4768                         Properties = new PropertyInfo [mi.Length];
4769                         mi.CopyTo (Properties, 0);
4770                         eclass = ExprClass.PropertyAccess;
4771                         type = TypeManager.object_type;
4772                         loc = l;
4773                 }
4774
4775                 public PropertyGroupExpr (MemberInfo [] mi, ArrayList args, Expression expr, Location l)
4776                         : this (mi, l)
4777                 {
4778                         arguments = args;
4779                         instance_expression = expr;
4780                 }
4781
4782                 public PropertyGroupExpr (ArrayList list, Location l)
4783                 {
4784                         Properties = new PropertyInfo [list.Count];
4785
4786                         try {
4787                                 list.CopyTo (Properties, 0);
4788                         } catch {
4789                                 foreach (MemberInfo m in list){
4790                                         if (!(m is PropertyInfo)){
4791                                                 Console.WriteLine ("Name " + m.Name);
4792                                                 Console.WriteLine ("Found a: " + m.GetType ().FullName);
4793                                         }
4794                                 }
4795                                 throw;
4796                         }
4797                         loc = l;
4798                         eclass = ExprClass.PropertyAccess;
4799                         type = TypeManager.object_type;
4800                 }
4801
4802                 public ArrayList Arguments {
4803                         get {
4804                                 return arguments;
4805                         }
4806                         set {
4807                                 arguments = value;
4808                         }
4809                 }
4810
4811                 public Type DeclaringType {
4812                         get {
4813                                 return Properties [0].DeclaringType;
4814                         }
4815                 }
4816
4817                 public bool IndexerAccessRequired {
4818                         get {
4819                                 return indexer_access_req;
4820                         }
4821                 }
4822
4823                 //
4824                 // 'A method group may have associated an instance expression' 
4825                 // 
4826                 public Expression InstanceExpression {
4827                         get {
4828                                 return instance_expression;
4829                         }
4830
4831                         set {
4832                                 instance_expression = value;
4833                         }
4834                 }
4835
4836                 public bool IsExplicitImpl {
4837                         get {
4838                                 return is_explicit_impl;
4839                         }
4840
4841                         set {
4842                                 is_explicit_impl = value;
4843                         }
4844                 }
4845
4846                 public string Name {
4847                         get {
4848                                 return Properties [0].Name;
4849                         }
4850                 }
4851
4852                 public bool IsInstance {
4853                         get {
4854                                 foreach (PropertyInfo pi in Properties) {
4855                                         MethodInfo mi = pi.GetGetMethod ();
4856                                         if (mi != null && !mi.IsStatic)
4857                                                 return true;
4858                                         mi = pi.GetSetMethod ();
4859                                         if (mi != null && !mi.IsStatic)
4860                                                 return true;
4861                                 }               
4862                                 return false;
4863                         }
4864                 }
4865
4866                 public bool IsStatic {
4867                         get {
4868                                 return (!IsInstance);
4869                         }
4870                 }
4871                 
4872                 public ArrayList GetAccessors () {
4873                         ArrayList GetAccessors = new ArrayList ();
4874                         foreach (PropertyInfo pi in Properties) {
4875                                 if (pi.GetGetMethod () != null)
4876                                         GetAccessors.Add (pi.GetGetMethod ());
4877 /*
4878                                 else if (pi.GetGetMethod (true) != null)
4879                                         GetAccessors.Add (pi.GetGetMethod (true));
4880 */
4881                                         
4882                         }
4883                         return GetAccessors;
4884                 }
4885                 
4886                 public ArrayList SetAccessors () {
4887                         ArrayList SetAccessors = new ArrayList ();
4888                         foreach (PropertyInfo pi in Properties) {
4889                                 if (pi.GetSetMethod () != null)
4890                                         SetAccessors.Add (pi.GetSetMethod ());
4891 /*
4892                                 else if (pi.GetSetMethod (true) != null)
4893                                         SetAccessors.Add (pi.GetSetMethod (true));
4894 */
4895                         }
4896                         return SetAccessors;
4897                 }
4898
4899                 override public Expression DoResolve (EmitContext ec)
4900                 {
4901                         if (instance_expression != null) {
4902                                 instance_expression = instance_expression.DoResolve (ec);
4903                                 if (instance_expression == null)
4904                                         return null;
4905                         }
4906
4907                         ArrayList members = GetAccessors ();
4908                         if (members == null || members.Count == 0) {
4909                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'get' accesor");
4910                                 return null;
4911                         }
4912
4913                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4914                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4915                         if ((method as MethodInfo) != null) {
4916                                 MethodInfo mi = method as MethodInfo;
4917                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
4918                                 indexer_access_req = false;
4919                                 eclass = ExprClass.Value;
4920                                 return this;
4921                         } else {
4922                                 // find a get method that doesnt take any arguments. Check the return type of
4923                                 // that method to find out if indexer access is required. Leave the rest to
4924                                 // 'Invocation's Resolve'
4925                                 method = Invocation.OverloadResolve (ec, m_expr, null, loc);
4926                                 if (method != null) {
4927                                         MethodInfo mi = method as MethodInfo;
4928                                         Type ret_type = mi.ReturnType;
4929                                         if (ret_type.IsArray)
4930                                                 indexer_access_req = true;
4931                                         else {
4932                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, ret_type, loc);
4933                                                 if (list != null && list.getters.Count > 0)
4934                                                         indexer_access_req = true;
4935                                                 else 
4936                                                         return null;
4937                                         }
4938                                         Arguments = null;
4939                                         type = mi.ReturnType;
4940                                         return this;
4941                                 }
4942                         }
4943
4944                         return null;
4945                 }
4946
4947                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side) {
4948                         if (instance_expression != null) {
4949                                 instance_expression = instance_expression.DoResolve (ec);
4950                                 if (instance_expression == null)
4951                                         return null;
4952                         }
4953
4954                         ArrayList members = SetAccessors ();
4955                         if (members == null || members.Count == 0) {
4956                                 Report.Error (30524, loc, "Property '" + Name + "' lacks a 'set' accesor");
4957                                 return null;
4958                         }
4959
4960                         MethodGroupExpr m_expr = new MethodGroupExpr (members, loc);
4961                         if (arguments == null)
4962                                 arguments = new ArrayList ();
4963                         arguments.Add (new Argument (right_side, Argument.AType.Expression));
4964                         method = Invocation.OverloadResolve (ec, m_expr, ref arguments, loc);
4965                         if (method != null) {
4966                                 //MethodInfo mi = method as MethodInfo;
4967                                 type = TypeManager.void_type; //TypeManager.TypeToCoreType (mi.ReturnType);
4968                                 eclass = ExprClass.Value;
4969                                 indexer_access_req = false;
4970                                 return this;
4971                         } else {
4972                                 // Look for properties that do not take any arguments.
4973                                 // Check if the return type has any indexers
4974                                 arguments = null;
4975                                 DoResolve (ec);
4976                                 if (method != null) {
4977                                         MethodInfo mi = method as MethodInfo;
4978                                         Type ret_type = mi.ReturnType;
4979                                         if (ret_type.IsArray)
4980                                                 indexer_access_req = true;
4981                                         else {
4982
4983                                                 Indexers list = Indexers.GetIndexersForType (ec.ContainerType, 
4984                                                                         ret_type, loc);
4985                                                 if (list != null && list.setters.Count > 0)
4986                                                         indexer_access_req = true;
4987                                                 else 
4988                                                         return null;
4989                                         }
4990                                         type = mi.ReturnType;
4991                                         return this;
4992                                 }
4993                         }
4994
4995                         return null;
4996                 }
4997
4998                 override public void Emit (EmitContext ec)
4999                 {
5000                         if (Arguments == null)
5001                                 Arguments = new ArrayList ();
5002                         Invocation.EmitCall (ec, false, IsStatic, instance_expression, method, null, Arguments, loc);
5003                 }
5004
5005                 override public void EmitStatement (EmitContext ec) 
5006                 {
5007                         Emit (ec);
5008                 }
5009
5010         }
5011
5012         /// <summary>
5013         ///   Fully resolved expression that evaluates to a Field
5014         /// </summary>
5015         public class FieldExpr : Expression, IAssignMethod, IMemoryLocation, IMemberExpr {
5016                 public readonly FieldInfo FieldInfo;
5017                 Expression instance_expr;
5018                 
5019                 public FieldExpr (FieldInfo fi, Location l)
5020                 {
5021                         FieldInfo = fi;
5022                         eclass = ExprClass.Variable;
5023                         type = fi.FieldType;
5024                         loc = l;
5025                 }
5026
5027                 public string Name {
5028                         get {
5029                                 return FieldInfo.Name;
5030                         }
5031                 }
5032
5033                 public bool IsInstance {
5034                         get {
5035                                 return !FieldInfo.IsStatic;
5036                         }
5037                 }
5038
5039                 public bool IsStatic {
5040                         get {
5041                                 return FieldInfo.IsStatic;
5042                         }
5043                 }
5044
5045                 public Type DeclaringType {
5046                         get {
5047                                 return FieldInfo.DeclaringType;
5048                         }
5049                 }
5050
5051                 public Expression InstanceExpression {
5052                         get {
5053                                 return instance_expr;
5054                         }
5055
5056                         set {
5057                                 instance_expr = value;
5058                         }
5059                 }
5060
5061                 override public Expression DoResolve (EmitContext ec)
5062                 {
5063                         if (!FieldInfo.IsStatic){
5064                                 if (instance_expr == null){
5065                                         throw new Exception ("non-static FieldExpr without instance var\n" +
5066                                                              "You have to assign the Instance variable\n" +
5067                                                              "Of the FieldExpr to set this\n");
5068                                 }
5069
5070                                 // Resolve the field's instance expression while flow analysis is turned
5071                                 // off: when accessing a field "a.b", we must check whether the field
5072                                 // "a.b" is initialized, not whether the whole struct "a" is initialized.
5073                                 instance_expr = instance_expr.Resolve (ec, ResolveFlags.VariableOrValue |
5074                                                                        ResolveFlags.DisableFlowAnalysis);
5075                                 if (instance_expr == null)
5076                                         return null;
5077                         }
5078
5079                         // If the instance expression is a local variable or parameter.
5080                         IVariable var = instance_expr as IVariable;
5081                         if ((var != null) && !var.IsFieldAssigned (ec, FieldInfo.Name, loc))
5082                                 return null;
5083
5084                         return this;
5085                 }
5086
5087                 void Report_AssignToReadonly (bool is_instance)
5088                 {
5089                         string msg;
5090                         
5091                         if (is_instance)
5092                                 msg = "Readonly field can not be assigned outside " +
5093                                 "of constructor or variable initializer";
5094                         else
5095                                 msg = "A static readonly field can only be assigned in " +
5096                                 "a static constructor";
5097
5098                         Report.Error (is_instance ? 191 : 198, loc, msg);
5099                 }
5100                 
5101                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5102                 {
5103                         IVariable var = instance_expr as IVariable;
5104                         if (var != null)
5105                                 var.SetFieldAssigned (ec, FieldInfo.Name);
5106
5107                         Expression e = DoResolve (ec);
5108
5109                         if (e == null)
5110                                 return null;
5111                         
5112                         if (!FieldInfo.IsInitOnly)
5113                                 return this;
5114
5115                         //
5116                         // InitOnly fields can only be assigned in constructors
5117                         //
5118
5119                         if (ec.IsConstructor)
5120                                 return this;
5121
5122                         Report_AssignToReadonly (true);
5123                         
5124                         return null;
5125                 }
5126
5127                 override public void Emit (EmitContext ec)
5128                 {
5129                         ILGenerator ig = ec.ig;
5130                         bool is_volatile = false;
5131
5132                         if (FieldInfo is FieldBuilder){
5133                                 FieldBase f = TypeManager.GetField (FieldInfo);
5134
5135                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5136                                         is_volatile = true;
5137                                 
5138                                 f.status |= Field.Status.USED;
5139                         }
5140                         
5141                         if (FieldInfo.IsStatic){
5142                                 if (is_volatile)
5143                                         ig.Emit (OpCodes.Volatile);
5144                                 
5145                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
5146                         } else {
5147                                 if (instance_expr.Type.IsValueType){
5148                                         IMemoryLocation ml;
5149                                         LocalTemporary tempo = null;
5150                                         
5151                                         if (!(instance_expr is IMemoryLocation)){
5152                                                 tempo = new LocalTemporary (
5153                                                         ec, instance_expr.Type);
5154
5155                                                 InstanceExpression.Emit (ec);
5156                                                 tempo.Store (ec);
5157                                                 ml = tempo;
5158                                         } else
5159                                                 ml = (IMemoryLocation) instance_expr;
5160
5161                                         ml.AddressOf (ec, AddressOp.Load);
5162                                 } else 
5163                                         instance_expr.Emit (ec);
5164
5165                                 if (is_volatile)
5166                                         ig.Emit (OpCodes.Volatile);
5167                                 
5168                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
5169                         }
5170                 }
5171
5172                 public void EmitAssign (EmitContext ec, Expression source)
5173                 {
5174                         FieldAttributes fa = FieldInfo.Attributes;
5175                         bool is_static = (fa & FieldAttributes.Static) != 0;
5176                         bool is_readonly = (fa & FieldAttributes.InitOnly) != 0;
5177                         ILGenerator ig = ec.ig;
5178
5179                         if (is_readonly && !ec.IsConstructor){
5180                                 Report_AssignToReadonly (!is_static);
5181                                 return;
5182                         }
5183                         
5184                         if (!is_static){
5185                                 Expression instance = instance_expr;
5186
5187                                 if (instance.Type.IsValueType){
5188                                         if (instance is IMemoryLocation){
5189                                                 IMemoryLocation ml = (IMemoryLocation) instance;
5190
5191                                                 ml.AddressOf (ec, AddressOp.Store);
5192                                         } else
5193                                                 throw new Exception ("The " + instance + " of type " +
5194                                                                      instance.Type +
5195                                                                      " represents a ValueType and does " +
5196                                                                      "not implement IMemoryLocation");
5197                                 } else
5198                                         instance.Emit (ec);
5199                         }
5200                         source.Emit (ec);
5201
5202                         if (FieldInfo is FieldBuilder){
5203                                 FieldBase f = TypeManager.GetField (FieldInfo);
5204                                 
5205                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5206                                         ig.Emit (OpCodes.Volatile);
5207                         }
5208                         
5209                         if (is_static)
5210                                 ig.Emit (OpCodes.Stsfld, FieldInfo);
5211                         else 
5212                                 ig.Emit (OpCodes.Stfld, FieldInfo);
5213
5214                         if (FieldInfo is FieldBuilder){
5215                                 FieldBase f = TypeManager.GetField (FieldInfo);
5216
5217                                 f.status |= Field.Status.ASSIGNED;
5218                         }
5219                 }
5220                 
5221                 public void AddressOf (EmitContext ec, AddressOp mode)
5222                 {
5223                         ILGenerator ig = ec.ig;
5224                         
5225                         if (FieldInfo is FieldBuilder){
5226                                 FieldBase f = TypeManager.GetField (FieldInfo);
5227                                 if ((f.ModFlags & Modifiers.VOLATILE) != 0)
5228                                         ig.Emit (OpCodes.Volatile);
5229                         }
5230
5231                         if (FieldInfo is FieldBuilder){
5232                                 FieldBase f = TypeManager.GetField (FieldInfo);
5233
5234                                 if ((mode & AddressOp.Store) != 0)
5235                                         f.status |= Field.Status.ASSIGNED;
5236                                 if ((mode & AddressOp.Load) != 0)
5237                                         f.status |= Field.Status.USED;
5238                         }
5239
5240                         //
5241                         // Handle initonly fields specially: make a copy and then
5242                         // get the address of the copy.
5243                         //
5244                         if (FieldInfo.IsInitOnly && !ec.IsConstructor){
5245                                 LocalBuilder local;
5246                                 
5247                                 Emit (ec);
5248                                 local = ig.DeclareLocal (type);
5249                                 ig.Emit (OpCodes.Stloc, local);
5250                                 ig.Emit (OpCodes.Ldloca, local);
5251                                 return;
5252                         }
5253
5254                         if (FieldInfo.IsStatic)
5255                                 ig.Emit (OpCodes.Ldsflda, FieldInfo);
5256                         else {
5257                                 if (instance_expr is IMemoryLocation)
5258                                         ((IMemoryLocation)instance_expr).AddressOf (ec, AddressOp.LoadStore);
5259                                 else
5260                                         instance_expr.Emit (ec);
5261                                 ig.Emit (OpCodes.Ldflda, FieldInfo);
5262                         }
5263                 }
5264         }
5265         
5266         /// <summary>
5267         ///   Expression that evaluates to a Property.  The Assign class
5268         ///   might set the 'Value' expression if we are in an assignment.
5269         ///
5270         ///   This is not an LValue because we need to re-write the expression, we
5271         ///   can not take data from the stack and store it.  
5272         /// </summary>
5273         public class PropertyExpr : ExpressionStatement, IAssignMethod, IMemberExpr {
5274                 public readonly PropertyInfo PropertyInfo;
5275                 public bool IsBase;
5276                 MethodInfo getter, setter;
5277                 bool is_static;
5278                 public ArrayList PropertyArgs;
5279
5280                 Expression instance_expr;
5281
5282                 public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l)
5283                 {
5284                         PropertyInfo = pi;
5285                         eclass = ExprClass.PropertyAccess;
5286                         PropertyArgs = null;
5287                         is_static = false;
5288                         loc = l;
5289
5290                         type = TypeManager.TypeToCoreType (pi.PropertyType);
5291
5292                         ResolveAccessors (ec);
5293                 }
5294
5295                 public string Name {
5296                         get {
5297                                 return PropertyInfo.Name;
5298                         }
5299                 }
5300
5301                 public bool IsInstance {
5302                         get {
5303                                 return !is_static;
5304                         }
5305                 }
5306
5307                 public bool IsStatic {
5308                         get {
5309                                 return is_static;
5310                         }
5311                 }
5312                 
5313                 public Type DeclaringType {
5314                         get {
5315                                 return PropertyInfo.DeclaringType;
5316                         }
5317                 }
5318
5319                 //
5320                 // The instance expression associated with this expression
5321                 //
5322                 public Expression InstanceExpression {
5323                         set {
5324                                 instance_expr = value;
5325                         }
5326
5327                         get {
5328                                 return instance_expr;
5329                         }
5330                 }
5331
5332                 public bool VerifyAssignable ()
5333                 {
5334                         if (!PropertyInfo.CanWrite){
5335                                 Report.Error (200, loc, 
5336                                               "The property '" + PropertyInfo.Name +
5337                                               "' can not be assigned to, as it has not set accessor");
5338                                 return false;
5339                         }
5340
5341                         return true;
5342                 }
5343
5344                 void ResolveAccessors (EmitContext ec)
5345                 {
5346                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
5347                         MemberInfo [] group;
5348                         
5349                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5350                                                               MemberTypes.Method, flags, "get_" + PropertyInfo.Name);
5351
5352                         //
5353                         // The first method is the closest to us
5354                         //
5355                         if (group != null && group.Length > 0){
5356                                 getter = (MethodInfo) group [0];
5357
5358                                 if (getter.IsStatic)
5359                                         is_static = true;
5360                         }                       
5361
5362                         //
5363                         // The first method is the closest to us
5364                         //
5365                         group = TypeManager.MemberLookup (ec.ContainerType, PropertyInfo.DeclaringType,
5366                                                           MemberTypes.Method, flags, "set_" + PropertyInfo.Name);
5367                         if (group != null && group.Length > 0){
5368                                 setter = (MethodInfo) group [0];
5369                                 if (setter.IsStatic)
5370                                         is_static = true;
5371                         }
5372                 }
5373
5374                 override public Expression DoResolve (EmitContext ec)
5375                 {
5376                         if (getter == null){
5377                                 Report.Error (30524, loc, 
5378                                               "The property '" + PropertyInfo.Name +
5379                                               "' can not be used in " +
5380                                               "this context because it lacks a get accessor");
5381                                 return null;
5382                         }
5383
5384                         if ((instance_expr == null) && ec.IsStatic && !is_static) {
5385                                 SimpleName.Error_ObjectRefRequired (ec, loc, PropertyInfo.Name);
5386                                 return null;
5387                         }
5388
5389                         if (instance_expr != null) {
5390                                 instance_expr = instance_expr.DoResolve (ec);
5391                                 if (instance_expr == null)
5392                                         return null;
5393                         }
5394
5395                         return this;
5396                 }
5397
5398                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
5399                 {
5400                         if (setter == null){
5401                                 Report.Error (30526, loc, 
5402                                               "The property '" + PropertyInfo.Name +
5403                                               "' can not be used in " +
5404                                               "this context because it lacks a set accessor");
5405                                 return null;
5406                         }
5407
5408                         if (instance_expr != null) {
5409                                 instance_expr = instance_expr.DoResolve (ec);
5410                                 if (instance_expr == null)
5411                                         return null;
5412                         }
5413
5414                         return this;
5415                 }
5416
5417                 override public void Emit (EmitContext ec)
5418                 {
5419                         //
5420                         // Special case: length of single dimension array property is turned into ldlen
5421                         //
5422                         if ((getter == TypeManager.system_int_array_get_length) ||
5423                             (getter == TypeManager.int_array_get_length)){
5424                                 Type iet = instance_expr.Type;
5425
5426                                 //
5427                                 // System.Array.Length can be called, but the Type does not
5428                                 // support invoking GetArrayRank, so test for that case first
5429                                 //
5430                                 if (iet != TypeManager.array_type && (iet.GetArrayRank () == 1)){
5431                                         instance_expr.Emit (ec);
5432                                         ec.ig.Emit (OpCodes.Ldlen);
5433                                         return;
5434                                 }
5435                         }
5436                         if (PropertyArgs == null)
5437                                 PropertyArgs = new ArrayList ();
5438                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, PropertyArgs, loc);
5439                 }
5440
5441                 //
5442                 // Implements the IAssignMethod interface for assignments
5443                 //
5444                 public void EmitAssign (EmitContext ec, Expression source)
5445                 {
5446                         Argument arg = new Argument (source, Argument.AType.Expression);
5447                         ArrayList args = new ArrayList ();
5448 //HERE
5449                         args.Add (arg);
5450                         Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, PropertyArgs,loc);
5451                 }
5452
5453                 override public void EmitStatement (EmitContext ec)
5454                 {
5455                         Emit (ec);
5456                         ec.ig.Emit (OpCodes.Pop);
5457                 }
5458         }
5459
5460         /// <summary>
5461         ///   Fully resolved expression that evaluates to an Event
5462         /// </summary>
5463         public class EventExpr : Expression, IMemberExpr {
5464                 public readonly EventInfo EventInfo;
5465                 public Expression instance_expr;
5466
5467                 bool is_static;
5468                 MethodInfo add_accessor, remove_accessor;
5469                 
5470                 public EventExpr (EventInfo ei, Location loc)
5471                 {
5472                         EventInfo = ei;
5473                         this.loc = loc;
5474                         eclass = ExprClass.EventAccess;
5475
5476                         add_accessor = TypeManager.GetAddMethod (ei);
5477                         remove_accessor = TypeManager.GetRemoveMethod (ei);
5478                         
5479                         if (add_accessor.IsStatic || remove_accessor.IsStatic)
5480                                 is_static = true;
5481
5482                         if (EventInfo is MyEventBuilder)
5483                                 type = ((MyEventBuilder) EventInfo).EventType;
5484                         else
5485                                 type = EventInfo.EventHandlerType;
5486                 }
5487
5488                 public string Name {
5489                         get {
5490                                 return EventInfo.Name;
5491                         }
5492                 }
5493
5494                 public bool IsInstance {
5495                         get {
5496                                 return !is_static;
5497                         }
5498                 }
5499
5500                 public bool IsStatic {
5501                         get {
5502                                 return is_static;
5503                         }
5504                 }
5505
5506                 public Type DeclaringType {
5507                         get {
5508                                 return EventInfo.DeclaringType;
5509                         }
5510                 }
5511
5512                 public Expression InstanceExpression {
5513                         get {
5514                                 return instance_expr;
5515                         }
5516
5517                         set {
5518                                 instance_expr = value;
5519                         }
5520                 }
5521
5522                 Expression field_expr = null;
5523
5524                 public override Expression DoResolve (EmitContext ec)
5525                 {
5526                         if (instance_expr != null) {
5527                                 instance_expr = instance_expr.DoResolve (ec);
5528                                 if (instance_expr == null)
5529                                         return null;
5530                         }
5531
5532                         if (this.DeclaringType == ec.ContainerType)     {
5533                                 MemberInfo mi = GetFieldFromEvent (this);
5534                                 if (mi == null)
5535                                         return null;
5536                                 field_expr = ExprClassFromMemberInfo (ec, mi, loc);
5537                                 ((FieldExpr) field_expr).InstanceExpression = instance_expr;
5538                                 field_expr = field_expr.DoResolve (ec);
5539                                 if (field_expr == null)
5540                                         return null;
5541                         }
5542
5543                         return this;
5544                 }
5545
5546                 public override void Emit (EmitContext ec)
5547                 {
5548                         if (field_expr != null)
5549                                 field_expr.Emit (ec);
5550                 }
5551
5552                 public void EmitAddOrRemove (EmitContext ec, Expression source)
5553                 {
5554                         Expression handler = ((Binary) source).Right;
5555                         
5556                         Argument arg = new Argument (handler, Argument.AType.Expression);
5557                         ArrayList args = new ArrayList ();
5558                                 
5559                         args.Add (arg);
5560                         
5561                         if (((Binary) source).Oper == Binary.Operator.Addition)
5562                                 Invocation.EmitCall (
5563                                         ec, false, IsStatic, instance_expr, add_accessor, args, loc);
5564                         else
5565                                 Invocation.EmitCall (
5566                                         ec, false, IsStatic, instance_expr, remove_accessor, args, loc);
5567                 }
5568         }
5569 }