2001-10-14 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10 // Ideas:
11 //   Maybe we should make Resolve be an instance method that just calls
12 //   the virtual DoResolve function and checks conditions like the eclass
13 //   and type being set if a non-null value is returned.  For robustness
14 //   purposes.
15 //
16
17 namespace CIR {
18         using System;
19         using System.Collections;
20         using System.Diagnostics;
21         using System.Reflection;
22         using System.Reflection.Emit;
23         using System.Text;
24         
25         // <remarks>
26         //   The ExprClass class contains the is used to pass the 
27         //   classification of an expression (value, variable, namespace,
28         //   type, method group, property access, event access, indexer access,
29         //   nothing).
30         // </remarks>
31         public enum ExprClass {
32                 Invalid,
33                 
34                 Value,
35                 Variable,   // Every Variable should implement LValue
36                 Namespace,
37                 Type,
38                 MethodGroup,
39                 PropertyAccess,
40                 EventAccess,
41                 IndexerAccess,
42                 Nothing, 
43         }
44
45         // <remarks>
46         //   Base class for expressions
47         // </remarks>
48         public abstract class Expression {
49                 protected ExprClass eclass;
50                 protected Type      type;
51                 
52                 public Type Type {
53                         get {
54                                 return type;
55                         }
56
57                         set {
58                                 type = value;
59                         }
60                 }
61
62                 public ExprClass ExprClass {
63                         get {
64                                 return eclass;
65                         }
66
67                         set {
68                                 eclass = value;
69                         }
70                 }
71
72                 // <summary>
73                 //   Utility wrapper routine for Error, just to beautify the code
74                 // </summary>
75                 static protected void Error (int error, string s)
76                 {
77                         Report.Error (error, s);
78                 }
79
80                 static protected void Error (int error, Location loc, string s)
81                 {
82                         Report.Error (error, loc, s);
83                 }
84                 
85                 // <summary>
86                 //   Utility wrapper routine for Warning, just to beautify the code
87                 // </summary>
88                 static protected void Warning (int warning, string s)
89                 {
90                         Report.Warning (warning, s);
91                 }
92
93                 // <summary>
94                 //   Performs semantic analysis on the Expression
95                 // </summary>
96                 //
97                 // <remarks>
98                 //   The Resolve method is invoked to perform the semantic analysis
99                 //   on the node.
100                 //
101                 //   The return value is an expression (it can be the
102                 //   same expression in some cases) or a new
103                 //   expression that better represents this node.
104                 //   
105                 //   For example, optimizations of Unary (LiteralInt)
106                 //   would return a new LiteralInt with a negated
107                 //   value.
108                 //   
109                 //   If there is an error during semantic analysis,
110                 //   then an error should be reported (using Report)
111                 //   and a null value should be returned.
112                 //   
113                 //   There are two side effects expected from calling
114                 //   Resolve(): the the field variable "eclass" should
115                 //   be set to any value of the enumeration
116                 //   `ExprClass' and the type variable should be set
117                 //   to a valid type (this is the type of the
118                 //   expression).
119                 // </remarks>
120                 
121                 public abstract Expression DoResolve (EmitContext ec);
122
123
124                 //
125                 // Currently Resolve wraps DoResolve to perform sanity
126                 // checking and assertion checking on what we expect from Resolve
127                 //
128
129                 public Expression Resolve (EmitContext ec)
130                 {
131                         Expression e = DoResolve (ec);
132
133                         if (e != null){
134                                 if (e is SimpleName)
135                                         return e;
136
137                                 if (e.ExprClass == ExprClass.Invalid)
138                                         throw new Exception ("Expression " + e +
139                                                              " ExprClass is Invalid after resolve");
140
141                                 if (e.ExprClass != ExprClass.MethodGroup)
142                                         if (e.type == null)
143                                                 throw new Exception ("Expression " + e +
144                                                                      " did not set its type after Resolve");
145
146                                 if (e is LValue)
147                                         e = ((LValue) e).LValueResolve (ec);
148                         }
149
150                         return e;
151                 }
152                        
153                 // <summary>
154                 //   Emits the code for the expression
155                 // </summary>
156                 //
157                 // <remarks>
158                 // 
159                 //   The Emit method is invoked to generate the code
160                 //   for the expression.  
161                 //
162                 // </remarks>
163                 public abstract void Emit (EmitContext ec);
164                 
165                 // <summary>
166                 //   Protected constructor.  Only derivate types should
167                 //   be able to be created
168                 // </summary>
169
170                 protected Expression ()
171                 {
172                         eclass = ExprClass.Invalid;
173                         type = null;
174                 }
175
176                 // <summary>
177                 //   Returns a literalized version of a literal FieldInfo
178                 // </summary>
179                 static Expression Literalize (FieldInfo fi)
180                 {
181                         Type t = fi.FieldType;
182                         object v = fi.GetValue (fi);
183
184                         if (t == TypeManager.int32_type)
185                                 return new IntLiteral ((int) v);
186                         else if (t == TypeManager.uint32_type)
187                                 return new UIntLiteral ((uint) v);
188                         else if (t == TypeManager.int64_type)
189                                 return new LongLiteral ((long) v);
190                         else if (t == TypeManager.uint64_type)
191                                 return new ULongLiteral ((ulong) v);
192                         else if (t == TypeManager.float_type)
193                                 return new FloatLiteral ((float) v);
194                         else if (t == TypeManager.double_type)
195                                 return new DoubleLiteral ((double) v);
196                         else if (t == TypeManager.string_type)
197                                 return new StringLiteral ((string) v);
198                         else if (t == TypeManager.short_type)
199                                 return new IntLiteral ((int) ((short)v));
200                         else if (t == TypeManager.ushort_type)
201                                 return new IntLiteral ((int) ((ushort)v));
202                         else if (t == TypeManager.sbyte_type)
203                                 return new IntLiteral ((int) ((sbyte)v));
204                         else if (t == TypeManager.byte_type)
205                                 return new IntLiteral ((int) ((byte)v));
206                         else if (t == TypeManager.char_type)
207                                 return new IntLiteral ((int) ((char)v));
208                         else
209                                 throw new Exception ("Unknown type for literal (" + v.GetType () +
210                                                      "), details: " + fi);
211                 }
212
213                 // 
214                 // Returns a fully formed expression after a MemberLookup
215                 //
216                 static Expression ExprClassFromMemberInfo (EmitContext ec, MemberInfo mi, Location loc)
217                 {
218                         if (mi is EventInfo){
219                                 return new EventExpr ((EventInfo) mi, loc);
220                         } else if (mi is FieldInfo){
221                                 FieldInfo fi = (FieldInfo) mi;
222
223                                 if (fi.IsLiteral){
224                                         Expression e = Literalize (fi);
225                                         e.Resolve (ec);
226
227                                         return e;
228                                 } else
229                                         return new FieldExpr (fi);
230                         } else if (mi is PropertyInfo){
231                                 return new PropertyExpr ((PropertyInfo) mi, loc);
232                         } else if (mi is Type)
233                                 return new TypeExpr ((Type) mi);
234
235                         return null;
236                 }
237                 
238                 //
239                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
240                 //
241                 // FIXME: We need to cope with access permissions here, or this wont
242                 // work!
243                 //
244                 // This code could use some optimizations, but we need to do some
245                 // measurements.  For example, we could use a delegate to `flag' when
246                 // something can not any longer be a method-group (because it is something
247                 // else).
248                 //
249                 // Return values:
250                 //     If the return value is an Array, then it is an array of
251                 //     MethodBases
252                 //   
253                 //     If the return value is an MemberInfo, it is anything, but a Method
254                 //
255                 //     null on error.
256                 //
257                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
258                 // the arguments here and have MemberLookup return only the methods that
259                 // match the argument count/type, unlike we are doing now (we delay this
260                 // decision).
261                 //
262                 // This is so we can catch correctly attempts to invoke instance methods
263                 // from a static body (scan for error 120 in ResolveSimpleName).
264                 //
265                 public static Expression MemberLookup (EmitContext ec, Type t, string name,
266                                                        bool same_type, MemberTypes mt,
267                                                        BindingFlags bf, Location loc)
268                 {
269                         if (same_type)
270                                 bf |= BindingFlags.NonPublic;
271
272                         MemberInfo [] mi = ec.TypeContainer.RootContext.TypeManager.FindMembers (
273                                 t, mt, bf, Type.FilterName, name);
274
275                         if (mi == null)
276                                 return null;
277
278                         // FIXME : How does this wierd case arise ?
279                         if (mi.Length == 0)
280                                 return null;
281                         
282                         if (mi.Length == 1 && !(mi [0] is MethodBase))
283                                 return Expression.ExprClassFromMemberInfo (ec, mi [0], loc);
284                         
285                         for (int i = 0; i < mi.Length; i++)
286                                 if (!(mi [i] is MethodBase)){
287                                         Error (-5, "Do not know how to reproduce this case: " + 
288                                                "Methods and non-Method with the same name, " +
289                                                "report this please");
290
291                                         for (i = 0; i < mi.Length; i++){
292                                                 Type tt = mi [i].GetType ();
293
294                                                 Console.WriteLine (i + ": " + mi [i]);
295                                                 while (tt != TypeManager.object_type){
296                                                         Console.WriteLine (tt);
297                                                         tt = tt.BaseType;
298                                                 }
299                                         }
300                                 }
301
302                         return new MethodGroupExpr (mi);
303                 }
304
305                 public const MemberTypes AllMemberTypes =
306                         MemberTypes.Constructor |
307                         MemberTypes.Event       |
308                         MemberTypes.Field       |
309                         MemberTypes.Method      |
310                         MemberTypes.NestedType  |
311                         MemberTypes.Property;
312                 
313                 public const BindingFlags AllBindingsFlags =
314                         BindingFlags.Public |
315                         BindingFlags.Static |
316                         BindingFlags.Instance;
317
318                 public static Expression MemberLookup (EmitContext ec, Type t, string name,
319                                                        bool same_type, Location loc)
320                 {
321                         return MemberLookup (ec, t, name, same_type, AllMemberTypes, AllBindingsFlags, loc);
322                 }
323
324                 //
325                 // I am in general unhappy with this implementation.
326                 //
327                 // I need to revise this.
328                 //
329 //                
330 //                static public Expression ResolveMemberAccess (EmitContext ec, string name)
331 //                {
332 //                        Expression left_e = null;
333 //                        int dot_pos = name.LastIndexOf (".");
334 //                        string left = name.Substring (0, dot_pos);
335 //                        string right = name.Substring (dot_pos + 1);
336 //                        Type t;
337 //
338 //                        if ((t = ec.TypeContainer.LookupType (left, false)) != null){
339 //                                Expression e;
340 //                                
341 //                                left_e = new TypeExpr (t);
342 //                                e = new MemberAccess (left_e, right);
343 //                                return e.Resolve (ec);
344 //                        } else {
345 //                                //
346 //                                // FIXME: IMplement:
347 //                                
348 //                                // Handle here:
349 //                                //    T.P  Static property access (P) on Type T.
350 //                                //    e.P  instance property access on instance e for P.
351 //                                //    p
352 //                                //
353 //                        }
354 //
355 //                        if (left_e == null){
356 //                                Error (246, "Can not find type or namespace `"+left+"'");
357 //                                return null;
358 //                        }
359 //
360 //                        switch (left_e.ExprClass){
361 //                        case ExprClass.Type:
362 //                                return  MemberLookup (ec,
363 //                                                      left_e.Type, right,
364 //                                                      left_e.Type == ec.TypeContainer.TypeBuilder);
365 //                                
366 //                        case ExprClass.Namespace:
367 //                        case ExprClass.PropertyAccess:
368 //                        case ExprClass.IndexerAccess:
369 //                        case ExprClass.Variable:
370 //                        case ExprClass.Value:
371 //                        case ExprClass.Nothing:
372 //                        case ExprClass.EventAccess:
373 //                        case ExprClass.MethodGroup:
374 //                        case ExprClass.Invalid:
375 //                                throw new Exception ("Should have got the " + left_e.ExprClass +
376 //                                                     " handled before");
377 //                        }
378 //                        
379 //                        return null;
380 //                }
381 //
382                 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
383                 {
384                         Type expr_type = expr.Type;
385
386                         if (target_type == TypeManager.object_type) {
387                                 if (expr_type.IsClass)
388                                         return new EmptyCast (expr, target_type);
389                                 if (expr_type.IsValueType)
390                                         return new BoxedCast (expr);
391                         } else if (expr_type.IsSubclassOf (target_type)) {
392                                 return new EmptyCast (expr, target_type);
393                         } else {
394                                 // from any class-type S to any interface-type T.
395                                 if (expr_type.IsClass && target_type.IsInterface) {
396                                         Type [] interfaces = expr_type.FindInterfaces (Module.FilterTypeName,
397                                                                                        target_type.FullName);
398                                         if (interfaces != null)
399                                                 return new EmptyCast (expr, target_type);
400                                 }       
401
402                                 // from any interface type S to interface-type T.
403                                 // FIXME : Is it right to use IsAssignableFrom ?
404                                 if (expr_type.IsInterface && target_type.IsInterface)
405                                         if (target_type.IsAssignableFrom (expr_type))
406                                                 return new EmptyCast (expr, target_type);
407                                 
408                                 
409                                 // from an array-type S to an array-type of type T
410                                 if (expr_type.IsArray && target_type.IsArray) {
411
412                                         Console.WriteLine ("{0} -> {1}", expr_type, target_type);
413                                         throw new Exception ("Implement array conversion");
414                                         
415                                 }
416                                 
417                                 // from an array-type to System.Array
418                                 if (expr_type.IsArray && target_type.IsAssignableFrom (expr_type))
419                                         return new EmptyCast (expr, target_type);
420                                 
421                                 // from any delegate type to System.Delegate
422                                 if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
423                                     target_type == TypeManager.delegate_type)
424                                         if (target_type.IsAssignableFrom (expr_type))
425                                                 return new EmptyCast (expr, target_type);
426                                         
427                                 // from any array-type or delegate type into System.ICloneable.
428                                 if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
429                                         if (target_type == TypeManager.icloneable_type)
430                                                 throw new Exception ("Implement conversion to System.ICloneable");
431                                 
432                                 // from the null type to any reference-type.
433                                 if (expr is NullLiteral)
434                                         return new EmptyCast (expr, target_type);
435
436                                 return null;
437
438                         }
439                         
440                         return null;
441                 }
442
443                 // <summary>
444                 //   Handles expressions like this: decimal d; d = 1;
445                 //   and changes them into: decimal d; d = new System.Decimal (1);
446                 // </summary>
447                 static Expression InternalTypeConstructor (EmitContext ec, Expression expr, Type target)
448                 {
449                         ArrayList args = new ArrayList ();
450
451                         args.Add (new Argument (expr, Argument.AType.Expression));
452
453                         Expression ne = new New (target.FullName, args,
454                                                  new Location (-1));
455
456                         return ne.Resolve (ec);
457                 }
458
459                 // <summary>
460                 //   Implicit Numeric Conversions.
461                 //
462                 //   expr is the expression to convert, returns a new expression of type
463                 //   target_type or null if an implicit conversion is not possible.
464                 //
465                 // </summary>
466                 static public Expression ImplicitNumericConversion (EmitContext ec, Expression expr,
467                                                                     Type target_type, Location loc)
468                 {
469                         Type expr_type = expr.Type;
470                         
471                         //
472                         // Attempt to do the implicit constant expression conversions
473
474                         if (expr is IntLiteral){
475                                 Expression e;
476                                 
477                                 e = TryImplicitIntConversion (target_type, (IntLiteral) expr);
478                                 if (e != null)
479                                         return e;
480                         } else if (expr is LongLiteral){
481                                 //
482                                 // Try the implicit constant expression conversion
483                                 // from long to ulong, instead of a nice routine,
484                                 // we just inline it
485                                 //
486                                 if (((LongLiteral) expr).Value > 0)
487                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
488                         }
489                         
490                         if (expr_type == TypeManager.sbyte_type){
491                                 //
492                                 // From sbyte to short, int, long, float, double.
493                                 //
494                                 if (target_type == TypeManager.int32_type)
495                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
496                                 if (target_type == TypeManager.int64_type)
497                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
498                                 if (target_type == TypeManager.double_type)
499                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
500                                 if (target_type == TypeManager.float_type)
501                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
502                                 if (target_type == TypeManager.short_type)
503                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
504                                 if (target_type == TypeManager.decimal_type)
505                                         return InternalTypeConstructor (ec, expr, target_type);
506                         } else if (expr_type == TypeManager.byte_type){
507                                 //
508                                 // From byte to short, ushort, int, uint, long, ulong, float, double
509                                 // 
510                                 if ((target_type == TypeManager.short_type) ||
511                                     (target_type == TypeManager.ushort_type) ||
512                                     (target_type == TypeManager.int32_type) ||
513                                     (target_type == TypeManager.uint32_type))
514                                         return new EmptyCast (expr, target_type);
515
516                                 if (target_type == TypeManager.uint64_type)
517                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
518                                 if (target_type == TypeManager.int64_type)
519                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
520                                 
521                                 if (target_type == TypeManager.float_type)
522                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
523                                 if (target_type == TypeManager.double_type)
524                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
525                                 if (target_type == TypeManager.decimal_type)
526                                         return InternalTypeConstructor (ec, expr, target_type);
527                         } else if (expr_type == TypeManager.short_type){
528                                 //
529                                 // From short to int, long, float, double
530                                 // 
531                                 if (target_type == TypeManager.int32_type)
532                                         return new EmptyCast (expr, target_type);
533                                 if (target_type == TypeManager.int64_type)
534                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
535                                 if (target_type == TypeManager.double_type)
536                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
537                                 if (target_type == TypeManager.float_type)
538                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
539                                 if (target_type == TypeManager.decimal_type)
540                                         return InternalTypeConstructor (ec, expr, target_type);
541                         } else if (expr_type == TypeManager.ushort_type){
542                                 //
543                                 // From ushort to int, uint, long, ulong, float, double
544                                 //
545                                 if (target_type == TypeManager.uint32_type)
546                                         return new EmptyCast (expr, target_type);
547
548                                 if (target_type == TypeManager.uint64_type)
549                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
550                                 if (target_type == TypeManager.int32_type)
551                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
552                                 if (target_type == TypeManager.int64_type)
553                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
554                                 if (target_type == TypeManager.double_type)
555                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
556                                 if (target_type == TypeManager.float_type)
557                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
558                                 if (target_type == TypeManager.decimal_type)
559                                         return InternalTypeConstructor (ec, expr, target_type);
560                         } else if (expr_type == TypeManager.int32_type){
561                                 //
562                                 // From int to long, float, double
563                                 //
564                                 if (target_type == TypeManager.int64_type)
565                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
566                                 if (target_type == TypeManager.double_type)
567                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
568                                 if (target_type == TypeManager.float_type)
569                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
570                                 if (target_type == TypeManager.decimal_type)
571                                         return InternalTypeConstructor (ec, expr, target_type);
572                         } else if (expr_type == TypeManager.uint32_type){
573                                 //
574                                 // From uint to long, ulong, float, double
575                                 //
576                                 if (target_type == TypeManager.int64_type)
577                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
578                                 if (target_type == TypeManager.uint64_type)
579                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
580                                 if (target_type == TypeManager.double_type)
581                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
582                                                                OpCodes.Conv_R8);
583                                 if (target_type == TypeManager.float_type)
584                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
585                                                                OpCodes.Conv_R4);
586                                 if (target_type == TypeManager.decimal_type)
587                                         return InternalTypeConstructor (ec, expr, target_type);
588                         } else if ((expr_type == TypeManager.uint64_type) ||
589                                    (expr_type == TypeManager.int64_type)){
590                                 //
591                                 // From long/ulong to float, double
592                                 //
593                                 if (target_type == TypeManager.double_type)
594                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
595                                                                OpCodes.Conv_R8);
596                                 if (target_type == TypeManager.float_type)
597                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
598                                                                OpCodes.Conv_R4);        
599                                 if (target_type == TypeManager.decimal_type)
600                                         return InternalTypeConstructor (ec, expr, target_type);
601                         } else if (expr_type == TypeManager.char_type){
602                                 //
603                                 // From char to ushort, int, uint, long, ulong, float, double
604                                 // 
605                                 if ((target_type == TypeManager.ushort_type) ||
606                                     (target_type == TypeManager.int32_type) ||
607                                     (target_type == TypeManager.uint32_type))
608                                         return new EmptyCast (expr, target_type);
609                                 if (target_type == TypeManager.uint64_type)
610                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
611                                 if (target_type == TypeManager.int64_type)
612                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
613                                 if (target_type == TypeManager.float_type)
614                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
615                                 if (target_type == TypeManager.double_type)
616                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
617                                 if (target_type == TypeManager.decimal_type)
618                                         return InternalTypeConstructor (ec, expr, target_type);
619                         } else if (expr_type == TypeManager.float_type){
620                                 //
621                                 // float to double
622                                 //
623                                 if (target_type == TypeManager.double_type)
624                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
625                         }
626
627                         return null;
628                 }
629
630                 // <summary>
631                 //  Determines if a standard implicit conversion exists from
632                 //  expr_type to target_type
633                 // </summary>
634                 public static bool StandardConversionExists (Type expr_type, Type target_type)
635                 {
636                         if (expr_type == target_type)
637                                 return true;
638
639                         // First numeric conversions 
640                         
641                         if (expr_type == TypeManager.sbyte_type){
642                                 //
643                                 // From sbyte to short, int, long, float, double.
644                                 //
645                                 if ((target_type == TypeManager.int32_type) || 
646                                     (target_type == TypeManager.int64_type) ||
647                                     (target_type == TypeManager.double_type) ||
648                                     (target_type == TypeManager.float_type)  ||
649                                     (target_type == TypeManager.short_type) ||
650                                     (target_type == TypeManager.decimal_type))
651                                         return true;
652                                 
653                         } else if (expr_type == TypeManager.byte_type){
654                                 //
655                                 // From byte to short, ushort, int, uint, long, ulong, float, double
656                                 // 
657                                 if ((target_type == TypeManager.short_type) ||
658                                     (target_type == TypeManager.ushort_type) ||
659                                     (target_type == TypeManager.int32_type) ||
660                                     (target_type == TypeManager.uint32_type) ||
661                                     (target_type == TypeManager.uint64_type) ||
662                                     (target_type == TypeManager.int64_type) ||
663                                     (target_type == TypeManager.float_type) ||
664                                     (target_type == TypeManager.double_type) ||
665                                     (target_type == TypeManager.decimal_type))
666                                         return true;
667         
668                         } else if (expr_type == TypeManager.short_type){
669                                 //
670                                 // From short to int, long, float, double
671                                 // 
672                                 if ((target_type == TypeManager.int32_type) ||
673                                     (target_type == TypeManager.int64_type) ||
674                                     (target_type == TypeManager.double_type) ||
675                                     (target_type == TypeManager.float_type) ||
676                                     (target_type == TypeManager.decimal_type))
677                                         return true;
678                                         
679                         } else if (expr_type == TypeManager.ushort_type){
680                                 //
681                                 // From ushort to int, uint, long, ulong, float, double
682                                 //
683                                 if ((target_type == TypeManager.uint32_type) ||
684                                     (target_type == TypeManager.uint64_type) ||
685                                     (target_type == TypeManager.int32_type) ||
686                                     (target_type == TypeManager.int64_type) ||
687                                     (target_type == TypeManager.double_type) ||
688                                     (target_type == TypeManager.float_type) ||
689                                     (target_type == TypeManager.decimal_type))
690                                         return true;
691                                     
692                         } else if (expr_type == TypeManager.int32_type){
693                                 //
694                                 // From int to long, float, double
695                                 //
696                                 if ((target_type == TypeManager.int64_type) ||
697                                     (target_type == TypeManager.double_type) ||
698                                     (target_type == TypeManager.float_type) ||
699                                     (target_type == TypeManager.decimal_type))
700                                         return true;
701                                         
702                         } else if (expr_type == TypeManager.uint32_type){
703                                 //
704                                 // From uint to long, ulong, float, double
705                                 //
706                                 if ((target_type == TypeManager.int64_type) ||
707                                     (target_type == TypeManager.uint64_type) ||
708                                     (target_type == TypeManager.double_type) ||
709                                     (target_type == TypeManager.float_type) ||
710                                     (target_type == TypeManager.decimal_type))
711                                         return true;
712                                         
713                         } else if ((expr_type == TypeManager.uint64_type) ||
714                                    (expr_type == TypeManager.int64_type)) {
715                                 //
716                                 // From long/ulong to float, double
717                                 //
718                                 if ((target_type == TypeManager.double_type) ||
719                                     (target_type == TypeManager.float_type) ||
720                                     (target_type == TypeManager.decimal_type))
721                                         return true;
722                                     
723                         } else if (expr_type == TypeManager.char_type){
724                                 //
725                                 // From char to ushort, int, uint, long, ulong, float, double
726                                 // 
727                                 if ((target_type == TypeManager.ushort_type) ||
728                                     (target_type == TypeManager.int32_type) ||
729                                     (target_type == TypeManager.uint32_type) ||
730                                     (target_type == TypeManager.uint64_type) ||
731                                     (target_type == TypeManager.int64_type) ||
732                                     (target_type == TypeManager.float_type) ||
733                                     (target_type == TypeManager.double_type) ||
734                                     (target_type == TypeManager.decimal_type))
735                                         return true;
736
737                         } else if (expr_type == TypeManager.float_type){
738                                 //
739                                 // float to double
740                                 //
741                                 if (target_type == TypeManager.double_type)
742                                         return true;
743                         }       
744                         
745                         // Next reference conversions
746
747                         if (target_type == TypeManager.object_type) {
748                                 if ((expr_type.IsClass) ||
749                                     (expr_type.IsValueType))
750                                         return true;
751                                 
752                         } else if (expr_type.IsSubclassOf (target_type)) {
753                                 return true;
754                                 
755                         } else {
756                                 // from any class-type S to any interface-type T.
757                                 if (expr_type.IsClass && target_type.IsInterface)
758                                         return true;
759                                 
760                                 // from any interface type S to interface-type T.
761                                 // FIXME : Is it right to use IsAssignableFrom ?
762                                 if (expr_type.IsInterface && target_type.IsInterface)
763                                         if (target_type.IsAssignableFrom (expr_type))
764                                                 return true;
765                                 
766                                 // from an array-type S to an array-type of type T
767                                 if (expr_type.IsArray && target_type.IsArray) 
768                                         return true;
769                                 
770                                 // from an array-type to System.Array
771                                 if (expr_type.IsArray && target_type.IsAssignableFrom (expr_type))
772                                         return true;
773                                 
774                                 // from any delegate type to System.Delegate
775                                 if (expr_type.IsSubclassOf (TypeManager.delegate_type) &&
776                                     target_type == TypeManager.delegate_type)
777                                         if (target_type.IsAssignableFrom (expr_type))
778                                                 return true;
779                                         
780                                 // from any array-type or delegate type into System.ICloneable.
781                                 if (expr_type.IsArray || expr_type.IsSubclassOf (TypeManager.delegate_type))
782                                         if (target_type == TypeManager.icloneable_type)
783                                                 return true;
784                                 
785                                 // from the null type to any reference-type.
786                                 // FIXME : How do we do this ?
787
788                         }
789
790                         return false;
791                 }
792                 
793                 // <summary>
794                 //  Finds "most encompassed type" according to the spec (13.4.2)
795                 //  amongst the methods in the MethodGroupExpr which convert from a
796                 //  type encompassing source_type
797                 // </summary>
798                 static Type FindMostEncompassedType (MethodGroupExpr me, Type source_type)
799                 {
800                         Type best = null;
801                         
802                         for (int i = me.Methods.Length; i > 0; ) {
803                                 i--;
804
805                                 MethodBase mb = me.Methods [i];
806                                 ParameterData pd = Invocation.GetParameterData (mb);
807                                 Type param_type = pd.ParameterType (0);
808
809                                 if (StandardConversionExists (source_type, param_type)) {
810                                         if (best == null)
811                                                 best = param_type;
812                                         
813                                         if (StandardConversionExists (param_type, best))
814                                                 best = param_type;
815                                 }
816                         }
817
818                         return best;
819                 }
820                 
821                 // <summary>
822                 //  Finds "most encompassing type" according to the spec (13.4.2)
823                 //  amongst the methods in the MethodGroupExpr which convert to a
824                 //  type encompassed by target_type
825                 // </summary>
826                 static Type FindMostEncompassingType (MethodGroupExpr me, Type target)
827                 {
828                         Type best = null;
829                         
830                         for (int i = me.Methods.Length; i > 0; ) {
831                                 i--;
832                                 
833                                 MethodInfo mi = (MethodInfo) me.Methods [i];
834                                 Type ret_type = mi.ReturnType;
835                                 
836                                 if (StandardConversionExists (ret_type, target)) {
837                                         if (best == null)
838                                                 best = ret_type;
839
840                                         if (!StandardConversionExists (ret_type, best))
841                                                 best = ret_type;
842                                 }
843                                 
844                         }
845                         
846                         return best;
847
848                 }
849                 
850
851                 // <summary>
852                 //  User-defined Implicit conversions
853                 // </summary>
854                 static public Expression ImplicitUserConversion (EmitContext ec, Expression source,
855                                                                  Type target, Location loc)
856                 {
857                         return UserDefinedConversion (ec, source, target, loc, false);
858                 }
859
860                 // <summary>
861                 //  User-defined Explicit conversions
862                 // </summary>
863                 static public Expression ExplicitUserConversion (EmitContext ec, Expression source,
864                                                                  Type target, Location loc)
865                 {
866                         return UserDefinedConversion (ec, source, target, loc, true);
867                 }
868                 
869                 // <summary>
870                 //   User-defined conversions
871                 // </summary>
872                 static public Expression UserDefinedConversion (EmitContext ec, Expression source,
873                                                                 Type target, Location loc,
874                                                                 bool look_for_explicit)
875                 {
876                         Expression mg1 = null, mg2 = null, mg3 = null, mg4 = null;
877                         Expression mg5 = null, mg6 = null, mg7 = null, mg8 = null;
878                         Expression e;
879                         MethodBase method = null;
880                         Type source_type = source.Type;
881
882                         string op_name;
883                         
884                         // If we have a boolean type, we need to check for the True operator
885
886                         // FIXME : How does the False operator come into the picture ?
887                         // FIXME : This doesn't look complete and very correct !
888                         if (target == TypeManager.bool_type)
889                                 op_name = "op_True";
890                         else
891                                 op_name = "op_Implicit";
892                         
893                         mg1 = MemberLookup (ec, source_type, op_name, false, loc);
894
895                         if (source_type.BaseType != null)
896                                 mg2 = MemberLookup (ec, source_type.BaseType, op_name, false, loc);
897                         
898                         mg3 = MemberLookup (ec, target, op_name, false, loc);
899
900                         if (target.BaseType != null)
901                                 mg4 = MemberLookup (ec, target.BaseType, op_name, false, loc);
902
903                         MethodGroupExpr union1 = Invocation.MakeUnionSet (mg1, mg2);
904                         MethodGroupExpr union2 = Invocation.MakeUnionSet (mg3, mg4);
905
906                         MethodGroupExpr union3 = Invocation.MakeUnionSet (union1, union2);
907
908                         MethodGroupExpr union4 = null;
909
910                         if (look_for_explicit) {
911
912                                 op_name = "op_Explicit";
913                                 
914                                 mg5 = MemberLookup (ec, source_type, op_name, false, loc);
915
916                                 if (source_type.BaseType != null)
917                                         mg6 = MemberLookup (ec, source_type.BaseType, op_name, false, loc);
918                                 
919                                 mg7 = MemberLookup (ec, target, op_name, false, loc);
920                                 
921                                 if (target.BaseType != null)
922                                         mg8 = MemberLookup (ec, target.BaseType, op_name, false, loc);
923                                 
924                                 MethodGroupExpr union5 = Invocation.MakeUnionSet (mg5, mg6);
925                                 MethodGroupExpr union6 = Invocation.MakeUnionSet (mg7, mg8);
926
927                                 union4 = Invocation.MakeUnionSet (union5, union6);
928                         }
929                         
930                         MethodGroupExpr union = Invocation.MakeUnionSet (union3, union4);
931
932                         if (union != null) {
933
934                                 Type most_specific_source, most_specific_target;
935
936                                 most_specific_source = FindMostEncompassedType (union, source_type);
937                                 if (most_specific_source == null)
938                                         return null;
939
940                                 most_specific_target = FindMostEncompassingType (union, target);
941                                 if (most_specific_target == null) 
942                                         return null;
943                                 
944                                 int count = 0;
945                                 
946                                 for (int i = union.Methods.Length; i > 0;) {
947                                         i--;
948
949                                         MethodBase mb = union.Methods [i];
950                                         ParameterData pd = Invocation.GetParameterData (mb);
951                                         MethodInfo mi = (MethodInfo) union.Methods [i];
952
953                                         if (pd.ParameterType (0) == most_specific_source &&
954                                             mi.ReturnType == most_specific_target) {
955                                                 method = mb;
956                                                 count++;
957                                         }
958                                 }
959
960                                 if (method == null || count > 1) {
961                                         Report.Error (-11, loc, "Ambiguous user defined conversion");
962                                         return null;
963                                 }
964                                 
965                                 //
966                                 // This will do the conversion to the best match that we
967                                 // found.  Now we need to perform an implict standard conversion
968                                 // if the best match was not the type that we were requested
969                                 // by target.
970                                 //
971                                 if (look_for_explicit)
972                                         source=ConvertExplicit (ec, source, most_specific_source, loc);
973                                 else
974                                         source = ConvertImplicitStandard (ec, source,
975                                                                           most_specific_source, loc);
976
977                                 if (source == null)
978                                         return null;
979                                 
980                                 e =  new UserCast ((MethodInfo) method, source);
981                                 
982                                 if (e.Type != target){
983                                         if (!look_for_explicit)
984                                                 e = ConvertImplicitStandard (ec, e, target, loc);
985                                         else
986                                                 e = ConvertExplicitStandard (ec, e, target, loc);
987
988                                         return e;
989                                 } else
990                                         return e;
991                         }
992                         
993                         return null;
994                 }
995                 
996                 // <summary>
997                 //   Converts implicitly the resolved expression `expr' into the
998                 //   `target_type'.  It returns a new expression that can be used
999                 //   in a context that expects a `target_type'. 
1000                 // </summary>
1001                 static public Expression ConvertImplicit (EmitContext ec, Expression expr,
1002                                                           Type target_type, Location loc)
1003                 {
1004                         Type expr_type = expr.Type;
1005                         Expression e;
1006
1007                         if (expr_type == target_type)
1008                                 return expr;
1009
1010                         e = ImplicitNumericConversion (ec, expr, target_type, loc);
1011                         if (e != null)
1012                                 return e;
1013
1014                         e = ImplicitReferenceConversion (expr, target_type);
1015                         if (e != null)
1016                                 return e;
1017
1018                         e = ImplicitUserConversion (ec, expr, target_type, loc);
1019                         if (e != null)
1020                                 return e;
1021
1022                         if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
1023                                 IntLiteral i = (IntLiteral) expr;
1024
1025                                 if (i.Value == 0)
1026                                         return new EmptyCast (expr, target_type);
1027                         }
1028
1029                         return null;
1030                 }
1031
1032                 
1033                 // <summary>
1034                 //   Attempts to apply the `Standard Implicit
1035                 //   Conversion' rules to the expression `expr' into
1036                 //   the `target_type'.  It returns a new expression
1037                 //   that can be used in a context that expects a
1038                 //   `target_type'.
1039                 //
1040                 //   This is different from `ConvertImplicit' in that the
1041                 //   user defined implicit conversions are excluded. 
1042                 // </summary>
1043                 static public Expression ConvertImplicitStandard (EmitContext ec, Expression expr,
1044                                                                   Type target_type, Location loc)
1045                 {
1046                         Type expr_type = expr.Type;
1047                         Expression e;
1048
1049                         if (expr_type == target_type)
1050                                 return expr;
1051
1052                         e = ImplicitNumericConversion (ec, expr, target_type, loc);
1053                         if (e != null)
1054                                 return e;
1055
1056                         e = ImplicitReferenceConversion (expr, target_type);
1057                         if (e != null)
1058                                 return e;
1059
1060                         if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){
1061                                 IntLiteral i = (IntLiteral) expr;
1062
1063                                 if (i.Value == 0)
1064                                         return new EmptyCast (expr, target_type);
1065                         }
1066                         return null;
1067                 }
1068                 // <summary>
1069                 //   Attemps to perform an implict constant conversion of the IntLiteral
1070                 //   into a different data type using casts (See Implicit Constant
1071                 //   Expression Conversions)
1072                 // </summary>
1073                 static protected Expression TryImplicitIntConversion (Type target_type, IntLiteral il)
1074                 {
1075                         int value = il.Value;
1076                         
1077                         if (target_type == TypeManager.sbyte_type){
1078                                 if (value >= SByte.MinValue && value <= SByte.MaxValue)
1079                                         return il;
1080                         } else if (target_type == TypeManager.byte_type){
1081                                 if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
1082                                         return il;
1083                         } else if (target_type == TypeManager.short_type){
1084                                 if (value >= Int16.MinValue && value <= Int16.MaxValue)
1085                                         return il;
1086                         } else if (target_type == TypeManager.ushort_type){
1087                                 if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1088                                         return il;
1089                         } else if (target_type == TypeManager.uint32_type){
1090                                 //
1091                                 // we can optimize this case: a positive int32
1092                                 // always fits on a uint32
1093                                 //
1094                                 if (value >= 0)
1095                                         return il;
1096                         } else if (target_type == TypeManager.uint64_type){
1097                                 //
1098                                 // we can optimize this case: a positive int32
1099                                 // always fits on a uint64.  But we need an opcode
1100                                 // to do it.
1101                                 //
1102                                 if (value >= 0)
1103                                         return new OpcodeCast (il, target_type, OpCodes.Conv_I8);
1104                         }
1105
1106                         return null;
1107                 }
1108
1109                 // <summary>
1110                 //   Attemptes to implicityly convert `target' into `type', using
1111                 //   ConvertImplicit.  If there is no implicit conversion, then
1112                 //   an error is signaled
1113                 // </summary>
1114                 static public Expression ConvertImplicitRequired (EmitContext ec, Expression target,
1115                                                                   Type type, Location loc)
1116                 {
1117                         Expression e;
1118                         
1119                         e = ConvertImplicit (ec, target, type, loc);
1120                         if (e != null)
1121                                 return e;
1122                         
1123                         string msg = "Can not convert implicitly from `"+
1124                                 TypeManager.CSharpName (target.Type) + "' to `" +
1125                                 TypeManager.CSharpName (type) + "'";
1126
1127                         Error (29, loc, msg);
1128
1129                         return null;
1130                 }
1131
1132                 // <summary>
1133                 //   Performs the explicit numeric conversions
1134                 // </summary>
1135                 static Expression ConvertNumericExplicit (EmitContext ec, Expression expr,
1136                                                           Type target_type)
1137                 {
1138                         Type expr_type = expr.Type;
1139                         
1140                         if (expr_type == TypeManager.sbyte_type){
1141                                 //
1142                                 // From sbyte to byte, ushort, uint, ulong, char
1143                                 //
1144                                 if (target_type == TypeManager.byte_type)
1145                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1146                                 if (target_type == TypeManager.ushort_type)
1147                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1148                                 if (target_type == TypeManager.uint32_type)
1149                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1150                                 if (target_type == TypeManager.uint64_type)
1151                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
1152                                 if (target_type == TypeManager.char_type)
1153                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1154                         } else if (expr_type == TypeManager.byte_type){
1155                                 //
1156                                 // From byte to sbyte and char
1157                                 //
1158                                 if (target_type == TypeManager.sbyte_type)
1159                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1160                                 if (target_type == TypeManager.char_type)
1161                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1162                         } else if (expr_type == TypeManager.short_type){
1163                                 //
1164                                 // From short to sbyte, byte, ushort, uint, ulong, char
1165                                 //
1166                                 if (target_type == TypeManager.sbyte_type)
1167                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1168                                 if (target_type == TypeManager.byte_type)
1169                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1170                                 if (target_type == TypeManager.ushort_type)
1171                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1172                                 if (target_type == TypeManager.uint32_type)
1173                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1174                                 if (target_type == TypeManager.uint64_type)
1175                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
1176                                 if (target_type == TypeManager.char_type)
1177                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1178                         } else if (expr_type == TypeManager.ushort_type){
1179                                 //
1180                                 // From ushort to sbyte, byte, short, char
1181                                 //
1182                                 if (target_type == TypeManager.sbyte_type)
1183                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1184                                 if (target_type == TypeManager.byte_type)
1185                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1186                                 if (target_type == TypeManager.short_type)
1187                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1188                                 if (target_type == TypeManager.char_type)
1189                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1190                         } else if (expr_type == TypeManager.int32_type){
1191                                 //
1192                                 // From int to sbyte, byte, short, ushort, uint, ulong, char
1193                                 //
1194                                 if (target_type == TypeManager.sbyte_type)
1195                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1196                                 if (target_type == TypeManager.byte_type)
1197                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1198                                 if (target_type == TypeManager.short_type)
1199                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1200                                 if (target_type == TypeManager.ushort_type)
1201                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1202                                 if (target_type == TypeManager.uint32_type)
1203                                         return new EmptyCast (expr, target_type);
1204                                 if (target_type == TypeManager.uint64_type)
1205                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
1206                                 if (target_type == TypeManager.char_type)
1207                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1208                         } else if (expr_type == TypeManager.uint32_type){
1209                                 //
1210                                 // From uint to sbyte, byte, short, ushort, int, char
1211                                 //
1212                                 if (target_type == TypeManager.sbyte_type)
1213                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1214                                 if (target_type == TypeManager.byte_type)
1215                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1216                                 if (target_type == TypeManager.short_type)
1217                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1218                                 if (target_type == TypeManager.ushort_type)
1219                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1220                                 if (target_type == TypeManager.int32_type)
1221                                         return new EmptyCast (expr, target_type);
1222                                 if (target_type == TypeManager.char_type)
1223                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1224                         } else if (expr_type == TypeManager.int64_type){
1225                                 //
1226                                 // From long to sbyte, byte, short, ushort, int, uint, ulong, char
1227                                 //
1228                                 if (target_type == TypeManager.sbyte_type)
1229                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1230                                 if (target_type == TypeManager.byte_type)
1231                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1232                                 if (target_type == TypeManager.short_type)
1233                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1234                                 if (target_type == TypeManager.ushort_type)
1235                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1236                                 if (target_type == TypeManager.int32_type)
1237                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
1238                                 if (target_type == TypeManager.uint32_type)
1239                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1240                                 if (target_type == TypeManager.uint64_type)
1241                                         return new EmptyCast (expr, target_type);
1242                                 if (target_type == TypeManager.char_type)
1243                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1244                         } else if (expr_type == TypeManager.uint64_type){
1245                                 //
1246                                 // From ulong to sbyte, byte, short, ushort, int, uint, long, char
1247                                 //
1248                                 if (target_type == TypeManager.sbyte_type)
1249                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1250                                 if (target_type == TypeManager.byte_type)
1251                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1252                                 if (target_type == TypeManager.short_type)
1253                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1254                                 if (target_type == TypeManager.ushort_type)
1255                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1256                                 if (target_type == TypeManager.int32_type)
1257                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
1258                                 if (target_type == TypeManager.uint32_type)
1259                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1260                                 if (target_type == TypeManager.int64_type)
1261                                         return new EmptyCast (expr, target_type);
1262                                 if (target_type == TypeManager.char_type)
1263                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1264                         } else if (expr_type == TypeManager.char_type){
1265                                 //
1266                                 // From char to sbyte, byte, short
1267                                 //
1268                                 if (target_type == TypeManager.sbyte_type)
1269                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1270                                 if (target_type == TypeManager.byte_type)
1271                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1272                                 if (target_type == TypeManager.short_type)
1273                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1274                         } else if (expr_type == TypeManager.float_type){
1275                                 //
1276                                 // From float to sbyte, byte, short,
1277                                 // ushort, int, uint, long, ulong, char
1278                                 // or decimal
1279                                 //
1280                                 if (target_type == TypeManager.sbyte_type)
1281                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1282                                 if (target_type == TypeManager.byte_type)
1283                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1284                                 if (target_type == TypeManager.short_type)
1285                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1286                                 if (target_type == TypeManager.ushort_type)
1287                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1288                                 if (target_type == TypeManager.int32_type)
1289                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
1290                                 if (target_type == TypeManager.uint32_type)
1291                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1292                                 if (target_type == TypeManager.int64_type)
1293                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
1294                                 if (target_type == TypeManager.uint64_type)
1295                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
1296                                 if (target_type == TypeManager.char_type)
1297                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1298                                 if (target_type == TypeManager.decimal_type)
1299                                         return InternalTypeConstructor (ec, expr, target_type);
1300                         } else if (expr_type == TypeManager.double_type){
1301                                 //
1302                                 // From double to byte, byte, short,
1303                                 // ushort, int, uint, long, ulong,
1304                                 // char, float or decimal
1305                                 //
1306                                 if (target_type == TypeManager.sbyte_type)
1307                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I1);
1308                                 if (target_type == TypeManager.byte_type)
1309                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U1);
1310                                 if (target_type == TypeManager.short_type)
1311                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
1312                                 if (target_type == TypeManager.ushort_type)
1313                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1314                                 if (target_type == TypeManager.int32_type)
1315                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
1316                                 if (target_type == TypeManager.uint32_type)
1317                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U4);
1318                                 if (target_type == TypeManager.int64_type)
1319                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
1320                                 if (target_type == TypeManager.uint64_type)
1321                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
1322                                 if (target_type == TypeManager.char_type)
1323                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U2);
1324                                 if (target_type == TypeManager.float_type)
1325                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
1326                                 if (target_type == TypeManager.decimal_type)
1327                                         return InternalTypeConstructor (ec, expr, target_type);
1328                         } 
1329
1330                         // decimal is taken care of by the op_Explicit methods.
1331
1332                         return null;
1333                 }
1334
1335                 // <summary>
1336                 //   Implements Explicit Reference conversions
1337                 // </summary>
1338                 static Expression ConvertReferenceExplicit (Expression source, Type target_type)
1339                 {
1340                         Type source_type = source.Type;
1341                         bool target_is_value_type = target_type.IsValueType;
1342                         
1343                         //
1344                         // From object to any reference type
1345                         //
1346                         if (source_type == TypeManager.object_type && !target_is_value_type)
1347                                 return new ClassCast (source, target_type);
1348
1349
1350                         //
1351                         // From any class S to any class-type T, provided S is a base class of T
1352                         //
1353                         if (target_type.IsSubclassOf (source_type))
1354                                 return new ClassCast (source, target_type);
1355
1356                         //
1357                         // From any interface type S to any interface T provided S is not derived from T
1358                         //
1359                         if (source_type.IsInterface && target_type.IsInterface){
1360                                 if (!target_type.IsSubclassOf (source_type))
1361                                         return new ClassCast (source, target_type);
1362                         }
1363                             
1364                         //
1365                         // From any class type S to any interface T, provides S is not sealed
1366                         // and provided S does not implement T.
1367                         //
1368                         if (target_type.IsInterface && !source_type.IsSealed &&
1369                             !target_type.IsAssignableFrom (source_type))
1370                                 return new ClassCast (source, target_type);
1371
1372                         //
1373                         // From any interface-type S to to any class type T, provided T is not
1374                         // sealed, or provided T implements S.
1375                         //
1376                         if (source_type.IsInterface &&
1377                             (!target_type.IsSealed || source_type.IsAssignableFrom (target_type)))
1378                                 return new ClassCast (source, target_type);
1379
1380                         //
1381                         // FIXME: Implemet
1382                         //
1383
1384                         // From an array typ eS with an element type Se to an array type T with an 
1385                         // element type Te provided all the following are true:
1386                         //     * S and T differe only in element type, in other words, S and T
1387                         //       have the same number of dimensions.
1388                         //     * Both Se and Te are reference types
1389                         //     * An explicit referenc conversions exist from Se to Te
1390                         //
1391
1392                         // From System.Array to any array-type
1393                         if (source_type == TypeManager.array_type &&
1394                             target_type.IsSubclassOf (TypeManager.array_type)){
1395                                 return new ClassCast (source, target_type);
1396                         }
1397
1398                         //
1399                         // From System delegate to any delegate-type
1400                         //
1401                         if (source_type == TypeManager.delegate_type &&
1402                             target_type.IsSubclassOf (TypeManager.delegate_type))
1403                                 return new ClassCast (source, target_type);
1404
1405                         //
1406                         // From ICloneable to Array or Delegate types
1407                         //
1408                         if (source_type == TypeManager.icloneable_type &&
1409                             (target_type == TypeManager.array_type ||
1410                              target_type == TypeManager.delegate_type))
1411                                 return new ClassCast (source, target_type);
1412                         
1413                         return null;
1414                 }
1415                 
1416                 // <summary>
1417                 //   Performs an explicit conversion of the expression `expr' whose
1418                 //   type is expr.Type to `target_type'.
1419                 // </summary>
1420                 static public Expression ConvertExplicit (EmitContext ec, Expression expr,
1421                                                           Type target_type, Location loc)
1422                 {
1423                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, loc);
1424
1425                         if (ne != null)
1426                                 return ne;
1427
1428                         ne = ConvertNumericExplicit (ec, expr, target_type);
1429                         if (ne != null)
1430                                 return ne;
1431
1432                         ne = ConvertReferenceExplicit (expr, target_type);
1433                         if (ne != null)
1434                                 return ne;
1435
1436                         ne = ExplicitUserConversion (ec, expr, target_type, loc);
1437                         if (ne != null)
1438                                 return ne;
1439
1440                         Report.Error (30, loc, "Cannot convert type '" + TypeManager.CSharpName (expr.Type) + "' to '"
1441                                       + TypeManager.CSharpName (target_type) + "'");
1442                         return null;
1443                 }
1444
1445                 // <summary>
1446                 //   Same as ConverExplicit, only it doesn't include user defined conversions
1447                 // </summary>
1448                 static public Expression ConvertExplicitStandard (EmitContext ec, Expression expr,
1449                                                                   Type target_type, Location l)
1450                 {
1451                         Expression ne = ConvertImplicitStandard (ec, expr, target_type, l);
1452
1453                         if (ne != null)
1454                                 return ne;
1455
1456                         ne = ConvertNumericExplicit (ec, expr, target_type);
1457                         if (ne != null)
1458                                 return ne;
1459
1460                         ne = ConvertReferenceExplicit (expr, target_type);
1461                         if (ne != null)
1462                                 return ne;
1463
1464                         Report.Error (30, l, "Cannot convert type '" +
1465                                       TypeManager.CSharpName (expr.Type) + "' to '" + 
1466                                       TypeManager.CSharpName (target_type) + "'");
1467                         return null;
1468                 }
1469
1470                 static string ExprClassName (ExprClass c)
1471                 {
1472                         switch (c){
1473                         case ExprClass.Invalid:
1474                                 return "Invalid";
1475                         case ExprClass.Value:
1476                                 return "value";
1477                         case ExprClass.Variable:
1478                                 return "variable";
1479                         case ExprClass.Namespace:
1480                                 return "namespace";
1481                         case ExprClass.Type:
1482                                 return "type";
1483                         case ExprClass.MethodGroup:
1484                                 return "method group";
1485                         case ExprClass.PropertyAccess:
1486                                 return "property access";
1487                         case ExprClass.EventAccess:
1488                                 return "event access";
1489                         case ExprClass.IndexerAccess:
1490                                 return "indexer access";
1491                         case ExprClass.Nothing:
1492                                 return "null";
1493                         }
1494                         throw new Exception ("Should not happen");
1495                 }
1496                 
1497                 // <summary>
1498                 //   Reports that we were expecting `expr' to be of class `expected'
1499                 // </summary>
1500                 protected void report118 (Location loc, Expression expr, string expected)
1501                 {
1502                         string kind = "Unknown";
1503                         
1504                         if (expr != null)
1505                                 kind = ExprClassName (expr.ExprClass);
1506
1507                         Error (118, loc, "Expression denotes a '" + kind +
1508                                "' where an " + expected + " was expected");
1509                 }
1510         }
1511
1512         // <summary>
1513         //   This is just a base class for expressions that can
1514         //   appear on statements (invocations, object creation,
1515         //   assignments, post/pre increment and decrement).  The idea
1516         //   being that they would support an extra Emition interface that
1517         //   does not leave a result on the stack.
1518         // </summary>
1519
1520         public abstract class ExpressionStatement : Expression {
1521
1522                 // <summary>
1523                 //   Requests the expression to be emitted in a `statement'
1524                 //   context.  This means that no new value is left on the
1525                 //   stack after invoking this method (constrasted with
1526                 //   Emit that will always leave a value on the stack).
1527                 // </summary>
1528                 public abstract void EmitStatement (EmitContext ec);
1529         }
1530
1531         // <summary>
1532         //   This kind of cast is used to encapsulate the child
1533         //   whose type is child.Type into an expression that is
1534         //   reported to return "return_type".  This is used to encapsulate
1535         //   expressions which have compatible types, but need to be dealt
1536         //   at higher levels with.
1537         //
1538         //   For example, a "byte" expression could be encapsulated in one
1539         //   of these as an "unsigned int".  The type for the expression
1540         //   would be "unsigned int".
1541         //
1542         // </summary>
1543         
1544         public class EmptyCast : Expression {
1545                 protected Expression child;
1546
1547                 public EmptyCast (Expression child, Type return_type)
1548                 {
1549                         ExprClass = child.ExprClass;
1550                         type = return_type;
1551                         this.child = child;
1552                 }
1553
1554                 public override Expression DoResolve (EmitContext ec)
1555                 {
1556                         // This should never be invoked, we are born in fully
1557                         // initialized state.
1558
1559                         return this;
1560                 }
1561
1562                 public override void Emit (EmitContext ec)
1563                 {
1564                         child.Emit (ec);
1565                 }                       
1566         }
1567
1568         // <summary>
1569         //   This kind of cast is used to encapsulate Value Types in objects.
1570         //
1571         //   The effect of it is to box the value type emitted by the previous
1572         //   operation.
1573         // </summary>
1574         public class BoxedCast : EmptyCast {
1575
1576                 public BoxedCast (Expression expr)
1577                         : base (expr, TypeManager.object_type)
1578                 {
1579                 }
1580
1581                 public override Expression DoResolve (EmitContext ec)
1582                 {
1583                         // This should never be invoked, we are born in fully
1584                         // initialized state.
1585
1586                         return this;
1587                 }
1588
1589                 public override void Emit (EmitContext ec)
1590                 {
1591                         base.Emit (ec);
1592                         ec.ig.Emit (OpCodes.Box, child.Type);
1593                 }
1594         }
1595
1596         // <summary>
1597         //   This kind of cast is used to encapsulate a child expression
1598         //   that can be trivially converted to a target type using one or 
1599         //   two opcodes.  The opcodes are passed as arguments.
1600         // </summary>
1601         public class OpcodeCast : EmptyCast {
1602                 OpCode op, op2;
1603                 bool second_valid;
1604                 
1605                 public OpcodeCast (Expression child, Type return_type, OpCode op)
1606                         : base (child, return_type)
1607                         
1608                 {
1609                         this.op = op;
1610                         second_valid = false;
1611                 }
1612
1613                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
1614                         : base (child, return_type)
1615                         
1616                 {
1617                         this.op = op;
1618                         this.op2 = op2;
1619                         second_valid = true;
1620                 }
1621
1622                 public override Expression DoResolve (EmitContext ec)
1623                 {
1624                         // This should never be invoked, we are born in fully
1625                         // initialized state.
1626
1627                         return this;
1628                 }
1629
1630                 public override void Emit (EmitContext ec)
1631                 {
1632                         base.Emit (ec);
1633                         ec.ig.Emit (op);
1634
1635                         if (second_valid)
1636                                 ec.ig.Emit (op2);
1637                 }                       
1638                 
1639         }
1640
1641         // <summary>
1642         //   This kind of cast is used to encapsulate a child and cast it
1643         //   to the class requested
1644         // </summary>
1645         public class ClassCast : EmptyCast {
1646                 public ClassCast (Expression child, Type return_type)
1647                         : base (child, return_type)
1648                         
1649                 {
1650                 }
1651
1652                 public override Expression DoResolve (EmitContext ec)
1653                 {
1654                         // This should never be invoked, we are born in fully
1655                         // initialized state.
1656
1657                         return this;
1658                 }
1659
1660                 public override void Emit (EmitContext ec)
1661                 {
1662                         base.Emit (ec);
1663
1664                         ec.ig.Emit (OpCodes.Castclass, type);
1665                 }                       
1666                 
1667         }
1668         
1669         // <summary>
1670         //   Unary expressions.  
1671         // </summary>
1672         //
1673         // <remarks>
1674         //   Unary implements unary expressions.   It derives from
1675         //   ExpressionStatement becuase the pre/post increment/decrement
1676         //   operators can be used in a statement context.
1677         // </remarks>
1678         public class Unary : ExpressionStatement {
1679                 public enum Operator {
1680                         Addition, Subtraction, Negate, BitComplement,
1681                         Indirection, AddressOf, PreIncrement,
1682                         PreDecrement, PostIncrement, PostDecrement
1683                 }
1684
1685                 Operator   oper;
1686                 Expression expr;
1687                 ArrayList  Arguments;
1688                 MethodBase method;
1689                 Location   loc;
1690                 
1691                 public Unary (Operator op, Expression expr, Location loc)
1692                 {
1693                         this.oper = op;
1694                         this.expr = expr;
1695                         this.loc = loc;
1696                 }
1697
1698                 public Expression Expr {
1699                         get {
1700                                 return expr;
1701                         }
1702
1703                         set {
1704                                 expr = value;
1705                         }
1706                 }
1707
1708                 public Operator Oper {
1709                         get {
1710                                 return oper;
1711                         }
1712
1713                         set {
1714                                 oper = value;
1715                         }
1716                 }
1717
1718                 // <summary>
1719                 //   Returns a stringified representation of the Operator
1720                 // </summary>
1721                 string OperName ()
1722                 {
1723                         switch (oper){
1724                         case Operator.Addition:
1725                                 return "+";
1726                         case Operator.Subtraction:
1727                                 return "-";
1728                         case Operator.Negate:
1729                                 return "!";
1730                         case Operator.BitComplement:
1731                                 return "~";
1732                         case Operator.AddressOf:
1733                                 return "&";
1734                         case Operator.Indirection:
1735                                 return "*";
1736                         case Operator.PreIncrement : case Operator.PostIncrement :
1737                                 return "++";
1738                         case Operator.PreDecrement : case Operator.PostDecrement :
1739                                 return "--";
1740                         }
1741
1742                         return oper.ToString ();
1743                 }
1744
1745                 Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
1746                 {
1747                         if (expr.Type == target_type)
1748                                 return expr;
1749
1750                         return ConvertImplicit (ec, expr, target_type, new Location (-1));
1751                 }
1752
1753                 void error23 (Type t)
1754                 {
1755                         Report.Error (
1756                                 23, loc, "Operator " + OperName () +
1757                                 " cannot be applied to operand of type `" +
1758                                 TypeManager.CSharpName (t) + "'");
1759                 }
1760
1761                 // <summary>
1762                 //   Returns whether an object of type `t' can be incremented
1763                 //   or decremented with add/sub (ie, basically whether we can
1764                 //   use pre-post incr-decr operations on it, but it is not a
1765                 //   System.Decimal, which we test elsewhere)
1766                 // </summary>
1767                 static bool IsIncrementableNumber (Type t)
1768                 {
1769                         return (t == TypeManager.sbyte_type) ||
1770                                 (t == TypeManager.byte_type) ||
1771                                 (t == TypeManager.short_type) ||
1772                                 (t == TypeManager.ushort_type) ||
1773                                 (t == TypeManager.int32_type) ||
1774                                 (t == TypeManager.uint32_type) ||
1775                                 (t == TypeManager.int64_type) ||
1776                                 (t == TypeManager.uint64_type) ||
1777                                 (t == TypeManager.char_type) ||
1778                                 (t.IsSubclassOf (TypeManager.enum_type)) ||
1779                                 (t == TypeManager.float_type) ||
1780                                 (t == TypeManager.double_type);
1781                 }
1782                         
1783                 Expression ResolveOperator (EmitContext ec)
1784                 {
1785                         Type expr_type = expr.Type;
1786
1787                         //
1788                         // Step 1: Perform Operator Overload location
1789                         //
1790                         Expression mg;
1791                         string op_name;
1792                                 
1793                         if (oper == Operator.PostIncrement || oper == Operator.PreIncrement)
1794                                 op_name = "op_Increment";
1795                         else if (oper == Operator.PostDecrement || oper == Operator.PreDecrement)
1796                                 op_name = "op_Decrement";
1797                         else
1798                                 op_name = "op_" + oper;
1799
1800                         mg = MemberLookup (ec, expr_type, op_name, false, loc);
1801                         
1802                         if (mg == null && expr_type.BaseType != null)
1803                                 mg = MemberLookup (ec, expr_type.BaseType, op_name, false, loc);
1804                         
1805                         if (mg != null) {
1806                                 Arguments = new ArrayList ();
1807                                 Arguments.Add (new Argument (expr, Argument.AType.Expression));
1808                                 
1809                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg,
1810                                                                      Arguments, loc);
1811                                 if (method != null) {
1812                                         MethodInfo mi = (MethodInfo) method;
1813                                         type = mi.ReturnType;
1814                                         return this;
1815                                 } else {
1816                                         error23 (expr_type);
1817                                         return null;
1818                                 }
1819                                         
1820                         }
1821
1822                         //
1823                         // Step 2: Default operations on CLI native types.
1824                         //
1825
1826                         // Only perform numeric promotions on:
1827                         // +, -, ++, --
1828
1829                         if (expr_type == null)
1830                                 return null;
1831                         
1832                         if (oper == Operator.Negate){
1833                                 if (expr_type != TypeManager.bool_type) {
1834                                         error23 (expr.Type);
1835                                         return null;
1836                                 }
1837                                 
1838                                 type = TypeManager.bool_type;
1839                                 return this;
1840                         }
1841
1842                         if (oper == Operator.BitComplement) {
1843                                 if (!((expr_type == TypeManager.int32_type) ||
1844                                       (expr_type == TypeManager.uint32_type) ||
1845                                       (expr_type == TypeManager.int64_type) ||
1846                                       (expr_type == TypeManager.uint64_type) ||
1847                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
1848                                         error23 (expr.Type);
1849                                         return null;
1850                                 }
1851                                 type = expr_type;
1852                                 return this;
1853                         }
1854
1855                         if (oper == Operator.Addition) {
1856                                 //
1857                                 // A plus in front of something is just a no-op, so return the child.
1858                                 //
1859                                 return expr;
1860                         }
1861
1862                         //
1863                         // Deals with -literals
1864                         // int     operator- (int x)
1865                         // long    operator- (long x)
1866                         // float   operator- (float f)
1867                         // double  operator- (double d)
1868                         // decimal operator- (decimal d)
1869                         //
1870                         if (oper == Operator.Subtraction){
1871                                 //
1872                                 // Fold a "- Constant" into a negative constant
1873                                 //
1874                         
1875                                 Expression e = null;
1876
1877                                 //
1878                                 // Is this a constant? 
1879                                 //
1880                                 if (expr is IntLiteral)
1881                                         e = new IntLiteral (-((IntLiteral) expr).Value);
1882                                 else if (expr is LongLiteral)
1883                                         e = new LongLiteral (-((LongLiteral) expr).Value);
1884                                 else if (expr is FloatLiteral)
1885                                         e = new FloatLiteral (-((FloatLiteral) expr).Value);
1886                                 else if (expr is DoubleLiteral)
1887                                         e = new DoubleLiteral (-((DoubleLiteral) expr).Value);
1888                                 else if (expr is DecimalLiteral)
1889                                         e = new DecimalLiteral (-((DecimalLiteral) expr).Value);
1890                                 
1891                                 if (e != null){
1892                                         e = e.Resolve (ec);
1893                                         return e;
1894                                 }
1895
1896                                 //
1897                                 // Not a constant we can optimize, perform numeric 
1898                                 // promotions to int, long, double.
1899                                 //
1900                                 //
1901                                 // The following is inneficient, because we call
1902                                 // ConvertImplicit too many times.
1903                                 //
1904                                 // It is also not clear if we should convert to Float
1905                                 // or Double initially.
1906                                 //
1907                                 if (expr_type == TypeManager.uint32_type){
1908                                         //
1909                                         // FIXME: handle exception to this rule that
1910                                         // permits the int value -2147483648 (-2^31) to
1911                                         // bt written as a decimal interger literal
1912                                         //
1913                                         type = TypeManager.int64_type;
1914                                         expr = ConvertImplicit (ec, expr, type, loc);
1915                                         return this;
1916                                 }
1917
1918                                 if (expr_type == TypeManager.uint64_type){
1919                                         //
1920                                         // FIXME: Handle exception of `long value'
1921                                         // -92233720368547758087 (-2^63) to be written as
1922                                         // decimal integer literal.
1923                                         //
1924                                         error23 (expr_type);
1925                                         return null;
1926                                 }
1927
1928                                 e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);
1929                                 if (e != null){
1930                                         expr = e;
1931                                         type = e.Type;
1932                                         return this;
1933                                 } 
1934
1935                                 e = ConvertImplicit (ec, expr, TypeManager.int64_type, loc);
1936                                 if (e != null){
1937                                         expr = e;
1938                                         type = e.Type;
1939                                         return this;
1940                                 }
1941
1942                                 e = ConvertImplicit (ec, expr, TypeManager.double_type, loc);
1943                                 if (e != null){
1944                                         expr = e;
1945                                         type = e.Type;
1946                                         return this;
1947                                 }
1948
1949                                 error23 (expr_type);
1950                                 return null;
1951                         }
1952
1953                         //
1954                         // The operand of the prefix/postfix increment decrement operators
1955                         // should be an expression that is classified as a variable,
1956                         // a property access or an indexer access
1957                         //
1958                         if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
1959                             oper == Operator.PostDecrement || oper == Operator.PostIncrement){
1960                                 if (expr.ExprClass == ExprClass.Variable){
1961                                         if (IsIncrementableNumber (expr_type) ||
1962                                             expr_type == TypeManager.decimal_type){
1963                                                 type = expr_type;
1964                                                 return this;
1965                                         }
1966                                 } else if (expr.ExprClass == ExprClass.IndexerAccess){
1967                                         //
1968                                         // FIXME: Verify that we have both get and set methods
1969                                         //
1970                                         throw new Exception ("Implement me");
1971                                 } else if (expr.ExprClass == ExprClass.PropertyAccess){
1972                                         //
1973                                         // FIXME: Verify that we have both get and set methods
1974                                         //
1975                                         throw new Exception ("Implement me");
1976                                 } else {
1977                                         report118 (loc, expr, "variable, indexer or property access");
1978                                 }
1979                         }
1980
1981                         if (oper == Operator.AddressOf){
1982                                 if (expr.ExprClass != ExprClass.Variable){
1983                                         Error (211, "Cannot take the address of non-variables");
1984                                         return null;
1985                                 }
1986                                 type = Type.GetType (expr.Type.ToString () + "*");
1987                         }
1988                         
1989                         Error (187, "No such operator '" + OperName () + "' defined for type '" +
1990                                TypeManager.CSharpName (expr_type) + "'");
1991                         return null;
1992
1993                 }
1994
1995                 public override Expression DoResolve (EmitContext ec)
1996                 {
1997                         expr = expr.Resolve (ec);
1998
1999                         if (expr == null)
2000                                 return null;
2001
2002                         eclass = ExprClass.Value;
2003                         return ResolveOperator (ec);
2004                 }
2005
2006                 public override void Emit (EmitContext ec)
2007                 {
2008                         ILGenerator ig = ec.ig;
2009                         Type expr_type = expr.Type;
2010
2011                         if (method != null) {
2012
2013                                 // Note that operators are static anyway
2014                                 
2015                                 if (Arguments != null) 
2016                                         Invocation.EmitArguments (ec, method, Arguments);
2017
2018                                 //
2019                                 // Post increment/decrement operations need a copy at this
2020                                 // point.
2021                                 //
2022                                 if (oper == Operator.PostDecrement || oper == Operator.PostIncrement)
2023                                         ig.Emit (OpCodes.Dup);
2024                                 
2025
2026                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
2027
2028                                 //
2029                                 // Pre Increment and Decrement operators
2030                                 //
2031                                 if (oper == Operator.PreIncrement || oper == Operator.PreDecrement){
2032                                         ig.Emit (OpCodes.Dup);
2033                                 }
2034                                 
2035                                 //
2036                                 // Increment and Decrement should store the result
2037                                 //
2038                                 if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
2039                                     oper == Operator.PostDecrement || oper == Operator.PostIncrement){
2040                                         ((LValue) expr).Store (ec);
2041                                 }
2042                                 return;
2043                         }
2044                         
2045                         switch (oper) {
2046                         case Operator.Addition:
2047                                 throw new Exception ("This should be caught by Resolve");
2048                                 
2049                         case Operator.Subtraction:
2050                                 expr.Emit (ec);
2051                                 ig.Emit (OpCodes.Neg);
2052                                 break;
2053                                 
2054                         case Operator.Negate:
2055                                 expr.Emit (ec);
2056                                 ig.Emit (OpCodes.Ldc_I4_0);
2057                                 ig.Emit (OpCodes.Ceq);
2058                                 break;
2059                                 
2060                         case Operator.BitComplement:
2061                                 expr.Emit (ec);
2062                                 ig.Emit (OpCodes.Not);
2063                                 break;
2064                                 
2065                         case Operator.AddressOf:
2066                                 ((MemoryLocation)expr).AddressOf (ec);
2067                                 break;
2068                                 
2069                         case Operator.Indirection:
2070                                 throw new Exception ("Not implemented yet");
2071                                 
2072                         case Operator.PreIncrement:
2073                         case Operator.PreDecrement:
2074                                 if (expr.ExprClass == ExprClass.Variable){
2075                                         //
2076                                         // Resolve already verified that it is an "incrementable"
2077                                         // 
2078                                         expr.Emit (ec);
2079                                         ig.Emit (OpCodes.Ldc_I4_1);
2080                                         
2081                                         if (oper == Operator.PreDecrement)
2082                                                 ig.Emit (OpCodes.Sub);
2083                                         else
2084                                                 ig.Emit (OpCodes.Add);
2085                                         ig.Emit (OpCodes.Dup);
2086                                         ((LValue) expr).Store (ec);
2087                                 } else {
2088                                         throw new Exception ("Handle Indexers and Properties here");
2089                                 }
2090                                 break;
2091                                 
2092                         case Operator.PostIncrement:
2093                         case Operator.PostDecrement:
2094                                 if (expr.ExprClass == ExprClass.Variable){
2095                                         //
2096                                         // Resolve already verified that it is an "incrementable"
2097                                         // 
2098                                         expr.Emit (ec);
2099                                         ig.Emit (OpCodes.Dup);
2100                                         ig.Emit (OpCodes.Ldc_I4_1);
2101                                         
2102                                         if (oper == Operator.PostDecrement)
2103                                                 ig.Emit (OpCodes.Sub);
2104                                         else
2105                                                 ig.Emit (OpCodes.Add);
2106                                         ((LValue) expr).Store (ec);
2107                                 } else {
2108                                         throw new Exception ("Handle Indexers and Properties here");
2109                                 }
2110                                 break;
2111                                 
2112                         default:
2113                                 throw new Exception ("This should not happen: Operator = "
2114                                                      + oper.ToString ());
2115                         }
2116                 }
2117                 
2118
2119                 public override void EmitStatement (EmitContext ec)
2120                 {
2121                         //
2122                         // FIXME: we should rewrite this code to generate
2123                         // better code for ++ and -- as we know we wont need
2124                         // the values on the stack
2125                         //
2126                         Emit (ec);
2127                         ec.ig.Emit (OpCodes.Pop);
2128                 }
2129         }
2130         
2131         public class Probe : Expression {
2132                 public readonly string ProbeType;
2133                 public readonly Operator Oper;
2134                 Expression expr;
2135                 Type probe_type;
2136                 
2137                 public enum Operator {
2138                         Is, As
2139                 }
2140                 
2141                 public Probe (Operator oper, Expression expr, string probe_type)
2142                 {
2143                         Oper = oper;
2144                         ProbeType = probe_type;
2145                         this.expr = expr;
2146                 }
2147
2148                 public Expression Expr {
2149                         get {
2150                                 return expr;
2151                         }
2152                 }
2153                 
2154                 public override Expression DoResolve (EmitContext ec)
2155                 {
2156                         probe_type = ec.TypeContainer.LookupType (ProbeType, false);
2157
2158                         if (probe_type == null)
2159                                 return null;
2160
2161                         expr = expr.Resolve (ec);
2162                         
2163                         type = TypeManager.bool_type;
2164                         eclass = ExprClass.Value;
2165
2166                         return this;
2167                 }
2168
2169                 public override void Emit (EmitContext ec)
2170                 {
2171                         ILGenerator ig = ec.ig;
2172                         
2173                         expr.Emit (ec);
2174                         
2175                         if (Oper == Operator.Is){
2176                                 ig.Emit (OpCodes.Isinst, probe_type);
2177                                 ig.Emit (OpCodes.Ldnull);
2178                                 ig.Emit (OpCodes.Cgt_Un);
2179                         } else {
2180                                 ig.Emit (OpCodes.Isinst, probe_type);
2181                         }
2182                 }
2183         }
2184
2185         // <summary>
2186         //   This represents a typecast in the source language.
2187         //
2188         //   FIXME: Cast expressions have an unusual set of parsing
2189         //   rules, we need to figure those out.
2190         // </summary>
2191         public class Cast : Expression {
2192                 string target_type;
2193                 Expression expr;
2194                 Location   loc;
2195                         
2196                 public Cast (string cast_type, Expression expr, Location loc)
2197                 {
2198                         this.target_type = cast_type;
2199                         this.expr = expr;
2200                         this.loc = loc;
2201                 }
2202
2203                 public string TargetType {
2204                         get {
2205                                 return target_type;
2206                         }
2207                 }
2208
2209                 public Expression Expr {
2210                         get {
2211                                 return expr;
2212                         }
2213                         set {
2214                                 expr = value;
2215                         }
2216                 }
2217                 
2218                 public override Expression DoResolve (EmitContext ec)
2219                 {
2220                         expr = expr.Resolve (ec);
2221                         if (expr == null)
2222                                 return null;
2223                         
2224                         type = ec.TypeContainer.LookupType (target_type, false);
2225                         eclass = ExprClass.Value;
2226                         
2227                         if (type == null)
2228                                 return null;
2229
2230                         expr = ConvertExplicit (ec, expr, type, loc);
2231
2232                         return expr;
2233                 }
2234
2235                 public override void Emit (EmitContext ec)
2236                 {
2237                         //
2238                         // This one will never happen
2239                         //
2240                         throw new Exception ("Should not happen");
2241                 }
2242         }
2243
2244         public class Binary : Expression {
2245                 public enum Operator {
2246                         Multiply, Division, Modulus,
2247                         Addition, Subtraction,
2248                         LeftShift, RightShift,
2249                         LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
2250                         Equality, Inequality,
2251                         BitwiseAnd,
2252                         ExclusiveOr,
2253                         BitwiseOr,
2254                         LogicalAnd,
2255                         LogicalOr
2256                 }
2257
2258                 Operator oper;
2259                 Expression left, right;
2260                 MethodBase method;
2261                 ArrayList  Arguments;
2262                 Location   loc;
2263                 
2264
2265                 public Binary (Operator oper, Expression left, Expression right, Location loc)
2266                 {
2267                         this.oper = oper;
2268                         this.left = left;
2269                         this.right = right;
2270                         this.loc = loc;
2271                 }
2272
2273                 public Operator Oper {
2274                         get {
2275                                 return oper;
2276                         }
2277                         set {
2278                                 oper = value;
2279                         }
2280                 }
2281                 
2282                 public Expression Left {
2283                         get {
2284                                 return left;
2285                         }
2286                         set {
2287                                 left = value;
2288                         }
2289                 }
2290
2291                 public Expression Right {
2292                         get {
2293                                 return right;
2294                         }
2295                         set {
2296                                 right = value;
2297                         }
2298                 }
2299
2300
2301                 // <summary>
2302                 //   Returns a stringified representation of the Operator
2303                 // </summary>
2304                 string OperName ()
2305                 {
2306                         switch (oper){
2307                         case Operator.Multiply:
2308                                 return "*";
2309                         case Operator.Division:
2310                                 return "/";
2311                         case Operator.Modulus:
2312                                 return "%";
2313                         case Operator.Addition:
2314                                 return "+";
2315                         case Operator.Subtraction:
2316                                 return "-";
2317                         case Operator.LeftShift:
2318                                 return "<<";
2319                         case Operator.RightShift:
2320                                 return ">>";
2321                         case Operator.LessThan:
2322                                 return "<";
2323                         case Operator.GreaterThan:
2324                                 return ">";
2325                         case Operator.LessThanOrEqual:
2326                                 return "<=";
2327                         case Operator.GreaterThanOrEqual:
2328                                 return ">=";
2329                         case Operator.Equality:
2330                                 return "==";
2331                         case Operator.Inequality:
2332                                 return "!=";
2333                         case Operator.BitwiseAnd:
2334                                 return "&";
2335                         case Operator.BitwiseOr:
2336                                 return "|";
2337                         case Operator.ExclusiveOr:
2338                                 return "^";
2339                         case Operator.LogicalOr:
2340                                 return "||";
2341                         case Operator.LogicalAnd:
2342                                 return "&&";
2343                         }
2344
2345                         return oper.ToString ();
2346                 }
2347
2348                 Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
2349                 {
2350                         if (expr.Type == target_type)
2351                                 return expr;
2352
2353                         return ConvertImplicit (ec, expr, target_type, new Location (-1));
2354                 }
2355                 
2356                 //
2357                 // Note that handling the case l == Decimal || r == Decimal
2358                 // is taken care of by the Step 1 Operator Overload resolution.
2359                 //
2360                 void DoNumericPromotions (EmitContext ec, Type l, Type r)
2361                 {
2362                         if (l == TypeManager.double_type || r == TypeManager.double_type){
2363                                 //
2364                                 // If either operand is of type double, the other operand is
2365                                 // conveted to type double.
2366                                 //
2367                                 if (r != TypeManager.double_type)
2368                                         right = ConvertImplicit (ec, right, TypeManager.double_type, loc);
2369                                 if (l != TypeManager.double_type)
2370                                         left = ConvertImplicit (ec, left, TypeManager.double_type, loc);
2371                                 
2372                                 type = TypeManager.double_type;
2373                         } else if (l == TypeManager.float_type || r == TypeManager.float_type){
2374                                 //
2375                                 // if either operand is of type float, th eother operand is
2376                                 // converd to type float.
2377                                 //
2378                                 if (r != TypeManager.double_type)
2379                                         right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
2380                                 if (l != TypeManager.double_type)
2381                                         left = ConvertImplicit (ec, left, TypeManager.float_type, loc);
2382                                 type = TypeManager.float_type;
2383                         } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
2384                                 Expression e;
2385                                 Type other;
2386                                 //
2387                                 // If either operand is of type ulong, the other operand is
2388                                 // converted to type ulong.  or an error ocurrs if the other
2389                                 // operand is of type sbyte, short, int or long
2390                                 //
2391                                 
2392                                 if (l == TypeManager.uint64_type){
2393                                         if (r != TypeManager.uint64_type && right is IntLiteral){
2394                                                 e = TryImplicitIntConversion (l, (IntLiteral) right);
2395                                                 if (e != null)
2396                                                         right = e;
2397                                         }
2398                                         other = right.Type;
2399                                 } else {
2400                                         if (left is IntLiteral){
2401                                                 e = TryImplicitIntConversion (r, (IntLiteral) left);
2402                                                 if (e != null)
2403                                                         left = e;
2404                                         }
2405                                         other = left.Type;
2406                                 }
2407
2408                                 if ((other == TypeManager.sbyte_type) ||
2409                                     (other == TypeManager.short_type) ||
2410                                     (other == TypeManager.int32_type) ||
2411                                     (other == TypeManager.int64_type)){
2412                                         string oper = OperName ();
2413                                         
2414                                         Error (34, loc, "Operator `" + OperName ()
2415                                                + "' is ambiguous on operands of type `"
2416                                                + TypeManager.CSharpName (l) + "' "
2417                                                + "and `" + TypeManager.CSharpName (r)
2418                                                + "'");
2419                                 }
2420                                 type = TypeManager.uint64_type;
2421                         } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
2422                                 //
2423                                 // If either operand is of type long, the other operand is converted
2424                                 // to type long.
2425                                 //
2426                                 if (l != TypeManager.int64_type)
2427                                         left = ConvertImplicit (ec, left, TypeManager.int64_type, loc);
2428                                 if (r != TypeManager.int64_type)
2429                                         right = ConvertImplicit (ec, right, TypeManager.int64_type, loc);
2430
2431                                 type = TypeManager.int64_type;
2432                         } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
2433                                 //
2434                                 // If either operand is of type uint, and the other
2435                                 // operand is of type sbyte, short or int, othe operands are
2436                                 // converted to type long.
2437                                 //
2438                                 Type other = null;
2439                                 
2440                                 if (l == TypeManager.uint32_type)
2441                                         other = r;
2442                                 else if (r == TypeManager.uint32_type)
2443                                         other = l;
2444
2445                                 if ((other == TypeManager.sbyte_type) ||
2446                                     (other == TypeManager.short_type) ||
2447                                     (other == TypeManager.int32_type)){
2448                                         left = ForceConversion (ec, left, TypeManager.int64_type);
2449                                         right = ForceConversion (ec, right, TypeManager.int64_type);
2450                                         type = TypeManager.int64_type;
2451                                 } else {
2452                                         //
2453                                         // if either operand is of type uint, the other
2454                                         // operand is converd to type uint
2455                                         //
2456                                         left = ForceConversion (ec, left, TypeManager.uint32_type);
2457                                         right = ForceConversion (ec, right, TypeManager.uint32_type);
2458                                         type = TypeManager.uint32_type;
2459                                 } 
2460                         } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
2461                                 if (l != TypeManager.decimal_type)
2462                                         left = ConvertImplicit (ec, left, TypeManager.decimal_type, loc);
2463                                 if (r != TypeManager.decimal_type)
2464                                         right = ConvertImplicit (ec, right, TypeManager.decimal_type, loc);
2465
2466                                 type = TypeManager.decimal_type;
2467                         } else {
2468                                 Expression l_tmp, r_tmp;
2469
2470                                 l_tmp = ForceConversion (ec, left, TypeManager.int32_type);
2471                                 if (l_tmp == null) {
2472                                         error19 ();
2473                                         left = l_tmp;
2474                                         return;
2475                                 }
2476                                 
2477                                 r_tmp = ForceConversion (ec, right, TypeManager.int32_type);
2478                                 if (r_tmp == null) {
2479                                         error19 ();
2480                                         right = r_tmp;
2481                                         return;
2482                                 }
2483                                 
2484                                 type = TypeManager.int32_type;
2485                         }
2486                 }
2487
2488                 void error19 ()
2489                 {
2490                         Error (19, loc,
2491                                "Operator " + OperName () + " cannot be applied to operands of type `" +
2492                                TypeManager.CSharpName (left.Type) + "' and `" +
2493                                TypeManager.CSharpName (right.Type) + "'");
2494                                                      
2495                 }
2496                 
2497                 Expression CheckShiftArguments (EmitContext ec)
2498                 {
2499                         Expression e;
2500                         Type l = left.Type;
2501                         Type r = right.Type;
2502
2503                         e = ForceConversion (ec, right, TypeManager.int32_type);
2504                         if (e == null){
2505                                 error19 ();
2506                                 return null;
2507                         }
2508                         right = e;
2509
2510                         if (((e = ConvertImplicit (ec, left, TypeManager.int32_type, loc)) != null) ||
2511                             ((e = ConvertImplicit (ec, left, TypeManager.uint32_type, loc)) != null) ||
2512                             ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) ||
2513                             ((e = ConvertImplicit (ec, left, TypeManager.uint64_type, loc)) != null)){
2514                                 left = e;
2515                                 type = e.Type;
2516
2517                                 return this;
2518                         }
2519                         error19 ();
2520                         return null;
2521                 }
2522                 
2523                 Expression ResolveOperator (EmitContext ec)
2524                 {
2525                         Type l = left.Type;
2526                         Type r = right.Type;
2527
2528                         //
2529                         // Step 1: Perform Operator Overload location
2530                         //
2531                         Expression left_expr, right_expr;
2532                         
2533                         string op = "op_" + oper;
2534
2535                         left_expr = MemberLookup (ec, l, op, false, loc);
2536                         if (left_expr == null && l.BaseType != null)
2537                                 left_expr = MemberLookup (ec, l.BaseType, op, false, loc);
2538                         
2539                         right_expr = MemberLookup (ec, r, op, false, loc);
2540                         if (right_expr == null && r.BaseType != null)
2541                                 right_expr = MemberLookup (ec, r.BaseType, op, false, loc);
2542                         
2543                         MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
2544                         
2545                         if (union != null) {
2546                                 Arguments = new ArrayList ();
2547                                 Arguments.Add (new Argument (left, Argument.AType.Expression));
2548                                 Arguments.Add (new Argument (right, Argument.AType.Expression));
2549                                 
2550                                 method = Invocation.OverloadResolve (ec, union, Arguments, loc);
2551                                 if (method != null) {
2552                                         MethodInfo mi = (MethodInfo) method;
2553                                         type = mi.ReturnType;
2554                                         return this;
2555                                 } else {
2556                                         error19 ();
2557                                         return null;
2558                                 }
2559                         }       
2560
2561                         //
2562                         // Step 2: Default operations on CLI native types.
2563                         //
2564                         
2565                         // Only perform numeric promotions on:
2566                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
2567                         //
2568                         if (oper == Operator.Addition){
2569                                 //
2570                                 // If any of the arguments is a string, cast to string
2571                                 //
2572                                 if (l == TypeManager.string_type){
2573                                         if (r == TypeManager.string_type){
2574                                                 // string + string
2575                                                 method = TypeManager.string_concat_string_string;
2576                                         } else {
2577                                                 // string + object
2578                                                 method = TypeManager.string_concat_object_object;
2579                                                 right = ConvertImplicit (ec, right,
2580                                                                          TypeManager.object_type, loc);
2581                                         }
2582                                         type = TypeManager.string_type;
2583
2584                                         Arguments = new ArrayList ();
2585                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
2586                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
2587
2588                                         return this;
2589                                         
2590                                 } else if (r == TypeManager.string_type){
2591                                         // object + string
2592                                         method = TypeManager.string_concat_object_object;
2593                                         Arguments = new ArrayList ();
2594                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
2595                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
2596
2597                                         left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
2598                                         type = TypeManager.string_type;
2599
2600                                         return this;
2601                                 }
2602
2603                                 //
2604                                 // FIXME: is Delegate operator + (D x, D y) handled?
2605                                 //
2606                         }
2607                         
2608                         if (oper == Operator.LeftShift || oper == Operator.RightShift)
2609                                 return CheckShiftArguments (ec);
2610
2611                         if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
2612                                 if (l != TypeManager.bool_type || r != TypeManager.bool_type)
2613                                         error19 ();
2614
2615                                 type = TypeManager.bool_type;
2616                                 return this;
2617                         } 
2618
2619                         //
2620                         // We are dealing with numbers
2621                         //
2622
2623                         DoNumericPromotions (ec, l, r);
2624
2625                         if (left == null || right == null)
2626                                 return null;
2627
2628                         
2629                         if (oper == Operator.BitwiseAnd ||
2630                             oper == Operator.BitwiseOr ||
2631                             oper == Operator.ExclusiveOr){
2632                                 if (!((l == TypeManager.int32_type) ||
2633                                       (l == TypeManager.uint32_type) ||
2634                                       (l == TypeManager.int64_type) ||
2635                                       (l == TypeManager.uint64_type))){
2636                                         error19 ();
2637                                         return null;
2638                                 }
2639                                 type = l;
2640                         }
2641
2642                         if (oper == Operator.Equality ||
2643                             oper == Operator.Inequality ||
2644                             oper == Operator.LessThanOrEqual ||
2645                             oper == Operator.LessThan ||
2646                             oper == Operator.GreaterThanOrEqual ||
2647                             oper == Operator.GreaterThan){
2648                                 type = TypeManager.bool_type;
2649                         }
2650
2651                         return this;
2652                 }
2653                 
2654                 public override Expression DoResolve (EmitContext ec)
2655                 {
2656                         left = left.Resolve (ec);
2657                         right = right.Resolve (ec);
2658
2659                         if (left == null || right == null)
2660                                 return null;
2661
2662                         if (left.Type == null)
2663                                 throw new Exception (
2664                                         "Resolve returned non null, but did not set the type! (" +
2665                                         left + ")");
2666                         if (right.Type == null)
2667                                 throw new Exception (
2668                                         "Resolve returned non null, but did not set the type! (" +
2669                                         right + ")");
2670
2671                         eclass = ExprClass.Value;
2672
2673                         return ResolveOperator (ec);
2674                 }
2675
2676                 public bool IsBranchable ()
2677                 {
2678                         if (oper == Operator.Equality ||
2679                             oper == Operator.Inequality ||
2680                             oper == Operator.LessThan ||
2681                             oper == Operator.GreaterThan ||
2682                             oper == Operator.LessThanOrEqual ||
2683                             oper == Operator.GreaterThanOrEqual){
2684                                 return true;
2685                         } else
2686                                 return false;
2687                 }
2688
2689                 // <summary>
2690                 //   This entry point is used by routines that might want
2691                 //   to emit a brfalse/brtrue after an expression, and instead
2692                 //   they could use a more compact notation.
2693                 //
2694                 //   Typically the code would generate l.emit/r.emit, followed
2695                 //   by the comparission and then a brtrue/brfalse.  The comparissions
2696                 //   are sometimes inneficient (there are not as complete as the branches
2697                 //   look for the hacks in Emit using double ceqs).
2698                 //
2699                 //   So for those cases we provide EmitBranchable that can emit the
2700                 //   branch with the test
2701                 // </summary>
2702                 public void EmitBranchable (EmitContext ec, int target)
2703                 {
2704                         OpCode opcode;
2705                         bool close_target = false;
2706                         
2707                         left.Emit (ec);
2708                         right.Emit (ec);
2709                         
2710                         switch (oper){
2711                         case Operator.Equality:
2712                                 if (close_target)
2713                                         opcode = OpCodes.Beq_S;
2714                                 else
2715                                         opcode = OpCodes.Beq;
2716                                 break;
2717
2718                         case Operator.Inequality:
2719                                 if (close_target)
2720                                         opcode = OpCodes.Bne_Un_S;
2721                                 else
2722                                         opcode = OpCodes.Bne_Un;
2723                                 break;
2724
2725                         case Operator.LessThan:
2726                                 if (close_target)
2727                                         opcode = OpCodes.Blt_S;
2728                                 else
2729                                         opcode = OpCodes.Blt;
2730                                 break;
2731
2732                         case Operator.GreaterThan:
2733                                 if (close_target)
2734                                         opcode = OpCodes.Bgt_S;
2735                                 else
2736                                         opcode = OpCodes.Bgt;
2737                                 break;
2738
2739                         case Operator.LessThanOrEqual:
2740                                 if (close_target)
2741                                         opcode = OpCodes.Ble_S;
2742                                 else
2743                                         opcode = OpCodes.Ble;
2744                                 break;
2745
2746                         case Operator.GreaterThanOrEqual:
2747                                 if (close_target)
2748                                         opcode = OpCodes.Bge_S;
2749                                 else
2750                                         opcode = OpCodes.Ble;
2751                                 break;
2752
2753                         default:
2754                                 throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
2755                                                      + oper.ToString ());
2756                         }
2757
2758                         ec.ig.Emit (opcode, target);
2759                 }
2760                 
2761                 public override void Emit (EmitContext ec)
2762                 {
2763                         ILGenerator ig = ec.ig;
2764                         Type l = left.Type;
2765                         Type r = right.Type;
2766                         OpCode opcode;
2767
2768                         if (method != null) {
2769
2770                                 // Note that operators are static anyway
2771                                 
2772                                 if (Arguments != null) 
2773                                         Invocation.EmitArguments (ec, method, Arguments);
2774                                 
2775                                 if (method is MethodInfo)
2776                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
2777                                 else
2778                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
2779
2780                                 return;
2781                         }
2782                         
2783                         left.Emit (ec);
2784                         right.Emit (ec);
2785
2786                         switch (oper){
2787                         case Operator.Multiply:
2788                                 if (ec.CheckState){
2789                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
2790                                                 opcode = OpCodes.Mul_Ovf;
2791                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
2792                                                 opcode = OpCodes.Mul_Ovf_Un;
2793                                         else
2794                                                 opcode = OpCodes.Mul;
2795                                 } else
2796                                         opcode = OpCodes.Mul;
2797
2798                                 break;
2799
2800                         case Operator.Division:
2801                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
2802                                         opcode = OpCodes.Div_Un;
2803                                 else
2804                                         opcode = OpCodes.Div;
2805                                 break;
2806
2807                         case Operator.Modulus:
2808                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
2809                                         opcode = OpCodes.Rem_Un;
2810                                 else
2811                                         opcode = OpCodes.Rem;
2812                                 break;
2813
2814                         case Operator.Addition:
2815                                 if (ec.CheckState){
2816                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
2817                                                 opcode = OpCodes.Add_Ovf;
2818                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
2819                                                 opcode = OpCodes.Add_Ovf_Un;
2820                                         else
2821                                                 opcode = OpCodes.Mul;
2822                                 } else
2823                                         opcode = OpCodes.Add;
2824                                 break;
2825
2826                         case Operator.Subtraction:
2827                                 if (ec.CheckState){
2828                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
2829                                                 opcode = OpCodes.Sub_Ovf;
2830                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
2831                                                 opcode = OpCodes.Sub_Ovf_Un;
2832                                         else
2833                                                 opcode = OpCodes.Sub;
2834                                 } else
2835                                         opcode = OpCodes.Sub;
2836                                 break;
2837
2838                         case Operator.RightShift:
2839                                 opcode = OpCodes.Shr;
2840                                 break;
2841                                 
2842                         case Operator.LeftShift:
2843                                 opcode = OpCodes.Shl;
2844                                 break;
2845
2846                         case Operator.Equality:
2847                                 opcode = OpCodes.Ceq;
2848                                 break;
2849
2850                         case Operator.Inequality:
2851                                 ec.ig.Emit (OpCodes.Ceq);
2852                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
2853                                 
2854                                 opcode = OpCodes.Ceq;
2855                                 break;
2856
2857                         case Operator.LessThan:
2858                                 opcode = OpCodes.Clt;
2859                                 break;
2860
2861                         case Operator.GreaterThan:
2862                                 opcode = OpCodes.Cgt;
2863                                 break;
2864
2865                         case Operator.LessThanOrEqual:
2866                                 ec.ig.Emit (OpCodes.Cgt);
2867                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
2868                                 
2869                                 opcode = OpCodes.Ceq;
2870                                 break;
2871
2872                         case Operator.GreaterThanOrEqual:
2873                                 ec.ig.Emit (OpCodes.Clt);
2874                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
2875                                 
2876                                 opcode = OpCodes.Sub;
2877                                 break;
2878
2879                         case Operator.LogicalOr:
2880                         case Operator.BitwiseOr:
2881                                 opcode = OpCodes.Or;
2882                                 break;
2883
2884                         case Operator.LogicalAnd:
2885                         case Operator.BitwiseAnd:
2886                                 opcode = OpCodes.And;
2887                                 break;
2888
2889                         case Operator.ExclusiveOr:
2890                                 opcode = OpCodes.Xor;
2891                                 break;
2892
2893                         default:
2894                                 throw new Exception ("This should not happen: Operator = "
2895                                                      + oper.ToString ());
2896                         }
2897
2898                         ig.Emit (opcode);
2899                 }
2900         }
2901
2902         public class Conditional : Expression {
2903                 Expression expr, trueExpr, falseExpr;
2904                 Location loc;
2905                 
2906                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
2907                 {
2908                         this.expr = expr;
2909                         this.trueExpr = trueExpr;
2910                         this.falseExpr = falseExpr;
2911                         this.loc = l;
2912                 }
2913
2914                 public Expression Expr {
2915                         get {
2916                                 return expr;
2917                         }
2918                 }
2919
2920                 public Expression TrueExpr {
2921                         get {
2922                                 return trueExpr;
2923                         }
2924                 }
2925
2926                 public Expression FalseExpr {
2927                         get {
2928                                 return falseExpr;
2929                         }
2930                 }
2931
2932                 public override Expression DoResolve (EmitContext ec)
2933                 {
2934                         expr = expr.Resolve (ec);
2935
2936                         if (expr.Type != TypeManager.bool_type)
2937                                 expr = Expression.ConvertImplicitRequired (
2938                                         ec, expr, TypeManager.bool_type, loc);
2939                         
2940                         trueExpr = trueExpr.Resolve (ec);
2941                         falseExpr = falseExpr.Resolve (ec);
2942
2943                         if (expr == null || trueExpr == null || falseExpr == null)
2944                                 return null;
2945                         
2946                         if (trueExpr.Type == falseExpr.Type)
2947                                 type = trueExpr.Type;
2948                         else {
2949                                 Expression conv;
2950
2951                                 //
2952                                 // First, if an implicit conversion exists from trueExpr
2953                                 // to falseExpr, then the result type is of type falseExpr.Type
2954                                 //
2955                                 conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
2956                                 if (conv != null){
2957                                         type = falseExpr.Type;
2958                                         trueExpr = conv;
2959                                 } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
2960                                         type = trueExpr.Type;
2961                                         falseExpr = conv;
2962                                 } else {
2963                                         Error (173, loc, "The type of the conditional expression can " +
2964                                                "not be computed because there is no implicit conversion" +
2965                                                " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
2966                                                " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
2967                                         return null;
2968                                 }
2969                         }
2970
2971                         eclass = ExprClass.Value;
2972                         return this;
2973                 }
2974
2975                 public override void Emit (EmitContext ec)
2976                 {
2977                         ILGenerator ig = ec.ig;
2978                         Label false_target = ig.DefineLabel ();
2979                         Label end_target = ig.DefineLabel ();
2980
2981                         expr.Emit (ec);
2982                         ig.Emit (OpCodes.Brfalse, false_target);
2983                         trueExpr.Emit (ec);
2984                         ig.Emit (OpCodes.Br, end_target);
2985                         ig.MarkLabel (false_target);
2986                         falseExpr.Emit (ec);
2987                         ig.MarkLabel (end_target);
2988                 }
2989         }
2990
2991         //
2992         // SimpleName expressions are initially formed of a single
2993         // word and it only happens at the beginning of the expression.
2994         //
2995         // The expression will try to be bound to a Field, a Method
2996         // group or a Property.  If those fail we pass the name to our
2997         // caller and the SimpleName is compounded to perform a type
2998         // lookup.  The idea behind this process is that we want to avoid
2999         // creating a namespace map from the assemblies, as that requires
3000         // the GetExportedTypes function to be called and a hashtable to
3001         // be constructed which reduces startup time.  If later we find
3002         // that this is slower, we should create a `NamespaceExpr' expression
3003         // that fully participates in the resolution process. 
3004         //
3005         // For example `System.Console.WriteLine' is decomposed into
3006         // MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine")
3007         //
3008         // The first SimpleName wont produce a match on its own, so it will
3009         // be turned into:
3010         // MemberAccess (SimpleName ("System.Console"), "WriteLine").
3011         //
3012         // System.Console will produce a TypeExpr match.
3013         //
3014         // The downside of this is that we might be hitting `LookupType' too many
3015         // times with this scheme.
3016         //
3017         public class SimpleName : Expression {
3018                 public readonly string Name;
3019                 public readonly Location Location;
3020                 
3021                 public SimpleName (string name, Location l)
3022                 {
3023                         Name = name;
3024                         Location = l;
3025                 }
3026
3027                 public static void Error120 (Location l, string name)
3028                 {
3029                         Report.Error (
3030                                 120, l,
3031                                 "An object reference is required " +
3032                                 "for the non-static field `"+name+"'");
3033                 }
3034                 
3035                 //
3036                 // Checks whether we are trying to access an instance
3037                 // property, method or field from a static body.
3038                 //
3039                 Expression MemberStaticCheck (Expression e)
3040                 {
3041                         if (e is FieldExpr){
3042                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
3043                                 
3044                                 if (!fi.IsStatic){
3045                                         Error120 (Location, Name);
3046                                         return null;
3047                                 }
3048                         } else if (e is MethodGroupExpr){
3049                                 MethodGroupExpr mg = (MethodGroupExpr) e;
3050
3051                                 if (!mg.RemoveInstanceMethods ()){
3052                                         Error120 (Location, mg.Methods [0].Name);
3053                                         return null;
3054                                 }
3055                                 return e;
3056                         } else if (e is PropertyExpr){
3057                                 if (!((PropertyExpr) e).IsStatic){
3058                                         Error120 (Location, Name);
3059                                         return null;
3060                                 }
3061                         }
3062
3063                         return e;
3064                 }
3065                 
3066                 //
3067                 // 7.5.2: Simple Names. 
3068                 //
3069                 // Local Variables and Parameters are handled at
3070                 // parse time, so they never occur as SimpleNames.
3071                 //
3072                 public override Expression DoResolve (EmitContext ec)
3073                 {
3074                         Expression e;
3075
3076                         //
3077                         // Stage 1: Performed by the parser (binding to local or parameters).
3078                         //
3079
3080                         //
3081                         // Stage 2: Lookup members
3082                         //
3083                         e = MemberLookup (ec, ec.TypeContainer.TypeBuilder, Name, true, Location);
3084                         if (e == null){
3085                                 //
3086                                 // Stage 3: Lookup symbol in the various namespaces. 
3087                                 // 
3088                                 Type t;
3089                                 
3090                                 if ((t = ec.TypeContainer.LookupType (Name, true)) != null)
3091                                         return new TypeExpr (t);
3092
3093                                 //
3094                                 // Stage 3 part b: Lookup up if we are an alias to a type
3095                                 // or a namespace.
3096                                 //
3097                                 // Since we are cheating: we only do the Alias lookup for
3098                                 // namespaces if the name does not include any dots in it
3099                                 //
3100                                 
3101                                 // IMPLEMENT ME.  Read mcs/mcs/TODO for ideas, or rewrite
3102                                 // using NamespaceExprs (dunno how that fixes the alias
3103                                 // per-file though).
3104                                 
3105                                 // No match, maybe our parent can compose us
3106                                 // into something meaningful.
3107                                 //
3108                                 return this;
3109                         }
3110
3111                         // Step 2, continues here.
3112                         if (e is TypeExpr)
3113                                 return e;
3114
3115                         if (e is FieldExpr){
3116                                 FieldExpr fe = (FieldExpr) e;
3117                                 
3118                                 if (!fe.FieldInfo.IsStatic)
3119                                         fe.InstanceExpression = new This (Location.Null);
3120                         }                               
3121
3122                         if (ec.IsStatic)
3123                                 return MemberStaticCheck (e);
3124                         else
3125                                 return e;
3126                 }
3127
3128                 public override void Emit (EmitContext ec)
3129                 {
3130                         //
3131                         // If this is ever reached, then we failed to
3132                         // find the name as a namespace
3133                         //
3134
3135                         Error (103, Location, "The name `" + Name +
3136                                "' does not exist in the class `" +
3137                                ec.TypeContainer.Name + "'");
3138                 }
3139         }
3140
3141         // <summary>
3142         //   A simple interface that should be implemeneted by LValues
3143         // </summary>
3144         public interface LValue {
3145
3146                 // <summary>
3147                 //   The Store method should store the contents of the top
3148                 //   of the stack into the storage that is implemented by
3149                 //   the particular implementation of LValue
3150                 // </summary>
3151                 void Store     (EmitContext ec);
3152
3153                 // <summary>
3154                 //   Allows an LValue to perform any necessary semantic
3155                 //   analysis in an lvalue-context.
3156                 // </summary>
3157
3158                 Expression LValueResolve (EmitContext ec);
3159         }
3160
3161         // <summary>
3162         //   This interface is implemented by variables
3163         // </summary>
3164         public interface MemoryLocation {
3165                 // <summary>
3166                 //   The AddressOf method should generate code that loads
3167                 //   the address of the LValue and leaves it on the stack
3168                 // </summary>
3169                 void AddressOf (EmitContext ec);
3170         }
3171
3172         public class LocalTemporary : Expression, LValue, MemoryLocation {
3173                 LocalBuilder builder;
3174                 
3175                 public LocalTemporary (EmitContext ec, Type t)
3176                 {
3177                         type = t;
3178                         eclass = ExprClass.Value;
3179                         builder = ec.GetTemporaryStorage (t);
3180                 }
3181
3182                 public override Expression DoResolve (EmitContext ec)
3183                 {
3184                         return this;
3185                 }
3186
3187                 public Expression LValueResolve (EmitContext ec)
3188                 {
3189                         return this;
3190                 }
3191                 
3192                 public override void Emit (EmitContext ec)
3193                 {
3194                         ec.ig.Emit (OpCodes.Ldloc, builder); 
3195                 }
3196
3197                 public void Store (EmitContext ec)
3198                 {
3199                         ec.ig.Emit (OpCodes.Stloc, builder);
3200                 }
3201
3202                 public void AddressOf (EmitContext ec)
3203                 {
3204                         ec.ig.Emit (OpCodes.Ldloca, builder);
3205                 }
3206         }
3207         
3208         public class LocalVariableReference : Expression, LValue, MemoryLocation {
3209                 public readonly string Name;
3210                 public readonly Block Block;
3211
3212                 VariableInfo variable_info;
3213                 
3214                 public LocalVariableReference (Block block, string name)
3215                 {
3216                         Block = block;
3217                         Name = name;
3218                         eclass = ExprClass.Variable;
3219                 }
3220
3221                 public VariableInfo VariableInfo {
3222                         get {
3223                                 if (variable_info == null)
3224                                         variable_info = Block.GetVariableInfo (Name);
3225                                 return variable_info;
3226                         }
3227                 }
3228                 
3229                 public override Expression DoResolve (EmitContext ec)
3230                 {
3231                         VariableInfo vi = VariableInfo;
3232
3233                         type = vi.VariableType;
3234                         return this;
3235                 }
3236
3237                 public Expression LValueResolve (EmitContext ec)
3238                 {
3239                         return this;
3240                 }
3241                 
3242                 public override void Emit (EmitContext ec)
3243                 {
3244                         VariableInfo vi = VariableInfo;
3245                         ILGenerator ig = ec.ig;
3246                         int idx = vi.Idx;
3247
3248                         vi.Used = true;
3249                         
3250                         switch (idx){
3251                         case 0:
3252                                 ig.Emit (OpCodes.Ldloc_0);
3253                                 break;
3254                                 
3255                         case 1:
3256                                 ig.Emit (OpCodes.Ldloc_1);
3257                                 break;
3258
3259                         case 2:
3260                                 ig.Emit (OpCodes.Ldloc_2);
3261                                 break;
3262
3263                         case 3:
3264                                 ig.Emit (OpCodes.Ldloc_3);
3265                                 break;
3266
3267                         default:
3268                                 if (idx <= 255)
3269                                         ig.Emit (OpCodes.Ldloc_S, (byte) idx);
3270                                 else
3271                                         ig.Emit (OpCodes.Ldloc, idx);
3272                                 break;
3273                         }
3274                 }
3275
3276                 public static void Store (ILGenerator ig, int idx)
3277                 {
3278                         switch (idx){
3279                         case 0:
3280                                 ig.Emit (OpCodes.Stloc_0);
3281                                 break;
3282                                 
3283                         case 1:
3284                                 ig.Emit (OpCodes.Stloc_1);
3285                                 break;
3286                                 
3287                         case 2:
3288                                 ig.Emit (OpCodes.Stloc_2);
3289                                 break;
3290                                 
3291                         case 3:
3292                                 ig.Emit (OpCodes.Stloc_3);
3293                                 break;
3294                                 
3295                         default:
3296                                 if (idx <= 255)
3297                                         ig.Emit (OpCodes.Stloc_S, (byte) idx);
3298                                 else
3299                                         ig.Emit (OpCodes.Stloc, idx);
3300                                 break;
3301                         }
3302                 }
3303                 
3304                 public void Store (EmitContext ec)
3305                 {
3306                         ILGenerator ig = ec.ig;
3307                         VariableInfo vi = VariableInfo;
3308
3309                         vi.Assigned = true;
3310
3311                         // Funny seems the above generates optimal code for us, but
3312                         // seems to take too long to generate what we need.
3313                         // ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
3314
3315                         Store (ig, vi.Idx);
3316                 }
3317
3318                 public void AddressOf (EmitContext ec)
3319                 {
3320                         VariableInfo vi = VariableInfo;
3321                         int idx = vi.Idx;
3322
3323                         vi.Used = true;
3324                         vi.Assigned = true;
3325                         
3326                         if (idx <= 255)
3327                                 ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
3328                         else
3329                                 ec.ig.Emit (OpCodes.Ldloca, idx);
3330                 }
3331         }
3332
3333         public class ParameterReference : Expression, LValue, MemoryLocation {
3334                 public readonly Parameters Pars;
3335                 public readonly String Name;
3336                 public readonly int Idx;
3337                 int arg_idx;
3338                 
3339                 public ParameterReference (Parameters pars, int idx, string name)
3340                 {
3341                         Pars = pars;
3342                         Idx  = idx;
3343                         Name = name;
3344                         eclass = ExprClass.Variable;
3345                 }
3346
3347                 public override Expression DoResolve (EmitContext ec)
3348                 {
3349                         Type [] types = Pars.GetParameterInfo (ec.TypeContainer);
3350
3351                         type = types [Idx];
3352
3353                         arg_idx = Idx;
3354                         if (!ec.IsStatic)
3355                                 arg_idx++;
3356                         
3357                         return this;
3358                 }
3359
3360                 public override void Emit (EmitContext ec)
3361                 {
3362                         if (arg_idx <= 255)
3363                                 ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
3364                         else
3365                                 ec.ig.Emit (OpCodes.Ldarg, arg_idx);
3366                 }
3367
3368                 public void Store (EmitContext ec)
3369                 {
3370                         if (arg_idx <= 255)
3371                                 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
3372                         else
3373                                 ec.ig.Emit (OpCodes.Starg, arg_idx);
3374                         
3375                 }
3376
3377                 public void AddressOf (EmitContext ec)
3378                 {
3379                         if (arg_idx <= 255)
3380                                 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
3381                         else
3382                                 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
3383                 }
3384
3385                 public Expression LValueResolve (EmitContext ec)
3386                 {
3387                         return this;
3388                 }
3389         }
3390         
3391         // <summary>
3392         //   Used for arguments to New(), Invocation()
3393         // </summary>
3394         public class Argument {
3395                 public enum AType {
3396                         Expression,
3397                         Ref,
3398                         Out
3399                 };
3400
3401                 public readonly AType Type;
3402                 public Expression expr;
3403
3404                 public Argument (Expression expr, AType type)
3405                 {
3406                         this.expr = expr;
3407                         this.Type = type;
3408                 }
3409
3410                 public Expression Expr {
3411                         get {
3412                                 return expr;
3413                         }
3414
3415                         set {
3416                                 expr = value;
3417                         }
3418                 }
3419
3420                 public bool Resolve (EmitContext ec)
3421                 {
3422                         expr = expr.Resolve (ec);
3423
3424                         return expr != null;
3425                 }
3426
3427                 public void Emit (EmitContext ec)
3428                 {
3429                         expr.Emit (ec);
3430                 }
3431         }
3432
3433         // <summary>
3434         //   Invocation of methods or delegates.
3435         // </summary>
3436         public class Invocation : ExpressionStatement {
3437                 public readonly ArrayList Arguments;
3438                 public readonly Location Location;
3439                 
3440                 Expression expr;
3441                 MethodBase method = null;
3442                         
3443                 static Hashtable method_parameter_cache;
3444
3445                 static Invocation ()
3446                 {
3447                         method_parameter_cache = new Hashtable ();
3448                 }
3449                         
3450                 //
3451                 // arguments is an ArrayList, but we do not want to typecast,
3452                 // as it might be null.
3453                 //
3454                 // FIXME: only allow expr to be a method invocation or a
3455                 // delegate invocation (7.5.5)
3456                 //
3457                 public Invocation (Expression expr, ArrayList arguments, Location l)
3458                 {
3459                         this.expr = expr;
3460                         Arguments = arguments;
3461                         Location = l;
3462                 }
3463
3464                 public Expression Expr {
3465                         get {
3466                                 return expr;
3467                         }
3468                 }
3469
3470                 // <summary>
3471                 //   Returns the Parameters (a ParameterData interface) for the
3472                 //   Method `mb'
3473                 // </summary>
3474                 public static ParameterData GetParameterData (MethodBase mb)
3475                 {
3476                         object pd = method_parameter_cache [mb];
3477
3478                         if (pd != null)
3479                                 return (ParameterData) pd;
3480
3481                         if (mb is MethodBuilder || mb is ConstructorBuilder){
3482                                 MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
3483
3484                                 InternalParameters ip = mc.ParameterInfo;
3485                                 method_parameter_cache [mb] = ip;
3486
3487                                 return (ParameterData) ip;
3488                         } else {
3489                                 ParameterInfo [] pi = mb.GetParameters ();
3490                                 ReflectionParameters rp = new ReflectionParameters (pi);
3491                                 method_parameter_cache [mb] = rp;
3492
3493                                 return (ParameterData) rp;
3494                         }
3495                 }
3496
3497                 // <summary>
3498                 //   Tells whether a user defined conversion from Type `from' to
3499                 //   Type `to' exists.
3500                 //
3501                 //   FIXME: we could implement a cache here. 
3502                 // </summary>
3503                 static bool ConversionExists (EmitContext ec, Type from, Type to, Location loc)
3504                 {
3505                         // Locate user-defined implicit operators
3506
3507                         Expression mg;
3508                         
3509                         mg = MemberLookup (ec, to, "op_Implicit", false, loc);
3510
3511                         if (mg != null) {
3512                                 MethodGroupExpr me = (MethodGroupExpr) mg;
3513                                 
3514                                 for (int i = me.Methods.Length; i > 0;) {
3515                                         i--;
3516                                         MethodBase mb = me.Methods [i];
3517                                         ParameterData pd = GetParameterData (mb);
3518                                         
3519                                         if (from == pd.ParameterType (0))
3520                                                 return true;
3521                                 }
3522                         }
3523
3524                         mg = MemberLookup (ec, from, "op_Implicit", false, loc);
3525
3526                         if (mg != null) {
3527                                 MethodGroupExpr me = (MethodGroupExpr) mg;
3528
3529                                 for (int i = me.Methods.Length; i > 0;) {
3530                                         i--;
3531                                         MethodBase mb = me.Methods [i];
3532                                         MethodInfo mi = (MethodInfo) mb;
3533                                         
3534                                         if (mi.ReturnType == to)
3535                                                 return true;
3536                                 }
3537                         }
3538                         
3539                         return false;
3540                 }
3541                 
3542                 // <summary>
3543                 //  Determines "better conversion" as specified in 7.4.2.3
3544                 //  Returns : 1 if a->p is better
3545                 //            0 if a->q or neither is better 
3546                 // </summary>
3547                 static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, bool use_standard,
3548                                              Location loc)
3549                 {
3550                         Type argument_type = a.Expr.Type;
3551                         Expression argument_expr = a.Expr;
3552
3553                         if (argument_type == null)
3554                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
3555
3556                         if (p == q)
3557                                 return 0;
3558                         
3559                         if (argument_type == p)
3560                                 return 1;
3561
3562                         if (argument_type == q)
3563                                 return 0;
3564
3565                         //
3566                         // Now probe whether an implicit constant expression conversion
3567                         // can be used.
3568                         //
3569                         // An implicit constant expression conversion permits the following
3570                         // conversions:
3571                         //
3572                         //    * A constant-expression of type `int' can be converted to type
3573                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
3574                         //      of the expression is withing the range of the destination type.
3575                         //
3576                         //    * A constant-expression of type long can be converted to type
3577                         //      ulong, provided the value of the constant expression is not negative
3578                         //
3579                         // FIXME: Note that this assumes that constant folding has
3580                         // taken place.  We dont do constant folding yet.
3581                         //
3582
3583                         if (argument_expr is IntLiteral){
3584                                 IntLiteral ei = (IntLiteral) argument_expr;
3585                                 int value = ei.Value;
3586                                 
3587                                 if (p == TypeManager.sbyte_type){
3588                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
3589                                                 return 1;
3590                                 } else if (p == TypeManager.byte_type){
3591                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
3592                                                 return 1;
3593                                 } else if (p == TypeManager.short_type){
3594                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
3595                                                 return 1;
3596                                 } else if (p == TypeManager.ushort_type){
3597                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
3598                                                 return 1;
3599                                 } else if (p == TypeManager.uint32_type){
3600                                         //
3601                                         // we can optimize this case: a positive int32
3602                                         // always fits on a uint32
3603                                         //
3604                                         if (value >= 0)
3605                                                 return 1;
3606                                 } else if (p == TypeManager.uint64_type){
3607                                         //
3608                                         // we can optimize this case: a positive int32
3609                                         // always fits on a uint64
3610                                         //
3611                                         if (value >= 0)
3612                                                 return 1;
3613                                 }
3614                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
3615                                 LongLiteral ll = (LongLiteral) argument_expr;
3616                                 
3617                                 if (p == TypeManager.uint64_type){
3618                                         if (ll.Value > 0)
3619                                                 return 1;
3620                                 }
3621                         }
3622
3623                         if (q == null) {
3624
3625                                 Expression tmp;
3626
3627                                 if (use_standard)
3628                                         tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
3629                                 else
3630                                         tmp = ConvertImplicit (ec, argument_expr, p, loc);
3631
3632                                 if (tmp != null)
3633                                         return 1;
3634                                 else
3635                                         return 0;
3636
3637                         }
3638
3639                         if (ConversionExists (ec, p, q, loc) == true &&
3640                             ConversionExists (ec, q, p, loc) == false)
3641                                 return 1;
3642
3643                         if (p == TypeManager.sbyte_type)
3644                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
3645                                     q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3646                                         return 1;
3647
3648                         if (p == TypeManager.short_type)
3649                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
3650                                     q == TypeManager.uint64_type)
3651                                         return 1;
3652
3653                         if (p == TypeManager.int32_type)
3654                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
3655                                         return 1;
3656
3657                         if (p == TypeManager.int64_type)
3658                                 if (q == TypeManager.uint64_type)
3659                                         return 1;
3660
3661                         return 0;
3662                 }
3663                 
3664                 // <summary>
3665                 //  Determines "Better function" and returns an integer indicating :
3666                 //  0 if candidate ain't better
3667                 //  1 if candidate is better than the current best match
3668                 // </summary>
3669                 static int BetterFunction (EmitContext ec, ArrayList args,
3670                                            MethodBase candidate, MethodBase best,
3671                                            bool use_standard, Location loc)
3672                 {
3673                         ParameterData candidate_pd = GetParameterData (candidate);
3674                         ParameterData best_pd;
3675                         int argument_count;
3676
3677                         if (args == null)
3678                                 argument_count = 0;
3679                         else
3680                                 argument_count = args.Count;
3681
3682                         if (candidate_pd.Count == 0 && argument_count == 0)
3683                                 return 1;
3684
3685                         if (best == null) {
3686                                 if (candidate_pd.Count == argument_count) {
3687                                         int x = 0;
3688                                         for (int j = argument_count; j > 0;) {
3689                                                 j--;
3690                                                 
3691                                                 Argument a = (Argument) args [j];
3692                                                 
3693                                                 x = BetterConversion (
3694                                                         ec, a, candidate_pd.ParameterType (j), null,
3695                                                         use_standard, loc);
3696                                                 
3697                                                 if (x <= 0)
3698                                                         break;
3699                                         }
3700                                         
3701                                         if (x > 0)
3702                                                 return 1;
3703                                         else
3704                                                 return 0;
3705                                         
3706                                 } else
3707                                         return 0;
3708                         }
3709
3710                         best_pd = GetParameterData (best);
3711
3712                         if (candidate_pd.Count == argument_count && best_pd.Count == argument_count) {
3713                                 int rating1 = 0, rating2 = 0;
3714                                 
3715                                 for (int j = argument_count; j > 0;) {
3716                                         j--;
3717                                         int x, y;
3718                                         
3719                                         Argument a = (Argument) args [j];
3720
3721                                         x = BetterConversion (ec, a, candidate_pd.ParameterType (j),
3722                                                               best_pd.ParameterType (j), use_standard, loc);
3723                                         y = BetterConversion (ec, a, best_pd.ParameterType (j),
3724                                                               candidate_pd.ParameterType (j), use_standard,
3725                                                               loc);
3726                                         
3727                                         rating1 += x;
3728                                         rating2 += y;
3729                                 }
3730
3731                                 if (rating1 > rating2)
3732                                         return 1;
3733                                 else
3734                                         return 0;
3735                         } else
3736                                 return 0;
3737                         
3738                 }
3739
3740                 public static string FullMethodDesc (MethodBase mb)
3741                 {
3742                         StringBuilder sb = new StringBuilder (mb.Name);
3743                         ParameterData pd = GetParameterData (mb);
3744                         
3745                         sb.Append (" (");
3746                         for (int i = pd.Count; i > 0;) {
3747                                 i--;
3748                                 sb.Append (TypeManager.CSharpName (pd.ParameterType (i)));
3749                                 if (i != 0)
3750                                         sb.Append (", ");
3751                         }
3752                         
3753                         sb.Append (")");
3754                         return sb.ToString ();
3755                 }
3756
3757                 public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2)
3758                 {
3759                         MemberInfo [] miset;
3760                         MethodGroupExpr union;
3761                         
3762                         if (mg1 != null && mg2 != null) {
3763                                 
3764                                 MethodGroupExpr left_set = null, right_set = null;
3765                                 int length1 = 0, length2 = 0;
3766                                 
3767                                 left_set = (MethodGroupExpr) mg1;
3768                                 length1 = left_set.Methods.Length;
3769                                 
3770                                 right_set = (MethodGroupExpr) mg2;
3771                                 length2 = right_set.Methods.Length;
3772
3773                                 ArrayList common = new ArrayList ();
3774                                 
3775                                 for (int i = 0; i < left_set.Methods.Length; i++) {
3776                                         for (int j = 0; j < right_set.Methods.Length; j++) {
3777                                                 if (left_set.Methods [i] == right_set.Methods [j]) 
3778                                                         common.Add (left_set.Methods [i]);
3779                                         }
3780                                 }
3781                                 
3782                                 miset = new MemberInfo [length1 + length2 - common.Count];
3783
3784                                 left_set.Methods.CopyTo (miset, 0);
3785
3786                                 int k = 0;
3787                                 
3788                                 for (int j = 0; j < right_set.Methods.Length; j++)
3789                                         if (!common.Contains (right_set.Methods [j]))
3790                                                 miset [length1 + k++] = right_set.Methods [j];
3791                                 
3792                                 union = new MethodGroupExpr (miset);
3793
3794                                 return union;
3795
3796                         } else if (mg1 == null && mg2 != null) {
3797                                 
3798                                 MethodGroupExpr me = (MethodGroupExpr) mg2; 
3799                                 
3800                                 miset = new MemberInfo [me.Methods.Length];
3801                                 me.Methods.CopyTo (miset, 0);
3802
3803                                 union = new MethodGroupExpr (miset);
3804                                 
3805                                 return union;
3806
3807                         } else if (mg2 == null && mg1 != null) {
3808                                 
3809                                 MethodGroupExpr me = (MethodGroupExpr) mg1; 
3810                                 
3811                                 miset = new MemberInfo [me.Methods.Length];
3812                                 me.Methods.CopyTo (miset, 0);
3813
3814                                 union = new MethodGroupExpr (miset);
3815                                 
3816                                 return union;
3817                         }
3818                         
3819                         return null;
3820                 }
3821
3822                 // <summary>
3823                 //   Find the Applicable Function Members (7.4.2.1)
3824                 //
3825                 //   me: Method Group expression with the members to select.
3826                 //       it might contain constructors or methods (or anything
3827                 //       that maps to a method).
3828                 //
3829                 //   Arguments: ArrayList containing resolved Argument objects.
3830                 //
3831                 //   loc: The location if we want an error to be reported, or a Null
3832                 //        location for "probing" purposes.
3833                 //
3834                 //   inside_user_defined: controls whether OverloadResolve should use the 
3835                 //   ConvertImplicit or ConvertImplicitStandard during overload resolution.
3836                 //
3837                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
3838                 //            that is the best match of me on Arguments.
3839                 //
3840                 // </summary>
3841                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
3842                                                           ArrayList Arguments, Location loc,
3843                                                           bool use_standard)
3844                 {
3845                         ArrayList afm = new ArrayList ();
3846                         int best_match_idx = -1;
3847                         MethodBase method = null;
3848                         int argument_count;
3849                         
3850                         for (int i = me.Methods.Length; i > 0; ){
3851                                 i--;
3852                                 MethodBase candidate  = me.Methods [i];
3853                                 int x;
3854
3855                                 x = BetterFunction (ec, Arguments, candidate, method, use_standard, loc);
3856                                 
3857                                 if (x == 0)
3858                                         continue;
3859                                 else {
3860                                         best_match_idx = i;
3861                                         method = me.Methods [best_match_idx];
3862                                 }
3863                         }
3864
3865                         if (Arguments == null)
3866                                 argument_count = 0;
3867                         else
3868                                 argument_count = Arguments.Count;
3869                         
3870                         ParameterData pd;
3871                         
3872                         // Now we see if we can at least find a method with the same number of arguments
3873                         // and then try doing implicit conversion on the arguments
3874                         if (best_match_idx == -1) {
3875                                 
3876                                 for (int i = me.Methods.Length; i > 0;) {
3877                                         i--;
3878                                         MethodBase mb = me.Methods [i];
3879                                         pd = GetParameterData (mb);
3880                                         
3881                                         if (pd.Count == argument_count) {
3882                                                 best_match_idx = i;
3883                                                 method = me.Methods [best_match_idx];
3884                                                 break;
3885                                         } else
3886                                                 continue;
3887                                 }
3888
3889                         }
3890
3891                         if (method == null)
3892                                 return null;
3893
3894                         // And now convert implicitly, each argument to the required type
3895                         
3896                         pd = GetParameterData (method);
3897
3898                         for (int j = argument_count; j > 0;) {
3899                                 j--;
3900                                 Argument a = (Argument) Arguments [j];
3901                                 Expression a_expr = a.Expr;
3902                                 Type parameter_type = pd.ParameterType (j);
3903                                 
3904                                 if (a_expr.Type != parameter_type){
3905                                         Expression conv;
3906
3907                                         if (use_standard)
3908                                                 conv = ConvertImplicitStandard (ec, a_expr, parameter_type,
3909                                                                                 Location.Null);
3910                                         else
3911                                                 conv = ConvertImplicit (ec, a_expr, parameter_type,
3912                                                                         Location.Null);
3913
3914                                         if (conv == null){
3915                                                 if (!Location.IsNull (loc)) {
3916                                                         Error (1502, loc,
3917                                                                "The best overloaded match for method '" + FullMethodDesc (method) +
3918                                                                "' has some invalid arguments");
3919                                                         Error (1503, loc,
3920                                                                "Argument " + (j+1) +
3921                                                                ": Cannot convert from '" + TypeManager.CSharpName (a_expr.Type)
3922                                                                + "' to '" + TypeManager.CSharpName (pd.ParameterType (j)) + "'");
3923                                                 }
3924                                                 return null;
3925                                         }
3926                                         //
3927                                         // Update the argument with the implicit conversion
3928                                         //
3929                                         if (a_expr != conv)
3930                                                 a.Expr = conv;
3931                                 }
3932                         }
3933                         
3934                         return method;
3935                 }
3936
3937                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
3938                                                           ArrayList Arguments, Location loc)
3939                 {
3940                         return OverloadResolve (ec, me, Arguments, loc, false);
3941                 }
3942                         
3943                 public override Expression DoResolve (EmitContext ec)
3944                 {
3945                         //
3946                         // First, resolve the expression that is used to
3947                         // trigger the invocation
3948                         //
3949                         this.expr = expr.Resolve (ec);
3950                         if (this.expr == null)
3951                                 return null;
3952
3953                         if (!(this.expr is MethodGroupExpr)){
3954                                 report118 (Location, this.expr, "method group");
3955                                 return null;
3956                         }
3957
3958                         //
3959                         // Next, evaluate all the expressions in the argument list
3960                         //
3961                         if (Arguments != null){
3962                                 for (int i = Arguments.Count; i > 0;){
3963                                         --i;
3964                                         Argument a = (Argument) Arguments [i];
3965
3966                                         if (!a.Resolve (ec))
3967                                                 return null;
3968                                 }
3969                         }
3970
3971                         method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments,
3972                                                   Location);
3973
3974                         if (method == null){
3975                                 Error (-6, Location,
3976                                        "Could not find any applicable function for this argument list");
3977                                 return null;
3978                         }
3979
3980                         if (method is MethodInfo)
3981                                 type = ((MethodInfo)method).ReturnType;
3982
3983                         eclass = ExprClass.Value;
3984                         return this;
3985                 }
3986
3987                 public static void EmitArguments (EmitContext ec, MethodBase method, ArrayList Arguments)
3988                 {
3989                         int top;
3990
3991                         if (Arguments != null)
3992                                 top = Arguments.Count;
3993                         else
3994                                 top = 0;
3995
3996                         for (int i = 0; i < top; i++){
3997                                 Argument a = (Argument) Arguments [i];
3998
3999                                 a.Emit (ec);
4000                         }
4001                 }
4002
4003                 public static void EmitCall (EmitContext ec,
4004                                              bool is_static, Expression instance_expr,
4005                                              MethodBase method, ArrayList Arguments)
4006                 {
4007                         ILGenerator ig = ec.ig;
4008                         bool struct_call = false;
4009                                 
4010                         if (!is_static){
4011                                 //
4012                                 // If this is ourselves, push "this"
4013                                 //
4014                                 if (instance_expr == null){
4015                                         ig.Emit (OpCodes.Ldarg_0);
4016                                 } else {
4017                                         //
4018                                         // Push the instance expression
4019                                         //
4020                                         if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
4021
4022                                                 struct_call = true;
4023
4024                                                 //
4025                                                 // If the expression is an LValue, then
4026                                                 // we can optimize and use AddressOf on the
4027                                                 // return.
4028                                                 //
4029                                                 // If not we have to use some temporary storage for
4030                                                 // it.
4031                                                 if (instance_expr is MemoryLocation)
4032                                                         ((MemoryLocation) instance_expr).AddressOf (ec);
4033                                                 else {
4034                                                         Type t = instance_expr.Type;
4035                                                         
4036                                                         instance_expr.Emit (ec);
4037                                                         LocalBuilder temp = ec.GetTemporaryStorage (t);
4038                                                         ig.Emit (OpCodes.Stloc, temp);
4039                                                         ig.Emit (OpCodes.Ldloca, temp);
4040                                                 }
4041                                         } else 
4042                                                 instance_expr.Emit (ec);
4043                                 }
4044                         }
4045
4046                         if (Arguments != null)
4047                                 EmitArguments (ec, method, Arguments);
4048
4049                         if (is_static || struct_call){
4050                                 if (method is MethodInfo)
4051                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
4052                                 else
4053                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
4054                         } else {
4055                                 if (method is MethodInfo)
4056                                         ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
4057                                 else
4058                                         ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
4059                         }
4060                 }
4061                 
4062                 public override void Emit (EmitContext ec)
4063                 {
4064                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
4065                         
4066                         EmitCall (ec, method.IsStatic, mg.InstanceExpression, method, Arguments);
4067                 }
4068
4069                 public override void EmitStatement (EmitContext ec)
4070                 {
4071                         Emit (ec);
4072
4073                         // 
4074                         // Pop the return value if there is one
4075                         //
4076                         if (method is MethodInfo){
4077                                 if (((MethodInfo)method).ReturnType != TypeManager.void_type)
4078                                         ec.ig.Emit (OpCodes.Pop);
4079                         }
4080                 }
4081         }
4082
4083         public class New : ExpressionStatement {
4084
4085                 public enum NType {
4086                         Object,
4087                         Array
4088                 };
4089
4090                 public readonly NType     NewType;
4091                 public readonly ArrayList Arguments;
4092                 public readonly string    RequestedType;
4093
4094                 // These are for the case when we have an array
4095                 public readonly string    Rank;
4096                 public readonly ArrayList Initializers;
4097
4098                 Location Location;
4099                 MethodBase method = null;
4100
4101
4102                 //
4103                 // If set, the new expression is for a value_target, and
4104                 // we will not leave anything on the stack.
4105                 //
4106                 Expression value_target;
4107                 
4108                 public New (string requested_type, ArrayList arguments, Location loc)
4109                 {
4110                         RequestedType = requested_type;
4111                         Arguments = arguments;
4112                         NewType = NType.Object;
4113                         Location = loc;
4114                 }
4115
4116                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers, Location loc)
4117                 {
4118                         RequestedType = requested_type;
4119                         Rank          = rank;
4120                         Initializers  = initializers;
4121                         NewType       = NType.Array;
4122                         Location      = loc;
4123
4124                         Arguments = new ArrayList ();
4125
4126                         foreach (Expression e in exprs)
4127                                 Arguments.Add (new Argument (e, Argument.AType.Expression));
4128                         
4129                 }
4130
4131                 public static string FormLookupType (string base_type, int idx_count, string rank)
4132                 {
4133                         StringBuilder sb = new StringBuilder (base_type);
4134
4135                         sb.Append (rank);
4136
4137                         sb.Append ("[");
4138                         for (int i = 1; i < idx_count; i++)
4139                                 sb.Append (",");
4140                         sb.Append ("]");
4141                         
4142                         return sb.ToString ();
4143                 }
4144                 
4145                 public Expression ValueTypeVariable {
4146                         get {
4147                                 return value_target;
4148                         }
4149
4150                         set {
4151                                 value_target = value;
4152                         }
4153                 }
4154                 
4155                 public override Expression DoResolve (EmitContext ec)
4156                 {
4157                         if (NewType == NType.Object) {
4158                                 type = ec.TypeContainer.LookupType (RequestedType, false);
4159                                 
4160                                 if (type == null)
4161                                         return null;
4162                                 
4163                                 Expression ml;
4164
4165                                 ml = MemberLookup (ec, type, ".ctor", false,
4166                                                    MemberTypes.Constructor, AllBindingsFlags, Location);
4167
4168                                 bool is_struct;
4169                                 is_struct = type.IsSubclassOf (TypeManager.value_type);
4170
4171                                 if (! (ml is MethodGroupExpr)){
4172                                         if (!is_struct){
4173                                                 report118 (Location, ml, "method group");
4174                                                 return null;
4175                                         }
4176                                 }
4177
4178                                 if (ml != null){
4179                                         if (Arguments != null){
4180                                                 for (int i = Arguments.Count; i > 0;){
4181                                                         --i;
4182                                                         Argument a = (Argument) Arguments [i];
4183                                                         
4184                                                         if (!a.Resolve (ec))
4185                                                                 return null;
4186                                                 }
4187                                         }
4188                                         
4189                                         method = Invocation.OverloadResolve (
4190                                                 ec, (MethodGroupExpr) ml,
4191                                                 Arguments, Location);
4192                                 
4193                                         if (method == null && !is_struct) {
4194                                                 Error (-6, Location,
4195                                                        "New invocation: Can not find a constructor for " +
4196                                                        "this argument list");
4197                                                 return null;
4198                                         }
4199                                 } 
4200                                 
4201                                 eclass = ExprClass.Value;
4202                                 return this;
4203                         }
4204
4205                         if (NewType == NType.Array) {
4206                                 throw new Exception ("Finish array creation");
4207                         }
4208
4209                         return null;
4210                 }
4211
4212                 //
4213                 // This DoEmit can be invoked in two contexts:
4214                 //    * As a mechanism that will leave a value on the stack (new object)
4215                 //    * As one that wont (init struct)
4216                 //
4217                 // You can control whether a value is required on the stack by passing
4218                 // need_value_on_stack.  The code *might* leave a value on the stack
4219                 // so it must be popped manually
4220                 //
4221                 // Returns whether a value is left on the stack
4222                 //
4223                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
4224                 {
4225                         if (method == null){
4226                                 MemoryLocation ml = (MemoryLocation) value_target;
4227
4228                                 ml.AddressOf (ec);
4229                         } else {
4230                                 Invocation.EmitArguments (ec, method, Arguments);
4231                                 ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
4232                                 return true;
4233                         }
4234
4235                         //
4236                         // It must be a value type, sanity check
4237                         //
4238                         if (value_target != null){
4239                                 ec.ig.Emit (OpCodes.Initobj, type);
4240
4241                                 if (need_value_on_stack){
4242                                         value_target.Emit (ec);
4243                                         return true;
4244                                 }
4245                                 return false;
4246                         }
4247
4248                         throw new Exception ("No method and no value type");
4249                 }
4250
4251                 public override void Emit (EmitContext ec)
4252                 {
4253                         DoEmit (ec, true);
4254                 }
4255                 
4256                 public override void EmitStatement (EmitContext ec)
4257                 {
4258                         if (DoEmit (ec, false))
4259                                 ec.ig.Emit (OpCodes.Pop);
4260                 }
4261         }
4262
4263         //
4264         // Represents the `this' construct
4265         //
4266         public class This : Expression, LValue, MemoryLocation {
4267                 Location loc;
4268                 
4269                 public This (Location loc)
4270                 {
4271                         this.loc = loc;
4272                 }
4273                 
4274                 public override Expression DoResolve (EmitContext ec)
4275                 {
4276                         eclass = ExprClass.Variable;
4277                         type = ec.TypeContainer.TypeBuilder;
4278
4279                         if (ec.IsStatic){
4280                                 Report.Error (26, loc,
4281                                               "Keyword this not valid in static code");
4282                                 return null;
4283                         }
4284                         
4285                         return this;
4286                 }
4287
4288                 public override void Emit (EmitContext ec)
4289                 {
4290                         ec.ig.Emit (OpCodes.Ldarg_0);
4291                 }
4292
4293                 public void Store (EmitContext ec)
4294                 {
4295                         ec.ig.Emit (OpCodes.Starg, 0);
4296                 }
4297
4298                 public void AddressOf (EmitContext ec)
4299                 {
4300                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
4301                 }
4302
4303                 public Expression LValueResolve (EmitContext ec)
4304                 {
4305                         if (ec.TypeContainer is Class){
4306                                 Report.Error (1604, loc, "Cannot assign to `this'");
4307                                 return null;
4308                         }
4309
4310                         return this;
4311                 }
4312         }
4313
4314         // <summary>
4315         //   Implements the typeof operator
4316         // </summary>
4317         public class TypeOf : Expression {
4318                 public readonly string QueriedType;
4319                 Type typearg;
4320                 
4321                 public TypeOf (string queried_type)
4322                 {
4323                         QueriedType = queried_type;
4324                 }
4325
4326                 public override Expression DoResolve (EmitContext ec)
4327                 {
4328                         typearg = ec.TypeContainer.LookupType (QueriedType, false);
4329
4330                         if (typearg == null)
4331                                 return null;
4332
4333                         type = TypeManager.type_type;
4334                         eclass = ExprClass.Type;
4335                         return this;
4336                 }
4337
4338                 public override void Emit (EmitContext ec)
4339                 {
4340                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
4341                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
4342                 }
4343         }
4344
4345         public class SizeOf : Expression {
4346                 public readonly string QueriedType;
4347                 
4348                 public SizeOf (string queried_type)
4349                 {
4350                         this.QueriedType = queried_type;
4351                 }
4352
4353                 public override Expression DoResolve (EmitContext ec)
4354                 {
4355                         // FIXME: Implement;
4356                         throw new Exception ("Unimplemented");
4357                         // return this;
4358                 }
4359
4360                 public override void Emit (EmitContext ec)
4361                 {
4362                         throw new Exception ("Implement me");
4363                 }
4364         }
4365
4366         public class MemberAccess : Expression {
4367                 public readonly string Identifier;
4368                 Expression expr;
4369                 Expression member_lookup;
4370                 Location loc;
4371                 
4372                 public MemberAccess (Expression expr, string id, Location l)
4373                 {
4374                         this.expr = expr;
4375                         Identifier = id;
4376                         loc = l;
4377                 }
4378
4379                 public Expression Expr {
4380                         get {
4381                                 return expr;
4382                         }
4383                 }
4384
4385                 void error176 (Location loc, string name)
4386                 {
4387                         Report.Error (176, loc, "Static member `" +
4388                                       name + "' cannot be accessed " +
4389                                       "with an instance reference, qualify with a " +
4390                                       "type name instead");
4391                 }
4392                 
4393                 public override Expression DoResolve (EmitContext ec)
4394                 {
4395                         expr = expr.Resolve (ec);
4396
4397                         if (expr == null)
4398                                 return null;
4399
4400                         if (expr is SimpleName){
4401                                 SimpleName child_expr = (SimpleName) expr;
4402                                 
4403                                 expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
4404
4405                                 return expr.Resolve (ec);
4406                         }
4407                                         
4408                         member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
4409
4410                         //
4411                         // Method Groups
4412                         //
4413                         if (member_lookup is MethodGroupExpr){
4414                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
4415                                 
4416                                 //
4417                                 // Type.MethodGroup
4418                                 //
4419                                 if (expr is TypeExpr){
4420                                         if (!mg.RemoveInstanceMethods ()){
4421                                                 SimpleName.Error120 (loc, mg.Methods [0].Name); 
4422                                                 return null;
4423                                         }
4424
4425                                         return member_lookup;
4426                                 }
4427
4428                                 //
4429                                 // Instance.MethodGroup
4430                                 //
4431                                 if (!mg.RemoveStaticMethods ()){
4432                                         error176 (loc, mg.Methods [0].Name);
4433                                         return null;
4434                                 }
4435                                 
4436                                 mg.InstanceExpression = expr;
4437                                         
4438                                 return member_lookup;
4439                         }
4440
4441                         if (member_lookup is FieldExpr){
4442                                 FieldExpr fe = (FieldExpr) member_lookup;
4443
4444                                 if (expr is TypeExpr){
4445                                         if (!fe.FieldInfo.IsStatic){
4446                                                 error176 (loc, fe.FieldInfo.Name);
4447                                                 return null;
4448                                         }
4449                                         return member_lookup;
4450                                 } else {
4451                                         if (fe.FieldInfo.IsStatic){
4452                                                 error176 (loc, fe.FieldInfo.Name);
4453                                                 return null;
4454                                         }
4455                                         fe.InstanceExpression = expr;
4456
4457                                         return fe;
4458                                 }
4459                         }
4460
4461                         if (member_lookup is PropertyExpr){
4462                                 PropertyExpr pe = (PropertyExpr) member_lookup;
4463
4464                                 if (expr is TypeExpr){
4465                                         if (!pe.IsStatic){
4466                                                 SimpleName.Error120 (loc, pe.PropertyInfo.Name);
4467                                                 return null;
4468                                         }
4469                                         return pe;
4470                                 } else {
4471                                         if (pe.IsStatic){
4472                                                 error176 (loc, pe.PropertyInfo.Name);
4473                                                 return null;
4474                                         }
4475                                         pe.InstanceExpression = expr;
4476
4477                                         return pe;
4478                                 }
4479                         }
4480                         
4481                         Console.WriteLine ("Support for " + member_lookup + " is not present yet");
4482                         Environment.Exit (0);
4483                         return null;
4484                 }
4485
4486                 public override void Emit (EmitContext ec)
4487                 {
4488                         throw new Exception ("Should not happen I think");
4489                 }
4490
4491         }
4492
4493         // <summary>
4494         //   Fully resolved expression that evaluates to a type
4495         // </summary>
4496         public class TypeExpr : Expression {
4497                 public TypeExpr (Type t)
4498                 {
4499                         Type = t;
4500                         eclass = ExprClass.Type;
4501                 }
4502
4503                 override public Expression DoResolve (EmitContext ec)
4504                 {
4505                         return this;
4506                 }
4507
4508                 override public void Emit (EmitContext ec)
4509                 {
4510                         throw new Exception ("Implement me");
4511                 }
4512         }
4513
4514         // <summary>
4515         //   MethodGroup Expression.
4516         //  
4517         //   This is a fully resolved expression that evaluates to a type
4518         // </summary>
4519         public class MethodGroupExpr : Expression {
4520                 public MethodBase [] Methods;
4521                 Expression instance_expression = null;
4522                 
4523                 public MethodGroupExpr (MemberInfo [] mi)
4524                 {
4525                         Methods = new MethodBase [mi.Length];
4526                         mi.CopyTo (Methods, 0);
4527                         eclass = ExprClass.MethodGroup;
4528                 }
4529
4530                 //
4531                 // `A method group may have associated an instance expression' 
4532                 // 
4533                 public Expression InstanceExpression {
4534                         get {
4535                                 return instance_expression;
4536                         }
4537
4538                         set {
4539                                 instance_expression = value;
4540                         }
4541                 }
4542                 
4543                 override public Expression DoResolve (EmitContext ec)
4544                 {
4545                         return this;
4546                 }
4547
4548                 override public void Emit (EmitContext ec)
4549                 {
4550                         throw new Exception ("This should never be reached");
4551                 }
4552
4553                 bool RemoveMethods (bool keep_static)
4554                 {
4555                         ArrayList smethods = new ArrayList ();
4556                         int top = Methods.Length;
4557                         int i;
4558                         
4559                         for (i = 0; i < top; i++){
4560                                 MethodBase mb = Methods [i];
4561
4562                                 if (mb.IsStatic == keep_static)
4563                                         smethods.Add (mb);
4564                         }
4565
4566                         if (smethods.Count == 0)
4567                                 return false;
4568
4569                         Methods = new MethodBase [smethods.Count];
4570                         smethods.CopyTo (Methods, 0);
4571
4572                         return true;
4573                 }
4574                 
4575                 // <summary>
4576                 //   Removes any instance methods from the MethodGroup, returns
4577                 //   false if the resulting set is empty.
4578                 // </summary>
4579                 public bool RemoveInstanceMethods ()
4580                 {
4581                         return RemoveMethods (true);
4582                 }
4583
4584                 // <summary>
4585                 //   Removes any static methods from the MethodGroup, returns
4586                 //   false if the resulting set is empty.
4587                 // </summary>
4588                 public bool RemoveStaticMethods ()
4589                 {
4590                         return RemoveMethods (false);
4591                 }
4592         }
4593
4594         // <summary>
4595         //   Fully resolved expression that evaluates to a Field
4596         // </summary>
4597         public class FieldExpr : Expression, LValue, MemoryLocation {
4598                 public readonly FieldInfo FieldInfo;
4599                 public Expression InstanceExpression;
4600                         
4601                 public FieldExpr (FieldInfo fi)
4602                 {
4603                         FieldInfo = fi;
4604                         eclass = ExprClass.Variable;
4605                         type = fi.FieldType;
4606                 }
4607
4608                 override public Expression DoResolve (EmitContext ec)
4609                 {
4610                         if (!FieldInfo.IsStatic){
4611                                 if (InstanceExpression == null){
4612                                         throw new Exception ("non-static FieldExpr without instance var\n" +
4613                                                              "You have to assign the Instance variable\n" +
4614                                                              "Of the FieldExpr to set this\n");
4615                                 }
4616
4617                                 InstanceExpression = InstanceExpression.Resolve (ec);
4618                                 if (InstanceExpression == null)
4619                                         return null;
4620                                 
4621                         }
4622                         return this;
4623                 }
4624
4625                 override public void Emit (EmitContext ec)
4626                 {
4627                         ILGenerator ig = ec.ig;
4628
4629                         if (FieldInfo.IsStatic)
4630                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
4631                         else {
4632                                 InstanceExpression.Emit (ec);
4633                                 
4634                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
4635                         }
4636                 }
4637
4638                 public void Store (EmitContext ec)
4639                 {
4640                         if (FieldInfo.IsStatic)
4641                                 ec.ig.Emit (OpCodes.Stsfld, FieldInfo);
4642                         else
4643                                 ec.ig.Emit (OpCodes.Stfld, FieldInfo);
4644                 }
4645
4646                 public void AddressOf (EmitContext ec)
4647                 {
4648                         if (FieldInfo.IsStatic)
4649                                 ec.ig.Emit (OpCodes.Ldsflda, FieldInfo);
4650                         else {
4651                                 InstanceExpression.Emit (ec);
4652                                 ec.ig.Emit (OpCodes.Ldflda, FieldInfo);
4653                         }
4654                 }
4655
4656                 public Expression LValueResolve (EmitContext ec)
4657                 {
4658                         if (!FieldInfo.IsInitOnly)
4659                                 return this;
4660
4661                         //
4662                         // InitOnly fields can only be assigned in constructors
4663                         //
4664
4665                         if (ec.IsConstructor)
4666                                 return this;
4667
4668                         return null;
4669                 }
4670         }
4671         
4672         // <summary>
4673         //   Expression that evaluates to a Property.  The Assign class
4674         //   might set the `Value' expression if we are in an assignment. 
4675         // </summary>
4676         public class PropertyExpr : ExpressionStatement {
4677                 public readonly PropertyInfo PropertyInfo;
4678                 public readonly bool IsStatic;
4679                 MethodInfo [] Accessors;
4680                 Location loc;
4681                 
4682                 Expression instance_expr;
4683                 Expression value;
4684                 
4685                 public PropertyExpr (PropertyInfo pi, Location l)
4686                 {
4687                         PropertyInfo = pi;
4688                         eclass = ExprClass.PropertyAccess;
4689                         IsStatic = false;
4690                         loc = l;
4691                         Accessors = TypeManager.GetAccessors (pi);
4692
4693                         if (Accessors != null)
4694                                 for (int i = 0; i < Accessors.Length; i++){
4695                                         if (Accessors [i] != null)
4696                                                 if (Accessors [i].IsStatic)
4697                                                         IsStatic = true;
4698                                 }
4699                         else
4700                                 Accessors = new MethodInfo [2];
4701                         
4702                         type = pi.PropertyType;
4703                 }
4704
4705                 //
4706                 // Controls the Value of the PropertyExpr.  If the value
4707                 // is null, then the property is being used in a `read' mode.
4708                 // otherwise the property is used in assignment mode.
4709                 //
4710                 // The value is set to a fully resolved type by assign.
4711                 //
4712                 public Expression Value {
4713                         get {
4714                                 return value;
4715                         }
4716
4717                         set {
4718                                 this.value = value;
4719                         }
4720                 }
4721
4722                 //
4723                 // The instance expression associated with this expression
4724                 //
4725                 public Expression InstanceExpression {
4726                         set {
4727                                 instance_expr = value;
4728                         }
4729
4730                         get {
4731                                 return instance_expr;
4732                         }
4733                 }
4734
4735                 public bool VerifyAssignable ()
4736                 {
4737                         if (!PropertyInfo.CanWrite){
4738                                 Report.Error (200, loc, 
4739                                               "The property `" + PropertyInfo.Name +
4740                                               "' can not be assigned to, as it has not set accessor");
4741                                 return false;
4742                         }
4743
4744                         return true;
4745                 }
4746                 
4747                 override public Expression DoResolve (EmitContext ec)
4748                 {
4749                         //
4750                         // Not really sure who should call perform the test below
4751                         // given that `assignable' has special code for this.
4752                         //
4753                         if (!PropertyInfo.CanRead){
4754                                 Report.Error (154, loc, 
4755                                               "The property `" + PropertyInfo.Name +
4756                                               "' can not be used in " +
4757                                               "this context because it lacks a get accessor");
4758                                 return null;
4759                         }
4760                         
4761                         return this;
4762                 }
4763
4764                 override public void Emit (EmitContext ec)
4765                 {
4766                         if (value == null)
4767                                 Invocation.EmitCall (ec, IsStatic, instance_expr, Accessors [0], null);
4768                         else {
4769                                 Argument arg = new Argument (value, Argument.AType.Expression);
4770                                 ArrayList args = new ArrayList ();
4771
4772                                 args.Add (arg);
4773                                 Invocation.EmitCall (ec, IsStatic, instance_expr, Accessors [1], args);
4774                         }
4775                 }
4776
4777                 override public void EmitStatement (EmitContext ec)
4778                 {
4779                         Emit (ec);
4780                         if (value == null){
4781                                 ec.ig.Emit (OpCodes.Pop);
4782                         }
4783                 }
4784         }
4785
4786         // <summary>
4787         //   Fully resolved expression that evaluates to a Expression
4788         // </summary>
4789         public class EventExpr : Expression {
4790                 public readonly EventInfo EventInfo;
4791                 Location loc;
4792                 
4793                 public EventExpr (EventInfo ei, Location loc)
4794                 {
4795                         EventInfo = ei;
4796                         this.loc = loc;
4797                         eclass = ExprClass.EventAccess;
4798                 }
4799
4800                 override public Expression DoResolve (EmitContext ec)
4801                 {
4802                         // We are born in resolved state. 
4803                         return this;
4804                 }
4805
4806                 override public void Emit (EmitContext ec)
4807                 {
4808                         throw new Exception ("Implement me");
4809                         // FIXME: Implement.
4810                 }
4811         }
4812         
4813         public class CheckedExpr : Expression {
4814
4815                 public Expression Expr;
4816
4817                 public CheckedExpr (Expression e)
4818                 {
4819                         Expr = e;
4820                 }
4821
4822                 public override Expression DoResolve (EmitContext ec)
4823                 {
4824                         Expr = Expr.Resolve (ec);
4825
4826                         if (Expr == null)
4827                                 return null;
4828
4829                         eclass = Expr.ExprClass;
4830                         type = Expr.Type;
4831                         return this;
4832                 }
4833
4834                 public override void Emit (EmitContext ec)
4835                 {
4836                         bool last_check = ec.CheckState;
4837                         
4838                         ec.CheckState = true;
4839                         Expr.Emit (ec);
4840                         ec.CheckState = last_check;
4841                 }
4842                 
4843         }
4844
4845         public class UnCheckedExpr : Expression {
4846
4847                 public Expression Expr;
4848
4849                 public UnCheckedExpr (Expression e)
4850                 {
4851                         Expr = e;
4852                 }
4853
4854                 public override Expression DoResolve (EmitContext ec)
4855                 {
4856                         Expr = Expr.Resolve (ec);
4857
4858                         if (Expr == null)
4859                                 return null;
4860
4861                         eclass = Expr.ExprClass;
4862                         type = Expr.Type;
4863                         return this;
4864                 }
4865
4866                 public override void Emit (EmitContext ec)
4867                 {
4868                         bool last_check = ec.CheckState;
4869                         
4870                         ec.CheckState = false;
4871                         Expr.Emit (ec);
4872                         ec.CheckState = last_check;
4873                 }
4874                 
4875         }
4876         
4877         public class ElementAccess : Expression, LValue {
4878                 
4879                 public ArrayList  Arguments;
4880                 public Expression Expr;
4881
4882                 Location   location;
4883                 
4884                 public ElementAccess (Expression e, ArrayList e_list, Location loc)
4885                 {
4886                         Expr = e;
4887
4888                         Arguments = new ArrayList ();
4889                         foreach (Expression tmp in e_list)
4890                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
4891                         
4892                         location  = loc;
4893                 }
4894
4895                 public override Expression DoResolve (EmitContext ec)
4896                 {
4897                         Expr = Expr.Resolve (ec);
4898
4899                         //Console.WriteLine (Expr.ToString ());
4900
4901                         if (Expr == null) 
4902                                 return null;
4903
4904                         if (Arguments == null)
4905                                 return null;
4906
4907                         if (Expr.ExprClass != ExprClass.Variable) {
4908                                 report118 (location, Expr, "variable");
4909                                 return null;
4910                         }
4911
4912                         if (Arguments != null){
4913                                 for (int i = Arguments.Count; i > 0;){
4914                                         --i;
4915                                         Argument a = (Argument) Arguments [i];
4916                                         
4917                                         if (!a.Resolve (ec))
4918                                                 return null;
4919                                         
4920                                         Type a_type = a.expr.Type;
4921                                         if (!(StandardConversionExists (a_type, TypeManager.int32_type) ||
4922                                               StandardConversionExists (a_type, TypeManager.uint32_type) ||
4923                                               StandardConversionExists (a_type, TypeManager.int64_type) ||
4924                                               StandardConversionExists (a_type, TypeManager.uint64_type)))
4925                                                 return null;
4926                                         
4927                                 }
4928                         }                       
4929
4930                         // FIXME : Implement the actual storage here.
4931                         
4932                         throw new Exception ("Finish element access");
4933                         
4934                 }
4935
4936                 public void Store (EmitContext ec)
4937                 {
4938                         throw new Exception ("Implement me !");
4939                 }
4940
4941                 public override void Emit (EmitContext ec)
4942                 {
4943                         throw new Exception ("Implement me !");
4944                 }
4945
4946                 public Expression LValueResolve (EmitContext ec)
4947                 {
4948                         return this;
4949                 }
4950         }
4951         
4952         public class BaseAccess : Expression {
4953
4954                 public enum BaseAccessType {
4955                         Member,
4956                         Indexer
4957                 };
4958                 
4959                 public readonly BaseAccessType BAType;
4960                 public readonly string         Member;
4961                 public readonly ArrayList      Arguments;
4962
4963                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
4964                 {
4965                         BAType = t;
4966                         Member = member;
4967                         Arguments = args;
4968                         
4969                 }
4970
4971                 public override Expression DoResolve (EmitContext ec)
4972                 {
4973                         // FIXME: Implement;
4974                         throw new Exception ("Unimplemented");
4975                         // return this;
4976                 }
4977
4978                 public override void Emit (EmitContext ec)
4979                 {
4980                         throw new Exception ("Unimplemented");
4981                 }
4982         }
4983
4984         // <summary>
4985         //   This class exists solely to pass the Type around and to be a dummy
4986         //   that can be passed to the conversion functions (this is used by
4987         //   foreach implementation to typecast the object return value from
4988         //   get_Current into the proper type.  All code has been generated and
4989         //   we only care about the side effect conversions to be performed
4990         // </summary>
4991         
4992         public class EmptyExpression : Expression {
4993                 public EmptyExpression ()
4994                 {
4995                         type = TypeManager.object_type;
4996                         eclass = ExprClass.Value;
4997                 }
4998
4999                 public override Expression DoResolve (EmitContext ec)
5000                 {
5001                         return this;
5002                 }
5003
5004                 public override void Emit (EmitContext ec)
5005                 {
5006                         // nothing, as we only exist to not do anything.
5007                 }
5008         }
5009
5010         public class UserCast : Expression {
5011                 MethodBase method;
5012                 Expression source;
5013                 
5014                 public UserCast (MethodInfo method, Expression source)
5015                 {
5016                         this.method = method;
5017                         this.source = source;
5018                         type = method.ReturnType;
5019                         eclass = ExprClass.Value;
5020                 }
5021
5022                 public override Expression DoResolve (EmitContext ec)
5023                 {
5024                         //
5025                         // We are born fully resolved
5026                         //
5027                         return this;
5028                 }
5029
5030                 public override void Emit (EmitContext ec)
5031                 {
5032                         ILGenerator ig = ec.ig;
5033
5034                         source.Emit (ec);
5035                         
5036                         if (method is MethodInfo)
5037                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
5038                         else
5039                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5040
5041                 }
5042
5043         }
5044 }