2001-09-18 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 namespace CIR {
10         using System.Collections;
11         using System.Diagnostics;
12         using System;
13         using System.Reflection;
14         using System.Reflection.Emit;
15
16         // <remarks>
17         //   The ExprClass class contains the is used to pass the 
18         //   classification of an expression (value, variable, namespace,
19         //   type, method group, property access, event access, indexer access,
20         //   nothing).
21         // </remarks>
22         public enum ExprClass {
23                 Invalid,
24                 
25                 Value, 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                                 if ((tc.ModFlags & Modifiers.STATIC) != 0)
1342                                         return MemberStaticCheck (r, e);
1343                                 else
1344                                         return e;
1345                         }
1346
1347                         //
1348                         // Do step 3 of the Simple Name resolution.
1349                         //
1350                         // FIXME: implement me.
1351                         
1352                         return this;
1353                 }
1354                 
1355                 //
1356                 // SimpleName needs to handle a multitude of cases:
1357                 //
1358                 // simple_names and qualified_identifiers are placed on
1359                 // the tree equally.
1360                 //
1361                 public override Expression Resolve (TypeContainer tc)
1362                 {
1363                         if (name.IndexOf (".") != -1)
1364                                 return ResolveMemberAccess (tc, name);
1365                         else
1366                                 return ResolveSimpleName (tc);
1367                 }
1368
1369                 public override void Emit (EmitContext ec)
1370                 {
1371                 }
1372         }
1373         
1374         public class LocalVariableReference : Expression {
1375                 public readonly string Name;
1376                 public readonly Block Block;
1377                 
1378                 public LocalVariableReference (Block block, string name)
1379                 {
1380                         Block = block;
1381                         Name = name;
1382                         eclass = ExprClass.Variable;
1383                 }
1384
1385                 public VariableInfo VariableInfo {
1386                         get {
1387                                 return Block.GetVariableInfo (Name);
1388                         }
1389                 }
1390                 
1391                 public override Expression Resolve (TypeContainer tc)
1392                 {
1393                         VariableInfo vi = Block.GetVariableInfo (Name);
1394
1395                         type = vi.VariableType;
1396                         return this;
1397                 }
1398
1399                 public override void Emit (EmitContext ec)
1400                 {
1401                         VariableInfo vi = VariableInfo;
1402                         ILGenerator ig = ec.ig;
1403                         int idx = vi.Idx;
1404                         
1405                         switch (idx){
1406                         case 0:
1407                                 ig.Emit (OpCodes.Ldloc_0);
1408                                 break;
1409                                 
1410                         case 1:
1411                                 ig.Emit (OpCodes.Ldloc_1);
1412                                 break;
1413
1414                         case 2:
1415                                 ig.Emit (OpCodes.Ldloc_2);
1416                                 break;
1417
1418                         case 3:
1419                                 ig.Emit (OpCodes.Ldloc_3);
1420                                 break;
1421
1422                         default:
1423                                 if (idx < 255)
1424                                         ig.Emit (OpCodes.Ldloc_S, idx);
1425                                 else
1426                                         ig.Emit (OpCodes.Ldloc, idx);
1427                                 break;
1428                         }
1429                 }
1430         }
1431
1432         public class ParameterReference : Expression {
1433                 public readonly Parameters Pars;
1434                 public readonly String Name;
1435                 public readonly int Idx;
1436                 
1437                 public ParameterReference (Parameters pars, int idx, string name)
1438                 {
1439                         Pars = pars;
1440                         Idx  = idx;
1441                         Name = name;
1442                 }
1443
1444                 public override Expression Resolve (TypeContainer tc)
1445                 {
1446                         Type [] types = Pars.GetParameterInfo (tc);
1447
1448                         type = types [Idx];
1449                         
1450                         return this;
1451                 }
1452
1453                 public override void Emit (EmitContext ec)
1454                 {
1455                         if (Idx < 255)
1456                                 ec.ig.Emit (OpCodes.Ldarg_S, Idx);
1457                         else
1458                                 ec.ig.Emit (OpCodes.Ldarg, Idx);
1459                 }
1460         }
1461         
1462         // <summary>
1463         //   Used for arguments to New(), Invocation()
1464         // </summary>
1465         public class Argument {
1466                 public enum AType {
1467                         Expression,
1468                         Ref,
1469                         Out
1470                 };
1471
1472                 public readonly AType Type;
1473                 Expression expr;
1474
1475                 public Argument (Expression expr, AType type)
1476                 {
1477                         this.expr = expr;
1478                         this.Type = type;
1479                 }
1480
1481                 public Expression Expr {
1482                         get {
1483                                 return expr;
1484                         }
1485                 }
1486
1487                 public bool Resolve (TypeContainer tc)
1488                 {
1489                         expr = expr.Resolve (tc);
1490
1491                         return expr != null;
1492                 }
1493
1494                 public void Emit (EmitContext ec)
1495                 {
1496                         expr.Emit (ec);
1497                 }
1498         }
1499
1500         // <summary>
1501         //   Invocation of methods or delegates.
1502         // </summary>
1503         public class Invocation : Expression {
1504                 public readonly ArrayList Arguments;
1505                 Expression expr;
1506                 MethodBase method = null;
1507                 
1508                 static Hashtable method_parameter_cache;
1509
1510                 static Invocation ()
1511                 {
1512                         method_parameter_cache = new Hashtable ();
1513                 }
1514                         
1515                 //
1516                 // arguments is an ArrayList, but we do not want to typecast,
1517                 // as it might be null.
1518                 //
1519                 // FIXME: only allow expr to be a method invocation or a
1520                 // delegate invocation (7.5.5)
1521                 //
1522                 public Invocation (Expression expr, ArrayList arguments)
1523                 {
1524                         this.expr = expr;
1525                         Arguments = arguments;
1526                 }
1527
1528                 public Expression Expr {
1529                         get {
1530                                 return expr;
1531                         }
1532                 }
1533
1534                 /// <summary>
1535                 ///   Computes whether Argument `a' and the ParameterInfo `pi' are
1536                 ///   compatible, and if so, how good is the match (in terms of
1537                 ///   "better conversions" (7.4.2.3).
1538                 ///
1539                 ///   0   is the best possible match.
1540                 ///   -1  represents a type mismatch.
1541                 ///   -2  represents a ref/out mismatch.
1542                 /// </summary>
1543                 static int Badness (Argument a, Type t)
1544                 {
1545                         if (a.Expr.Type == null){
1546                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
1547                         }
1548                         
1549                         if (t == a.Expr.Type) 
1550                                 return 0;
1551                         
1552                         // FIXME: Implement implicit conversions here.
1553                         // FIXME: Implement better conversion here.
1554                         
1555                         return -1;
1556                 }
1557
1558                 // <summary>
1559                 //   Returns the Parameters (a ParameterData interface) for the
1560                 //   Method `mb'
1561                 // </summary>
1562                 static ParameterData GetParameterData (MethodBase mb)
1563                 {
1564                         object pd = method_parameter_cache [mb];
1565
1566                         if (pd != null)
1567                                 return (ParameterData) pd;
1568
1569                         if (mb is MethodBuilder || mb is ConstructorBuilder){
1570                                 MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
1571
1572                                 InternalParameters ip = mc.ParameterInfo;
1573                                 method_parameter_cache [mb] = ip;
1574
1575                                 return (ParameterData) ip;
1576                         } else {
1577                                 ParameterInfo [] pi = mb.GetParameters ();
1578                                 ReflectionParameters rp = new ReflectionParameters (pi);
1579                                 method_parameter_cache [mb] = rp;
1580
1581                                 return (ParameterData) rp;
1582                         }
1583                 }
1584                 
1585                 // <summary>
1586                 //   Find the Applicable Function Members (7.4.2.1)
1587                 //
1588                 //   me: Method Group expression with the members to select.
1589                 //       it might contain constructors or methods (or anything
1590                 //       that maps to a method).
1591                 //
1592                 //   Arguments: ArrayList containing resolved Argument objects.
1593                 //
1594                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
1595                 //            that is the best match of me on Arguments.
1596                 //
1597                 // </summary>
1598                 public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
1599                 {
1600                         ArrayList afm = new ArrayList ();
1601                         int best_match = 10000;
1602                         int best_match_idx = -1;
1603                         MethodBase method = null;
1604                         int argument_count;
1605
1606                         if (Arguments == null)
1607                                 argument_count = 0;
1608                         else
1609                                 argument_count = Arguments.Count;
1610
1611                         for (int i = me.Methods.Length; i > 0; ){
1612                                 i--;
1613                                 MethodBase mb = me.Methods [i];
1614                                 ParameterData pd;
1615
1616                                 pd = GetParameterData (mb);
1617
1618                                 // If this is the case, we have a method with no args - presumably
1619                                 if (pd == null && argument_count == 0)
1620                                         return me.Methods [0];
1621
1622                                 //
1623                                 // Compute how good this is
1624                                 //
1625                                 if (pd.Count == argument_count){
1626                                         int badness = 0;
1627                                         
1628                                         for (int j = argument_count; j > 0;){
1629                                                 int x;
1630                                                 j--;
1631                                                 
1632                                                 Argument a = (Argument) Arguments [j];
1633
1634                                                 x = Badness (a, pd.ParameterType (j));
1635                                                 
1636                                                 if (x < 0){
1637                                                         badness = best_match;
1638                                                         continue;
1639                                                 }
1640                                                 
1641                                                 badness += x;
1642                                         }
1643                                         
1644                                         if (badness < best_match){
1645                                                 best_match = badness;
1646                                                 method = me.Methods [i];
1647                                                 best_match_idx = i;
1648                                         }
1649                                 }
1650                         }
1651
1652                         if (best_match_idx == -1)
1653                                 return null;
1654                         
1655                         return method;
1656                 }
1657
1658                         
1659                 public override Expression Resolve (TypeContainer tc)
1660                 {
1661                         //
1662                         // First, resolve the expression that is used to
1663                         // trigger the invocation
1664                         //
1665                         this.expr = expr.Resolve (tc);
1666                         if (this.expr == null)
1667                                 return null;
1668
1669                         if (!(this.expr is MethodGroupExpr)){
1670                                 tc.RootContext.Report.Error (118,
1671                                        "Denotes a non-method (Detail: ExprClass=" + this.expr.ExprClass+")");
1672                                 return null;
1673                         }
1674
1675                         //
1676                         // Next, evaluate all the expressions in the argument list
1677                         //
1678                         if (Arguments != null){
1679                                 for (int i = Arguments.Count; i > 0;){
1680                                         --i;
1681                                         Argument a = (Argument) Arguments [i];
1682
1683                                         if (!a.Resolve (tc))
1684                                                 return null;
1685                                 }
1686                         }
1687
1688                         method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
1689
1690                         if (method == null){
1691                                 tc.RootContext.Report.Error (-6,
1692                                 "Figure out error: Can not find a good function for this argument list");
1693                                 return null;
1694                         }
1695
1696                         if (method is MethodInfo)
1697                                 type = ((MethodInfo)method).ReturnType;
1698
1699                         return this;
1700                 }
1701
1702                 public static void EmitArguments (EmitContext ec, ArrayList Arguments)
1703                 {
1704                         int top;
1705
1706                         if (Arguments != null)
1707                                 top = Arguments.Count;
1708                         else
1709                                 top = 0;
1710
1711                         for (int i = 0; i < top; i++){
1712                                 Argument a = (Argument) Arguments [i];
1713
1714                                 a.Emit (ec);
1715                         }
1716                 }
1717                 
1718                 public override void Emit (EmitContext ec)
1719                 {
1720                         bool is_static = method.IsStatic;
1721
1722                         if (!is_static){
1723                                 MethodGroupExpr mg = (MethodGroupExpr) this.expr;
1724
1725                                 if (mg.InstanceExpression == null){
1726                                         Console.WriteLine ("Internal compiler error.  Should check in the method groups for static/instance");
1727                                 }
1728
1729                                 mg.InstanceExpression.Emit (ec);
1730                         }
1731
1732                         if (Arguments != null)
1733                                 EmitArguments (ec, Arguments);
1734
1735                         if (is_static){
1736                                 if (method is MethodInfo)
1737                                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
1738                                 else
1739                                         ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1740                         } else {
1741                                 if (method is MethodInfo)
1742                                         ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
1743                                 else
1744                                         ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
1745                         } 
1746
1747                 }
1748         }
1749
1750         public class New : Expression {
1751
1752                 public enum NType {
1753                         Object,
1754                         Array
1755                 };
1756
1757                 public readonly NType     NewType;
1758                 public readonly ArrayList Arguments;
1759                 public readonly string    RequestedType;
1760                 // These are for the case when we have an array
1761                 public readonly string    Rank;
1762                 public readonly ArrayList Indices;
1763                 public readonly ArrayList Initializers;
1764                 
1765                 MethodBase method = null;
1766
1767                 public New (string requested_type, ArrayList arguments)
1768                 {
1769                         RequestedType = requested_type;
1770                         Arguments = arguments;
1771                         NewType = NType.Object;
1772                 }
1773
1774                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
1775                 {
1776                         RequestedType = requested_type;
1777                         Indices       = exprs;
1778                         Rank          = rank;
1779                         Initializers  = initializers;
1780                         NewType       = NType.Array;
1781                 }
1782                 
1783                 public override Expression Resolve (TypeContainer tc)
1784                 {
1785                         type = tc.LookupType (RequestedType, false);
1786
1787                         if (type == null)
1788                                 return null;
1789
1790                         Expression ml;
1791
1792                         ml = MemberLookup (tc.RootContext, type, ".ctor", false,
1793                                            MemberTypes.Constructor, AllBindingsFlags);
1794
1795                         if (! (ml is MethodGroupExpr)){
1796                                 //
1797                                 // FIXME: Find proper error
1798                                 //
1799                                 tc.RootContext.Report.Error (118, "Did find something that is not a method");
1800                                 return null;
1801                         }
1802                         
1803                         if (Arguments != null){
1804                                 for (int i = Arguments.Count; i > 0;){
1805                                         --i;
1806                                         Argument a = (Argument) Arguments [i];
1807
1808                                         if (!a.Resolve (tc))
1809                                                 return null;
1810                                 }
1811                         }
1812
1813                         method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
1814
1815                         if (method == null) {
1816                                 tc.RootContext.Report.Error (-6,
1817                                 "New invocation: Can not find a constructor for this argument list");
1818                                 return null;
1819                         }
1820
1821                         return this;
1822                 }
1823
1824                 public override void Emit (EmitContext ec)
1825                 {
1826                         Invocation.EmitArguments (ec, Arguments);
1827                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
1828                 }
1829         }
1830
1831         public class This : Expression {
1832                 public override Expression Resolve (TypeContainer tc)
1833                 {
1834                         // FIXME: Implement;
1835                         return this;
1836                 }
1837
1838                 public override void Emit (EmitContext ec)
1839                 {
1840                 }
1841         }
1842
1843         public class TypeOf : Expression {
1844                 public readonly string QueriedType;
1845                 
1846                 public TypeOf (string queried_type)
1847                 {
1848                         QueriedType = queried_type;
1849                 }
1850
1851                 public override Expression Resolve (TypeContainer tc)
1852                 {
1853                         // FIXME: Implement;
1854                         return this;
1855                 }
1856
1857                 public override void Emit (EmitContext ec)
1858                 {
1859                 }
1860         }
1861
1862         public class SizeOf : Expression {
1863                 public readonly string QueriedType;
1864                 
1865                 public SizeOf (string queried_type)
1866                 {
1867                         this.QueriedType = queried_type;
1868                 }
1869
1870                 public override Expression Resolve (TypeContainer tc)
1871                 {
1872                         // FIXME: Implement;
1873                         return this;
1874                 }
1875
1876                 public override void Emit (EmitContext ec)
1877                 {
1878                 }
1879         }
1880
1881         public class MemberAccess : Expression {
1882                 public readonly string Identifier;
1883                 Expression expr;
1884                 Expression member_lookup;
1885                 
1886                 public MemberAccess (Expression expr, string id)
1887                 {
1888                         this.expr = expr;
1889                         Identifier = id;
1890                 }
1891
1892                 public Expression Expr {
1893                         get {
1894                                 return expr;
1895                         }
1896                 }
1897                 
1898                 public override Expression Resolve (TypeContainer tc)
1899                 {
1900                         Expression new_expression = expr.Resolve (tc);
1901
1902                         if (new_expression == null)
1903                                 return null;
1904
1905                         Console.WriteLine ("This is what I figured: " + expr.Type + "/" + expr.ExprClass);
1906
1907                         member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
1908
1909                         if (member_lookup is MethodGroupExpr){
1910                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
1911
1912                                 //
1913                                 // Bind the instance expression to it
1914                                 //
1915                                 // FIXME: This is a horrible way of detecting if it is
1916                                 // an instance expression.  Figure out how to fix this.
1917                                 //
1918                                 Console.WriteLine ("FIXME: Horrible way of figuring if something is an isntance");
1919
1920                                 if (expr is LocalVariableReference)
1921                                         mg.InstanceExpression = expr;
1922                                         
1923                                 return member_lookup;
1924                         } else
1925                                 //
1926                                 // FIXME: This should generate the proper node
1927                                 // ie, for a Property Access, it should like call it
1928                                 // and stuff.
1929
1930                                 return null;
1931                 }
1932
1933                 public override void Emit (EmitContext ec)
1934                 {
1935                 }
1936
1937         }
1938
1939         // <summary>
1940         //   Nodes of type Namespace are created during the semantic
1941         //   analysis to resolve member_access/qualified_identifier/simple_name
1942         //   accesses.
1943         //
1944         //   They are born `resolved'. 
1945         // </summary>
1946         public class NamespaceExpr : Expression {
1947                 public readonly string Name;
1948                 
1949                 public NamespaceExpr (string name)
1950                 {
1951                         Name = name;
1952                         eclass = ExprClass.Namespace;
1953                 }
1954
1955                 public override Expression Resolve (TypeContainer tc)
1956                 {
1957                         return this;
1958                 }
1959
1960                 public override void Emit (EmitContext ec)
1961                 {
1962                 }
1963         }
1964
1965         // <summary>
1966         //   Fully resolved expression that evaluates to a type
1967         // </summary>
1968         public class TypeExpr : Expression {
1969                 public TypeExpr (Type t)
1970                 {
1971                         Type = t;
1972                         eclass = ExprClass.Type;
1973                 }
1974
1975                 override public Expression Resolve (TypeContainer tc)
1976                 {
1977                         return this;
1978                 }
1979
1980                 override public void Emit (EmitContext ec)
1981                 {
1982                         
1983                 }
1984         }
1985
1986         // <summary>
1987         //   MethodGroup Expression.
1988         //  
1989         //   This is a fully resolved expression that evaluates to a type
1990         // </summary>
1991         public class MethodGroupExpr : Expression {
1992                 public readonly MethodBase [] Methods;
1993                 Expression instance_expression = null;
1994                 
1995                 public MethodGroupExpr (MemberInfo [] mi)
1996                 {
1997                         Methods = new MethodBase [mi.Length];
1998                         mi.CopyTo (Methods, 0);
1999                         eclass = ExprClass.MethodGroup;
2000                 }
2001
2002                 //
2003                 // `A method group may have associated an instance expression' 
2004                 // 
2005                 public Expression InstanceExpression {
2006                         get {
2007                                 return instance_expression;
2008                         }
2009
2010                         set {
2011                                 instance_expression = value;
2012                         }
2013                 }
2014                 
2015                 override public Expression Resolve (TypeContainer tc)
2016                 {
2017                         return this;
2018                 }
2019
2020                 override public void Emit (EmitContext ec)
2021                 {
2022                         
2023                 }
2024         }
2025         
2026         public class BuiltinTypeAccess : Expression {
2027                 public readonly string AccessBase;
2028                 public readonly string Method;
2029                 
2030                 public BuiltinTypeAccess (string type, string method)
2031                 {
2032                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
2033                         AccessBase = type;
2034                         Method = method;
2035                 }
2036
2037                 public override Expression Resolve (TypeContainer tc)
2038                 {
2039                         // FIXME: Implement;
2040                         return this;
2041                 }
2042
2043                 public override void Emit (EmitContext ec)
2044                 {
2045                 }
2046         }
2047
2048
2049         //   Fully resolved expression that evaluates to a Field
2050         // </summary>
2051         public class FieldExpr : Expression {
2052                 public readonly FieldInfo FieldInfo;
2053
2054                 public FieldExpr (FieldInfo fi)
2055                 {
2056                         FieldInfo = fi;
2057                         eclass = ExprClass.Variable;
2058                         type = fi.FieldType;
2059                 }
2060
2061                 override public Expression Resolve (TypeContainer tc)
2062                 {
2063                         // We are born in resolved state. 
2064                         return this;
2065                 }
2066
2067                 override public void Emit (EmitContext ec)
2068                 {
2069                         // FIXME: Assert that this should not be reached?
2070                 }
2071         }
2072         
2073         // <summary>
2074         //   Fully resolved expression that evaluates to a Property
2075         // </summary>
2076         public class PropertyExpr : Expression {
2077                 public readonly PropertyInfo PropertyInfo;
2078                 public readonly bool IsStatic;
2079                 
2080                 public PropertyExpr (PropertyInfo pi)
2081                 {
2082                         PropertyInfo = pi;
2083                         eclass = ExprClass.PropertyAccess;
2084                         IsStatic = false;
2085                                 
2086                         MethodBase [] acc = pi.GetAccessors ();
2087
2088                         for (int i = 0; i < acc.Length; i++)
2089                                 if (acc [i].IsStatic)
2090                                         IsStatic = true;
2091
2092                         type = pi.PropertyType;
2093                 }
2094
2095                 override public Expression Resolve (TypeContainer tc)
2096                 {
2097                         // We are born in resolved state. 
2098                         return this;
2099                 }
2100
2101                 override public void Emit (EmitContext ec)
2102                 {
2103                         // FIXME: Implement.
2104                 }
2105         }
2106
2107         // <summary>
2108         //   Fully resolved expression that evaluates to a Property
2109         // </summary>
2110         public class EventExpr : Expression {
2111                 public readonly EventInfo EventInfo;
2112                 
2113                 public EventExpr (EventInfo ei)
2114                 {
2115                         EventInfo = ei;
2116                         eclass = ExprClass.EventAccess;
2117                 }
2118
2119                 override public Expression Resolve (TypeContainer tc)
2120                 {
2121                         // We are born in resolved state. 
2122                         return this;
2123                 }
2124
2125                 override public void Emit (EmitContext ec)
2126                 {
2127                         // FIXME: Implement.
2128                 }
2129         }
2130         
2131         public class CheckedExpr : Expression {
2132
2133                 public readonly Expression Expr;
2134
2135                 public CheckedExpr (Expression e)
2136                 {
2137                         Expr = e;
2138                 }
2139
2140                 public override Expression Resolve (TypeContainer tc)
2141                 {
2142                         // FIXME : Implement !
2143                         return this;
2144                 }
2145
2146                 public override void Emit (EmitContext ec)
2147                 {
2148                 }
2149                 
2150         }
2151
2152         public class UnCheckedExpr : Expression {
2153
2154                 public readonly Expression Expr;
2155
2156                 public UnCheckedExpr (Expression e)
2157                 {
2158                         Expr = e;
2159                 }
2160
2161                 public override Expression Resolve (TypeContainer tc)
2162                 {
2163                         // FIXME : Implement !
2164                         return this;
2165                 }
2166
2167                 public override void Emit (EmitContext ec)
2168                 {
2169                 }
2170                 
2171         }
2172         
2173         public class ElementAccess : Expression {
2174                 
2175                 public readonly ArrayList  Arguments;
2176                 public readonly Expression Expr;
2177                 
2178                 public ElementAccess (Expression e, ArrayList e_list)
2179                 {
2180                         Expr = e;
2181                         Arguments = e_list;
2182                 }
2183
2184                 public override Expression Resolve (TypeContainer tc)
2185                 {
2186                         // FIXME : Implement
2187                         return this;
2188                 }
2189                 
2190                 public override void Emit (EmitContext ec)
2191                 {
2192                         // FIXME : Implement !
2193                 }
2194                 
2195         }
2196         
2197         public class BaseAccess : Expression {
2198
2199                 public enum BaseAccessType {
2200                         Member,
2201                         Indexer
2202                 };
2203                 
2204                 public readonly BaseAccessType BAType;
2205                 public readonly string         Member;
2206                 public readonly ArrayList      Arguments;
2207
2208                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
2209                 {
2210                         BAType = t;
2211                         Member = member;
2212                         Arguments = args;
2213                         
2214                 }
2215
2216                 public override Expression Resolve (TypeContainer tc)
2217                 {
2218                         // FIXME : Implement !
2219                         return this;
2220                 }
2221
2222                 public override void Emit (EmitContext ec)
2223                 {
2224                 }
2225         }
2226 }