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