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