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