2001-09-21 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 namespace CIR {
10         using System.Collections;
11         using System.Diagnostics;
12         using System;
13         using System.Reflection;
14         using System.Reflection.Emit;
15
16         // <remarks>
17         //   The ExprClass class contains the is used to pass the 
18         //   classification of an expression (value, variable, namespace,
19         //   type, method group, property access, event access, indexer access,
20         //   nothing).
21         // </remarks>
22         public enum ExprClass {
23                 Invalid,
24                 
25                 Value,
26                 Variable,   // Every Variable should implement LValue
27                 Namespace,
28                 Type,
29                 MethodGroup,
30                 PropertyAccess,
31                 EventAccess,
32                 IndexerAccess,
33                 Nothing, 
34         }
35
36         // <remarks>
37         //   Base class for expressions
38         // </remarks>
39         public abstract class Expression {
40                 protected ExprClass eclass;
41                 protected Type      type;
42                 
43                 public Type Type {
44                         get {
45                                 return type;
46                         }
47
48                         set {
49                                 type = value;
50                         }
51                 }
52
53                 public ExprClass ExprClass {
54                         get {
55                                 return eclass;
56                         }
57
58                         set {
59                                 eclass = value;
60                         }
61                 }
62
63                 public abstract Expression Resolve (TypeContainer tc);
64
65                 //
66                 // Return value indicates whether a value is left on the stack or not
67                 //
68                 public abstract bool Emit (EmitContext ec);
69                 
70                 // <summary>
71                 //   Protected constructor.  Only derivate types should
72                 //   be able to be created
73                 // </summary>
74
75                 protected Expression ()
76                 {
77                         eclass = ExprClass.Invalid;
78                         type = null;
79                 }
80
81                 // 
82                 // Returns a fully formed expression after a MemberLookup
83                 //
84                 static Expression ExprClassFromMemberInfo (MemberInfo mi)
85                 {
86                         if (mi is EventInfo){
87                                 return new EventExpr ((EventInfo) mi);
88                         } else if (mi is FieldInfo){
89                                 return new FieldExpr ((FieldInfo) mi);
90                         } else if (mi is PropertyInfo){
91                                 return new PropertyExpr ((PropertyInfo) mi);
92                         } else if (mi is Type)
93                                 return new TypeExpr ((Type) mi);
94
95                         return null;
96                 }
97                 
98                 //
99                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
100                 //
101                 // FIXME: We need to cope with access permissions here, or this wont
102                 // work!
103                 //
104                 // This code could use some optimizations, but we need to do some
105                 // measurements.  For example, we could use a delegate to `flag' when
106                 // something can not any longer be a method-group (because it is something
107                 // else).
108                 //
109                 // Return values:
110                 //     If the return value is an Array, then it is an array of
111                 //     MethodBases
112                 //   
113                 //     If the return value is an MemberInfo, it is anything, but a Method
114                 //
115                 //     null on error.
116                 //
117                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
118                 // the arguments here and have MemberLookup return only the methods that
119                 // match the argument count/type, unlike we are doing now (we delay this
120                 // decision).
121                 //
122                 // This is so we can catch correctly attempts to invoke instance methods
123                 // from a static body (scan for error 120 in ResolveSimpleName).
124                 //
125                 public static Expression MemberLookup (RootContext rc, Type t, string name,
126                                                           bool same_type, MemberTypes mt, BindingFlags bf)
127                 {
128                         if (same_type)
129                                 bf |= BindingFlags.NonPublic;
130
131                         MemberInfo [] mi = rc.TypeManager.FindMembers (t, mt, bf, Type.FilterName, name);
132
133                         if (mi == null)
134                                 return null;
135                         
136                         if (mi.Length == 1 && !(mi [0] is MethodBase))
137                                 return Expression.ExprClassFromMemberInfo (mi [0]);
138                         
139                         for (int i = 0; i < mi.Length; i++)
140                                 if (!(mi [i] is MethodBase)){
141                                         rc.Report.Error (-5, "Do not know how to reproduce this case: " + 
142                                                          "Methods and non-Method with the same name, report this please");
143
144                                         for (i = 0; i < mi.Length; i++){
145                                                 Type tt = mi [i].GetType ();
146
147                                                 Console.WriteLine (i + ": " + mi [i]);
148                                                 while (tt != TypeManager.object_type){
149                                                         Console.WriteLine (tt);
150                                                         tt = tt.BaseType;
151                                                 }
152                                         }
153                                 }
154
155                         return new MethodGroupExpr (mi);
156                 }
157
158                 public const MemberTypes AllMemberTypes =
159                         MemberTypes.Constructor |
160                         MemberTypes.Event       |
161                         MemberTypes.Field       |
162                         MemberTypes.Method      |
163                         MemberTypes.NestedType  |
164                         MemberTypes.Property;
165                 
166                 public const BindingFlags AllBindingsFlags =
167                         BindingFlags.Public |
168                         BindingFlags.Static |
169                         BindingFlags.Instance;
170
171                 public static Expression MemberLookup (RootContext rc, Type t, string name,
172                                                        bool same_type)
173                 {
174                         return MemberLookup (rc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
175                 }
176                 
177                 // <summary>
178                 //   Resolves the E in `E.I' side for a member_access
179                 //
180                 //   This is suboptimal and should be merged with ResolveMemberAccess
181                 // </summary>
182                 static Expression ResolvePrimary (TypeContainer tc, string name)
183                 {
184                         int dot_pos = name.LastIndexOf (".");
185
186                         if (tc.RootContext.IsNamespace (name))
187                                 return new NamespaceExpr (name);
188
189                         if (dot_pos != -1){
190                         } else {
191                                 Type t = tc.LookupType (name, false);
192
193                                 if (t != null)
194                                         return new TypeExpr (t);
195                         }
196
197                         return null;
198                 }
199                         
200                 static public Expression ResolveMemberAccess (TypeContainer tc, string name)
201                 {
202                         Expression left_e;
203                         int dot_pos = name.LastIndexOf (".");
204                         string left = name.Substring (0, dot_pos);
205                         string right = name.Substring (dot_pos + 1);
206
207                         left_e = ResolvePrimary (tc, left);
208                         if (left_e == null)
209                                 return null;
210
211                         switch (left_e.ExprClass){
212                         case ExprClass.Type:
213                                 return  MemberLookup (tc.RootContext,
214                                                       left_e.Type, right,
215                                                       left_e.Type == tc.TypeBuilder);
216                                 
217                         case ExprClass.Namespace:
218                         case ExprClass.PropertyAccess:
219                         case ExprClass.IndexerAccess:
220                         case ExprClass.Variable:
221                         case ExprClass.Value:
222                         case ExprClass.Nothing:
223                         case ExprClass.EventAccess:
224                         case ExprClass.MethodGroup:
225                         case ExprClass.Invalid:
226                                 tc.RootContext.Report.Error (-1000,
227                                                              "Internal compiler error, should have " +
228                                                              "got these handled before");
229                                 break;
230                         }
231                         
232                         return null;
233                 }
234
235                 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
236                 {
237                         Type expr_type = expr.Type;
238                         
239                         if (target_type == TypeManager.object_type) {
240                                 if (expr_type.IsClass)
241                                         return new EmptyCast (expr, target_type);
242                                 if (expr_type.IsValueType)
243                                         return new BoxedCast (expr, target_type);
244                         } else if (expr_type.IsSubclassOf (target_type))
245                                 return new EmptyCast (expr, target_type);
246                         else 
247                                 // FIXME: missing implicit reference conversions:
248                                 // 
249                                 // from any class-type S to any interface-type T.
250                                 // from any interface type S to interface-type T.
251                                 // from an array-type S to an array-type of type T
252                                 // from an array-type to System.Array
253                                 // from any delegate type to System.Delegate
254                                 // from any array-type or delegate type into System.ICloneable.
255                                 // from the null type to any reference-type.
256                                      
257                                 return null;
258
259                         return null;
260                 }
261                        
262                 // <summary>
263                 //   Converts implicitly the resolved expression `expr' into the
264                 //   `target_type'.  It returns a new expression that can be used
265                 //   in a context that expects a `target_type'. 
266                 // </summary>
267                 static public Expression ConvertImplicit (Expression expr, Type target_type)
268                 {
269                         Type expr_type = expr.Type;
270
271                         if (expr_type == target_type){
272                                 Console.WriteLine ("Hey, ConvertImplicit was called with no job to do");
273                                 return expr;
274                         }
275
276                         //
277                         // Step 1: Perform implicit conversions as found on expr.Type
278                         //
279
280                         //
281                         // Step 2: Built-in conversions.
282                         //
283                         if (expr_type == TypeManager.sbyte_type){
284                                 //
285                                 // From sbyte to short, int, long, float, double.
286                                 //
287                                 if (target_type == TypeManager.int32_type)
288                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
289                                 if (target_type == TypeManager.int64_type)
290                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
291                                 if (target_type == TypeManager.double_type)
292                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
293                                 if (target_type == TypeManager.float_type)
294                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
295                                 if (target_type == TypeManager.short_type)
296                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
297                         } else if (expr_type == TypeManager.byte_type){
298                                 //
299                                 // From byte to short, ushort, int, uint, long, ulong, float, double
300                                 // 
301                                 if ((target_type == TypeManager.short_type) ||
302                                     (target_type == TypeManager.ushort_type) ||
303                                     (target_type == TypeManager.int32_type) ||
304                                     (target_type == TypeManager.uint32_type))
305                                         return new EmptyCast (expr, target_type);
306
307                                 if (target_type == TypeManager.uint64_type)
308                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
309                                 if (target_type == TypeManager.int64_type)
310                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
311                                 
312                                 if (target_type == TypeManager.float_type)
313                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
314                                 if (target_type == TypeManager.double_type)
315                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
316                         } else if (expr_type == TypeManager.short_type){
317                                 //
318                                 // From short to int, long, float, double
319                                 // 
320                                 if (target_type == TypeManager.int32_type)
321                                         return new EmptyCast (expr, target_type);
322                                 if (target_type == TypeManager.int64_type)
323                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
324                                 if (target_type == TypeManager.double_type)
325                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
326                                 if (target_type == TypeManager.float_type)
327                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
328                         } else if (expr_type == TypeManager.ushort_type){
329                                 //
330                                 // From ushort to int, uint, long, ulong, float, double
331                                 //
332                                 if ((target_type == TypeManager.uint32_type) ||
333                                     (target_type == TypeManager.uint64_type))
334                                         return new EmptyCast (expr, target_type);
335                                         
336                                 if (target_type == TypeManager.int32_type)
337                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
338                                 if (target_type == TypeManager.int64_type)
339                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
340                                 if (target_type == TypeManager.double_type)
341                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
342                                 if (target_type == TypeManager.float_type)
343                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
344                         } else if (expr_type == TypeManager.int32_type){
345                                 //
346                                 // From int to long, float, double
347                                 //
348                                 if (target_type == TypeManager.int64_type)
349                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
350                                 if (target_type == TypeManager.double_type)
351                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
352                                 if (target_type == TypeManager.float_type)
353                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
354                         } else if (expr_type == TypeManager.uint32_type){
355                                 //
356                                 // From uint to long, ulong, float, double
357                                 //
358                                 if (target_type == TypeManager.int64_type)
359                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
360                                 if (target_type == TypeManager.uint64_type)
361                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
362                                 if (target_type == TypeManager.double_type)
363                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
364                                                                OpCodes.Conv_R8);
365                                 if (target_type == TypeManager.float_type)
366                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
367                                                                OpCodes.Conv_R4);
368                         } else if ((expr_type == TypeManager.uint64_type) ||
369                                    (expr_type == TypeManager.int64_type)){
370                                 //
371                                 // From long to float, double
372                                 //
373                                 if (target_type == TypeManager.double_type)
374                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
375                                                                OpCodes.Conv_R8);
376                                 if (target_type == TypeManager.float_type)
377                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
378                                                                OpCodes.Conv_R4);        
379                         } else if (expr_type == TypeManager.char_type){
380                                 //
381                                 // From char to ushort, int, uint, long, ulong, float, double
382                                 // 
383                                 if ((target_type == TypeManager.ushort_type) ||
384                                     (target_type == TypeManager.int32_type) ||
385                                     (target_type == TypeManager.uint32_type))
386                                         return new EmptyCast (expr, target_type);
387                                 if (target_type == TypeManager.uint64_type)
388                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
389                                 if (target_type == TypeManager.int64_type)
390                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
391                                 if (target_type == TypeManager.float_type)
392                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
393                                 if (target_type == TypeManager.double_type)
394                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
395                         } else
396                                 return ImplicitReferenceConversion (expr, target_type);
397
398                         
399
400                         //
401                         //  Could not find an implicit cast.
402                         //
403                         return null;
404                 }
405
406                 // <summary>
407                 //   Performs an explicit conversion of the expression `expr' whose
408                 //   type is expr.Type to `target_type'.
409                 // </summary>
410                 static public Expression ConvertExplicit (Expression expr, Type target_type)
411                 {
412                         return expr;
413                 }
414
415                 void report (TypeContainer tc, int error, string s)
416                 {
417                         tc.RootContext.Report.Error (error, s);
418                 }
419
420                 static string ExprClassName (ExprClass c)
421                 {
422                         switch (c){
423                         case ExprClass.Invalid:
424                                 return "Invalid";
425                         case ExprClass.Value:
426                                 return "value";
427                         case ExprClass.Variable:
428                                 return "variable";
429                         case ExprClass.Namespace:
430                                 return "namespace";
431                         case ExprClass.Type:
432                                 return "type";
433                         case ExprClass.MethodGroup:
434                                 return "method group";
435                         case ExprClass.PropertyAccess:
436                                 return "property access";
437                         case ExprClass.EventAccess:
438                                 return "event access";
439                         case ExprClass.IndexerAccess:
440                                 return "indexer access";
441                         case ExprClass.Nothing:
442                                 return "null";
443                         }
444                         throw new Exception ("Should not happen");
445                 }
446                 
447                 // <summary>
448                 //   Reports that we were expecting `expr' to be of class `expected'
449                 // </summary>
450                 protected void report118 (TypeContainer tc, Expression expr, string expected)
451                 {
452                         report (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
453                                 "' where an " + expected + " was expected");
454                 }
455         }
456
457         // <summary>
458         //   This kind of cast is used to encapsulate the child
459         //   whose type is child.Type into an expression that is
460         //   reported to return "return_type".  This is used to encapsulate
461         //   expressions which have compatible types, but need to be dealt
462         //   at higher levels with.
463         //
464         //   For example, a "byte" expression could be encapsulated in one
465         //   of these as an "unsigned int".  The type for the expression
466         //   would be "unsigned int".
467         //
468         // </summary>
469         
470         public class EmptyCast : Expression {
471                 protected Expression child;
472
473                 public EmptyCast (Expression child, Type return_type)
474                 {
475                         ExprClass = child.ExprClass;
476                         type = return_type;
477                         this.child = child;
478                 }
479
480                 public override Expression Resolve (TypeContainer tc)
481                 {
482                         // This should never be invoked, we are born in fully
483                         // initialized state.
484
485                         return this;
486                 }
487
488                 public override bool Emit (EmitContext ec)
489                 {
490                         return child.Emit (ec);
491                 }                       
492         }
493
494         // <summary>
495         //   This kind of cast is used to encapsulate Value Types in objects.
496         //
497         //   The effect of it is to box the value type emitted by the previous
498         //   operation.
499         // </summary>
500         public class BoxedCast : EmptyCast {
501
502                 public BoxedCast (Expression expr, Type target_type)
503                         : base (expr, target_type)
504                 {
505                 }
506
507                 public override Expression Resolve (TypeContainer tc)
508                 {
509                         // This should never be invoked, we are born in fully
510                         // initialized state.
511
512                         return this;
513                 }
514
515                 public override bool Emit (EmitContext ec)
516                 {
517                         base.Emit (ec);
518                         ec.ig.Emit (OpCodes.Box, child.Type);
519                         return true;
520                 }
521         }
522         
523
524         // <summary>
525         //   This kind of cast is used to encapsulate a child expression
526         //   that can be trivially converted to a target type using one or 
527         //   two opcodes.  The opcodes are passed as arguments.
528         // </summary>
529         public class OpcodeCast : EmptyCast {
530                 OpCode op, op2;
531                 bool second_valid;
532                 
533                 public OpcodeCast (Expression child, Type return_type, OpCode op)
534                         : base (child, return_type)
535                         
536                 {
537                         this.op = op;
538                         second_valid = false;
539                 }
540
541                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
542                         : base (child, return_type)
543                         
544                 {
545                         this.op = op;
546                         this.op2 = op2;
547                         second_valid = true;
548                 }
549
550                 public override Expression Resolve (TypeContainer tc)
551                 {
552                         // This should never be invoked, we are born in fully
553                         // initialized state.
554
555                         return this;
556                 }
557
558                 public override bool Emit (EmitContext ec)
559                 {
560                         base.Emit (ec);
561                         ec.ig.Emit (op);
562
563                         if (second_valid)
564                                 ec.ig.Emit (op2);
565
566                         return true;
567                 }                       
568                 
569         }
570         
571         public class Unary : Expression {
572                 public enum Operator {
573                         Add, Subtract, Negate, BitComplement,
574                         Indirection, AddressOf, PreIncrement,
575                         PreDecrement, PostIncrement, PostDecrement
576                 }
577
578                 Operator   oper;
579                 Expression expr;
580                 ArrayList  Arguments;
581                 MethodBase method;
582                 
583                 public Unary (Operator op, Expression expr)
584                 {
585                         this.oper = op;
586                         this.expr = expr;
587                 }
588
589                 public Expression Expr {
590                         get {
591                                 return expr;
592                         }
593
594                         set {
595                                 expr = value;
596                         }
597                 }
598
599                 public Operator Oper {
600                         get {
601                                 return oper;
602                         }
603
604                         set {
605                                 oper = value;
606                         }
607                 }
608
609                 // <summary>
610                 //   Returns a stringified representation of the Operator
611                 // </summary>
612                 string OperName ()
613                 {
614                         switch (oper){
615                         case Operator.Add:
616                                 return "+";
617                         case Operator.Subtract:
618                                 return "-";
619                         case Operator.Negate:
620                                 return "!";
621                         case Operator.BitComplement:
622                                 return "~";
623                         case Operator.AddressOf:
624                                 return "&";
625                         case Operator.Indirection:
626                                 return "*";
627                         case Operator.PreIncrement : case Operator.PostIncrement :
628                                 return "++";
629                         case Operator.PreDecrement : case Operator.PostDecrement :
630                                 return "--";
631                         }
632
633                         return oper.ToString ();
634                 }
635
636                 Expression ForceConversion (Expression expr, Type target_type)
637                 {
638                         if (expr.Type == target_type)
639                                 return expr;
640
641                         return ConvertImplicit (expr, target_type);
642                 }
643
644                 void report23 (Report r, Type t)
645                 {
646                         r.Error (23, "Operator " + OperName () + " cannot be applied to operand of type `" +
647                                  TypeManager.CSharpName (t) + "'");
648                 }
649
650                 // <summary>
651                 //   Returns whether an object of type `t' can be incremented
652                 //   or decremented with add/sub (ie, basically whether we can
653                 //   use pre-post incr-decr operations on it, but it is not a
654                 //   System.Decimal, which we test elsewhere)
655                 // </summary>
656                 static bool IsIncrementableNumber (Type t)
657                 {
658                         return (t == TypeManager.sbyte_type) ||
659                                 (t == TypeManager.byte_type) ||
660                                 (t == TypeManager.short_type) ||
661                                 (t == TypeManager.ushort_type) ||
662                                 (t == TypeManager.int32_type) ||
663                                 (t == TypeManager.uint32_type) ||
664                                 (t == TypeManager.int64_type) ||
665                                 (t == TypeManager.uint64_type) ||
666                                 (t == TypeManager.char_type) ||
667                                 (t.IsSubclassOf (TypeManager.enum_type)) ||
668                                 (t == TypeManager.float_type) ||
669                                 (t == TypeManager.double_type);
670                 }
671                         
672                 Expression ResolveOperator (TypeContainer tc)
673                 {
674                         Type expr_type = expr.Type;
675
676                         //
677                         // Step 1: Perform Operator Overload location
678                         //
679                         Expression mg;
680                         string op_name;
681                                 
682                         if (oper == Operator.PostIncrement || oper == Operator.PreIncrement)
683                                 op_name = "op_Increment";
684                         else if (oper == Operator.PostDecrement || oper == Operator.PreDecrement)
685                                 op_name = "op_Decrement";
686                         else
687                                 op_name = "op_" + oper;
688
689                         mg = MemberLookup (tc.RootContext, expr_type, op_name, false);
690                         
691                         if (mg != null) {
692                                 Arguments = new ArrayList ();
693                                 Arguments.Add (new Argument (expr, Argument.AType.Expression));
694                                 
695                                 method = Invocation.OverloadResolve ((MethodGroupExpr) mg, Arguments);
696                                 if (method != null)
697                                         return this;
698                         }
699
700                         //
701                         // Step 2: Default operations on CLI native types.
702                         //
703
704                         // Only perform numeric promotions on:
705                         // +, -, ++, --
706
707                         if (expr_type == null)
708                                 return null;
709                         
710                         if (oper == Operator.Negate && expr_type != TypeManager.bool_type) {
711                                 report23 (tc.RootContext.Report, expr.Type);
712                                 return null;
713                         } else {
714                                 expr = ForceConversion (expr, TypeManager.int32_type);
715                                 type = TypeManager.int32_type;
716                         }
717                         
718                         if (oper == Operator.BitComplement) {
719                                 if (!((expr_type == TypeManager.int32_type) ||
720                                       (expr_type == TypeManager.uint32_type) ||
721                                       (expr_type == TypeManager.int64_type) ||
722                                       (expr_type == TypeManager.uint64_type) ||
723                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
724                                         report23 (tc.RootContext.Report, expr.Type);
725                                         return null;
726                                 }
727                                 
728                                 return this;
729                         }
730
731                         if (oper == Operator.Add) {
732                                 //
733                                 // A plus in front of something is just a no-op, so return the child.
734                                 //
735                                 return expr;
736                         }
737
738                         if (oper == Operator.Subtract){
739                                 //
740                                 // Fold -Constant into a negative constant
741                                 
742                         
743                                 Expression e = null;
744                                 
745                                 if (expr is IntLiteral)
746                                         e = new IntLiteral (-((IntLiteral) expr).Value);
747                                 else if (expr is LongLiteral)
748                                         e = new LongLiteral (-((LongLiteral) expr).Value);
749                                 else if (expr is FloatLiteral)
750                                         e = new FloatLiteral (-((FloatLiteral) expr).Value);
751
752                                 if (e != null){
753                                         e = e.Resolve (tc);
754                                         return e;
755                                 }
756
757                                 report23 (tc.RootContext.Report, expr.Type);
758                                 return null;
759                         }
760
761                         //
762                         // The operand of the prefix/postfix increment decrement operators
763                         // should be an expression that is classified as a variable,
764                         // a property access or an indexer access
765                         //
766                         if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
767                             oper == Operator.PostDecrement || oper == Operator.PostIncrement){
768                                 if (expr.ExprClass == ExprClass.Variable){
769                                         if (IsIncrementableNumber (expr_type) ||
770                                             expr_type == TypeManager.decimal_type)
771                                                 return this;
772                                 } else if (expr.ExprClass == ExprClass.IndexerAccess){
773                                         //
774                                         // FIXME: Verify that we have both get and set methods
775                                         //
776                                         throw new Exception ("Implement me");
777                                 } else if (expr.ExprClass == ExprClass.PropertyAccess){
778                                         //
779                                         // FIXME: Verify that we have both get and set methods
780                                         //
781                                         throw new Exception ("Implement me");
782                                 } else {
783                                         report118 (tc, expr, "variable, indexer or property access");
784                                 }
785                         }
786
787                         tc.RootContext.Report.Error (187, "No such operator '" + OperName () +
788                                                      "' defined for type '" +
789                                                      TypeManager.CSharpName (expr_type) + "'");
790                         return null;
791
792                 }
793
794                 public override Expression Resolve (TypeContainer tc)
795                 {
796                         expr = expr.Resolve (tc);
797
798                         if (expr == null)
799                                 return null;
800                         
801                         return ResolveOperator (tc);
802                 }
803
804                 public override bool Emit (EmitContext ec)
805                 {
806                         ILGenerator ig = ec.ig;
807                         Type expr_type = expr.Type;
808
809                         if (method != null) {
810
811                                 // Note that operators are static anyway
812                                 
813                                 if (Arguments != null) 
814                                         Invocation.EmitArguments (ec, method, Arguments);
815                                 
816                                 if (method is MethodInfo)
817                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
818                                 else
819                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
820                                 
821                                 return true;
822                         }
823                         
824                         switch (oper){
825                         case Operator.Add:
826                                 throw new Exception ("This should be caught by Resolve");
827
828                         case Operator.Subtract:
829                                 throw new Exception ("THis should have been caught by Resolve");
830                                 
831                         case Operator.Negate:
832                                 expr.Emit (ec);
833                                 ig.Emit (OpCodes.Ldc_I4_0);
834                                 ig.Emit (OpCodes.Ceq);
835                                 break;
836
837                         case Operator.BitComplement:
838                                 expr.Emit (ec);
839                                 ig.Emit (OpCodes.Not);
840                                 break;
841
842                         case Operator.AddressOf:
843                                 throw new Exception ("Not implemented yet");
844
845                         case Operator.Indirection:
846                                 throw new Exception ("Not implemented yet");
847
848                         case Operator.PreIncrement:
849                         case Operator.PreDecrement:
850                                 if (expr.ExprClass == ExprClass.Variable){
851                                         if (expr_type == TypeManager.decimal_type){
852                                                 throw new Exception ("FIXME: Add pre inc/dec for decimals");
853                                         } else {
854                                                 //
855                                                 // Resolve already verified that it is an "incrementable"
856                                                 // 
857                                                 expr.Emit (ec);
858                                                 ig.Emit (OpCodes.Ldc_I4_1);
859
860                                                 if (oper == Operator.PreDecrement)
861                                                         ig.Emit (OpCodes.Sub);
862                                                 else
863                                                         ig.Emit (OpCodes.Add);
864                                                 ((LValue) expr).Store (ig);
865                                                 ig.Emit (OpCodes.Dup);
866                                         } 
867                                 } else {
868                                         throw new Exception ("Handle Indexers and Properties here");
869                                 }
870                                 break;
871                                 
872                         case Operator.PostIncrement:
873                         case Operator.PostDecrement:
874                                 if (expr.ExprClass == ExprClass.Variable){
875                                         if (expr_type == TypeManager.decimal_type){
876                                                 throw new Exception ("FIXME: Add pre inc/dec for decimals");
877                                         } else {
878                                                 //
879                                                 // Resolve already verified that it is an "incrementable"
880                                                 // 
881                                                 expr.Emit (ec);
882                                                 ig.Emit (OpCodes.Dup);
883                                                 ig.Emit (OpCodes.Ldc_I4_1);
884
885                                                 if (oper == Operator.PostDecrement)
886                                                         ig.Emit (OpCodes.Sub);
887                                                 else
888                                                         ig.Emit (OpCodes.Add);
889                                                 ((LValue) expr).Store (ig);
890                                         } 
891                                 } else {
892                                         throw new Exception ("Handle Indexers and Properties here");
893                                 }
894                                 break;
895                                 
896                         default:
897                                 throw new Exception ("This should not happen: Operator = "
898                                                      + oper.ToString ());
899                         }
900
901                         //
902                         // yes, we leave a value on the stack
903                         //
904                         return true;
905                 }
906                 
907         }
908         
909         public class Probe : Expression {
910                 string probe_type;
911                 Expression expr;
912                 Operator oper;
913
914                 public enum Operator {
915                         Is, As
916                 }
917                 
918                 public Probe (Operator oper, Expression expr, string probe_type)
919                 {
920                         this.oper = oper;
921                         this.probe_type = probe_type;
922                         this.expr = expr;
923                 }
924
925                 public Operator Oper {
926                         get {
927                                 return oper;
928                         }
929                 }
930
931                 public Expression Expr {
932                         get {
933                                 return expr;
934                         }
935                 }
936
937                 public string ProbeType {
938                         get {
939                                 return probe_type;
940                         }
941                 }
942
943                 public override Expression Resolve (TypeContainer tc)
944                 {
945                         // FIXME: Implement;
946                         throw new Exception ("Unimplemented");
947                         // return this;
948                 }
949
950                 public override bool Emit (EmitContext ec)
951                 {
952                         return true;
953                 }
954         }
955         
956         public class Cast : Expression {
957                 string target_type;
958                 Expression expr;
959                 
960                 public Cast (string cast_type, Expression expr)
961                 {
962                         this.target_type = cast_type;
963                         this.expr = expr;
964                 }
965
966                 public string TargetType {
967                         get {
968                                 return target_type;
969                         }
970                 }
971
972                 public Expression Expr {
973                         get {
974                                 return expr;
975                         }
976                         set {
977                                 expr = value;
978                         }
979                 }
980                 
981                 public override Expression Resolve (TypeContainer tc)
982                 {
983                         type = tc.LookupType (target_type, false);
984                         eclass = ExprClass.Value;
985                         
986                         if (type == null)
987                                 return null;
988
989                         //
990                         // FIXME: Unimplemented
991                         //
992                         throw new Exception ("FINISH ME");
993                 }
994
995                 public override bool Emit (EmitContext ec)
996                 {
997                         return true;
998                 }
999         }
1000
1001         public class Binary : Expression {
1002                 public enum Operator {
1003                         Multiply, Divide, Modulo,
1004                         Add, Subtract,
1005                         ShiftLeft, ShiftRight,
1006                         LessThan, GreaterThan, LessOrEqual, GreaterOrEqual, 
1007                         Equal, NotEqual,
1008                         BitwiseAnd,
1009                         ExclusiveOr,
1010                         BitwiseOr,
1011                         LogicalAnd,
1012                         LogicalOr
1013                 }
1014
1015                 Operator oper;
1016                 Expression left, right;
1017                 MethodBase method;
1018                 ArrayList  Arguments;
1019                 
1020
1021                 public Binary (Operator oper, Expression left, Expression right)
1022                 {
1023                         this.oper = oper;
1024                         this.left = left;
1025                         this.right = right;
1026                 }
1027
1028                 public Operator Oper {
1029                         get {
1030                                 return oper;
1031                         }
1032                         set {
1033                                 oper = value;
1034                         }
1035                 }
1036                 
1037                 public Expression Left {
1038                         get {
1039                                 return left;
1040                         }
1041                         set {
1042                                 left = value;
1043                         }
1044                 }
1045
1046                 public Expression Right {
1047                         get {
1048                                 return right;
1049                         }
1050                         set {
1051                                 right = value;
1052                         }
1053                 }
1054
1055
1056                 // <summary>
1057                 //   Returns a stringified representation of the Operator
1058                 // </summary>
1059                 string OperName ()
1060                 {
1061                         switch (oper){
1062                         case Operator.Multiply:
1063                                 return "*";
1064                         case Operator.Divide:
1065                                 return "/";
1066                         case Operator.Modulo:
1067                                 return "%";
1068                         case Operator.Add:
1069                                 return "+";
1070                         case Operator.Subtract:
1071                                 return "-";
1072                         case Operator.ShiftLeft:
1073                                 return "<<";
1074                         case Operator.ShiftRight:
1075                                 return ">>";
1076                         case Operator.LessThan:
1077                                 return "<";
1078                         case Operator.GreaterThan:
1079                                 return ">";
1080                         case Operator.LessOrEqual:
1081                                 return "<=";
1082                         case Operator.GreaterOrEqual:
1083                                 return ">=";
1084                         case Operator.Equal:
1085                                 return "==";
1086                         case Operator.NotEqual:
1087                                 return "!=";
1088                         case Operator.BitwiseAnd:
1089                                 return "&";
1090                         case Operator.BitwiseOr:
1091                                 return "|";
1092                         case Operator.ExclusiveOr:
1093                                 return "^";
1094                         case Operator.LogicalOr:
1095                                 return "||";
1096                         case Operator.LogicalAnd:
1097                                 return "&&";
1098                         }
1099
1100                         return oper.ToString ();
1101                 }
1102
1103                 Expression ForceConversion (Expression expr, Type target_type)
1104                 {
1105                         if (expr.Type == target_type)
1106                                 return expr;
1107
1108                         return ConvertImplicit (expr, target_type);
1109                 }
1110                 
1111                 //
1112                 // Note that handling the case l == Decimal || r == Decimal
1113                 // is taken care of by the Step 1 Operator Overload resolution.
1114                 //
1115                 void DoNumericPromotions (TypeContainer tc, Type l, Type r)
1116                 {
1117                         if (l == TypeManager.double_type || r == TypeManager.double_type){
1118                                 //
1119                                 // If either operand is of type double, the other operand is
1120                                 // conveted to type double.
1121                                 //
1122                                 if (r != TypeManager.double_type)
1123                                         right = ConvertImplicit (right, TypeManager.double_type);
1124                                 if (l != TypeManager.double_type)
1125                                         left = ConvertImplicit (left, TypeManager.double_type);
1126                                 
1127                                 type = TypeManager.double_type;
1128                         } else if (l == TypeManager.float_type || r == TypeManager.float_type){
1129                                 //
1130                                 // if either operand is of type float, th eother operand is
1131                                 // converd to type float.
1132                                 //
1133                                 if (r != TypeManager.double_type)
1134                                         right = ConvertImplicit (right, TypeManager.float_type);
1135                                 if (l != TypeManager.double_type)
1136                                         left = ConvertImplicit (left, TypeManager.float_type);
1137                                 type = TypeManager.float_type;
1138                         } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
1139                                 //
1140                                 // If either operand is of type ulong, the other operand is
1141                                 // converted to type ulong.  or an error ocurrs if the other
1142                                 // operand is of type sbyte, short, int or long
1143                                 //
1144                                 Type other = null;
1145                                 
1146                                 if (l == TypeManager.uint64_type)
1147                                         other = r;
1148                                 else if (r == TypeManager.uint64_type)
1149                                         other = l;
1150
1151                                 if ((other == TypeManager.sbyte_type) ||
1152                                     (other == TypeManager.short_type) ||
1153                                     (other == TypeManager.int32_type) ||
1154                                     (other == TypeManager.int64_type)){
1155                                         string oper = OperName ();
1156                                         
1157                                         tc.RootContext.Report.Error (34, "Operator `" + OperName ()
1158                                                                      + "' is ambiguous on operands of type `"
1159                                                                      + TypeManager.CSharpName (l) + "' "
1160                                                                      + "and `" + TypeManager.CSharpName (r)
1161                                                                      + "'");
1162                                 }
1163                                 type = TypeManager.uint64_type;
1164                         } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
1165                                 //
1166                                 // If either operand is of type long, the other operand is converted
1167                                 // to type long.
1168                                 //
1169                                 if (l != TypeManager.int64_type)
1170                                         left = ConvertImplicit (left, TypeManager.int64_type);
1171                                 if (r != TypeManager.int64_type)
1172                                         right = ConvertImplicit (right, TypeManager.int64_type);
1173
1174                                 type = TypeManager.int64_type;
1175                         } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
1176                                 //
1177                                 // If either operand is of type uint, and the other
1178                                 // operand is of type sbyte, short or int, othe operands are
1179                                 // converted to type long.
1180                                 //
1181                                 Type other = null;
1182                                 
1183                                 if (l == TypeManager.uint32_type)
1184                                         other = r;
1185                                 else if (r == TypeManager.uint32_type)
1186                                         other = l;
1187
1188                                 if ((other == TypeManager.sbyte_type) ||
1189                                     (other == TypeManager.short_type) ||
1190                                     (other == TypeManager.int32_type)){
1191                                         left = ForceConversion (left, TypeManager.int64_type);
1192                                         right = ForceConversion (right, TypeManager.int64_type);
1193                                         type = TypeManager.int64_type;
1194                                 } else {
1195                                         //
1196                                         // if either operand is of type uint, the other
1197                                         // operand is converd to type uint
1198                                         //
1199                                         left = ForceConversion (left, TypeManager.uint32_type);
1200                                         right = ForceConversion (left, TypeManager.uint32_type);
1201                                         type = TypeManager.uint32_type;
1202                                 } 
1203                         } else {
1204                                 left = ForceConversion (left, TypeManager.int32_type);
1205                                 right = ForceConversion (right, TypeManager.int32_type);
1206                                 type = TypeManager.int32_type;
1207                         }
1208                 }
1209
1210                 void error19 (TypeContainer tc)
1211                 {
1212                         tc.RootContext.Report.Error (
1213                                 19,
1214                                 "Operator " + OperName () + " cannot be applied to operands of type `" +
1215                                 TypeManager.CSharpName (left.Type) + "' and `" +
1216                                 TypeManager.CSharpName (right.Type) + "'");
1217                                                      
1218                 }
1219                 
1220                 Expression CheckShiftArguments (TypeContainer tc)
1221                 {
1222                         Expression e;
1223                         Type l = left.Type;
1224                         Type r = right.Type;
1225
1226                         e = ForceConversion (right, TypeManager.int32_type);
1227                         if (e == null){
1228                                 error19 (tc);
1229                                 return null;
1230                         }
1231                         right = e;
1232
1233                         if (((e = ConvertImplicit (left, TypeManager.int32_type)) != null) ||
1234                             ((e = ConvertImplicit (left, TypeManager.uint32_type)) != null) ||
1235                             ((e = ConvertImplicit (left, TypeManager.int64_type)) != null) ||
1236                             ((e = ConvertImplicit (left, TypeManager.uint64_type)) != null)){
1237                                 left = e;
1238
1239                                 return this;
1240                         }
1241                         error19 (tc);
1242                         return null;
1243                 }
1244                 
1245                 Expression ResolveOperator (TypeContainer tc)
1246                 {
1247                         Type l = left.Type;
1248                         Type r = right.Type;
1249
1250                         //
1251                         // Step 1: Perform Operator Overload location
1252                         //
1253                         Expression left_expr, right_expr;
1254                         
1255                         string op = "op_" + oper;
1256
1257                         left_expr = MemberLookup (tc.RootContext, l, op, false);
1258
1259                         right_expr = MemberLookup (tc.RootContext, r, op, false);
1260
1261                         if (left_expr != null || right_expr != null) {
1262                                 //
1263                                 // Now we need to form the union of these two sets and
1264                                 // then call OverloadResolve on that.
1265                                 //
1266                                 MethodGroupExpr left_set = null, right_set = null;
1267                                 int length1 = 0, length2 = 0;
1268
1269                                 if (left_expr != null) {
1270                                         left_set = (MethodGroupExpr) left_expr;
1271                                         length1 = left_set.Methods.Length;
1272                                 }
1273
1274                                 if (right_expr != null) {
1275                                         right_set = (MethodGroupExpr) right_expr;
1276                                         length2 = right_set.Methods.Length;
1277                                 }
1278
1279                                 MemberInfo [] mi = new MemberInfo [length1 + length2];
1280                                 if (left_set != null)
1281                                         left_set.Methods.CopyTo (mi, 0);
1282                                 if (right_set != null)
1283                                         right_set.Methods.CopyTo (mi, length1);
1284                                 
1285                                 MethodGroupExpr union = new MethodGroupExpr (mi);
1286                                 
1287                                 Arguments = new ArrayList ();
1288                                 Arguments.Add (new Argument (left, Argument.AType.Expression));
1289                                 Arguments.Add (new Argument (right, Argument.AType.Expression));
1290
1291                         
1292                                 method = Invocation.OverloadResolve (union, Arguments);
1293                                 if (method != null) 
1294                                         return this;
1295                         }
1296
1297                         //
1298                         // Step 2: Default operations on CLI native types.
1299                         //
1300                         
1301                         // Only perform numeric promotions on:
1302                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
1303                         //
1304                         if (oper == Operator.ShiftLeft || oper == Operator.ShiftRight){
1305                                 return CheckShiftArguments (tc);
1306                         } else if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
1307
1308                                 if (l != TypeManager.bool_type || r != TypeManager.bool_type)
1309                                         error19 (tc);
1310                         } else
1311                                 DoNumericPromotions (tc, l, r);
1312
1313                         if (left == null || right == null)
1314                                 return null;
1315
1316                         if (oper == Operator.BitwiseAnd ||
1317                             oper == Operator.BitwiseOr ||
1318                             oper == Operator.ExclusiveOr){
1319                                 if (!((l == TypeManager.int32_type) ||
1320                                       (l == TypeManager.uint32_type) ||
1321                                       (l == TypeManager.int64_type) ||
1322                                       (l == TypeManager.uint64_type))){
1323                                         error19 (tc);
1324                                         return null;
1325                                 }
1326                         }
1327
1328                         if (oper == Operator.Equal ||
1329                             oper == Operator.NotEqual ||
1330                             oper == Operator.LessOrEqual ||
1331                             oper == Operator.LessThan ||
1332                             oper == Operator.GreaterOrEqual ||
1333                             oper == Operator.GreaterThan){
1334                                 type = TypeManager.bool_type;
1335                         }
1336                         
1337                         return this;
1338                 }
1339                 
1340                 public override Expression Resolve (TypeContainer tc)
1341                 {
1342                         left = left.Resolve (tc);
1343                         right = right.Resolve (tc);
1344
1345                         if (left == null || right == null)
1346                                 return null;
1347
1348                         return ResolveOperator (tc);
1349                 }
1350
1351                 public bool IsBranchable ()
1352                 {
1353                         if (oper == Operator.Equal ||
1354                             oper == Operator.NotEqual ||
1355                             oper == Operator.LessThan ||
1356                             oper == Operator.GreaterThan ||
1357                             oper == Operator.LessOrEqual ||
1358                             oper == Operator.GreaterOrEqual){
1359                                 return true;
1360                         } else
1361                                 return false;
1362                 }
1363
1364                 // <summary>
1365                 //   This entry point is used by routines that might want
1366                 //   to emit a brfalse/brtrue after an expression, and instead
1367                 //   they could use a more compact notation.
1368                 //
1369                 //   Typically the code would generate l.emit/r.emit, followed
1370                 //   by the comparission and then a brtrue/brfalse.  The comparissions
1371                 //   are sometimes inneficient (there are not as complete as the branches
1372                 //   look for the hacks in Emit using double ceqs).
1373                 //
1374                 //   So for those cases we provide EmitBranchable that can emit the
1375                 //   branch with the test
1376                 // </summary>
1377                 public void EmitBranchable (EmitContext ec, int target)
1378                 {
1379                         OpCode opcode;
1380                         bool close_target = false;
1381                         
1382                         left.Emit (ec);
1383                         right.Emit (ec);
1384                         
1385                         switch (oper){
1386                         case Operator.Equal:
1387                                 if (close_target)
1388                                         opcode = OpCodes.Beq_S;
1389                                 else
1390                                         opcode = OpCodes.Beq;
1391                                 break;
1392
1393                         case Operator.NotEqual:
1394                                 if (close_target)
1395                                         opcode = OpCodes.Bne_Un_S;
1396                                 else
1397                                         opcode = OpCodes.Bne_Un;
1398                                 break;
1399
1400                         case Operator.LessThan:
1401                                 if (close_target)
1402                                         opcode = OpCodes.Blt_S;
1403                                 else
1404                                         opcode = OpCodes.Blt;
1405                                 break;
1406
1407                         case Operator.GreaterThan:
1408                                 if (close_target)
1409                                         opcode = OpCodes.Bgt_S;
1410                                 else
1411                                         opcode = OpCodes.Bgt;
1412                                 break;
1413
1414                         case Operator.LessOrEqual:
1415                                 if (close_target)
1416                                         opcode = OpCodes.Ble_S;
1417                                 else
1418                                         opcode = OpCodes.Ble;
1419                                 break;
1420
1421                         case Operator.GreaterOrEqual:
1422                                 if (close_target)
1423                                         opcode = OpCodes.Bge_S;
1424                                 else
1425                                         opcode = OpCodes.Ble;
1426                                 break;
1427
1428                         default:
1429                                 throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
1430                                                      + oper.ToString ());
1431                         }
1432
1433                         ec.ig.Emit (opcode, target);
1434                 }
1435                 
1436                 public override bool Emit (EmitContext ec)
1437                 {
1438                         ILGenerator ig = ec.ig;
1439                         Type l = left.Type;
1440                         Type r = right.Type;
1441                         OpCode opcode;
1442
1443                         if (method != null) {
1444
1445                                 // Note that operators are static anyway
1446                                 
1447                                 if (Arguments != null) 
1448                                         Invocation.EmitArguments (ec, method, Arguments);
1449                                 
1450                                 if (method is MethodInfo)
1451                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
1452                                 else
1453                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1454                                 
1455                                 return true;
1456                         }
1457                         
1458                         left.Emit (ec);
1459                         right.Emit (ec);
1460
1461                         switch (oper){
1462                         case Operator.Multiply:
1463                                 if (ec.CheckState){
1464                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1465                                                 opcode = OpCodes.Mul_Ovf;
1466                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1467                                                 opcode = OpCodes.Mul_Ovf_Un;
1468                                         else
1469                                                 opcode = OpCodes.Mul;
1470                                 } else
1471                                         opcode = OpCodes.Mul;
1472
1473                                 break;
1474
1475                         case Operator.Divide:
1476                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1477                                         opcode = OpCodes.Div_Un;
1478                                 else
1479                                         opcode = OpCodes.Div;
1480                                 break;
1481
1482                         case Operator.Modulo:
1483                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1484                                         opcode = OpCodes.Rem_Un;
1485                                 else
1486                                         opcode = OpCodes.Rem;
1487                                 break;
1488
1489                         case Operator.Add:
1490                                 if (ec.CheckState){
1491                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1492                                                 opcode = OpCodes.Add_Ovf;
1493                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1494                                                 opcode = OpCodes.Add_Ovf_Un;
1495                                         else
1496                                                 opcode = OpCodes.Mul;
1497                                 } else
1498                                         opcode = OpCodes.Add;
1499                                 break;
1500
1501                         case Operator.Subtract:
1502                                 if (ec.CheckState){
1503                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1504                                                 opcode = OpCodes.Sub_Ovf;
1505                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1506                                                 opcode = OpCodes.Sub_Ovf_Un;
1507                                         else
1508                                                 opcode = OpCodes.Sub;
1509                                 } else
1510                                         opcode = OpCodes.Sub;
1511                                 break;
1512
1513                         case Operator.ShiftRight:
1514                                 opcode = OpCodes.Shr;
1515                                 break;
1516                                 
1517                         case Operator.ShiftLeft:
1518                                 opcode = OpCodes.Shl;
1519                                 break;
1520
1521                         case Operator.Equal:
1522                                 opcode = OpCodes.Ceq;
1523                                 break;
1524
1525                         case Operator.NotEqual:
1526                                 ec.ig.Emit (OpCodes.Ceq);
1527                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1528                                 
1529                                 opcode = OpCodes.Ceq;
1530                                 break;
1531
1532                         case Operator.LessThan:
1533                                 opcode = OpCodes.Clt;
1534                                 break;
1535
1536                         case Operator.GreaterThan:
1537                                 opcode = OpCodes.Cgt;
1538                                 break;
1539
1540                         case Operator.LessOrEqual:
1541                                 ec.ig.Emit (OpCodes.Cgt);
1542                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1543                                 
1544                                 opcode = OpCodes.Ceq;
1545                                 break;
1546
1547                         case Operator.GreaterOrEqual:
1548                                 ec.ig.Emit (OpCodes.Clt);
1549                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
1550                                 
1551                                 opcode = OpCodes.Sub;
1552                                 break;
1553
1554                         case Operator.LogicalOr:
1555                         case Operator.BitwiseOr:
1556                                 opcode = OpCodes.Or;
1557                                 break;
1558
1559                         case Operator.LogicalAnd:
1560                         case Operator.BitwiseAnd:
1561                                 opcode = OpCodes.And;
1562                                 break;
1563
1564                         case Operator.ExclusiveOr:
1565                                 opcode = OpCodes.Xor;
1566                                 break;
1567
1568                         default:
1569                                 throw new Exception ("This should not happen: Operator = "
1570                                                      + oper.ToString ());
1571                         }
1572
1573                         ig.Emit (opcode);
1574
1575                         return true;
1576                 }
1577         }
1578
1579         public class Conditional : Expression {
1580                 Expression expr, trueExpr, falseExpr;
1581                 
1582                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
1583                 {
1584                         this.expr = expr;
1585                         this.trueExpr = trueExpr;
1586                         this.falseExpr = falseExpr;
1587                 }
1588
1589                 public Expression Expr {
1590                         get {
1591                                 return expr;
1592                         }
1593                 }
1594
1595                 public Expression TrueExpr {
1596                         get {
1597                                 return trueExpr;
1598                         }
1599                 }
1600
1601                 public Expression FalseExpr {
1602                         get {
1603                                 return falseExpr;
1604                         }
1605                 }
1606
1607                 public override Expression Resolve (TypeContainer tc)
1608                 {
1609                         // FIXME: Implement;
1610                         throw new Exception ("Unimplemented");
1611                         // return this;
1612                 }
1613
1614                 public override bool Emit (EmitContext ec)
1615                 {
1616                         return true;
1617                 }
1618         }
1619
1620         public class SimpleName : Expression {
1621                 public readonly string Name;
1622                 public readonly Location Location;
1623                 
1624                 public SimpleName (string name, Location l)
1625                 {
1626                         Name = name;
1627                         Location = l;
1628                 }
1629
1630                 //
1631                 // Checks whether we are trying to access an instance
1632                 // property, method or field from a static body.
1633                 //
1634                 Expression MemberStaticCheck (Report r, Expression e)
1635                 {
1636                         if (e is FieldExpr){
1637                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
1638                                 
1639                                 if (!fi.IsStatic){
1640                                         r.Error (120,
1641                                                  "An object reference is required " +
1642                                                  "for the non-static field `"+Name+"'");
1643                                         return null;
1644                                 }
1645                         } else if (e is MethodGroupExpr){
1646                                 // FIXME: Pending reorganization of MemberLookup
1647                                 // Basically at this point we should have the
1648                                 // best match already selected for us, and
1649                                 // we should only have to check a *single*
1650                                 // Method for its static on/off bit.
1651                                 return e;
1652                         } else if (e is PropertyExpr){
1653                                 if (!((PropertyExpr) e).IsStatic){
1654                                         r.Error (120,
1655                                                  "An object reference is required " +
1656                                                  "for the non-static property access `"+
1657                                                  Name+"'");
1658                                         return null;
1659                                 }
1660                         }
1661
1662                         return e;
1663                 }
1664                 
1665                 //
1666                 // 7.5.2: Simple Names. 
1667                 //
1668                 // Local Variables and Parameters are handled at
1669                 // parse time, so they never occur as SimpleNames.
1670                 //
1671                 Expression ResolveSimpleName (TypeContainer tc)
1672                 {
1673                         Expression e;
1674                         Report r = tc.RootContext.Report;
1675
1676                         e = MemberLookup (tc.RootContext, tc.TypeBuilder, Name, true);
1677                         if (e != null){
1678                                 if (e is TypeExpr)
1679                                         return e;
1680                                 else if (e is FieldExpr){
1681                                         FieldExpr fe = (FieldExpr) e;
1682
1683                                         if (!fe.FieldInfo.IsStatic)
1684                                                 fe.Instance = new This ();
1685                                 }
1686                                 
1687                                 if ((tc.ModFlags & Modifiers.STATIC) != 0)
1688                                         return MemberStaticCheck (r, e);
1689                                 else
1690                                         return e;
1691                         }
1692
1693                         //
1694                         // Do step 3 of the Simple Name resolution.
1695                         //
1696                         // FIXME: implement me.
1697
1698                         r.Error (103, Location, "The name `" + Name + "' does not exist in the class `" +
1699                                  tc.Name + "'");
1700
1701                         return null;
1702                 }
1703                 
1704                 //
1705                 // SimpleName needs to handle a multitude of cases:
1706                 //
1707                 // simple_names and qualified_identifiers are placed on
1708                 // the tree equally.
1709                 //
1710                 public override Expression Resolve (TypeContainer tc)
1711                 {
1712                         if (Name.IndexOf (".") != -1)
1713                                 return ResolveMemberAccess (tc, Name);
1714                         else
1715                                 return ResolveSimpleName (tc);
1716                 }
1717
1718                 public override bool Emit (EmitContext ec)
1719                 {
1720                         throw new Exception ("SimpleNames should be gone from the tree");
1721                 }
1722         }
1723
1724         // <summary>
1725         //   A simple interface that should be implemeneted by LValues
1726         // </summary>
1727         public interface LValue {
1728                 void Store (ILGenerator ig);
1729         }
1730         
1731         public class LocalVariableReference : Expression, LValue {
1732                 public readonly string Name;
1733                 public readonly Block Block;
1734                 
1735                 public LocalVariableReference (Block block, string name)
1736                 {
1737                         Block = block;
1738                         Name = name;
1739                         eclass = ExprClass.Variable;
1740                 }
1741
1742                 public VariableInfo VariableInfo {
1743                         get {
1744                                 return Block.GetVariableInfo (Name);
1745                         }
1746                 }
1747                 
1748                 public override Expression Resolve (TypeContainer tc)
1749                 {
1750                         VariableInfo vi = Block.GetVariableInfo (Name);
1751
1752                         type = vi.VariableType;
1753                         return this;
1754                 }
1755
1756                 public override bool Emit (EmitContext ec)
1757                 {
1758                         VariableInfo vi = VariableInfo;
1759                         ILGenerator ig = ec.ig;
1760                         int idx = vi.Idx;
1761
1762                         switch (idx){
1763                         case 0:
1764                                 ig.Emit (OpCodes.Ldloc_0);
1765                                 break;
1766                                 
1767                         case 1:
1768                                 ig.Emit (OpCodes.Ldloc_1);
1769                                 break;
1770
1771                         case 2:
1772                                 ig.Emit (OpCodes.Ldloc_2);
1773                                 break;
1774
1775                         case 3:
1776                                 ig.Emit (OpCodes.Ldloc_3);
1777                                 break;
1778
1779                         default:
1780                                 if (idx < 255)
1781                                         ig.Emit (OpCodes.Ldloc_S, idx);
1782                                 else
1783                                         ig.Emit (OpCodes.Ldloc, idx);
1784                                 break;
1785                         }
1786
1787                         return true;
1788                 }
1789
1790                 public void Store (ILGenerator ig)
1791                 {
1792                         VariableInfo vi = VariableInfo;
1793                         int idx = vi.Idx;
1794                                         
1795                         switch (idx){
1796                         case 0:
1797                                 ig.Emit (OpCodes.Stloc_0);
1798                                 break;
1799                                 
1800                         case 1:
1801                                 ig.Emit (OpCodes.Stloc_1);
1802                                 break;
1803                                 
1804                         case 2:
1805                                 ig.Emit (OpCodes.Stloc_2);
1806                                 break;
1807                                 
1808                         case 3:
1809                                 ig.Emit (OpCodes.Stloc_3);
1810                                 break;
1811                                 
1812                         default:
1813                                 if (idx < 255)
1814                                         ig.Emit (OpCodes.Stloc_S, idx);
1815                                 else
1816                                         ig.Emit (OpCodes.Stloc, idx);
1817                                 break;
1818                         }
1819                 }
1820         }
1821
1822         public class ParameterReference : Expression, LValue {
1823                 public readonly Parameters Pars;
1824                 public readonly String Name;
1825                 public readonly int Idx;
1826                 
1827                 public ParameterReference (Parameters pars, int idx, string name)
1828                 {
1829                         Pars = pars;
1830                         Idx  = idx;
1831                         Name = name;
1832                         eclass = ExprClass.Variable;
1833                 }
1834
1835                 public override Expression Resolve (TypeContainer tc)
1836                 {
1837                         Type [] types = Pars.GetParameterInfo (tc);
1838
1839                         type = types [Idx];
1840
1841                         return this;
1842                 }
1843
1844                 public override bool Emit (EmitContext ec)
1845                 {
1846                         if (Idx < 255)
1847                                 ec.ig.Emit (OpCodes.Ldarg_S, Idx);
1848                         else
1849                                 ec.ig.Emit (OpCodes.Ldarg, Idx);
1850
1851                         return true;
1852                 }
1853
1854                 public void Store (ILGenerator ig)
1855                 {
1856                         if (Idx < 255)
1857                                 ig.Emit (OpCodes.Starg_S, Idx);
1858                         else
1859                                 ig.Emit (OpCodes.Starg, Idx);
1860                         
1861                 }
1862         }
1863         
1864         // <summary>
1865         //   Used for arguments to New(), Invocation()
1866         // </summary>
1867         public class Argument {
1868                 public enum AType {
1869                         Expression,
1870                         Ref,
1871                         Out
1872                 };
1873
1874                 public readonly AType Type;
1875                 Expression expr;
1876
1877                 public Argument (Expression expr, AType type)
1878                 {
1879                         this.expr = expr;
1880                         this.Type = type;
1881                 }
1882
1883                 public Expression Expr {
1884                         get {
1885                                 return expr;
1886                         }
1887                 }
1888
1889                 public bool Resolve (TypeContainer tc)
1890                 {
1891                         expr = expr.Resolve (tc);
1892
1893                         return expr != null;
1894                 }
1895
1896                 public bool Emit (EmitContext ec)
1897                 {
1898                         return expr.Emit (ec);
1899                 }
1900         }
1901
1902         // <summary>
1903         //   Invocation of methods or delegates.
1904         // </summary>
1905         public class Invocation : Expression {
1906                 public readonly ArrayList Arguments;
1907                 public readonly Location Location;
1908                 
1909                 Expression expr;
1910                 MethodBase method = null;
1911                         
1912                 static Hashtable method_parameter_cache;
1913
1914                 static Invocation ()
1915                 {
1916                         method_parameter_cache = new Hashtable ();
1917                 }
1918                         
1919                 //
1920                 // arguments is an ArrayList, but we do not want to typecast,
1921                 // as it might be null.
1922                 //
1923                 // FIXME: only allow expr to be a method invocation or a
1924                 // delegate invocation (7.5.5)
1925                 //
1926                 public Invocation (Expression expr, ArrayList arguments, Location l)
1927                 {
1928                         this.expr = expr;
1929                         Arguments = arguments;
1930                         Location = l;
1931                 }
1932
1933                 public Expression Expr {
1934                         get {
1935                                 return expr;
1936                         }
1937                 }
1938
1939                 /// <summary>
1940                 ///   Computes whether Argument `a' and the Type t of the  ParameterInfo `pi' are
1941                 ///   compatible, and if so, how good is the match (in terms of
1942                 ///   "better conversions" (7.4.2.3).
1943                 ///
1944                 ///   0   is the best possible match.
1945                 ///   -1  represents a type mismatch.
1946                 ///   -2  represents a ref/out mismatch.
1947                 /// </summary>
1948                 static int Badness (Argument a, Type t)
1949                 {
1950                         Expression argument_expr = a.Expr;
1951                         Type argument_type = argument_expr.Type;
1952
1953                         if (argument_type == null){
1954                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
1955                         }
1956                         
1957                         if (t == argument_type) 
1958                                 return 0;
1959
1960                         //
1961                         // Now probe whether an implicit constant expression conversion
1962                         // can be used.
1963                         //
1964                         // An implicit constant expression conversion permits the following
1965                         // conversions:
1966                         //
1967                         //    * A constant-expression of type `int' can be converted to type
1968                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
1969                         //      of the expression is withing the range of the destination type.
1970                         //
1971                         //    * A constant-expression of type long can be converted to type
1972                         //      ulong, provided the value of the constant expression is not negative
1973                         //
1974                         // FIXME: Note that this assumes that constant folding has
1975                         // taken place.  We dont do constant folding yet.
1976                         //
1977
1978                         if (argument_type == TypeManager.int32_type && argument_expr is IntLiteral){
1979                                 IntLiteral ei = (IntLiteral) argument_expr;
1980                                 int value = ei.Value;
1981                                 
1982                                 if (t == TypeManager.sbyte_type){
1983                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
1984                                                 return 1;
1985                                 } else if (t == TypeManager.byte_type){
1986                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
1987                                                 return 1;
1988                                 } else if (t == TypeManager.short_type){
1989                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
1990                                                 return 1;
1991                                 } else if (t == TypeManager.ushort_type){
1992                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1993                                                 return 1;
1994                                 } else if (t == TypeManager.uint32_type){
1995                                         //
1996                                         // we can optimize this case: a positive int32
1997                                         // always fits on a uint32
1998                                         //
1999                                         if (value >= 0)
2000                                                 return 1;
2001                                 } else if (t == TypeManager.uint64_type){
2002                                         //
2003                                         // we can optimize this case: a positive int32
2004                                         // always fits on a uint64
2005                                         //
2006                                         if (value >= 0)
2007                                                 return 1;
2008                                 }
2009                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
2010                                 LongLiteral ll = (LongLiteral) argument_expr;
2011                                 
2012                                 if (t == TypeManager.uint64_type){
2013                                         if (ll.Value > 0)
2014                                                 return 1;
2015                                 }
2016                         }
2017                         
2018                         // FIXME: Implement user-defined implicit conversions here.
2019                         // FIXME: Implement better conversion here.
2020                         
2021                         return -1;
2022                 }
2023
2024                 // <summary>
2025                 //   Returns the Parameters (a ParameterData interface) for the
2026                 //   Method `mb'
2027                 // </summary>
2028                 static ParameterData GetParameterData (MethodBase mb)
2029                 {
2030                         object pd = method_parameter_cache [mb];
2031
2032                         if (pd != null)
2033                                 return (ParameterData) pd;
2034
2035                         if (mb is MethodBuilder || mb is ConstructorBuilder){
2036                                 MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
2037
2038                                 InternalParameters ip = mc.ParameterInfo;
2039                                 method_parameter_cache [mb] = ip;
2040
2041                                 return (ParameterData) ip;
2042                         } else {
2043                                 ParameterInfo [] pi = mb.GetParameters ();
2044                                 ReflectionParameters rp = new ReflectionParameters (pi);
2045                                 method_parameter_cache [mb] = rp;
2046
2047                                 return (ParameterData) rp;
2048                         }
2049                 }
2050
2051                 static bool ConversionExists (Type from, Type to)
2052                 {
2053                         // FIXME : Need to implement this !
2054                         return false;
2055                 }
2056                 
2057                 // <summary>
2058                 //  Determines "better conversion" as specified in 7.4.2.3
2059                 //  Returns : 1 if a->p is better
2060                 //            0 if a->q or neither is better 
2061                 // </summary>
2062                 static int BetterConversion (Argument a, Type p, Type q)
2063                 {
2064                         
2065                         Type argument_type = a.Expr.Type;
2066                         Expression argument_expr = a.Expr;
2067
2068                         if (argument_type == null){
2069                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
2070                         }
2071
2072                         if (p == q)
2073                                 return 0;
2074
2075                         if (argument_type == p)
2076                                 return 1;
2077
2078                         if (argument_type == q)
2079                                 return 0;
2080
2081                         // Implicit conversions come here
2082
2083                         //if (ConversionExists (p, q) == true &&
2084                         //    ConversionExists (q, p) == false)
2085                         //      return 1;
2086
2087                         //
2088                         // Now probe whether an implicit constant expression conversion
2089                         // can be used.
2090                         //
2091                         // An implicit constant expression conversion permits the following
2092                         // conversions:
2093                         //
2094                         //    * A constant-expression of type `int' can be converted to type
2095                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
2096                         //      of the expression is withing the range of the destination type.
2097                         //
2098                         //    * A constant-expression of type long can be converted to type
2099                         //      ulong, provided the value of the constant expression is not negative
2100                         //
2101                         // FIXME: Note that this assumes that constant folding has
2102                         // taken place.  We dont do constant folding yet.
2103                         //
2104
2105                         if (argument_type == TypeManager.int32_type && argument_expr is IntLiteral){
2106                                 IntLiteral ei = (IntLiteral) argument_expr;
2107                                 int value = ei.Value;
2108                                 
2109                                 if (p == TypeManager.sbyte_type){
2110                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
2111                                                 return 1;
2112                                 } else if (p == TypeManager.byte_type){
2113                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
2114                                                 return 1;
2115                                 } else if (p == TypeManager.short_type){
2116                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
2117                                                 return 1;
2118                                 } else if (p == TypeManager.ushort_type){
2119                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
2120                                                 return 1;
2121                                 } else if (p == TypeManager.uint32_type){
2122                                         //
2123                                         // we can optimize this case: a positive int32
2124                                         // always fits on a uint32
2125                                         //
2126                                         if (value >= 0)
2127                                                 return 1;
2128                                 } else if (p == TypeManager.uint64_type){
2129                                         //
2130                                         // we can optimize this case: a positive int32
2131                                         // always fits on a uint64
2132                                         //
2133                                         if (value >= 0)
2134                                                 return 1;
2135                                 }
2136                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
2137                                 LongLiteral ll = (LongLiteral) argument_expr;
2138                                 
2139                                 if (p == TypeManager.uint64_type){
2140                                         if (ll.Value > 0)
2141                                                 return 1;
2142                                 }
2143                         }
2144                         
2145                         
2146                         if (p == TypeManager.sbyte_type)
2147                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
2148                                     q == TypeManager.uint32_type || q == TypeManager.uint64_type) 
2149                                         return 1;
2150
2151                         if (p == TypeManager.short_type)
2152                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
2153                                     q == TypeManager.uint64_type)
2154                                         return 1;
2155
2156                         if (p == TypeManager.int32_type)
2157                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
2158                                         return 1;
2159
2160                         if (p == TypeManager.int64_type)
2161                                 if (q == TypeManager.uint64_type)
2162                                         return 1;
2163
2164                         return 0;
2165                 }
2166                 
2167                 // <summary>
2168                 //  Determines "Better function" and returns an integer indicating :
2169                 //  0 if candidate ain't better
2170                 //  1 if candidate is better than the current best match
2171                 // </summary>
2172                 static int BetterFunction (ArrayList args, MethodBase candidate, MethodBase best)
2173                 {
2174                         ParameterData candidate_pd = GetParameterData (candidate);
2175                         ParameterData best_pd;
2176                         int argument_count;
2177
2178                         if (args == null)
2179                                 argument_count = 0;
2180                         else
2181                                 argument_count = args.Count;
2182
2183                         if (candidate_pd.Count == 0 && argument_count == 0)
2184                                 return 1;
2185
2186                         if (best == null) {
2187                                 if (candidate_pd.Count == argument_count) {
2188                                         int x = 0;
2189                                         for (int j = argument_count; j > 0;) {
2190                                                 j--;
2191                                                 
2192                                                 Argument a = (Argument) args [j];
2193                                                 
2194                                                 x = BetterConversion (a, candidate_pd.ParameterType (j), null);
2195                                                 
2196                                                 if (x > 0)
2197                                                         continue;
2198                                                 else
2199                                                         break;
2200                                         }
2201                                         
2202                                         if (x > 0)
2203                                                 return 1;
2204                                         else
2205                                                 return 0;
2206                                         
2207                                 } else
2208                                         return 0;
2209                         }
2210
2211                         best_pd = GetParameterData (best);
2212
2213                         if (candidate_pd.Count == argument_count && best_pd.Count == argument_count) {
2214                                 int rating1 = 0, rating2 = 0;
2215                                 
2216                                 for (int j = argument_count; j > 0;) {
2217                                         j--;
2218                                         int x, y;
2219                                         
2220                                         Argument a = (Argument) args [j];
2221
2222                                         x = BetterConversion (a, candidate_pd.ParameterType (j), best_pd.ParameterType (j));
2223                                         y = BetterConversion (a, best_pd.ParameterType (j), candidate_pd.ParameterType (j));
2224
2225                                         rating1 += x;
2226                                         rating2 += y;
2227                                 }
2228
2229                                 if (rating1 > rating2)
2230                                         return 1;
2231                                 else
2232                                         return 0;
2233                         } else
2234                                 return 0;
2235                         
2236                 }
2237                 
2238                 // <summary>
2239                 //   Find the Applicable Function Members (7.4.2.1)
2240                 //
2241                 //   me: Method Group expression with the members to select.
2242                 //       it might contain constructors or methods (or anything
2243                 //       that maps to a method).
2244                 //
2245                 //   Arguments: ArrayList containing resolved Argument objects.
2246                 //
2247                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
2248                 //            that is the best match of me on Arguments.
2249                 //
2250                 // </summary>
2251                 public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
2252                 {
2253                         ArrayList afm = new ArrayList ();
2254                         int best_match_idx = -1;
2255                         MethodBase method = null;
2256
2257                         for (int i = me.Methods.Length; i > 0; ){
2258                                 i--;
2259                                 MethodBase candidate  = me.Methods [i];
2260                                 int x;
2261                                 
2262                                 x = BetterFunction (Arguments, candidate, method);
2263                                 
2264                                 if (x == 0)
2265                                         continue;
2266                                 else {
2267                                         best_match_idx = i;
2268                                         method = me.Methods [best_match_idx];
2269                                 }
2270                         }
2271                         
2272                         if (best_match_idx == -1)
2273                                 return null;
2274
2275                         return method;
2276                 }
2277
2278                         
2279                 public override Expression Resolve (TypeContainer tc)
2280                 {
2281                         //
2282                         // First, resolve the expression that is used to
2283                         // trigger the invocation
2284                         //
2285                         this.expr = expr.Resolve (tc);
2286                         if (this.expr == null)
2287                                 return null;
2288
2289                         if (!(this.expr is MethodGroupExpr)){
2290                                 report118 (tc, this.expr, "method group");
2291                                 return null;
2292                         }
2293
2294                         //
2295                         // Next, evaluate all the expressions in the argument list
2296                         //
2297                         if (Arguments != null){
2298                                 for (int i = Arguments.Count; i > 0;){
2299                                         --i;
2300                                         Argument a = (Argument) Arguments [i];
2301
2302                                         if (!a.Resolve (tc))
2303                                                 return null;
2304                                 }
2305                         }
2306
2307                         method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
2308
2309                         if (method == null){
2310                                 tc.RootContext.Report.Error (-6, Location,
2311                                 "Figure out error: Can not find a good function for this argument list");
2312                                 return null;
2313                         }
2314
2315                         if (method is MethodInfo)
2316                                 type = ((MethodInfo)method).ReturnType;
2317
2318                         return this;
2319                 }
2320
2321                 public static void EmitArguments (EmitContext ec, MethodBase method, ArrayList Arguments)
2322                 {
2323                         int top;
2324
2325                         if (Arguments != null)
2326                                 top = Arguments.Count;
2327                         else
2328                                 top = 0;
2329
2330                         for (int i = 0; i < top; i++){
2331                                 Argument a = (Argument) Arguments [i];
2332
2333                                 Console.WriteLine ("Perform the actual type widening of arguments here for things like: void fn (sbyte s);  ... fn (1)");
2334                                 
2335                                 a.Emit (ec);
2336                         }
2337                 }
2338                 
2339                 public override bool Emit (EmitContext ec)
2340                 {
2341                         bool is_static = method.IsStatic;
2342
2343                         if (!is_static){
2344                                 MethodGroupExpr mg = (MethodGroupExpr) this.expr;
2345
2346                                 if (mg.InstanceExpression == null){
2347                                         throw new Exception ("Internal compiler error.  Should check in the method groups for static/instance");
2348                                 }
2349
2350                                 mg.InstanceExpression.Emit (ec);
2351                         }
2352
2353                         if (Arguments != null)
2354                                 EmitArguments (ec, method, Arguments);
2355
2356                         if (is_static){
2357                                 if (method is MethodInfo)
2358                                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
2359                                 else
2360                                         ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
2361                         } else {
2362                                 if (method is MethodInfo)
2363                                         ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
2364                                 else
2365                                         ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
2366                         }
2367
2368                         if (method is MethodInfo){
2369                                 return ((MethodInfo)method).ReturnType != TypeManager.void_type;
2370                         } else {
2371                                 //
2372                                 // Constructors do not leave any values on the stack
2373                                 //
2374                                 return false;
2375                         }
2376                 }
2377         }
2378
2379         public class New : Expression {
2380
2381                 public enum NType {
2382                         Object,
2383                         Array
2384                 };
2385
2386                 public readonly NType     NewType;
2387                 public readonly ArrayList Arguments;
2388                 public readonly string    RequestedType;
2389                 // These are for the case when we have an array
2390                 public readonly string    Rank;
2391                 public readonly ArrayList Indices;
2392                 public readonly ArrayList Initializers;
2393                 
2394                 MethodBase method = null;
2395
2396                 public New (string requested_type, ArrayList arguments)
2397                 {
2398                         RequestedType = requested_type;
2399                         Arguments = arguments;
2400                         NewType = NType.Object;
2401                 }
2402
2403                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
2404                 {
2405                         RequestedType = requested_type;
2406                         Indices       = exprs;
2407                         Rank          = rank;
2408                         Initializers  = initializers;
2409                         NewType       = NType.Array;
2410                 }
2411                 
2412                 public override Expression Resolve (TypeContainer tc)
2413                 {
2414                         type = tc.LookupType (RequestedType, false);
2415
2416                         if (type == null)
2417                                 return null;
2418
2419                         Expression ml;
2420
2421                         ml = MemberLookup (tc.RootContext, type, ".ctor", false,
2422                                            MemberTypes.Constructor, AllBindingsFlags);
2423
2424                         if (! (ml is MethodGroupExpr)){
2425                                 //
2426                                 // FIXME: Find proper error
2427                                 //
2428                                 report118 (tc, ml, "method group");
2429                                 return null;
2430                         }
2431                         
2432                         if (Arguments != null){
2433                                 for (int i = Arguments.Count; i > 0;){
2434                                         --i;
2435                                         Argument a = (Argument) Arguments [i];
2436
2437                                         if (!a.Resolve (tc))
2438                                                 return null;
2439                                 }
2440                         }
2441
2442                         method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
2443
2444                         if (method == null) {
2445                                 tc.RootContext.Report.Error (-6,
2446                                 "New invocation: Can not find a constructor for this argument list");
2447                                 return null;
2448                         }
2449
2450                         return this;
2451                 }
2452
2453                 public override bool Emit (EmitContext ec)
2454                 {
2455                         Invocation.EmitArguments (ec, method, Arguments);
2456                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
2457                         return true;
2458                 }
2459         }
2460
2461         //
2462         // Represents the `this' construct
2463         //
2464         public class This : Expression, LValue {
2465                 public override Expression Resolve (TypeContainer tc)
2466                 {
2467                         eclass = ExprClass.Variable;
2468                         type = tc.TypeBuilder;
2469
2470                         //
2471                         // FIXME: Verify that this is only used in instance contexts.
2472                         //
2473                         return this;
2474                 }
2475
2476                 public override bool Emit (EmitContext ec)
2477                 {
2478                         ec.ig.Emit (OpCodes.Ldarg_0);
2479                         return true;
2480                 }
2481
2482                 public void Store (ILGenerator ig)
2483                 {
2484                         //
2485                         // Assignment to the "this" variable
2486                         //
2487                         ig.Emit (OpCodes.Starg, 0);
2488                 }
2489         }
2490
2491         public class TypeOf : Expression {
2492                 public readonly string QueriedType;
2493                 
2494                 public TypeOf (string queried_type)
2495                 {
2496                         QueriedType = queried_type;
2497                 }
2498
2499                 public override Expression Resolve (TypeContainer tc)
2500                 {
2501                         type = tc.LookupType (QueriedType, false);
2502
2503                         if (type == null)
2504                                 return null;
2505                         
2506                         eclass = ExprClass.Type;
2507                         return this;
2508                 }
2509
2510                 public override bool Emit (EmitContext ec)
2511                 {
2512                         throw new Exception ("Implement me");
2513                         // FIXME: Implement.
2514                 }
2515         }
2516
2517         public class SizeOf : Expression {
2518                 public readonly string QueriedType;
2519                 
2520                 public SizeOf (string queried_type)
2521                 {
2522                         this.QueriedType = queried_type;
2523                 }
2524
2525                 public override Expression Resolve (TypeContainer tc)
2526                 {
2527                         // FIXME: Implement;
2528                         throw new Exception ("Unimplemented");
2529                         // return this;
2530                 }
2531
2532                 public override bool Emit (EmitContext ec)
2533                 {
2534                         throw new Exception ("Implement me");
2535                 }
2536         }
2537
2538         public class MemberAccess : Expression {
2539                 public readonly string Identifier;
2540                 Expression expr;
2541                 Expression member_lookup;
2542                 
2543                 public MemberAccess (Expression expr, string id)
2544                 {
2545                         this.expr = expr;
2546                         Identifier = id;
2547                 }
2548
2549                 public Expression Expr {
2550                         get {
2551                                 return expr;
2552                         }
2553                 }
2554                 
2555                 public override Expression Resolve (TypeContainer tc)
2556                 {
2557                         Expression new_expression = expr.Resolve (tc);
2558
2559                         if (new_expression == null)
2560                                 return null;
2561
2562                         member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
2563
2564                         if (member_lookup is MethodGroupExpr){
2565                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
2566
2567                                 //
2568                                 // Bind the instance expression to it
2569                                 //
2570                                 // FIXME: This is a horrible way of detecting if it is
2571                                 // an instance expression.  Figure out how to fix this.
2572                                 //
2573
2574                                 if (expr is LocalVariableReference ||
2575                                     expr is ParameterReference ||
2576                                     expr is FieldExpr)
2577                                         mg.InstanceExpression = expr;
2578                                         
2579                                 return member_lookup;
2580                         } else if (member_lookup is FieldExpr){
2581                                 FieldExpr fe = (FieldExpr) member_lookup;
2582
2583                                 fe.Instance = expr;
2584
2585                                 return member_lookup;
2586                         } else
2587                                 //
2588                                 // FIXME: This should generate the proper node
2589                                 // ie, for a Property Access, it should like call it
2590                                 // and stuff.
2591
2592                                 return member_lookup;
2593                 }
2594
2595                 public override bool Emit (EmitContext ec)
2596                 {
2597                         throw new Exception ("Implement me");
2598                 }
2599
2600         }
2601
2602         // <summary>
2603         //   Nodes of type Namespace are created during the semantic
2604         //   analysis to resolve member_access/qualified_identifier/simple_name
2605         //   accesses.
2606         //
2607         //   They are born `resolved'. 
2608         // </summary>
2609         public class NamespaceExpr : Expression {
2610                 public readonly string Name;
2611                 
2612                 public NamespaceExpr (string name)
2613                 {
2614                         Name = name;
2615                         eclass = ExprClass.Namespace;
2616                 }
2617
2618                 public override Expression Resolve (TypeContainer tc)
2619                 {
2620                         return this;
2621                 }
2622
2623                 public override bool Emit (EmitContext ec)
2624                 {
2625                         throw new Exception ("Namespace expressions should never be emitted");
2626                 }
2627         }
2628
2629         // <summary>
2630         //   Fully resolved expression that evaluates to a type
2631         // </summary>
2632         public class TypeExpr : Expression {
2633                 public TypeExpr (Type t)
2634                 {
2635                         Type = t;
2636                         eclass = ExprClass.Type;
2637                 }
2638
2639                 override public Expression Resolve (TypeContainer tc)
2640                 {
2641                         return this;
2642                 }
2643
2644                 override public bool Emit (EmitContext ec)
2645                 {
2646                         throw new Exception ("Implement me");
2647                 }
2648         }
2649
2650         // <summary>
2651         //   MethodGroup Expression.
2652         //  
2653         //   This is a fully resolved expression that evaluates to a type
2654         // </summary>
2655         public class MethodGroupExpr : Expression {
2656                 public readonly MethodBase [] Methods;
2657                 Expression instance_expression = null;
2658                 
2659                 public MethodGroupExpr (MemberInfo [] mi)
2660                 {
2661                         Methods = new MethodBase [mi.Length];
2662                         mi.CopyTo (Methods, 0);
2663                         eclass = ExprClass.MethodGroup;
2664                 }
2665
2666                 //
2667                 // `A method group may have associated an instance expression' 
2668                 // 
2669                 public Expression InstanceExpression {
2670                         get {
2671                                 return instance_expression;
2672                         }
2673
2674                         set {
2675                                 instance_expression = value;
2676                         }
2677                 }
2678                 
2679                 override public Expression Resolve (TypeContainer tc)
2680                 {
2681                         return this;
2682                 }
2683
2684                 override public bool Emit (EmitContext ec)
2685                 {
2686                         throw new Exception ("This should never be reached");
2687                 }
2688         }
2689         
2690         public class BuiltinTypeAccess : Expression {
2691                 public readonly string AccessBase;
2692                 public readonly string Method;
2693                 
2694                 public BuiltinTypeAccess (string type, string method)
2695                 {
2696                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
2697                         AccessBase = type;
2698                         Method = method;
2699                 }
2700
2701                 public override Expression Resolve (TypeContainer tc)
2702                 {
2703                         // FIXME: Implement;
2704                         throw new Exception ("Unimplemented");
2705                         // return this;
2706                 }
2707
2708                 public override bool Emit (EmitContext ec)
2709                 {
2710                         throw new Exception ("Unimplemented");
2711                 }
2712         }
2713
2714
2715         //   Fully resolved expression that evaluates to a Field
2716         // </summary>
2717         public class FieldExpr : Expression, LValue {
2718                 public readonly FieldInfo FieldInfo;
2719                 public Expression Instance;
2720                         
2721                 public FieldExpr (FieldInfo fi)
2722                 {
2723                         FieldInfo = fi;
2724                         eclass = ExprClass.Variable;
2725                         type = fi.FieldType;
2726                 }
2727
2728                 override public Expression Resolve (TypeContainer tc)
2729                 {
2730                         if (!FieldInfo.IsStatic){
2731                                 if (Instance == null){
2732                                         throw new Exception ("non-static FieldExpr without instance var\n" +
2733                                                              "You have to assign the Instance variable\n" +
2734                                                              "Of the FieldExpr to set this\n");
2735                                 }
2736
2737                                 Instance = Instance.Resolve (tc);
2738                                 if (Instance == null)
2739                                         return null;
2740                                 
2741                         }
2742                         return this;
2743                 }
2744
2745                 override public bool Emit (EmitContext ec)
2746                 {
2747                         ILGenerator ig = ec.ig;
2748
2749                         if (FieldInfo.IsStatic)
2750                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2751                         else {
2752                                 Instance.Emit (ec);
2753                                 
2754                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
2755                         }
2756
2757                         return true;
2758                 }
2759
2760                 public void Store (ILGenerator ig)
2761                 {
2762                         if (FieldInfo.IsStatic)
2763                                 ig.Emit (OpCodes.Stsfld, FieldInfo);
2764                         else
2765                                 ig.Emit (OpCodes.Stfld, FieldInfo);
2766                 }
2767         }
2768         
2769         // <summary>
2770         //   Fully resolved expression that evaluates to a Property
2771         // </summary>
2772         public class PropertyExpr : Expression {
2773                 public readonly PropertyInfo PropertyInfo;
2774                 public readonly bool IsStatic;
2775                 
2776                 public PropertyExpr (PropertyInfo pi)
2777                 {
2778                         PropertyInfo = pi;
2779                         eclass = ExprClass.PropertyAccess;
2780                         IsStatic = false;
2781                                 
2782                         MethodBase [] acc = pi.GetAccessors ();
2783
2784                         for (int i = 0; i < acc.Length; i++)
2785                                 if (acc [i].IsStatic)
2786                                         IsStatic = true;
2787
2788                         type = pi.PropertyType;
2789                 }
2790
2791                 override public Expression Resolve (TypeContainer tc)
2792                 {
2793                         // We are born in resolved state. 
2794                         return this;
2795                 }
2796
2797                 override public bool Emit (EmitContext ec)
2798                 {
2799                         // FIXME: Implement;
2800                         throw new Exception ("Unimplemented");
2801                 }
2802         }
2803
2804         // <summary>
2805         //   Fully resolved expression that evaluates to a Property
2806         // </summary>
2807         public class EventExpr : Expression {
2808                 public readonly EventInfo EventInfo;
2809                 
2810                 public EventExpr (EventInfo ei)
2811                 {
2812                         EventInfo = ei;
2813                         eclass = ExprClass.EventAccess;
2814                 }
2815
2816                 override public Expression Resolve (TypeContainer tc)
2817                 {
2818                         // We are born in resolved state. 
2819                         return this;
2820                 }
2821
2822                 override public bool Emit (EmitContext ec)
2823                 {
2824                         throw new Exception ("Implement me");
2825                         // FIXME: Implement.
2826                 }
2827         }
2828         
2829         public class CheckedExpr : Expression {
2830
2831                 public Expression Expr;
2832
2833                 public CheckedExpr (Expression e)
2834                 {
2835                         Expr = e;
2836                 }
2837
2838                 public override Expression Resolve (TypeContainer tc)
2839                 {
2840                         Expr = Expr.Resolve (tc);
2841
2842                         if (Expr == null)
2843                                 return null;
2844
2845                         eclass = Expr.ExprClass;
2846                         type = Expr.Type;
2847                         return this;
2848                 }
2849
2850                 public override bool Emit (EmitContext ec)
2851                 {
2852                         bool last_check = ec.CheckState;
2853                         bool v;
2854                         
2855                         ec.CheckState = true;
2856                         
2857                         v = Expr.Emit (ec);
2858
2859                         ec.CheckState = last_check;
2860
2861                         return v;
2862                 }
2863                 
2864         }
2865
2866         public class UnCheckedExpr : Expression {
2867
2868                 public Expression Expr;
2869
2870                 public UnCheckedExpr (Expression e)
2871                 {
2872                         Expr = e;
2873                 }
2874
2875                 public override Expression Resolve (TypeContainer tc)
2876                 {
2877                         Expr = Expr.Resolve (tc);
2878
2879                         if (Expr == null)
2880                                 return null;
2881
2882                         eclass = Expr.ExprClass;
2883                         type = Expr.Type;
2884                         return this;
2885                 }
2886
2887                 public override bool Emit (EmitContext ec)
2888                 {
2889                         bool last_check = ec.CheckState;
2890                         bool v;
2891                         
2892                         ec.CheckState = false;
2893                         
2894                         v = Expr.Emit (ec);
2895
2896                         ec.CheckState = last_check;
2897
2898                         return v;
2899                 }
2900                 
2901         }
2902         
2903         public class ElementAccess : Expression {
2904                 
2905                 public readonly ArrayList  Arguments;
2906                 public readonly Expression Expr;
2907                 
2908                 public ElementAccess (Expression e, ArrayList e_list)
2909                 {
2910                         Expr = e;
2911                         Arguments = e_list;
2912                 }
2913
2914                 public override Expression Resolve (TypeContainer tc)
2915                 {
2916                         // FIXME: Implement;
2917                         throw new Exception ("Unimplemented");
2918                         // return this;
2919                 }
2920                 
2921                 public override bool Emit (EmitContext ec)
2922                 {
2923                         // FIXME : Implement !
2924                         throw new Exception ("Unimplemented");
2925                 }
2926                 
2927         }
2928         
2929         public class BaseAccess : Expression {
2930
2931                 public enum BaseAccessType {
2932                         Member,
2933                         Indexer
2934                 };
2935                 
2936                 public readonly BaseAccessType BAType;
2937                 public readonly string         Member;
2938                 public readonly ArrayList      Arguments;
2939
2940                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
2941                 {
2942                         BAType = t;
2943                         Member = member;
2944                         Arguments = args;
2945                         
2946                 }
2947
2948                 public override Expression Resolve (TypeContainer tc)
2949                 {
2950                         // FIXME: Implement;
2951                         throw new Exception ("Unimplemented");
2952                         // return this;
2953                 }
2954
2955                 public override bool Emit (EmitContext ec)
2956                 {
2957                         throw new Exception ("Unimplemented");
2958                 }
2959         }
2960 }