2001-10-31 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10 // Ideas:
11 //   Maybe we should make Resolve be an instance method that just calls
12 //   the virtual DoResolve function and checks conditions like the eclass
13 //   and type being set if a non-null value is returned.  For robustness
14 //   purposes.
15 //
16
17 namespace CIR {
18         using System;
19         using System.Collections;
20         using System.Diagnostics;
21         using System.Reflection;
22         using System.Reflection.Emit;
23         using System.Text;
24         
25         // <remarks>
26         //   The ExprClass class contains the is used to pass the 
27         //   classification of an expression (value, variable, namespace,
28         //   type, method group, property access, event access, indexer access,
29         //   nothing).
30         // </remarks>
31         public enum ExprClass {
32                 Invalid,
33                 
34                 Value,
35                 Variable,
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                 //   Find the Applicable Function Members (7.4.2.1)
3969                 //
3970                 //   me: Method Group expression with the members to select.
3971                 //       it might contain constructors or methods (or anything
3972                 //       that maps to a method).
3973                 //
3974                 //   Arguments: ArrayList containing resolved Argument objects.
3975                 //
3976                 //   loc: The location if we want an error to be reported, or a Null
3977                 //        location for "probing" purposes.
3978                 //
3979                 //   inside_user_defined: controls whether OverloadResolve should use the 
3980                 //   ConvertImplicit or ConvertImplicitStandard during overload resolution.
3981                 //
3982                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
3983                 //            that is the best match of me on Arguments.
3984                 //
3985                 // </summary>
3986                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
3987                                                           ArrayList Arguments, Location loc,
3988                                                           bool use_standard)
3989                 {
3990                         ArrayList afm = new ArrayList ();
3991                         int best_match_idx = -1;
3992                         MethodBase method = null;
3993                         int argument_count;
3994                         
3995                         for (int i = me.Methods.Length; i > 0; ){
3996                                 i--;
3997                                 MethodBase candidate  = me.Methods [i];
3998                                 int x;
3999
4000                                 x = BetterFunction (ec, Arguments, candidate, method, use_standard, loc);
4001                                 
4002                                 if (x == 0)
4003                                         continue;
4004                                 else {
4005                                         best_match_idx = i;
4006                                         method = me.Methods [best_match_idx];
4007                                 }
4008                         }
4009
4010                         if (Arguments == null)
4011                                 argument_count = 0;
4012                         else
4013                                 argument_count = Arguments.Count;
4014                         
4015                         ParameterData pd;
4016                         
4017                         // Now we see if we can at least find a method with the same number of arguments
4018                         // and then try doing implicit conversion on the arguments
4019                         if (best_match_idx == -1) {
4020                                 
4021                                 for (int i = me.Methods.Length; i > 0;) {
4022                                         i--;
4023                                         MethodBase mb = me.Methods [i];
4024                                         pd = GetParameterData (mb);
4025                                         
4026                                         if (pd.Count == argument_count) {
4027                                                 best_match_idx = i;
4028                                                 method = me.Methods [best_match_idx];
4029                                                 break;
4030                                         } else
4031                                                 continue;
4032                                 }
4033
4034                         }
4035
4036                         if (method == null)
4037                                 return null;
4038
4039                         // And now convert implicitly, each argument to the required type
4040                         
4041                         pd = GetParameterData (method);
4042
4043                         for (int j = 0; j < argument_count; j++) {
4044
4045                                 Argument a = (Argument) Arguments [j];
4046                                 Expression a_expr = a.Expr;
4047                                 Type parameter_type = pd.ParameterType (j);
4048
4049                                 if (a.Type != parameter_type){
4050                                         Expression conv;
4051                                         
4052                                         if (use_standard)
4053                                                 conv = ConvertImplicitStandard (ec, a_expr, parameter_type,
4054                                                                                 Location.Null);
4055                                         else
4056                                                 conv = ConvertImplicit (ec, a_expr, parameter_type,
4057                                                                         Location.Null);
4058
4059                                         if (conv == null){
4060                                                 if (!Location.IsNull (loc)) {
4061                                                         Error (1502, loc,
4062                                                         "The best overloaded match for method '" + FullMethodDesc (method)+
4063                                                                "' has some invalid arguments");
4064                                                         Error (1503, loc,
4065                                                          "Argument " + (j+1) +
4066                                                          ": Cannot convert from '" + Argument.FullDesc (a) 
4067                                                          + "' to '" + pd.ParameterDesc (j) + "'");
4068                                                 }
4069                                                 return null;
4070                                         }
4071                                         
4072                         
4073                                         
4074                                         //
4075                                         // Update the argument with the implicit conversion
4076                                         //
4077                                         if (a_expr != conv)
4078                                                 a.Expr = conv;
4079                                 }
4080
4081                                 if (a.GetParameterModifier () != pd.ParameterModifier (j)) {
4082                                         if (!Location.IsNull (loc)) {
4083                                                 Error (1502, loc,
4084                                                        "The best overloaded match for method '" + FullMethodDesc (method)+
4085                                                        "' has some invalid arguments");
4086                                                 Error (1503, loc,
4087                                                        "Argument " + (j+1) +
4088                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
4089                                                        + "' to '" + pd.ParameterDesc (j) + "'");
4090                                         }
4091                                         return null;
4092                                 }
4093                         }
4094                         
4095                         return method;
4096                 }
4097
4098                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
4099                                                           ArrayList Arguments, Location loc)
4100                 {
4101                         return OverloadResolve (ec, me, Arguments, loc, false);
4102                 }
4103                         
4104                 public override Expression DoResolve (EmitContext ec)
4105                 {
4106                         //
4107                         // First, resolve the expression that is used to
4108                         // trigger the invocation
4109                         //
4110                         expr = expr.Resolve (ec);
4111                         if (expr == null)
4112                                 return null;
4113
4114                         if (!(expr is MethodGroupExpr)) {
4115                                 Type expr_type = expr.Type;
4116
4117                                 if (expr_type != null){
4118                                         bool IsDelegate = TypeManager.IsDelegateType (expr_type);
4119                                         if (IsDelegate)
4120                                                 return (new DelegateInvocation (
4121                                                         this.expr, Arguments, Location)).Resolve (ec);
4122                                 }
4123                         }
4124
4125                         if (!(expr is MethodGroupExpr)){
4126                                 report118 (Location, this.expr, "method group");
4127                                 return null;
4128                         }
4129
4130                         //
4131                         // Next, evaluate all the expressions in the argument list
4132                         //
4133                         if (Arguments != null){
4134                                 for (int i = Arguments.Count; i > 0;){
4135                                         --i;
4136                                         Argument a = (Argument) Arguments [i];
4137
4138                                         if (!a.Resolve (ec))
4139                                                 return null;
4140                                 }
4141                         }
4142
4143                         method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments,
4144                                                   Location);
4145
4146                         if (method == null){
4147                                 Error (-6, Location,
4148                                        "Could not find any applicable function for this argument list");
4149                                 return null;
4150                         }
4151
4152                         if (method is MethodInfo)
4153                                 type = ((MethodInfo)method).ReturnType;
4154
4155                         eclass = ExprClass.Value;
4156                         return this;
4157                 }
4158
4159                 public static void EmitArguments (EmitContext ec, ArrayList Arguments)
4160                 {
4161                         int top;
4162
4163                         if (Arguments != null)
4164                                 top = Arguments.Count;
4165                         else
4166                                 top = 0;
4167
4168                         for (int i = 0; i < top; i++){
4169                                 Argument a = (Argument) Arguments [i];
4170
4171                                 a.Emit (ec);
4172                         }
4173                 }
4174
4175                 public static void EmitCall (EmitContext ec,
4176                                              bool is_static, Expression instance_expr,
4177                                              MethodBase method, ArrayList Arguments)
4178                 {
4179                         ILGenerator ig = ec.ig;
4180                         bool struct_call = false;
4181                                 
4182                         if (!is_static){
4183                                 //
4184                                 // If this is ourselves, push "this"
4185                                 //
4186                                 if (instance_expr == null){
4187                                         ig.Emit (OpCodes.Ldarg_0);
4188                                 } else {
4189                                         //
4190                                         // Push the instance expression
4191                                         //
4192                                         if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
4193
4194                                                 struct_call = true;
4195
4196                                                 //
4197                                                 // If the expression implements IMemoryLocation, then
4198                                                 // we can optimize and use AddressOf on the
4199                                                 // return.
4200                                                 //
4201                                                 // If not we have to use some temporary storage for
4202                                                 // it.
4203                                                 if (instance_expr is IMemoryLocation)
4204                                                         ((IMemoryLocation) instance_expr).AddressOf (ec);
4205                                                 else {
4206                                                         Type t = instance_expr.Type;
4207                                                         
4208                                                         instance_expr.Emit (ec);
4209                                                         LocalBuilder temp = ec.GetTemporaryStorage (t);
4210                                                         ig.Emit (OpCodes.Stloc, temp);
4211                                                         ig.Emit (OpCodes.Ldloca, temp);
4212                                                 }
4213                                         } else 
4214                                                 instance_expr.Emit (ec);
4215                                 }
4216                         }
4217
4218                         if (Arguments != null)
4219                                 EmitArguments (ec, Arguments);
4220
4221                         if (is_static || struct_call){
4222                                 if (method is MethodInfo)
4223                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
4224                                 else
4225                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
4226                         } else {
4227                                 if (method is MethodInfo)
4228                                         ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
4229                                 else
4230                                         ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
4231                         }
4232                 }
4233                 
4234                 public override void Emit (EmitContext ec)
4235                 {
4236                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
4237                         EmitCall (ec, method.IsStatic, mg.InstanceExpression, method, Arguments);
4238                 }
4239                 
4240                 public override void EmitStatement (EmitContext ec)
4241                 {
4242                         Emit (ec);
4243
4244                         // 
4245                         // Pop the return value if there is one
4246                         //
4247                         if (method is MethodInfo){
4248                                 if (((MethodInfo)method).ReturnType != TypeManager.void_type)
4249                                         ec.ig.Emit (OpCodes.Pop);
4250                         }
4251                 }
4252         }
4253
4254         public class New : ExpressionStatement {
4255                 public readonly ArrayList Arguments;
4256                 public readonly string    RequestedType;
4257
4258                 Location Location;
4259                 MethodBase method = null;
4260
4261                 //
4262                 // If set, the new expression is for a value_target, and
4263                 // we will not leave anything on the stack.
4264                 //
4265                 Expression value_target;
4266                 
4267                 public New (string requested_type, ArrayList arguments, Location loc)
4268                 {
4269                         RequestedType = requested_type;
4270                         Arguments = arguments;
4271                         Location = loc;
4272                 }
4273
4274                 public Expression ValueTypeVariable {
4275                         get {
4276                                 return value_target;
4277                         }
4278
4279                         set {
4280                                 value_target = value;
4281                         }
4282                 }
4283
4284                 public override Expression DoResolve (EmitContext ec)
4285                 {
4286                         type = ec.TypeContainer.LookupType (RequestedType, false);
4287                         
4288                         if (type == null)
4289                                 return null;
4290                         
4291                         bool IsDelegate = TypeManager.IsDelegateType (type);
4292                         
4293                         if (IsDelegate)
4294                                 return (new NewDelegate (type, Arguments, Location)).Resolve (ec);
4295                         
4296                         Expression ml;
4297                         
4298                         ml = MemberLookup (ec, type, ".ctor", false,
4299                                            MemberTypes.Constructor, AllBindingsFlags, Location);
4300                         
4301                         bool is_struct = false;
4302                         is_struct = type.IsSubclassOf (TypeManager.value_type);
4303                         
4304                         if (! (ml is MethodGroupExpr)){
4305                                 if (!is_struct){
4306                                         report118 (Location, ml, "method group");
4307                                         return null;
4308                                 }
4309                         }
4310                         
4311                         if (ml != null) {
4312                                 if (Arguments != null){
4313                                         for (int i = Arguments.Count; i > 0;){
4314                                                 --i;
4315                                                 Argument a = (Argument) Arguments [i];
4316                                                 
4317                                                 if (!a.Resolve (ec))
4318                                                         return null;
4319                                         }
4320                                 }
4321
4322                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
4323                                                                      Arguments, Location);
4324                         }
4325                         
4326                         if (method == null && !is_struct) {
4327                                 Error (-6, Location,
4328                                        "New invocation: Can not find a constructor for " +
4329                                        "this argument list");
4330                                 return null;
4331                         }
4332                         
4333                         eclass = ExprClass.Value;
4334                         return this;
4335                 }
4336
4337                 //
4338                 // This DoEmit can be invoked in two contexts:
4339                 //    * As a mechanism that will leave a value on the stack (new object)
4340                 //    * As one that wont (init struct)
4341                 //
4342                 // You can control whether a value is required on the stack by passing
4343                 // need_value_on_stack.  The code *might* leave a value on the stack
4344                 // so it must be popped manually
4345                 //
4346                 // Returns whether a value is left on the stack
4347                 //
4348                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
4349                 {
4350                         if (method == null){
4351                                 IMemoryLocation ml = (IMemoryLocation) value_target;
4352
4353                                 ml.AddressOf (ec);
4354                         } else {
4355                                 Invocation.EmitArguments (ec, Arguments);
4356                                 ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
4357                                 return true;
4358                         }
4359
4360                         //
4361                         // It must be a value type, sanity check
4362                         //
4363                         if (value_target != null){
4364                                 ec.ig.Emit (OpCodes.Initobj, type);
4365
4366                                 if (need_value_on_stack){
4367                                         value_target.Emit (ec);
4368                                         return true;
4369                                 }
4370                                 return false;
4371                         }
4372
4373                         throw new Exception ("No method and no value type");
4374                 }
4375
4376                 public override void Emit (EmitContext ec)
4377                 {
4378                         DoEmit (ec, true);
4379                 }
4380                 
4381                 public override void EmitStatement (EmitContext ec)
4382                 {
4383                         if (DoEmit (ec, false))
4384                                 ec.ig.Emit (OpCodes.Pop);
4385                 }
4386         }
4387
4388         // <summary>
4389         //   Represents an array creation expression.
4390         // </summary>
4391         //
4392         // <remarks>
4393         //   There are two possible scenarios here: one is an array creation
4394         //   expression that specifies the dimensions and optionally the
4395         //   initialization data
4396         // </remarks>
4397         public class ArrayCreation : ExpressionStatement {
4398
4399                 string RequestedType;
4400                 string Rank;
4401                 ArrayList Initializers;
4402                 Location  Location;
4403                 ArrayList Arguments;
4404
4405                 MethodBase method = null;
4406                 Type array_element_type;
4407                 bool IsOneDimensional = false;
4408                 
4409                 bool IsBuiltinType = false;
4410
4411                 public ArrayCreation (string requested_type, ArrayList exprs,
4412                                       string rank, ArrayList initializers, Location l)
4413                 {
4414                         RequestedType = requested_type;
4415                         Rank          = rank;
4416                         Initializers  = initializers;
4417                         Location      = l;
4418
4419                         Arguments = new ArrayList ();
4420
4421                         foreach (Expression e in exprs)
4422                                 Arguments.Add (new Argument (e, Argument.AType.Expression));
4423                         
4424                 }
4425
4426                 public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
4427                 {
4428                         RequestedType = requested_type;
4429                         Rank = rank;
4430                         Initializers = initializers;
4431                         Location = l;
4432                 }
4433
4434                 public static string FormArrayType (string base_type, int idx_count, string rank)
4435                 {
4436                         StringBuilder sb = new StringBuilder (base_type);
4437
4438                         sb.Append (rank);
4439                         
4440                         sb.Append ("[");
4441                         for (int i = 1; i < idx_count; i++)
4442                                 sb.Append (",");
4443                         sb.Append ("]");
4444                         
4445                         return sb.ToString ();
4446                 }
4447
4448                 public static string FormElementType (string base_type, int idx_count, string rank)
4449                 {
4450                         StringBuilder sb = new StringBuilder (base_type);
4451                         
4452                         sb.Append ("[");
4453                         for (int i = 1; i < idx_count; i++)
4454                                 sb.Append (",");
4455                         sb.Append ("]");
4456
4457                         sb.Append (rank);
4458
4459                         string val = sb.ToString ();
4460
4461                         return val.Substring (0, val.LastIndexOf ("["));
4462                 }
4463                 
4464
4465                 public override Expression DoResolve (EmitContext ec)
4466                 {
4467                         int arg_count;
4468                         
4469                         if (Arguments == null)
4470                                 arg_count = 0;
4471                         else
4472                                 arg_count = Arguments.Count;
4473                         
4474                         string array_type = FormArrayType (RequestedType, arg_count, Rank);
4475
4476                         string element_type = FormElementType (RequestedType, arg_count, Rank);
4477
4478                         type = ec.TypeContainer.LookupType (array_type, false);
4479                         
4480                         array_element_type = ec.TypeContainer.LookupType (element_type, false);
4481                         
4482                         if (type == null)
4483                                 return null;
4484                         
4485                         if (arg_count == 1) {
4486                                 IsOneDimensional = true;
4487                                 eclass = ExprClass.Value;
4488                                 return this;
4489                         }
4490
4491                         IsBuiltinType = TypeManager.IsBuiltinType (type);
4492                         
4493                         if (IsBuiltinType) {
4494                                 
4495                                 Expression ml;
4496                                 
4497                                 ml = MemberLookup (ec, type, ".ctor", false, MemberTypes.Constructor,
4498                                                    AllBindingsFlags, Location);
4499                                 
4500                                 if (!(ml is MethodGroupExpr)){
4501                                         report118 (Location, ml, "method group");
4502                                         return null;
4503                                 }
4504                                 
4505                                 if (ml == null) {
4506                                         Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
4507                                                       "this argument list");
4508                                         return null;
4509                                 }
4510                                 
4511                                 if (Arguments != null) {
4512                                         for (int i = arg_count; i > 0;){
4513                                                 --i;
4514                                                 Argument a = (Argument) Arguments [i];
4515                                                 
4516                                                 if (!a.Resolve (ec))
4517                                                         return null;
4518                                         }
4519                                 }
4520                                 
4521                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, Location);
4522                                 
4523                                 if (method == null) {
4524                                         Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
4525                                                       "this argument list");
4526                                         return null;
4527                                 }
4528                                 
4529                                 eclass = ExprClass.Value;
4530                                 return this;
4531                                 
4532                         } else {
4533
4534                                 ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
4535
4536                                 ArrayList args = new ArrayList ();
4537                                 if (Arguments != null){
4538                                         for (int i = arg_count; i > 0;){
4539                                                 --i;
4540                                                 Argument a = (Argument) Arguments [i];
4541                                                 
4542                                                 if (!a.Resolve (ec))
4543                                                         return null;
4544                                                 
4545                                                 args.Add (a.Type);
4546                                         }
4547                                 }
4548                                 
4549                                 Type [] arg_types = null;
4550                                 
4551                                 if (args.Count > 0)
4552                                         arg_types = new Type [args.Count];
4553                                 
4554                                 args.CopyTo (arg_types, 0);
4555                                 
4556                                 method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
4557                                                             arg_types);
4558                                 
4559                                 if (method == null) {
4560                                         Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
4561                                                       "this argument list");
4562                                         return null;
4563                                 }
4564                                 
4565                                 eclass = ExprClass.Value;
4566                                 return this;
4567                                 
4568                         }
4569                 }
4570
4571                 public override void Emit (EmitContext ec)
4572                 {
4573                         if (IsOneDimensional) {
4574                                 Invocation.EmitArguments (ec, Arguments);
4575                                 ec.ig.Emit (OpCodes.Newarr, array_element_type);
4576                                 
4577                         } else {
4578                                 Invocation.EmitArguments (ec, Arguments);
4579
4580                                 if (IsBuiltinType)
4581                                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
4582                                 else
4583                                         ec.ig.Emit (OpCodes.Newobj, (MethodInfo) method);
4584                         }
4585                         
4586                 }
4587                 
4588                 public override void EmitStatement (EmitContext ec)
4589                 {
4590                         Emit (ec);
4591                         ec.ig.Emit (OpCodes.Pop);
4592                 }
4593                 
4594         }
4595         
4596         //
4597         // Represents the `this' construct
4598         //
4599         public class This : Expression, IStackStore, IMemoryLocation {
4600                 Location loc;
4601                 
4602                 public This (Location loc)
4603                 {
4604                         this.loc = loc;
4605                 }
4606
4607                 public override Expression DoResolve (EmitContext ec)
4608                 {
4609                         eclass = ExprClass.Variable;
4610                         type = ec.TypeContainer.TypeBuilder;
4611
4612                         if (ec.IsStatic){
4613                                 Report.Error (26, loc,
4614                                               "Keyword this not valid in static code");
4615                                 return null;
4616                         }
4617                         
4618                         return this;
4619                 }
4620
4621                 public Expression DoResolveLValue (EmitContext ec)
4622                 {
4623                         DoResolve (ec);
4624                         
4625                         if (ec.TypeContainer is Class){
4626                                 Report.Error (1604, loc, "Cannot assign to `this'");
4627                                 return null;
4628                         }
4629
4630                         return this;
4631                 }
4632
4633                 public override void Emit (EmitContext ec)
4634                 {
4635                         ec.ig.Emit (OpCodes.Ldarg_0);
4636                 }
4637
4638                 public void Store (EmitContext ec)
4639                 {
4640                         ec.ig.Emit (OpCodes.Starg, 0);
4641                 }
4642
4643                 public void AddressOf (EmitContext ec)
4644                 {
4645                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
4646                 }
4647         }
4648
4649         // <summary>
4650         //   Implements the typeof operator
4651         // </summary>
4652         public class TypeOf : Expression {
4653                 public readonly string QueriedType;
4654                 Type typearg;
4655                 
4656                 public TypeOf (string queried_type)
4657                 {
4658                         QueriedType = queried_type;
4659                 }
4660
4661                 public override Expression DoResolve (EmitContext ec)
4662                 {
4663                         typearg = ec.TypeContainer.LookupType (QueriedType, false);
4664
4665                         if (typearg == null)
4666                                 return null;
4667
4668                         type = TypeManager.type_type;
4669                         eclass = ExprClass.Type;
4670                         return this;
4671                 }
4672
4673                 public override void Emit (EmitContext ec)
4674                 {
4675                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
4676                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
4677                 }
4678         }
4679
4680         public class SizeOf : Expression {
4681                 public readonly string QueriedType;
4682                 
4683                 public SizeOf (string queried_type)
4684                 {
4685                         this.QueriedType = queried_type;
4686                 }
4687
4688                 public override Expression DoResolve (EmitContext ec)
4689                 {
4690                         // FIXME: Implement;
4691                         throw new Exception ("Unimplemented");
4692                         // return this;
4693                 }
4694
4695                 public override void Emit (EmitContext ec)
4696                 {
4697                         throw new Exception ("Implement me");
4698                 }
4699         }
4700
4701         public class MemberAccess : Expression {
4702                 public readonly string Identifier;
4703                 Expression expr;
4704                 Expression member_lookup;
4705                 Location loc;
4706                 
4707                 public MemberAccess (Expression expr, string id, Location l)
4708                 {
4709                         this.expr = expr;
4710                         Identifier = id;
4711                         loc = l;
4712                 }
4713
4714                 public Expression Expr {
4715                         get {
4716                                 return expr;
4717                         }
4718                 }
4719
4720                 void error176 (Location loc, string name)
4721                 {
4722                         Report.Error (176, loc, "Static member `" +
4723                                       name + "' cannot be accessed " +
4724                                       "with an instance reference, qualify with a " +
4725                                       "type name instead");
4726                 }
4727                 
4728                 public override Expression DoResolve (EmitContext ec)
4729                 {
4730                         //
4731                         // We are the sole users of ResolveWithSimpleName (ie, the only
4732                         // ones that can cope with it
4733                         //
4734                         expr = expr.ResolveWithSimpleName (ec);
4735
4736                         if (expr == null)
4737                                 return null;
4738
4739                         if (expr is SimpleName){
4740                                 SimpleName child_expr = (SimpleName) expr;
4741                                 
4742                                 expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
4743
4744                                 return expr.Resolve (ec);
4745                         }
4746                                         
4747                         member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
4748
4749                         if (member_lookup == null)
4750                                 return null;
4751                         
4752                         //
4753                         // Method Groups
4754                         //
4755                         if (member_lookup is MethodGroupExpr){
4756                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
4757                                 
4758                                 //
4759                                 // Type.MethodGroup
4760                                 //
4761                                 if (expr is TypeExpr){
4762                                         if (!mg.RemoveInstanceMethods ()){
4763                                                 SimpleName.Error120 (loc, mg.Methods [0].Name); 
4764                                                 return null;
4765                                         }
4766
4767                                         return member_lookup;
4768                                 }
4769
4770                                 //
4771                                 // Instance.MethodGroup
4772                                 //
4773                                 if (!mg.RemoveStaticMethods ()){
4774                                         error176 (loc, mg.Methods [0].Name);
4775                                         return null;
4776                                 }
4777                                 
4778                                 mg.InstanceExpression = expr;
4779                                         
4780                                 return member_lookup;
4781                         }
4782
4783                         if (member_lookup is FieldExpr){
4784                                 FieldExpr fe = (FieldExpr) member_lookup;
4785
4786                                 if (expr is TypeExpr){
4787                                         if (!fe.FieldInfo.IsStatic){
4788                                                 error176 (loc, fe.FieldInfo.Name);
4789                                                 return null;
4790                                         }
4791                                         return member_lookup;
4792                                 } else {
4793                                         if (fe.FieldInfo.IsStatic){
4794                                                 error176 (loc, fe.FieldInfo.Name);
4795                                                 return null;
4796                                         }
4797                                         fe.InstanceExpression = expr;
4798
4799                                         return fe;
4800                                 }
4801                         }
4802
4803                         if (member_lookup is PropertyExpr){
4804                                 PropertyExpr pe = (PropertyExpr) member_lookup;
4805
4806                                 if (expr is TypeExpr){
4807                                         if (!pe.IsStatic){
4808                                                 SimpleName.Error120 (loc, pe.PropertyInfo.Name);
4809                                                 return null;
4810                                         }
4811                                         return pe;
4812                                 } else {
4813                                         if (pe.IsStatic){
4814                                                 error176 (loc, pe.PropertyInfo.Name);
4815                                                 return null;
4816                                         }
4817                                         pe.InstanceExpression = expr;
4818
4819                                         return pe;
4820                                 }
4821                         }
4822                         
4823                         Console.WriteLine ("Support for [" + member_lookup + "] is not present yet");
4824                         Environment.Exit (0);
4825                         return null;
4826                 }
4827
4828                 public override void Emit (EmitContext ec)
4829                 {
4830                         throw new Exception ("Should not happen I think");
4831                 }
4832
4833         }
4834
4835         // <summary>
4836         //   Fully resolved expression that evaluates to a type
4837         // </summary>
4838         public class TypeExpr : Expression {
4839                 public TypeExpr (Type t)
4840                 {
4841                         Type = t;
4842                         eclass = ExprClass.Type;
4843                 }
4844
4845                 override public Expression DoResolve (EmitContext ec)
4846                 {
4847                         return this;
4848                 }
4849
4850                 override public void Emit (EmitContext ec)
4851                 {
4852                         throw new Exception ("Implement me");
4853                 }
4854         }
4855
4856         // <summary>
4857         //   MethodGroup Expression.
4858         //  
4859         //   This is a fully resolved expression that evaluates to a type
4860         // </summary>
4861         public class MethodGroupExpr : Expression {
4862                 public MethodBase [] Methods;
4863                 Expression instance_expression = null;
4864                 
4865                 public MethodGroupExpr (MemberInfo [] mi)
4866                 {
4867                         Methods = new MethodBase [mi.Length];
4868                         mi.CopyTo (Methods, 0);
4869                         eclass = ExprClass.MethodGroup;
4870                 }
4871
4872                 public MethodGroupExpr (ArrayList l)
4873                 {
4874                         Methods = new MethodBase [l.Count];
4875
4876                         l.CopyTo (Methods, 0);
4877                         eclass = ExprClass.MethodGroup;
4878                 }
4879                 
4880                 //
4881                 // `A method group may have associated an instance expression' 
4882                 // 
4883                 public Expression InstanceExpression {
4884                         get {
4885                                 return instance_expression;
4886                         }
4887
4888                         set {
4889                                 instance_expression = value;
4890                         }
4891                 }
4892                 
4893                 override public Expression DoResolve (EmitContext ec)
4894                 {
4895                         return this;
4896                 }
4897
4898                 override public void Emit (EmitContext ec)
4899                 {
4900                         throw new Exception ("This should never be reached");
4901                 }
4902
4903                 bool RemoveMethods (bool keep_static)
4904                 {
4905                         ArrayList smethods = new ArrayList ();
4906                         int top = Methods.Length;
4907                         int i;
4908                         
4909                         for (i = 0; i < top; i++){
4910                                 MethodBase mb = Methods [i];
4911
4912                                 if (mb.IsStatic == keep_static)
4913                                         smethods.Add (mb);
4914                         }
4915
4916                         if (smethods.Count == 0)
4917                                 return false;
4918
4919                         Methods = new MethodBase [smethods.Count];
4920                         smethods.CopyTo (Methods, 0);
4921
4922                         return true;
4923                 }
4924                 
4925                 // <summary>
4926                 //   Removes any instance methods from the MethodGroup, returns
4927                 //   false if the resulting set is empty.
4928                 // </summary>
4929                 public bool RemoveInstanceMethods ()
4930                 {
4931                         return RemoveMethods (true);
4932                 }
4933
4934                 // <summary>
4935                 //   Removes any static methods from the MethodGroup, returns
4936                 //   false if the resulting set is empty.
4937                 // </summary>
4938                 public bool RemoveStaticMethods ()
4939                 {
4940                         return RemoveMethods (false);
4941                 }
4942         }
4943
4944         // <summary>
4945         //   Fully resolved expression that evaluates to a Field
4946         // </summary>
4947         public class FieldExpr : Expression, IStackStore, IMemoryLocation {
4948                 public readonly FieldInfo FieldInfo;
4949                 public Expression InstanceExpression;
4950                 Location loc;
4951                 
4952                 public FieldExpr (FieldInfo fi, Location l)
4953                 {
4954                         FieldInfo = fi;
4955                         eclass = ExprClass.Variable;
4956                         type = fi.FieldType;
4957                         loc = l;
4958                 }
4959
4960                 override public Expression DoResolve (EmitContext ec)
4961                 {
4962                         if (!FieldInfo.IsStatic){
4963                                 if (InstanceExpression == null){
4964                                         throw new Exception ("non-static FieldExpr without instance var\n" +
4965                                                              "You have to assign the Instance variable\n" +
4966                                                              "Of the FieldExpr to set this\n");
4967                                 }
4968
4969                                 InstanceExpression = InstanceExpression.Resolve (ec);
4970                                 if (InstanceExpression == null)
4971                                         return null;
4972                                 
4973                         }
4974                         return this;
4975                 }
4976
4977                 public Expression DoResolveLValue (EmitContext ec)
4978                 {
4979                         if (!FieldInfo.IsInitOnly)
4980                                 return this;
4981
4982                         //
4983                         // InitOnly fields can only be assigned in constructors
4984                         //
4985
4986                         if (ec.IsConstructor)
4987                                 return this;
4988
4989                         Report.Error (191, loc,
4990                                       "Readonly field can not be assigned outside " +
4991                                       "of constructor or variable initializer");
4992                         
4993                         return null;
4994                 }
4995
4996                 override public void Emit (EmitContext ec)
4997                 {
4998                         ILGenerator ig = ec.ig;
4999
5000                         if (FieldInfo.IsStatic)
5001                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
5002                         else {
5003                                 InstanceExpression.Emit (ec);
5004                                 
5005                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
5006                         }
5007                 }
5008
5009                 public void Store (EmitContext ec)
5010                 {
5011                         if (FieldInfo.IsStatic)
5012                                 ec.ig.Emit (OpCodes.Stsfld, FieldInfo);
5013                         else
5014                                 ec.ig.Emit (OpCodes.Stfld, FieldInfo);
5015                 }
5016
5017                 public void AddressOf (EmitContext ec)
5018                 {
5019                         if (FieldInfo.IsStatic)
5020                                 ec.ig.Emit (OpCodes.Ldsflda, FieldInfo);
5021                         else {
5022                                 InstanceExpression.Emit (ec);
5023                                 ec.ig.Emit (OpCodes.Ldflda, FieldInfo);
5024                         }
5025                 }
5026         }
5027         
5028         // <summary>
5029         //   Expression that evaluates to a Property.  The Assign class
5030         //   might set the `Value' expression if we are in an assignment.
5031         //
5032         //   This is not an LValue because we need to re-write the expression, we
5033         //   can not take data from the stack and store it.  
5034         // </summary>
5035         public class PropertyExpr : ExpressionStatement, IAssignMethod {
5036                 public readonly PropertyInfo PropertyInfo;
5037                 public readonly bool IsStatic;
5038                 MethodInfo [] Accessors;
5039                 Location loc;
5040                 
5041                 Expression instance_expr;
5042                 
5043                 public PropertyExpr (PropertyInfo pi, Location l)
5044                 {
5045                         PropertyInfo = pi;
5046                         eclass = ExprClass.PropertyAccess;
5047                         IsStatic = false;
5048                         loc = l;
5049                         Accessors = TypeManager.GetAccessors (pi);
5050
5051                         if (Accessors != null)
5052                                 for (int i = 0; i < Accessors.Length; i++){
5053                                         if (Accessors [i] != null)
5054                                                 if (Accessors [i].IsStatic)
5055                                                         IsStatic = true;
5056                                 }
5057                         else
5058                                 Accessors = new MethodInfo [2];
5059                         
5060                         type = pi.PropertyType;
5061                 }
5062
5063                 //
5064                 // The instance expression associated with this expression
5065                 //
5066                 public Expression InstanceExpression {
5067                         set {
5068                                 instance_expr = value;
5069                         }
5070
5071                         get {
5072                                 return instance_expr;
5073                         }
5074                 }
5075
5076                 public bool VerifyAssignable ()
5077                 {
5078                         if (!PropertyInfo.CanWrite){
5079                                 Report.Error (200, loc, 
5080                                               "The property `" + PropertyInfo.Name +
5081                                               "' can not be assigned to, as it has not set accessor");
5082                                 return false;
5083                         }
5084
5085                         return true;
5086                 }
5087
5088                 override public Expression DoResolve (EmitContext ec)
5089                 {
5090                         if (!PropertyInfo.CanRead){
5091                                 Report.Error (154, loc, 
5092                                               "The property `" + PropertyInfo.Name +
5093                                               "' can not be used in " +
5094                                               "this context because it lacks a get accessor");
5095                                 return null;
5096                         }
5097
5098                         return this;
5099                 }
5100
5101                 override public void Emit (EmitContext ec)
5102                 {
5103                         Invocation.EmitCall (ec, IsStatic, instance_expr, Accessors [0], null);
5104                         
5105                 }
5106
5107                 //
5108                 // Implements the IAssignMethod interface for assignments
5109                 //
5110                 public void EmitAssign (EmitContext ec, Expression source)
5111                 {
5112                         Argument arg = new Argument (source, Argument.AType.Expression);
5113                         ArrayList args = new ArrayList ();
5114
5115                         args.Add (arg);
5116                         Invocation.EmitCall (ec, IsStatic, instance_expr, Accessors [1], args);
5117                 }
5118
5119                 override public void EmitStatement (EmitContext ec)
5120                 {
5121                         Emit (ec);
5122                         ec.ig.Emit (OpCodes.Pop);
5123                 }
5124         }
5125
5126         // <summary>
5127         //   Fully resolved expression that evaluates to a Expression
5128         // </summary>
5129         public class EventExpr : Expression {
5130                 public readonly EventInfo EventInfo;
5131                 Location loc;
5132                 
5133                 public EventExpr (EventInfo ei, Location loc)
5134                 {
5135                         EventInfo = ei;
5136                         this.loc = loc;
5137                         eclass = ExprClass.EventAccess;
5138                 }
5139
5140                 override public Expression DoResolve (EmitContext ec)
5141                 {
5142                         // We are born in resolved state. 
5143                         return this;
5144                 }
5145
5146                 override public void Emit (EmitContext ec)
5147                 {
5148                         throw new Exception ("Implement me");
5149                         // FIXME: Implement.
5150                 }
5151         }
5152         
5153         public class CheckedExpr : Expression {
5154
5155                 public Expression Expr;
5156
5157                 public CheckedExpr (Expression e)
5158                 {
5159                         Expr = e;
5160                 }
5161
5162                 public override Expression DoResolve (EmitContext ec)
5163                 {
5164                         Expr = Expr.Resolve (ec);
5165
5166                         if (Expr == null)
5167                                 return null;
5168
5169                         eclass = Expr.ExprClass;
5170                         type = Expr.Type;
5171                         return this;
5172                 }
5173
5174                 public override void Emit (EmitContext ec)
5175                 {
5176                         bool last_check = ec.CheckState;
5177                         
5178                         ec.CheckState = true;
5179                         Expr.Emit (ec);
5180                         ec.CheckState = last_check;
5181                 }
5182                 
5183         }
5184
5185         public class UnCheckedExpr : Expression {
5186
5187                 public Expression Expr;
5188
5189                 public UnCheckedExpr (Expression e)
5190                 {
5191                         Expr = e;
5192                 }
5193
5194                 public override Expression DoResolve (EmitContext ec)
5195                 {
5196                         Expr = Expr.Resolve (ec);
5197
5198                         if (Expr == null)
5199                                 return null;
5200
5201                         eclass = Expr.ExprClass;
5202                         type = Expr.Type;
5203                         return this;
5204                 }
5205
5206                 public override void Emit (EmitContext ec)
5207                 {
5208                         bool last_check = ec.CheckState;
5209                         
5210                         ec.CheckState = false;
5211                         Expr.Emit (ec);
5212                         ec.CheckState = last_check;
5213                 }
5214                 
5215         }
5216
5217         public class ElementAccess : Expression {
5218                 
5219                 public ArrayList  Arguments;
5220                 public Expression Expr;
5221                 public Location   loc;
5222                 
5223                 public ElementAccess (Expression e, ArrayList e_list, Location l)
5224                 {
5225                         Expr = e;
5226
5227                         Arguments = new ArrayList ();
5228                         foreach (Expression tmp in e_list)
5229                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
5230                         
5231                         loc  = l;
5232                 }
5233
5234                 bool CommonResolve (EmitContext ec)
5235                 {
5236                         Expr = Expr.Resolve (ec);
5237
5238                         if (Expr == null) 
5239                                 return false;
5240
5241                         if (Arguments == null)
5242                                 return false;
5243
5244                         for (int i = Arguments.Count; i > 0;){
5245                                 --i;
5246                                 Argument a = (Argument) Arguments [i];
5247                                 
5248                                 if (!a.Resolve (ec))
5249                                         return false;
5250                         }
5251
5252                         return true;
5253                 }
5254                                 
5255                 public override Expression DoResolve (EmitContext ec)
5256                 {
5257                         if (!CommonResolve (ec))
5258                                 return null;
5259
5260                         //
5261                         // We perform some simple tests, and then to "split" the emit and store
5262                         // code we create an instance of a different class, and return that.
5263                         //
5264                         // I am experimenting with this pattern.
5265                         //
5266                         if (Expr.Type == TypeManager.array_type)
5267                                 return (new ArrayAccess (this)).Resolve (ec);
5268                         else
5269                                 return (new IndexerAccess (this)).Resolve (ec);
5270                 }
5271
5272                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
5273                 {
5274                         if (!CommonResolve (ec))
5275                                 return null;
5276
5277                         if (Expr.Type == TypeManager.array_type)
5278                                 return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
5279                         else
5280                                 return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
5281                 }
5282                 
5283                 public override void Emit (EmitContext ec)
5284                 {
5285                         throw new Exception ("Should never be reached");
5286                 }
5287         }
5288
5289         public class ArrayAccess : Expression, IStackStore {
5290                 //
5291                 // Points to our "data" repository
5292                 //
5293                 ElementAccess ea;
5294                 
5295                 public ArrayAccess (ElementAccess ea_data)
5296                 {
5297                         ea = ea_data;
5298                         eclass = ExprClass.Variable;
5299
5300                         //
5301                         // FIXME: Figure out the type here
5302                         //
5303                 }
5304
5305                 Expression CommonResolve (EmitContext ec)
5306                 {
5307                         return this;
5308                 }
5309                 
5310                 public override Expression DoResolve (EmitContext ec)
5311                 {
5312                         if (ea.Expr.ExprClass != ExprClass.Variable) {
5313                                 report118 (ea.loc, ea.Expr, "variable");
5314                                 return null;
5315                         }
5316                         
5317                         throw new Exception ("Implement me");
5318                 }
5319
5320                 public void Store (EmitContext ec)
5321                 {
5322                         throw new Exception ("Implement me !");
5323                 }
5324
5325                 public override void Emit (EmitContext ec)
5326                 {
5327                         throw new Exception ("Implement me !");
5328                 }
5329         }
5330
5331         class Indexers {
5332                 public ArrayList getters, setters;
5333                 static Hashtable map;
5334
5335                 static Indexers ()
5336                 {
5337                         map = new Hashtable ();
5338                 }
5339
5340                 Indexers (MemberInfo [] mi)
5341                 {
5342                         foreach (PropertyInfo property in mi){
5343                                 MethodInfo get, set;
5344                                 
5345                                 get = property.GetGetMethod (true);
5346                                 if (get != null){
5347                                         if (getters == null)
5348                                                 getters = new ArrayList ();
5349
5350                                         getters.Add (get);
5351                                 }
5352                                 
5353                                 set = property.GetSetMethod (true);
5354                                 if (set != null){
5355                                         if (setters == null)
5356                                                 setters = new ArrayList ();
5357                                         setters.Add (set);
5358                                 }
5359                         }
5360                 }
5361                 
5362                 static public Indexers GetIndexersForType (Type t, TypeManager tm, Location loc) 
5363                 {
5364                         Indexers ix = (Indexers) map [t];
5365                         string p_name = TypeManager.IndexerPropertyName (t);
5366                         
5367                         if (ix != null)
5368                                 return ix;
5369
5370                         MemberInfo [] mi = tm.FindMembers (
5371                                 t, MemberTypes.Property,
5372                                 BindingFlags.Public | BindingFlags.Instance,
5373                                 Type.FilterName, p_name);
5374
5375                         if (mi == null || mi.Length == 0){
5376                                 Report.Error (21, loc,
5377                                               "Type `" + TypeManager.CSharpName (t) + "' does not have " +
5378                                               "any indexers defined");
5379                                 return null;
5380                         }
5381                         
5382                         ix = new Indexers (mi);
5383                         map [t] = ix;
5384
5385                         return ix;
5386                 }
5387         }
5388         
5389         public class IndexerAccess : Expression, IAssignMethod {
5390                 //
5391                 // Points to our "data" repository
5392                 //
5393                 ElementAccess ea;
5394                 MethodInfo get, set;
5395                 Indexers ilist;
5396                 ArrayList set_arguments;
5397                 
5398                 public IndexerAccess (ElementAccess ea_data)
5399                 {
5400                         ea = ea_data;
5401                         eclass = ExprClass.Value;
5402                 }
5403
5404                 public bool VerifyAssignable (Expression source)
5405                 {
5406                         throw new Exception ("Implement me!");
5407                 }
5408
5409                 public override Expression DoResolve (EmitContext ec)
5410                 {
5411                         Type indexer_type = ea.Expr.Type;
5412                         
5413                         //
5414                         // Step 1: Query for all `Item' *properties*.  Notice
5415                         // that the actual methods are pointed from here.
5416                         //
5417                         // This is a group of properties, piles of them.  
5418
5419                         if (ilist == null)
5420                                 ilist = Indexers.GetIndexersForType (
5421                                         indexer_type, ec.TypeContainer.RootContext.TypeManager, ea.loc);
5422                         
5423                         if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)
5424                                 get = (MethodInfo) Invocation.OverloadResolve (
5425                                         ec, new MethodGroupExpr (ilist.getters), ea.Arguments, ea.loc);
5426
5427                         if (get == null){
5428                                 Report.Error (154, ea.loc,
5429                                               "indexer can not be used in this context, because " +
5430                                               "it lacks a `get' accessor");
5431                                         return null;
5432                         }
5433                                 
5434                         type = get.ReturnType;
5435                         eclass = ExprClass.Value;
5436                         return this;
5437                 }
5438
5439                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
5440                 {
5441                         Type indexer_type = ea.Expr.Type;
5442                         Type right_type = right_side.Type;
5443
5444                         if (ilist == null)
5445                                 ilist = Indexers.GetIndexersForType (
5446                                         indexer_type, ec.TypeContainer.RootContext.TypeManager, ea.loc);
5447
5448                         if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
5449                                 set_arguments = (ArrayList) ea.Arguments.Clone ();
5450                                 set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
5451
5452                                 set = (MethodInfo) Invocation.OverloadResolve (
5453                                         ec, new MethodGroupExpr (ilist.setters), set_arguments, ea.loc);
5454                         }
5455                         
5456                         if (set == null){
5457                                 Report.Error (200, ea.loc,
5458                                               "indexer X.this [" + TypeManager.CSharpName (right_type) +
5459                                               "] lacks a `set' accessor");
5460                                         return null;
5461                         }
5462
5463                         type = TypeManager.void_type;
5464                         eclass = ExprClass.IndexerAccess;
5465                         return this;
5466                 }
5467                 
5468                 public override void Emit (EmitContext ec)
5469                 {
5470                         Invocation.EmitCall (ec, false, ea.Expr, get, ea.Arguments);
5471                 }
5472
5473                 //
5474                 // source is ignored, because we already have a copy of it from the
5475                 // LValue resolution and we have already constructed a pre-cached
5476                 // version of the arguments (ea.set_arguments);
5477                 //
5478                 public void EmitAssign (EmitContext ec, Expression source)
5479                 {
5480                         Invocation.EmitCall (ec, false, ea.Expr, set, set_arguments);
5481                 }
5482         }
5483         
5484         public class BaseAccess : Expression {
5485
5486                 public enum BaseAccessType {
5487                         Member,
5488                         Indexer
5489                 };
5490                 
5491                 public readonly BaseAccessType BAType;
5492                 public readonly string         Member;
5493                 public readonly ArrayList      Arguments;
5494
5495                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
5496                 {
5497                         BAType = t;
5498                         Member = member;
5499                         Arguments = args;
5500                         
5501                 }
5502
5503                 public override Expression DoResolve (EmitContext ec)
5504                 {
5505                         // FIXME: Implement;
5506                         throw new Exception ("Unimplemented");
5507                         // return this;
5508                 }
5509
5510                 public override void Emit (EmitContext ec)
5511                 {
5512                         throw new Exception ("Unimplemented");
5513                 }
5514         }
5515
5516         // <summary>
5517         //   This class exists solely to pass the Type around and to be a dummy
5518         //   that can be passed to the conversion functions (this is used by
5519         //   foreach implementation to typecast the object return value from
5520         //   get_Current into the proper type.  All code has been generated and
5521         //   we only care about the side effect conversions to be performed
5522         // </summary>
5523         
5524         public class EmptyExpression : Expression {
5525                 public EmptyExpression ()
5526                 {
5527                         type = TypeManager.object_type;
5528                         eclass = ExprClass.Value;
5529                 }
5530
5531                 public override Expression DoResolve (EmitContext ec)
5532                 {
5533                         return this;
5534                 }
5535
5536                 public override void Emit (EmitContext ec)
5537                 {
5538                         // nothing, as we only exist to not do anything.
5539                 }
5540         }
5541
5542         public class UserCast : Expression {
5543                 MethodBase method;
5544                 Expression source;
5545                 
5546                 public UserCast (MethodInfo method, Expression source)
5547                 {
5548                         this.method = method;
5549                         this.source = source;
5550                         type = method.ReturnType;
5551                         eclass = ExprClass.Value;
5552                 }
5553
5554                 public override Expression DoResolve (EmitContext ec)
5555                 {
5556                         //
5557                         // We are born fully resolved
5558                         //
5559                         return this;
5560                 }
5561
5562                 public override void Emit (EmitContext ec)
5563                 {
5564                         ILGenerator ig = ec.ig;
5565
5566                         source.Emit (ec);
5567                         
5568                         if (method is MethodInfo)
5569                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
5570                         else
5571                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5572
5573                 }
5574
5575         }
5576 }