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