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