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