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