2001-09-18 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 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, Variable, Namespace, Type,
26                 MethodGroup, PropertyAccess,
27                 EventAccess, IndexerAccess, Nothing, 
28         }
29
30         // <remarks>
31         //   Base class for expressions
32         // </remarks>
33         public abstract class Expression {
34                 protected ExprClass eclass;
35                 protected Type      type;
36                 
37                 public Type Type {
38                         get {
39                                 return type;
40                         }
41
42                         set {
43                                 type = value;
44                         }
45                 }
46
47                 public ExprClass ExprClass {
48                         get {
49                                 return eclass;
50                         }
51
52                         set {
53                                 eclass = value;
54                         }
55                 }
56
57                 public abstract Expression Resolve (TypeContainer tc);
58                 public abstract void Emit (EmitContext ec);
59                 
60                 // <summary>
61                 //   Protected constructor.  Only derivate types should
62                 //   be able to be created
63                 // </summary>
64
65                 protected Expression ()
66                 {
67                         eclass = ExprClass.Invalid;
68                         type = null;
69                 }
70
71                 // 
72                 // Returns a fully formed expression after a MemberLookup
73                 //
74                 static Expression ExprClassFromMemberInfo (MemberInfo mi)
75                 {
76                         if (mi is EventInfo){
77                                 return new EventExpr ((EventInfo) mi);
78                         } else if (mi is FieldInfo){
79                                 return new FieldExpr ((FieldInfo) mi);
80                         } else if (mi is PropertyInfo){
81                                 return new PropertyExpr ((PropertyInfo) mi);
82                         } else if (mi is Type)
83                                 return new TypeExpr ((Type) mi);
84
85                         return null;
86                 }
87                 
88                 //
89                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
90                 //
91                 // FIXME: We need to cope with access permissions here, or this wont
92                 // work!
93                 //
94                 // This code could use some optimizations, but we need to do some
95                 // measurements.  For example, we could use a delegate to `flag' when
96                 // something can not any longer be a method-group (because it is something
97                 // else).
98                 //
99                 // Return values:
100                 //     If the return value is an Array, then it is an array of
101                 //     MethodBases
102                 //   
103                 //     If the return value is an MemberInfo, it is anything, but a Method
104                 //
105                 //     null on error.
106                 //
107                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
108                 // the arguments here and have MemberLookup return only the methods that
109                 // match the argument count/type, unlike we are doing now (we delay this
110                 // decision).
111                 //
112                 // This is so we can catch correctly attempts to invoke instance methods
113                 // from a static body (scan for error 120 in ResolveSimpleName).
114                 //
115                 public static Expression MemberLookup (RootContext rc, Type t, string name,
116                                                           bool same_type, MemberTypes mt, BindingFlags bf)
117                 {
118                         if (same_type)
119                                 bf |= BindingFlags.NonPublic;
120
121                         MemberInfo [] mi = rc.TypeManager.FindMembers (t, mt, bf, Type.FilterName, name);
122
123                         if (mi == null)
124                                 return null;
125                         
126                         if (mi.Length == 1 && !(mi [0] is MethodBase))
127                                 return Expression.ExprClassFromMemberInfo (mi [0]);
128                         
129                         for (int i = 0; i < mi.Length; i++)
130                                 if (!(mi [i] is MethodBase)){
131                                         rc.Report.Error (-5, "Do not know how to reproduce this case: " + 
132                                                          "Methods and non-Method with the same name, report this please");
133
134                                         for (i = 0; i < mi.Length; i++){
135                                                 Type tt = mi [i].GetType ();
136
137                                                 Console.WriteLine (i + ": " + mi [i]);
138                                                 while (tt != TypeManager.object_type){
139                                                         Console.WriteLine (tt);
140                                                         tt = tt.BaseType;
141                                                 }
142                                         }
143                                 }
144
145                         return new MethodGroupExpr (mi);
146                 }
147
148                 public const MemberTypes AllMemberTypes =
149                         MemberTypes.Constructor |
150                         MemberTypes.Event       |
151                         MemberTypes.Field       |
152                         MemberTypes.Method      |
153                         MemberTypes.NestedType  |
154                         MemberTypes.Property;
155                 
156                 public const BindingFlags AllBindingsFlags =
157                         BindingFlags.Public |
158                         BindingFlags.Static |
159                         BindingFlags.Instance;
160
161                 public static Expression MemberLookup (RootContext rc, Type t, string name,
162                                                        bool same_type)
163                 {
164                         return MemberLookup (rc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
165                 }
166                 
167                 // <summary>
168                 //   Resolves the E in `E.I' side for a member_access
169                 //
170                 // This is suboptimal and should be merged with ResolveMemberAccess
171                 static Expression ResolvePrimary (TypeContainer tc, string name)
172                 {
173                         int dot_pos = name.LastIndexOf (".");
174
175                         if (tc.RootContext.IsNamespace (name))
176                                 return new NamespaceExpr (name);
177
178                         if (dot_pos != -1){
179                         } else {
180                                 Type t = tc.LookupType (name, false);
181
182                                 if (t != null)
183                                         return new TypeExpr (t);
184                         }
185
186                         return null;
187                 }
188                         
189                 static public Expression ResolveMemberAccess (TypeContainer tc, string name)
190                 {
191                         Expression left_e;
192                         int dot_pos = name.LastIndexOf (".");
193                         string left = name.Substring (0, dot_pos);
194                         string right = name.Substring (dot_pos + 1);
195
196                         left_e = ResolvePrimary (tc, left);
197                         if (left_e == null)
198                                 return null;
199
200                         switch (left_e.ExprClass){
201                         case ExprClass.Type:
202                                 return  MemberLookup (tc.RootContext,
203                                                       left_e.Type, right,
204                                                       left_e.Type == tc.TypeBuilder);
205                                 
206                         case ExprClass.Namespace:
207                         case ExprClass.PropertyAccess:
208                         case ExprClass.IndexerAccess:
209                         case ExprClass.Variable:
210                         case ExprClass.Value:
211                         case ExprClass.Nothing:
212                         case ExprClass.EventAccess:
213                         case ExprClass.MethodGroup:
214                         case ExprClass.Invalid:
215                                 tc.RootContext.Report.Error (-1000,
216                                                              "Internal compiler error, should have " +
217                                                              "got these handled before");
218                                 break;
219                         }
220                         
221                         return null;
222                 }
223
224                 static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
225                 {
226                         Type expr_type = expr.Type;
227                         
228                         if (target_type == TypeManager.object_type) {
229                                 if (expr_type.IsClass)
230                                         return new EmptyCast (expr, target_type);
231                                 if (expr_type.IsValueType)
232                                         return new BoxedCast (expr, target_type);
233                         } else if (expr_type.IsSubclassOf (target_type))
234                                 return new EmptyCast (expr, target_type);
235                         else 
236                                 // FIXME: missing implicit reference conversions:
237                                 // 
238                                 // from any class-type S to any interface-type T.
239                                 // from any interface type S to interface-type T.
240                                 // from an array-type S to an array-type of type T
241                                 // from an array-type to System.Array
242                                 // from any delegate type to System.Delegate
243                                 // from any array-type or delegate type into System.ICloneable.
244                                 // from the null type to any reference-type.
245                                      
246                                 return null;
247
248                         return null;
249                 }
250                        
251                 // <summary>
252                 //   Converts implicitly the resolved expression `expr' into the
253                 //   `target_type'.  It returns a new expression that can be used
254                 //   in a context that expects a `target_type'. 
255                 // </summary>
256                 static public Expression ConvertImplicit (Expression expr, Type target_type)
257                 {
258                         Type expr_type = expr.Type;
259
260                         if (expr_type == target_type){
261                                 Console.WriteLine ("Hey, ConvertImplicit was called with no job to do");
262                                 return expr;
263                         }
264
265                         //
266                         // Step 1: Perform implicit conversions as found on expr.Type
267                         //
268
269                         //
270                         // Step 2: Built-in conversions.
271                         //
272                         if (expr_type == TypeManager.sbyte_type){
273                                 //
274                                 // From sbyte to short, int, long, float, double.
275                                 //
276                                 if (target_type == TypeManager.int32_type)
277                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
278                                 if (target_type == TypeManager.int64_type)
279                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
280                                 if (target_type == TypeManager.double_type)
281                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
282                                 if (target_type == TypeManager.float_type)
283                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
284                                 if (target_type == TypeManager.short_type)
285                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I2);
286                         } else if (expr_type == TypeManager.byte_type){
287                                 //
288                                 // From byte to short, ushort, int, uint, long, ulong, float, double
289                                 // 
290                                 if ((target_type == TypeManager.short_type) ||
291                                     (target_type == TypeManager.ushort_type) ||
292                                     (target_type == TypeManager.int32_type) ||
293                                     (target_type == TypeManager.uint32_type))
294                                         return new EmptyCast (expr, target_type);
295
296                                 if (target_type == TypeManager.uint64_type)
297                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
298                                 if (target_type == TypeManager.int64_type)
299                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
300                                 
301                                 if (target_type == TypeManager.float_type)
302                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
303                                 if (target_type == TypeManager.double_type)
304                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
305                         } else if (expr_type == TypeManager.short_type){
306                                 //
307                                 // From short to int, long, float, double
308                                 // 
309                                 if (target_type == TypeManager.int32_type)
310                                         return new EmptyCast (expr, target_type);
311                                 if (target_type == TypeManager.int64_type)
312                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
313                                 if (target_type == TypeManager.double_type)
314                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
315                                 if (target_type == TypeManager.float_type)
316                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
317                         } else if (expr_type == TypeManager.ushort_type){
318                                 //
319                                 // From ushort to int, uint, long, ulong, float, double
320                                 //
321                                 if ((target_type == TypeManager.uint32_type) ||
322                                     (target_type == TypeManager.uint64_type))
323                                         return new EmptyCast (expr, target_type);
324                                         
325                                 if (target_type == TypeManager.int32_type)
326                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I4);
327                                 if (target_type == TypeManager.int64_type)
328                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
329                                 if (target_type == TypeManager.double_type)
330                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
331                                 if (target_type == TypeManager.float_type)
332                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
333                         } else if (expr_type == TypeManager.int32_type){
334                                 //
335                                 // From int to long, float, double
336                                 //
337                                 if (target_type == TypeManager.int64_type)
338                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
339                                 if (target_type == TypeManager.double_type)
340                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
341                                 if (target_type == TypeManager.float_type)
342                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
343                         } else if (expr_type == TypeManager.uint32_type){
344                                 //
345                                 // From uint to long, ulong, float, double
346                                 //
347                                 if (target_type == TypeManager.int64_type)
348                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
349                                 if (target_type == TypeManager.uint64_type)
350                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
351                                 if (target_type == TypeManager.double_type)
352                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
353                                                                OpCodes.Conv_R8);
354                                 if (target_type == TypeManager.float_type)
355                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R_Un,
356                                                                OpCodes.Conv_R4);
357                         } else if ((expr_type == TypeManager.uint64_type) ||
358                                    (expr_type == TypeManager.int64_type)){
359                                 //
360                                 // From long to float, double
361                                 //
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.char_type){
369                                 //
370                                 // From char to ushort, int, uint, long, ulong, float, double
371                                 // 
372                                 if ((target_type == TypeManager.ushort_type) ||
373                                     (target_type == TypeManager.int32_type) ||
374                                     (target_type == TypeManager.uint32_type))
375                                         return new EmptyCast (expr, target_type);
376                                 if (target_type == TypeManager.uint64_type)
377                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_U8);
378                                 if (target_type == TypeManager.int64_type)
379                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_I8);
380                                 if (target_type == TypeManager.float_type)
381                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R4);
382                                 if (target_type == TypeManager.double_type)
383                                         return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
384                         } else
385                                 return ImplicitReferenceConversion (expr, target_type);
386
387                         
388
389                         //
390                         //  Could not find an implicit cast.
391                         //
392                         return null;
393                 }
394
395                 // <summary>
396                 //   Performs an explicit conversion of the expression `expr' whose
397                 //   type is expr.Type to `target_type'.
398                 // </summary>
399                 static public Expression ConvertExplicit (Expression expr, Type target_type)
400                 {
401                         return expr;
402                 }
403                 
404         }
405
406         // <summary>
407         //   This kind of cast is used to encapsulate the child
408         //   whose type is child.Type into an expression that is
409         //   reported to return "return_type".  This is used to encapsulate
410         //   expressions which have compatible types, but need to be dealt
411         //   at higher levels with.
412         //
413         //   For example, a "byte" expression could be encapsulated in one
414         //   of these as an "unsigned int".  The type for the expression
415         //   would be "unsigned int".
416         //
417         // </summary>
418         
419         public class EmptyCast : Expression {
420                 protected Expression child;
421
422                 public EmptyCast (Expression child, Type return_type)
423                 {
424                         ExprClass = child.ExprClass;
425                         type = return_type;
426                         this.child = child;
427                 }
428
429                 public override Expression Resolve (TypeContainer tc)
430                 {
431                         // This should never be invoked, we are born in fully
432                         // initialized state.
433
434                         return this;
435                 }
436
437                 public override void Emit (EmitContext ec)
438                 {
439                         child.Emit (ec);
440                 }                       
441         }
442
443         public class BoxedCast : EmptyCast {
444
445                 public BoxedCast (Expression expr, Type target_type)
446                         : base (expr, target_type)
447                 {
448                 }
449
450                 public override Expression Resolve (TypeContainer tc)
451                 {
452                         // This should never be invoked, we are born in fully
453                         // initialized state.
454
455                         return this;
456                 }
457
458                 public override void Emit (EmitContext ec)
459                 {
460                         base.Emit (ec);
461                         ec.ig.Emit (OpCodes.Box, child.Type);
462                 }
463         }
464         
465
466         // <summary>
467         //   This kind of cast is used to encapsulate a child expression
468         //   that can be trivially converted to a target type using one or 
469         //   two opcodes.  The opcodes are passed as arguments.
470         // </summary>
471         public class OpcodeCast : EmptyCast {
472                 OpCode op, op2;
473                 bool second_valid;
474                 
475                 public OpcodeCast (Expression child, Type return_type, OpCode op)
476                         : base (child, return_type)
477                         
478                 {
479                         this.op = op;
480                         second_valid = false;
481                 }
482
483                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
484                         : base (child, return_type)
485                         
486                 {
487                         this.op = op;
488                         this.op2 = op2;
489                         second_valid = true;
490                 }
491
492                 public override Expression Resolve (TypeContainer tc)
493                 {
494                         // This should never be invoked, we are born in fully
495                         // initialized state.
496
497                         return this;
498                 }
499
500                 public override void Emit (EmitContext ec)
501                 {
502                         base.Emit (ec);
503                         ec.ig.Emit (op);
504
505                         if (second_valid)
506                                 ec.ig.Emit (op2);
507                 }                       
508                 
509         }
510         
511         public class Unary : Expression {
512                 public enum Operator {
513                         Plus, Minus, Negate, BitComplement,
514                         Indirection, AddressOf, PreIncrement,
515                         PreDecrement, PostIncrement, PostDecrement
516                 }
517
518                 Operator   oper;
519                 Expression expr;
520                 
521                 public Unary (Operator op, Expression expr)
522                 {
523                         this.oper = op;
524                         this.expr = expr;
525                 }
526
527                 public Expression Expr {
528                         get {
529                                 return expr;
530                         }
531
532                         set {
533                                 expr = value;
534                         }
535                 }
536
537                 public Operator Oper {
538                         get {
539                                 return oper;
540                         }
541
542                         set {
543                                 oper = value;
544                         }
545                 }
546
547                 public override Expression Resolve (TypeContainer tc)
548                 {
549                         // FIXME: Implement;
550                         return this;
551                 }
552
553                 public override void Emit (EmitContext ec)
554                 {
555                 }
556         }
557
558         public class Probe : Expression {
559                 string probe_type;
560                 Expression expr;
561                 Operator oper;
562
563                 public enum Operator {
564                         Is, As
565                 }
566                 
567                 public Probe (Operator oper, Expression expr, string probe_type)
568                 {
569                         this.oper = oper;
570                         this.probe_type = probe_type;
571                         this.expr = expr;
572                 }
573
574                 public Operator Oper {
575                         get {
576                                 return oper;
577                         }
578                 }
579
580                 public Expression Expr {
581                         get {
582                                 return expr;
583                         }
584                 }
585
586                 public string ProbeType {
587                         get {
588                                 return probe_type;
589                         }
590                 }
591
592                 public override Expression Resolve (TypeContainer tc)
593                 {
594                         // FIXME: Implement;
595                         return this;
596                 }
597
598                 public override void Emit (EmitContext ec)
599                 {
600                 }
601         }
602         
603         public class Cast : Expression {
604                 string target_type;
605                 Expression expr;
606                 
607                 public Cast (string cast_type, Expression expr)
608                 {
609                         this.target_type = target_type;
610                         this.expr = expr;
611                 }
612
613                 public string TargetType {
614                         get {
615                                 return target_type;
616                         }
617                 }
618
619                 public Expression Expr {
620                         get {
621                                 return expr;
622                         }
623                         set {
624                                 expr = value;
625                         }
626                 }
627                 
628                 public override Expression Resolve (TypeContainer tc)
629                 {
630                         // FIXME: Implement;
631                         return this;
632                 }
633
634                 public override void Emit (EmitContext ec)
635                 {
636                 }
637         }
638
639         public class Binary : Expression {
640                 public enum Operator {
641                         Multiply, Divide, Modulo,
642                         Add, Subtract,
643                         ShiftLeft, ShiftRight,
644                         LessThan, GreaterThan, LessOrEqual, GreaterOrEqual, 
645                         Equal, NotEqual,
646                         BitwiseAnd,
647                         ExclusiveOr,
648                         BitwiseOr,
649                         LogicalAnd,
650                         LogicalOr
651                 }
652
653                 Operator oper;
654                 Expression left, right;
655                 MethodBase method;
656                 ArrayList  Arguments;
657                 
658
659                 public Binary (Operator oper, Expression left, Expression right)
660                 {
661                         this.oper = oper;
662                         this.left = left;
663                         this.right = right;
664                 }
665
666                 public Operator Oper {
667                         get {
668                                 return oper;
669                         }
670                         set {
671                                 oper = value;
672                         }
673                 }
674                 
675                 public Expression Left {
676                         get {
677                                 return left;
678                         }
679                         set {
680                                 left = value;
681                         }
682                 }
683
684                 public Expression Right {
685                         get {
686                                 return right;
687                         }
688                         set {
689                                 right = value;
690                         }
691                 }
692
693
694                 // <summary>
695                 //   Retruns a stringified representation of the Operator
696                 // </summary>
697                 string OperName ()
698                 {
699                         switch (oper){
700                         case Operator.Multiply:
701                                 return "*";
702                         case Operator.Divide:
703                                 return "/";
704                         case Operator.Modulo:
705                                 return "%";
706                         case Operator.Add:
707                                 return "+";
708                         case Operator.Subtract:
709                                 return "-";
710                         case Operator.ShiftLeft:
711                                 return "<<";
712                         case Operator.ShiftRight:
713                                 return ">>";
714                         case Operator.LessThan:
715                                 return "<";
716                         case Operator.GreaterThan:
717                                 return ">";
718                         case Operator.LessOrEqual:
719                                 return "<=";
720                         case Operator.GreaterOrEqual:
721                                 return ">=";
722                         case Operator.Equal:
723                                 return "==";
724                         case Operator.NotEqual:
725                                 return "!=";
726                         case Operator.BitwiseAnd:
727                                 return "&";
728                         case Operator.BitwiseOr:
729                                 return "|";
730                         case Operator.ExclusiveOr:
731                                 return "^";
732                         case Operator.LogicalOr:
733                                 return "||";
734                         case Operator.LogicalAnd:
735                                 return "&&";
736                         }
737
738                         return oper.ToString ();
739                 }
740
741                 Expression ForceConversion (Expression expr, Type target_type)
742                 {
743                         if (expr.Type == target_type)
744                                 return expr;
745
746                         return ConvertImplicit (expr, target_type);
747                 }
748                 
749                 //
750                 // Note that handling the case l == Decimal || r == Decimal
751                 // is taken care of by the Step 1 Operator Overload resolution.
752                 //
753                 void DoNumericPromotions (TypeContainer tc, Type l, Type r)
754                 {
755                         if (l == TypeManager.double_type || r == TypeManager.double_type){
756                                 //
757                                 // If either operand is of type double, the other operand is
758                                 // conveted to type double.
759                                 //
760                                 if (r != TypeManager.double_type)
761                                         right = ConvertImplicit (right, TypeManager.double_type);
762                                 if (l != TypeManager.double_type)
763                                         left = ConvertImplicit (left, TypeManager.double_type);
764                                 
765                                 type = TypeManager.double_type;
766                         } else if (l == TypeManager.float_type || r == TypeManager.float_type){
767                                 //
768                                 // if either operand is of type float, th eother operand is
769                                 // converd to type float.
770                                 //
771                                 if (r != TypeManager.double_type)
772                                         right = ConvertImplicit (right, TypeManager.float_type);
773                                 if (l != TypeManager.double_type)
774                                         left = ConvertImplicit (left, TypeManager.float_type);
775                                 type = TypeManager.float_type;
776                         } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
777                                 //
778                                 // If either operand is of type ulong, the other operand is
779                                 // converted to type ulong.  or an error ocurrs if the other
780                                 // operand is of type sbyte, short, int or long
781                                 //
782                                 Type other = null;
783                                 
784                                 if (l == TypeManager.uint64_type)
785                                         other = r;
786                                 else if (r == TypeManager.uint64_type)
787                                         other = l;
788
789                                 if ((other == TypeManager.sbyte_type) ||
790                                     (other == TypeManager.short_type) ||
791                                     (other == TypeManager.int32_type) ||
792                                     (other == TypeManager.int64_type)){
793                                         string oper = OperName ();
794                                         
795                                         tc.RootContext.Report.Error (34, "Operator `" + OperName ()
796                                                                      + "' is ambiguous on operands of type `"
797                                                                      + TypeManager.CSharpName (l) + "' "
798                                                                      + "and `" + TypeManager.CSharpName (r)
799                                                                      + "'");
800                                 }
801                                 type = TypeManager.uint64_type;
802                         } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
803                                 //
804                                 // If either operand is of type long, the other operand is converted
805                                 // to type long.
806                                 //
807                                 if (l != TypeManager.int64_type)
808                                         left = ConvertImplicit (left, TypeManager.int64_type);
809                                 if (r != TypeManager.int64_type)
810                                         right = ConvertImplicit (right, TypeManager.int64_type);
811
812                                 type = TypeManager.int64_type;
813                         } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
814                                 //
815                                 // If either operand is of type uint, and the other
816                                 // operand is of type sbyte, short or int, othe operands are
817                                 // converted to type long.
818                                 //
819                                 Type other = null;
820                                 
821                                 if (l == TypeManager.uint32_type)
822                                         other = r;
823                                 else if (r == TypeManager.uint32_type)
824                                         other = l;
825
826                                 if ((other == TypeManager.sbyte_type) ||
827                                     (other == TypeManager.short_type) ||
828                                     (other == TypeManager.int32_type)){
829                                         left = ForceConversion (left, TypeManager.int64_type);
830                                         right = ForceConversion (right, TypeManager.int64_type);
831                                         type = TypeManager.int64_type;
832                                 } else {
833                                         //
834                                         // if either operand is of type uint, the other
835                                         // operand is converd to type uint
836                                         //
837                                         left = ForceConversion (left, TypeManager.uint32_type);
838                                         right = ForceConversion (left, TypeManager.uint32_type);
839                                         type = TypeManager.uint32_type;
840                                 } 
841                         } else {
842                                 left = ForceConversion (left, TypeManager.int32_type);
843                                 right = ForceConversion (right, TypeManager.int32_type);
844                                 type = TypeManager.int32_type;
845                         }
846                 }
847
848                 void error19 (TypeContainer tc)
849                 {
850                         tc.RootContext.Report.Error (
851                                 19,
852                                 "Operator " + OperName () + " cannot be applied to operands of type `" +
853                                 TypeManager.CSharpName (left.Type) + "' and `" +
854                                 TypeManager.CSharpName (right.Type) + "'");
855                                                      
856                 }
857                 
858                 Expression CheckShiftArguments (TypeContainer tc)
859                 {
860                         Expression e;
861                         Type l = left.Type;
862                         Type r = right.Type;
863
864                         e = ForceConversion (right, TypeManager.int32_type);
865                         if (e == null){
866                                 error19 (tc);
867                                 return null;
868                         }
869                         right = e;
870
871                         if (((e = ConvertImplicit (left, TypeManager.int32_type)) != null) ||
872                             ((e = ConvertImplicit (left, TypeManager.uint32_type)) != null) ||
873                             ((e = ConvertImplicit (left, TypeManager.int64_type)) != null) ||
874                             ((e = ConvertImplicit (left, TypeManager.uint64_type)) != null)){
875                                 left = e;
876
877                                 return this;
878                         }
879                         error19 (tc);
880                         return null;
881                 }
882                 
883                 Expression ResolveOperator (TypeContainer tc)
884                 {
885                         Type l = left.Type;
886                         Type r = right.Type;
887
888                         //
889                         // Step 1: Perform Operator Overload location
890                         //
891                         Expression left_expr, right_expr;
892                         
893                         string op = "Operator" + oper;
894
895                         left_expr = MemberLookup (tc.RootContext, l, op, false);
896
897                         if (!(left_expr is MethodGroupExpr)){
898                                 // FIXME: Find proper error
899                                 tc.RootContext.Report.Error (118, "Did find something that is not a method");
900                                 return null;
901                         }
902
903                         right_expr = MemberLookup (tc.RootContext, r, op, false);
904
905                         if (!(right_expr is MethodGroupExpr)){
906                                 // FIXME: Find proper error
907                                 tc.RootContext.Report.Error (118, "Did find something that is not a method");
908                                 return null;
909                         }
910
911                         if (left_expr != null || right_expr != null) {
912                                 //
913                                 // Now we need to form the union of these two sets and
914                                 // then call OverloadResolve on that.
915                                 //
916                                 MethodGroupExpr left_set = null, right_set = null;
917                                 int length1 = 0, length2 = 0;
918                                 
919                                 if (left_expr != null) {
920                                         left_set = (MethodGroupExpr) left_expr;
921                                         length1 = left_set.Methods.Length;
922                                 }
923
924                                 if (right_expr != null) {
925                                         right_set = (MethodGroupExpr) right_expr;
926                                         length2 = right_set.Methods.Length;
927                                 }
928
929                                 MemberInfo [] mi = new MemberInfo [length1 + length2];
930                                 if (left_set != null)
931                                         left_set.Methods.CopyTo (mi, 0);
932                                 if (right_set != null)
933                                         right_set.Methods.CopyTo (mi, length1);
934                                 
935                                 MethodGroupExpr union = new MethodGroupExpr (mi);
936                                 
937                                 Arguments = new ArrayList ();
938                                 Arguments.Add (new Argument (left, Argument.AType.Expression));
939                                 Arguments.Add (new Argument (right, Argument.AType.Expression));
940
941                                 method = Invocation.OverloadResolve (union, Arguments);
942                                 if (method != null)
943                                         return this;
944
945                         }
946
947                         //
948                         // Step 2: Default operations on CLI native types.
949                         //
950                         
951                         // Only perform numeric promotions on:
952                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
953                         //
954                         if (oper == Operator.ShiftLeft || oper == Operator.ShiftRight){
955                                 return CheckShiftArguments (tc);
956                         } else if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
957
958                                 if (l != TypeManager.bool_type || r != TypeManager.bool_type)
959                                         error19 (tc);
960                         } else
961                                 DoNumericPromotions (tc, l, r);
962
963                         if (left == null || right == null)
964                                 return null;
965
966                         if (oper == Operator.BitwiseAnd ||
967                             oper == Operator.BitwiseOr ||
968                             oper == Operator.ExclusiveOr){
969                                 if (!((l == TypeManager.int32_type) ||
970                                       (l == TypeManager.uint32_type) ||
971                                       (l == TypeManager.int64_type) ||
972                                       (l == TypeManager.uint64_type))){
973                                         error19 (tc);
974                                         return null;
975                                 }
976                         }
977
978                         if (oper == Operator.Equal ||
979                             oper == Operator.NotEqual ||
980                             oper == Operator.LessOrEqual ||
981                             oper == Operator.LessThan ||
982                             oper == Operator.GreaterOrEqual ||
983                             oper == Operator.GreaterThan){
984                                 type = TypeManager.bool_type;
985                         }
986                         
987                         return this;
988                 }
989                 
990                 public override Expression Resolve (TypeContainer tc)
991                 {
992                         left = left.Resolve (tc);
993                         right = right.Resolve (tc);
994
995                         if (left == null || right == null)
996                                 return null;
997
998                         return ResolveOperator (tc);
999                 }
1000
1001                 public bool IsBranchable ()
1002                 {
1003                         if (oper == Operator.Equal ||
1004                             oper == Operator.NotEqual ||
1005                             oper == Operator.LessThan ||
1006                             oper == Operator.GreaterThan ||
1007                             oper == Operator.LessOrEqual ||
1008                             oper == Operator.GreaterOrEqual){
1009                                 return true;
1010                         } else
1011                                 return false;
1012                 }
1013
1014                 // <summary>
1015                 //   This entry point is used by routines that might want
1016                 //   to emit a brfalse/brtrue after an expression, and instead
1017                 //   they could use a more compact notation.
1018                 //
1019                 //   Typically the code would generate l.emit/r.emit, followed
1020                 //   by the comparission and then a brtrue/brfalse.  The comparissions
1021                 //   are sometimes inneficient (there are not as complete as the branches
1022                 //   look for the hacks in Emit using double ceqs).
1023                 //
1024                 //   So for those cases we provide EmitBranchable that can emit the
1025                 //   branch with the test
1026                 // </summary>
1027                 public void EmitBranchable (EmitContext ec, int target)
1028                 {
1029                         OpCode opcode;
1030                         bool close_target = false;
1031                         
1032                         left.Emit (ec);
1033                         right.Emit (ec);
1034                         
1035                         switch (oper){
1036                         case Operator.Equal:
1037                                 if (close_target)
1038                                         opcode = OpCodes.Beq_S;
1039                                 else
1040                                         opcode = OpCodes.Beq;
1041                                 break;
1042
1043                         case Operator.NotEqual:
1044                                 if (close_target)
1045                                         opcode = OpCodes.Bne_Un_S;
1046                                 else
1047                                         opcode = OpCodes.Bne_Un;
1048                                 break;
1049
1050                         case Operator.LessThan:
1051                                 if (close_target)
1052                                         opcode = OpCodes.Blt_S;
1053                                 else
1054                                         opcode = OpCodes.Blt;
1055                                 break;
1056
1057                         case Operator.GreaterThan:
1058                                 if (close_target)
1059                                         opcode = OpCodes.Bgt_S;
1060                                 else
1061                                         opcode = OpCodes.Bgt;
1062                                 break;
1063
1064                         case Operator.LessOrEqual:
1065                                 if (close_target)
1066                                         opcode = OpCodes.Ble_S;
1067                                 else
1068                                         opcode = OpCodes.Ble;
1069                                 break;
1070
1071                         case Operator.GreaterOrEqual:
1072                                 if (close_target)
1073                                         opcode = OpCodes.Bge_S;
1074                                 else
1075                                         opcode = OpCodes.Ble;
1076                                 break;
1077
1078                         default:
1079                                 throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
1080                                                      + oper.ToString ());
1081                         }
1082
1083                         ec.ig.Emit (opcode, target);
1084                 }
1085                 
1086                 public override void Emit (EmitContext ec)
1087                 {
1088                         ILGenerator ig = ec.ig;
1089                         Type l = left.Type;
1090                         Type r = right.Type;
1091                         OpCode opcode;
1092
1093                         if (method != null) {
1094
1095                                 bool is_static = method.IsStatic;
1096
1097                                 // FIXME : I am just not able to get this right !!
1098                                 // There's something wrong with this part which causes
1099                                 // an InvalidProgramException if this code is emitted
1100                                 
1101                                 //if (Arguments != null)
1102                                 //      Invocation.EmitArguments (ec, Arguments);
1103                                 
1104                                 //if (is_static){
1105                                 //      if (method is MethodInfo)
1106                                 //              ig.Emit (OpCodes.Call, (MethodInfo) method);
1107                                 //      else
1108                                 //              ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1109                                 //} else {
1110                                 //      if (method is MethodInfo)
1111                                 //              ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
1112                                 //      else
1113                                 //              ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
1114                                 //}
1115                                 
1116                                 //return;
1117                         }
1118                         
1119                         left.Emit (ec);
1120                         right.Emit (ec);
1121
1122                         switch (oper){
1123                         case Operator.Multiply:
1124                                 if (ec.CheckState){
1125                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1126                                                 opcode = OpCodes.Mul_Ovf;
1127                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1128                                                 opcode = OpCodes.Mul_Ovf_Un;
1129                                         else
1130                                                 opcode = OpCodes.Mul;
1131                                 } else
1132                                         opcode = OpCodes.Mul;
1133
1134                                 break;
1135
1136                         case Operator.Divide:
1137                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1138                                         opcode = OpCodes.Div_Un;
1139                                 else
1140                                         opcode = OpCodes.Div;
1141                                 break;
1142
1143                         case Operator.Modulo:
1144                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1145                                         opcode = OpCodes.Rem_Un;
1146                                 else
1147                                         opcode = OpCodes.Rem;
1148                                 break;
1149
1150                         case Operator.Add:
1151                                 if (ec.CheckState){
1152                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1153                                                 opcode = OpCodes.Add_Ovf;
1154                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1155                                                 opcode = OpCodes.Add_Ovf_Un;
1156                                         else
1157                                                 opcode = OpCodes.Mul;
1158                                 } else
1159                                         opcode = OpCodes.Add;
1160                                 break;
1161
1162                         case Operator.Subtract:
1163                                 if (ec.CheckState){
1164                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1165                                                 opcode = OpCodes.Sub_Ovf;
1166                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1167                                                 opcode = OpCodes.Sub_Ovf_Un;
1168                                         else
1169                                                 opcode = OpCodes.Sub;
1170                                 } else
1171                                         opcode = OpCodes.Sub;
1172                                 break;
1173
1174                         case Operator.ShiftRight:
1175                                 opcode = OpCodes.Shr;
1176                                 break;
1177                                 
1178                         case Operator.ShiftLeft:
1179                                 opcode = OpCodes.Shl;
1180                                 break;
1181
1182                         case Operator.Equal:
1183                                 opcode = OpCodes.Ceq;
1184                                 break;
1185
1186                         case Operator.NotEqual:
1187                                 ec.ig.Emit (OpCodes.Ceq);
1188                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1189                                 
1190                                 opcode = OpCodes.Ceq;
1191                                 break;
1192
1193                         case Operator.LessThan:
1194                                 opcode = OpCodes.Clt;
1195                                 break;
1196
1197                         case Operator.GreaterThan:
1198                                 opcode = OpCodes.Cgt;
1199                                 break;
1200
1201                         case Operator.LessOrEqual:
1202                                 ec.ig.Emit (OpCodes.Cgt);
1203                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1204                                 
1205                                 opcode = OpCodes.Ceq;
1206                                 break;
1207
1208                         case Operator.GreaterOrEqual:
1209                                 ec.ig.Emit (OpCodes.Clt);
1210                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
1211                                 
1212                                 opcode = OpCodes.Sub;
1213                                 break;
1214
1215                         case Operator.LogicalOr:
1216                         case Operator.BitwiseOr:
1217                                 opcode = OpCodes.Or;
1218                                 break;
1219
1220                         case Operator.LogicalAnd:
1221                         case Operator.BitwiseAnd:
1222                                 opcode = OpCodes.And;
1223                                 break;
1224
1225                         case Operator.ExclusiveOr:
1226                                 opcode = OpCodes.Xor;
1227                                 break;
1228
1229                         default:
1230                                 throw new Exception ("This should not happen: Operator = "
1231                                                      + oper.ToString ());
1232                         }
1233
1234                         ec.ig.Emit (opcode);
1235                 }
1236         }
1237
1238         public class Conditional : Expression {
1239                 Expression expr, trueExpr, falseExpr;
1240                 
1241                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
1242                 {
1243                         this.expr = expr;
1244                         this.trueExpr = trueExpr;
1245                         this.falseExpr = falseExpr;
1246                 }
1247
1248                 public Expression Expr {
1249                         get {
1250                                 return expr;
1251                         }
1252                 }
1253
1254                 public Expression TrueExpr {
1255                         get {
1256                                 return trueExpr;
1257                         }
1258                 }
1259
1260                 public Expression FalseExpr {
1261                         get {
1262                                 return falseExpr;
1263                         }
1264                 }
1265
1266                 public override Expression Resolve (TypeContainer tc)
1267                 {
1268                         // FIXME: Implement;
1269                         return this;
1270                 }
1271
1272                 public override void Emit (EmitContext ec)
1273                 {
1274                 }
1275         }
1276
1277         public class SimpleName : Expression {
1278                 string name;
1279                 
1280                 public SimpleName (string name)
1281                 {
1282                         this.name = name;
1283                 }
1284
1285                 public string Name {
1286                         get {
1287                                 return name;
1288                         }
1289                 }
1290
1291                 //
1292                 // Checks whether we are trying to access an instance
1293                 // property, method or field from a static body.
1294                 //
1295                 Expression MemberStaticCheck (Report r, Expression e)
1296                 {
1297                         if (e is FieldExpr){
1298                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
1299                                 
1300                                 if (!fi.IsStatic){
1301                                         r.Error (120,
1302                                                  "An object reference is required " +
1303                                                  "for the non-static field `"+name+"'");
1304                                         return null;
1305                                 }
1306                         } else if (e is MethodGroupExpr){
1307                                 // FIXME: Pending reorganization of MemberLookup
1308                                 // Basically at this point we should have the
1309                                 // best match already selected for us, and
1310                                 // we should only have to check a *single*
1311                                 // Method for its static on/off bit.
1312                                 return e;
1313                         } else if (e is PropertyExpr){
1314                                 if (!((PropertyExpr) e).IsStatic){
1315                                         r.Error (120,
1316                                                  "An object reference is required " +
1317                                                  "for the non-static property access `"+
1318                                                  name+"'");
1319                                         return null;
1320                                 }
1321                         }
1322
1323                         return e;
1324                 }
1325                 
1326                 //
1327                 // 7.5.2: Simple Names. 
1328                 //
1329                 // Local Variables and Parameters are handled at
1330                 // parse time, so they never occur as SimpleNames.
1331                 //
1332                 Expression ResolveSimpleName (TypeContainer tc)
1333                 {
1334                         Expression e;
1335                         Report r = tc.RootContext.Report;
1336
1337                         e = MemberLookup (tc.RootContext, tc.TypeBuilder, name, true);
1338                         if (e != null){
1339                                 if (e is TypeExpr)
1340                                         return e;
1341                                 else if (e is FieldExpr){
1342                                         FieldExpr fe = (FieldExpr) e;
1343
1344                                         if (!fe.FieldInfo.IsStatic)
1345                                                 fe.Instance = new This ();
1346                                 }
1347                                 
1348                                 if ((tc.ModFlags & Modifiers.STATIC) != 0)
1349                                         return MemberStaticCheck (r, e);
1350                                 else
1351                                         return e;
1352                         }
1353
1354                         //
1355                         // Do step 3 of the Simple Name resolution.
1356                         //
1357                         // FIXME: implement me.
1358                         
1359                         return this;
1360                 }
1361                 
1362                 //
1363                 // SimpleName needs to handle a multitude of cases:
1364                 //
1365                 // simple_names and qualified_identifiers are placed on
1366                 // the tree equally.
1367                 //
1368                 public override Expression Resolve (TypeContainer tc)
1369                 {
1370                         if (name.IndexOf (".") != -1)
1371                                 return ResolveMemberAccess (tc, name);
1372                         else
1373                                 return ResolveSimpleName (tc);
1374                 }
1375
1376                 public override void Emit (EmitContext ec)
1377                 {
1378                 }
1379         }
1380         
1381         public class LocalVariableReference : Expression {
1382                 public readonly string Name;
1383                 public readonly Block Block;
1384                 
1385                 public LocalVariableReference (Block block, string name)
1386                 {
1387                         Block = block;
1388                         Name = name;
1389                         eclass = ExprClass.Variable;
1390                 }
1391
1392                 public VariableInfo VariableInfo {
1393                         get {
1394                                 return Block.GetVariableInfo (Name);
1395                         }
1396                 }
1397                 
1398                 public override Expression Resolve (TypeContainer tc)
1399                 {
1400                         VariableInfo vi = Block.GetVariableInfo (Name);
1401
1402                         type = vi.VariableType;
1403                         return this;
1404                 }
1405
1406                 public override void Emit (EmitContext ec)
1407                 {
1408                         VariableInfo vi = VariableInfo;
1409                         ILGenerator ig = ec.ig;
1410                         int idx = vi.Idx;
1411                         
1412                         switch (idx){
1413                         case 0:
1414                                 ig.Emit (OpCodes.Ldloc_0);
1415                                 break;
1416                                 
1417                         case 1:
1418                                 ig.Emit (OpCodes.Ldloc_1);
1419                                 break;
1420
1421                         case 2:
1422                                 ig.Emit (OpCodes.Ldloc_2);
1423                                 break;
1424
1425                         case 3:
1426                                 ig.Emit (OpCodes.Ldloc_3);
1427                                 break;
1428
1429                         default:
1430                                 if (idx < 255)
1431                                         ig.Emit (OpCodes.Ldloc_S, idx);
1432                                 else
1433                                         ig.Emit (OpCodes.Ldloc, idx);
1434                                 break;
1435                         }
1436                 }
1437         }
1438
1439         public class ParameterReference : Expression {
1440                 public readonly Parameters Pars;
1441                 public readonly String Name;
1442                 public readonly int Idx;
1443                 
1444                 public ParameterReference (Parameters pars, int idx, string name)
1445                 {
1446                         Pars = pars;
1447                         Idx  = idx;
1448                         Name = name;
1449                 }
1450
1451                 public override Expression Resolve (TypeContainer tc)
1452                 {
1453                         Type [] types = Pars.GetParameterInfo (tc);
1454
1455                         type = types [Idx];
1456                         
1457                         return this;
1458                 }
1459
1460                 public override void Emit (EmitContext ec)
1461                 {
1462                         if (Idx < 255)
1463                                 ec.ig.Emit (OpCodes.Ldarg_S, Idx);
1464                         else
1465                                 ec.ig.Emit (OpCodes.Ldarg, Idx);
1466                 }
1467         }
1468         
1469         // <summary>
1470         //   Used for arguments to New(), Invocation()
1471         // </summary>
1472         public class Argument {
1473                 public enum AType {
1474                         Expression,
1475                         Ref,
1476                         Out
1477                 };
1478
1479                 public readonly AType Type;
1480                 Expression expr;
1481
1482                 public Argument (Expression expr, AType type)
1483                 {
1484                         this.expr = expr;
1485                         this.Type = type;
1486                 }
1487
1488                 public Expression Expr {
1489                         get {
1490                                 return expr;
1491                         }
1492                 }
1493
1494                 public bool Resolve (TypeContainer tc)
1495                 {
1496                         expr = expr.Resolve (tc);
1497
1498                         return expr != null;
1499                 }
1500
1501                 public void Emit (EmitContext ec)
1502                 {
1503                         expr.Emit (ec);
1504                 }
1505         }
1506
1507         // <summary>
1508         //   Invocation of methods or delegates.
1509         // </summary>
1510         public class Invocation : Expression {
1511                 public readonly ArrayList Arguments;
1512                 Expression expr;
1513                 MethodBase method = null;
1514                 
1515                 static Hashtable method_parameter_cache;
1516
1517                 static Invocation ()
1518                 {
1519                         method_parameter_cache = new Hashtable ();
1520                 }
1521                         
1522                 //
1523                 // arguments is an ArrayList, but we do not want to typecast,
1524                 // as it might be null.
1525                 //
1526                 // FIXME: only allow expr to be a method invocation or a
1527                 // delegate invocation (7.5.5)
1528                 //
1529                 public Invocation (Expression expr, ArrayList arguments)
1530                 {
1531                         this.expr = expr;
1532                         Arguments = arguments;
1533                 }
1534
1535                 public Expression Expr {
1536                         get {
1537                                 return expr;
1538                         }
1539                 }
1540
1541                 /// <summary>
1542                 ///   Computes whether Argument `a' and the ParameterInfo `pi' are
1543                 ///   compatible, and if so, how good is the match (in terms of
1544                 ///   "better conversions" (7.4.2.3).
1545                 ///
1546                 ///   0   is the best possible match.
1547                 ///   -1  represents a type mismatch.
1548                 ///   -2  represents a ref/out mismatch.
1549                 /// </summary>
1550                 static int Badness (Argument a, Type t)
1551                 {
1552                         if (a.Expr.Type == null){
1553                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
1554                         }
1555                         
1556                         if (t == a.Expr.Type) 
1557                                 return 0;
1558                         
1559                         // FIXME: Implement implicit conversions here.
1560                         // FIXME: Implement better conversion here.
1561                         
1562                         return -1;
1563                 }
1564
1565                 // <summary>
1566                 //   Returns the Parameters (a ParameterData interface) for the
1567                 //   Method `mb'
1568                 // </summary>
1569                 static ParameterData GetParameterData (MethodBase mb)
1570                 {
1571                         object pd = method_parameter_cache [mb];
1572
1573                         if (pd != null)
1574                                 return (ParameterData) pd;
1575
1576                         if (mb is MethodBuilder || mb is ConstructorBuilder){
1577                                 MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
1578
1579                                 InternalParameters ip = mc.ParameterInfo;
1580                                 method_parameter_cache [mb] = ip;
1581
1582                                 return (ParameterData) ip;
1583                         } else {
1584                                 ParameterInfo [] pi = mb.GetParameters ();
1585                                 ReflectionParameters rp = new ReflectionParameters (pi);
1586                                 method_parameter_cache [mb] = rp;
1587
1588                                 return (ParameterData) rp;
1589                         }
1590                 }
1591                 
1592                 // <summary>
1593                 //   Find the Applicable Function Members (7.4.2.1)
1594                 //
1595                 //   me: Method Group expression with the members to select.
1596                 //       it might contain constructors or methods (or anything
1597                 //       that maps to a method).
1598                 //
1599                 //   Arguments: ArrayList containing resolved Argument objects.
1600                 //
1601                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
1602                 //            that is the best match of me on Arguments.
1603                 //
1604                 // </summary>
1605                 public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
1606                 {
1607                         ArrayList afm = new ArrayList ();
1608                         int best_match = 10000;
1609                         int best_match_idx = -1;
1610                         MethodBase method = null;
1611                         int argument_count;
1612
1613                         if (Arguments == null)
1614                                 argument_count = 0;
1615                         else
1616                                 argument_count = Arguments.Count;
1617
1618                         for (int i = me.Methods.Length; i > 0; ){
1619                                 i--;
1620                                 MethodBase mb = me.Methods [i];
1621                                 ParameterData pd;
1622
1623                                 pd = GetParameterData (mb);
1624
1625                                 // If this is the case, we have a method with no args - presumably
1626                                 if (pd == null && argument_count == 0)
1627                                         return me.Methods [0];
1628
1629                                 //
1630                                 // Compute how good this is
1631                                 //
1632                                 if (pd.Count == argument_count){
1633                                         int badness = 0;
1634                                         
1635                                         for (int j = argument_count; j > 0;){
1636                                                 int x;
1637                                                 j--;
1638                                                 
1639                                                 Argument a = (Argument) Arguments [j];
1640
1641                                                 x = Badness (a, pd.ParameterType (j));
1642                                                 
1643                                                 if (x < 0){
1644                                                         badness = best_match;
1645                                                         continue;
1646                                                 }
1647                                                 
1648                                                 badness += x;
1649                                         }
1650                                         
1651                                         if (badness < best_match){
1652                                                 best_match = badness;
1653                                                 method = me.Methods [i];
1654                                                 best_match_idx = i;
1655                                         }
1656                                 }
1657                         }
1658
1659                         if (best_match_idx == -1)
1660                                 return null;
1661                         
1662                         return method;
1663                 }
1664
1665                         
1666                 public override Expression Resolve (TypeContainer tc)
1667                 {
1668                         //
1669                         // First, resolve the expression that is used to
1670                         // trigger the invocation
1671                         //
1672                         this.expr = expr.Resolve (tc);
1673                         if (this.expr == null)
1674                                 return null;
1675
1676                         if (!(this.expr is MethodGroupExpr)){
1677                                 tc.RootContext.Report.Error (118,
1678                                        "Denotes a non-method (Detail: ExprClass=" + this.expr.ExprClass+")");
1679                                 return null;
1680                         }
1681
1682                         //
1683                         // Next, evaluate all the expressions in the argument list
1684                         //
1685                         if (Arguments != null){
1686                                 for (int i = Arguments.Count; i > 0;){
1687                                         --i;
1688                                         Argument a = (Argument) Arguments [i];
1689
1690                                         if (!a.Resolve (tc))
1691                                                 return null;
1692                                 }
1693                         }
1694
1695                         method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
1696
1697                         if (method == null){
1698                                 tc.RootContext.Report.Error (-6,
1699                                 "Figure out error: Can not find a good function for this argument list");
1700                                 return null;
1701                         }
1702
1703                         if (method is MethodInfo)
1704                                 type = ((MethodInfo)method).ReturnType;
1705
1706                         return this;
1707                 }
1708
1709                 public static void EmitArguments (EmitContext ec, ArrayList Arguments)
1710                 {
1711                         int top;
1712
1713                         if (Arguments != null)
1714                                 top = Arguments.Count;
1715                         else
1716                                 top = 0;
1717
1718                         for (int i = 0; i < top; i++){
1719                                 Argument a = (Argument) Arguments [i];
1720
1721                                 a.Emit (ec);
1722                         }
1723                 }
1724                 
1725                 public override void Emit (EmitContext ec)
1726                 {
1727                         bool is_static = method.IsStatic;
1728
1729                         if (!is_static){
1730                                 MethodGroupExpr mg = (MethodGroupExpr) this.expr;
1731
1732                                 if (mg.InstanceExpression == null){
1733                                         Console.WriteLine ("Internal compiler error.  Should check in the method groups for static/instance");
1734                                 }
1735
1736                                 mg.InstanceExpression.Emit (ec);
1737                         }
1738
1739                         if (Arguments != null)
1740                                 EmitArguments (ec, Arguments);
1741
1742                         if (is_static){
1743                                 if (method is MethodInfo)
1744                                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
1745                                 else
1746                                         ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1747                         } else {
1748                                 if (method is MethodInfo)
1749                                         ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
1750                                 else
1751                                         ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
1752                         } 
1753
1754                 }
1755         }
1756
1757         public class New : Expression {
1758
1759                 public enum NType {
1760                         Object,
1761                         Array
1762                 };
1763
1764                 public readonly NType     NewType;
1765                 public readonly ArrayList Arguments;
1766                 public readonly string    RequestedType;
1767                 // These are for the case when we have an array
1768                 public readonly string    Rank;
1769                 public readonly ArrayList Indices;
1770                 public readonly ArrayList Initializers;
1771                 
1772                 MethodBase method = null;
1773
1774                 public New (string requested_type, ArrayList arguments)
1775                 {
1776                         RequestedType = requested_type;
1777                         Arguments = arguments;
1778                         NewType = NType.Object;
1779                 }
1780
1781                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
1782                 {
1783                         RequestedType = requested_type;
1784                         Indices       = exprs;
1785                         Rank          = rank;
1786                         Initializers  = initializers;
1787                         NewType       = NType.Array;
1788                 }
1789                 
1790                 public override Expression Resolve (TypeContainer tc)
1791                 {
1792                         type = tc.LookupType (RequestedType, false);
1793
1794                         if (type == null)
1795                                 return null;
1796
1797                         Expression ml;
1798
1799                         ml = MemberLookup (tc.RootContext, type, ".ctor", false,
1800                                            MemberTypes.Constructor, AllBindingsFlags);
1801
1802                         if (! (ml is MethodGroupExpr)){
1803                                 //
1804                                 // FIXME: Find proper error
1805                                 //
1806                                 tc.RootContext.Report.Error (118, "Did find something that is not a method");
1807                                 return null;
1808                         }
1809                         
1810                         if (Arguments != null){
1811                                 for (int i = Arguments.Count; i > 0;){
1812                                         --i;
1813                                         Argument a = (Argument) Arguments [i];
1814
1815                                         if (!a.Resolve (tc))
1816                                                 return null;
1817                                 }
1818                         }
1819
1820                         method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
1821
1822                         if (method == null) {
1823                                 tc.RootContext.Report.Error (-6,
1824                                 "New invocation: Can not find a constructor for this argument list");
1825                                 return null;
1826                         }
1827
1828                         return this;
1829                 }
1830
1831                 public override void Emit (EmitContext ec)
1832                 {
1833                         Invocation.EmitArguments (ec, Arguments);
1834                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
1835                 }
1836         }
1837
1838         //
1839         // Represents the `this' construct
1840         //
1841         public class This : Expression {
1842                 public override Expression Resolve (TypeContainer tc)
1843                 {
1844                         eclass = ExprClass.Variable;
1845                         type = tc.TypeBuilder;
1846                         
1847                         return this;
1848                 }
1849
1850                 public override void Emit (EmitContext ec)
1851                 {
1852                         ec.ig.Emit (OpCodes.Ldarg_0);
1853                 }
1854         }
1855
1856         public class TypeOf : Expression {
1857                 public readonly string QueriedType;
1858                 
1859                 public TypeOf (string queried_type)
1860                 {
1861                         QueriedType = queried_type;
1862                 }
1863
1864                 public override Expression Resolve (TypeContainer tc)
1865                 {
1866                         type = tc.LookupType (QueriedType, false);
1867
1868                         if (type == null)
1869                                 return null;
1870                         
1871                         eclass = ExprClass.Type;
1872                         return this;
1873                 }
1874
1875                 public override void Emit (EmitContext ec)
1876                 {
1877                         // FIXME: Implement.
1878                 }
1879         }
1880
1881         public class SizeOf : Expression {
1882                 public readonly string QueriedType;
1883                 
1884                 public SizeOf (string queried_type)
1885                 {
1886                         this.QueriedType = queried_type;
1887                 }
1888
1889                 public override Expression Resolve (TypeContainer tc)
1890                 {
1891                         // FIXME: Implement;
1892                         return this;
1893                 }
1894
1895                 public override void Emit (EmitContext ec)
1896                 {
1897                 }
1898         }
1899
1900         public class MemberAccess : Expression {
1901                 public readonly string Identifier;
1902                 Expression expr;
1903                 Expression member_lookup;
1904                 
1905                 public MemberAccess (Expression expr, string id)
1906                 {
1907                         this.expr = expr;
1908                         Identifier = id;
1909                 }
1910
1911                 public Expression Expr {
1912                         get {
1913                                 return expr;
1914                         }
1915                 }
1916                 
1917                 public override Expression Resolve (TypeContainer tc)
1918                 {
1919                         Expression new_expression = expr.Resolve (tc);
1920
1921                         if (new_expression == null)
1922                                 return null;
1923
1924                         Console.WriteLine ("This is what I figured: " + expr.Type + "/" + expr.ExprClass);
1925
1926                         member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
1927
1928                         if (member_lookup is MethodGroupExpr){
1929                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
1930
1931                                 //
1932                                 // Bind the instance expression to it
1933                                 //
1934                                 // FIXME: This is a horrible way of detecting if it is
1935                                 // an instance expression.  Figure out how to fix this.
1936                                 //
1937
1938                                 if (expr is LocalVariableReference ||
1939                                     expr is ParameterReference ||
1940                                     expr is FieldExpr)
1941                                         mg.InstanceExpression = expr;
1942                                         
1943                                 return member_lookup;
1944                         } else if (member_lookup is FieldExpr){
1945                                 FieldExpr fe = (FieldExpr) member_lookup;
1946
1947                                 fe.Instance = expr;
1948
1949                                 return member_lookup;
1950                         } else
1951                                 //
1952                                 // FIXME: This should generate the proper node
1953                                 // ie, for a Property Access, it should like call it
1954                                 // and stuff.
1955
1956                                 return member_lookup;
1957                 }
1958
1959                 public override void Emit (EmitContext ec)
1960                 {
1961                 }
1962
1963         }
1964
1965         // <summary>
1966         //   Nodes of type Namespace are created during the semantic
1967         //   analysis to resolve member_access/qualified_identifier/simple_name
1968         //   accesses.
1969         //
1970         //   They are born `resolved'. 
1971         // </summary>
1972         public class NamespaceExpr : Expression {
1973                 public readonly string Name;
1974                 
1975                 public NamespaceExpr (string name)
1976                 {
1977                         Name = name;
1978                         eclass = ExprClass.Namespace;
1979                 }
1980
1981                 public override Expression Resolve (TypeContainer tc)
1982                 {
1983                         return this;
1984                 }
1985
1986                 public override void Emit (EmitContext ec)
1987                 {
1988                 }
1989         }
1990
1991         // <summary>
1992         //   Fully resolved expression that evaluates to a type
1993         // </summary>
1994         public class TypeExpr : Expression {
1995                 public TypeExpr (Type t)
1996                 {
1997                         Type = t;
1998                         eclass = ExprClass.Type;
1999                 }
2000
2001                 override public Expression Resolve (TypeContainer tc)
2002                 {
2003                         return this;
2004                 }
2005
2006                 override public void Emit (EmitContext ec)
2007                 {
2008                         
2009                 }
2010         }
2011
2012         // <summary>
2013         //   MethodGroup Expression.
2014         //  
2015         //   This is a fully resolved expression that evaluates to a type
2016         // </summary>
2017         public class MethodGroupExpr : Expression {
2018                 public readonly MethodBase [] Methods;
2019                 Expression instance_expression = null;
2020                 
2021                 public MethodGroupExpr (MemberInfo [] mi)
2022                 {
2023                         Methods = new MethodBase [mi.Length];
2024                         mi.CopyTo (Methods, 0);
2025                         eclass = ExprClass.MethodGroup;
2026                 }
2027
2028                 //
2029                 // `A method group may have associated an instance expression' 
2030                 // 
2031                 public Expression InstanceExpression {
2032                         get {
2033                                 return instance_expression;
2034                         }
2035
2036                         set {
2037                                 instance_expression = value;
2038                         }
2039                 }
2040                 
2041                 override public Expression Resolve (TypeContainer tc)
2042                 {
2043                         return this;
2044                 }
2045
2046                 override public void Emit (EmitContext ec)
2047                 {
2048                         
2049                 }
2050         }
2051         
2052         public class BuiltinTypeAccess : Expression {
2053                 public readonly string AccessBase;
2054                 public readonly string Method;
2055                 
2056                 public BuiltinTypeAccess (string type, string method)
2057                 {
2058                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
2059                         AccessBase = type;
2060                         Method = method;
2061                 }
2062
2063                 public override Expression Resolve (TypeContainer tc)
2064                 {
2065                         // FIXME: Implement;
2066                         return this;
2067                 }
2068
2069                 public override void Emit (EmitContext ec)
2070                 {
2071                 }
2072         }
2073
2074
2075         //   Fully resolved expression that evaluates to a Field
2076         // </summary>
2077         public class FieldExpr : Expression {
2078                 public readonly FieldInfo FieldInfo;
2079                 public Expression Instance;
2080                         
2081                 public FieldExpr (FieldInfo fi)
2082                 {
2083                         FieldInfo = fi;
2084                         eclass = ExprClass.Variable;
2085                         type = fi.FieldType;
2086                 }
2087
2088                 override public Expression Resolve (TypeContainer tc)
2089                 {
2090                         if (!FieldInfo.IsStatic){
2091                                 if (Instance == null){
2092                                         throw new Exception ("non-static FieldExpr without instance var\n" +
2093                                                              "You have to assign the Instance variable\n" +
2094                                                              "Of the FieldExpr to set this\n");
2095                                 }
2096
2097                                 Instance = Instance.Resolve (tc);
2098                                 if (Instance == null)
2099                                         return null;
2100                                 
2101                         }
2102                         return this;
2103                 }
2104
2105                 override public void Emit (EmitContext ec)
2106                 {
2107                         ILGenerator ig = ec.ig;
2108
2109                         if (FieldInfo.IsStatic)
2110                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2111                         else {
2112                                 Instance.Emit (ec);
2113                                 
2114                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
2115                         }
2116                 }
2117         }
2118         
2119         // <summary>
2120         //   Fully resolved expression that evaluates to a Property
2121         // </summary>
2122         public class PropertyExpr : Expression {
2123                 public readonly PropertyInfo PropertyInfo;
2124                 public readonly bool IsStatic;
2125                 
2126                 public PropertyExpr (PropertyInfo pi)
2127                 {
2128                         PropertyInfo = pi;
2129                         eclass = ExprClass.PropertyAccess;
2130                         IsStatic = false;
2131                                 
2132                         MethodBase [] acc = pi.GetAccessors ();
2133
2134                         for (int i = 0; i < acc.Length; i++)
2135                                 if (acc [i].IsStatic)
2136                                         IsStatic = true;
2137
2138                         type = pi.PropertyType;
2139                 }
2140
2141                 override public Expression Resolve (TypeContainer tc)
2142                 {
2143                         // We are born in resolved state. 
2144                         return this;
2145                 }
2146
2147                 override public void Emit (EmitContext ec)
2148                 {
2149                         // FIXME: Implement.
2150                 }
2151         }
2152
2153         // <summary>
2154         //   Fully resolved expression that evaluates to a Property
2155         // </summary>
2156         public class EventExpr : Expression {
2157                 public readonly EventInfo EventInfo;
2158                 
2159                 public EventExpr (EventInfo ei)
2160                 {
2161                         EventInfo = ei;
2162                         eclass = ExprClass.EventAccess;
2163                 }
2164
2165                 override public Expression Resolve (TypeContainer tc)
2166                 {
2167                         // We are born in resolved state. 
2168                         return this;
2169                 }
2170
2171                 override public void Emit (EmitContext ec)
2172                 {
2173                         // FIXME: Implement.
2174                 }
2175         }
2176         
2177         public class CheckedExpr : Expression {
2178
2179                 public Expression Expr;
2180
2181                 public CheckedExpr (Expression e)
2182                 {
2183                         Expr = e;
2184                 }
2185
2186                 public override Expression Resolve (TypeContainer tc)
2187                 {
2188                         Expr = Expr.Resolve (tc);
2189
2190                         if (Expr == null)
2191                                 return null;
2192
2193                         eclass = Expr.ExprClass;
2194                         type = Expr.Type;
2195                         return this;
2196                 }
2197
2198                 public override void Emit (EmitContext ec)
2199                 {
2200                         bool last_check = ec.CheckState;
2201
2202                         ec.CheckState = true;
2203                         
2204                         Expr.Emit (ec);
2205
2206                         ec.CheckState = last_check;
2207                 }
2208                 
2209         }
2210
2211         public class UnCheckedExpr : Expression {
2212
2213                 public Expression Expr;
2214
2215                 public UnCheckedExpr (Expression e)
2216                 {
2217                         Expr = e;
2218                 }
2219
2220                 public override Expression Resolve (TypeContainer tc)
2221                 {
2222                         Expr = Expr.Resolve (tc);
2223
2224                         if (Expr == null)
2225                                 return null;
2226
2227                         eclass = Expr.ExprClass;
2228                         type = Expr.Type;
2229                         return this;
2230                 }
2231
2232                 public override void Emit (EmitContext ec)
2233                 {
2234                         bool last_check = ec.CheckState;
2235
2236                         ec.CheckState = false;
2237                         
2238                         Expr.Emit (ec);
2239
2240                         ec.CheckState = last_check;
2241                 }
2242                 
2243         }
2244         
2245         public class ElementAccess : Expression {
2246                 
2247                 public readonly ArrayList  Arguments;
2248                 public readonly Expression Expr;
2249                 
2250                 public ElementAccess (Expression e, ArrayList e_list)
2251                 {
2252                         Expr = e;
2253                         Arguments = e_list;
2254                 }
2255
2256                 public override Expression Resolve (TypeContainer tc)
2257                 {
2258                         // FIXME : Implement
2259                         return this;
2260                 }
2261                 
2262                 public override void Emit (EmitContext ec)
2263                 {
2264                         // FIXME : Implement !
2265                 }
2266                 
2267         }
2268         
2269         public class BaseAccess : Expression {
2270
2271                 public enum BaseAccessType {
2272                         Member,
2273                         Indexer
2274                 };
2275                 
2276                 public readonly BaseAccessType BAType;
2277                 public readonly string         Member;
2278                 public readonly ArrayList      Arguments;
2279
2280                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
2281                 {
2282                         BAType = t;
2283                         Member = member;
2284                         Arguments = args;
2285                         
2286                 }
2287
2288                 public override Expression Resolve (TypeContainer tc)
2289                 {
2290                         // FIXME : Implement !
2291                         return this;
2292                 }
2293
2294                 public override void Emit (EmitContext ec)
2295                 {
2296                 }
2297         }
2298 }