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