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