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                 static ParameterData GetParameterData (TypeContainer tc, MethodBase mb)
1455                 {
1456                         object pd = method_parameter_cache [mb];
1457
1458                         if (pd != null)
1459                                 return (ParameterData) pd;
1460
1461                         if (mb is MethodBuilder){
1462                                 Method m = tc.LookupMethodByBuilder ((MethodBuilder) mb);
1463
1464                                 InternalParameters ip = m.GetParameters ();
1465                                 method_parameter_cache [mb] = ip;
1466
1467                                 return (ParameterData) ip;
1468                         } else {
1469                                 ParameterInfo [] pi = mb.GetParameters ();
1470                                 ReflectionParameters rp = new ReflectionParameters (pi);
1471                                 method_parameter_cache [mb] = rp;
1472
1473                                 return (ParameterData) rp;
1474                         }
1475                 }
1476                 
1477                 // <summary>
1478                 //   Find the Applicable Function Members (7.4.2.1)
1479                 // </summary>
1480                 static MethodInfo OverloadResolve (TypeContainer tc, MethodGroupExpr me, ArrayList Arguments)
1481                 {
1482                         ArrayList afm = new ArrayList ();
1483                         int best_match = 10000;
1484                         int best_match_idx = -1;
1485                         MethodInfo method = null;
1486                         
1487                         for (int i = me.Methods.Length; i > 0; ){
1488                                 i--;
1489                                 MethodBase mb = me.Methods [i];
1490                                 ParameterData pd;
1491
1492                                 pd = GetParameterData (tc, mb);
1493
1494                                 //
1495                                 // Compute how good this is
1496                                 //
1497                                 if (pd.Count == Arguments.Count){
1498                                         int badness = 0;
1499                                         
1500                                         for (int j = Arguments.Count; j > 0;){
1501                                                 int x;
1502                                                 j--;
1503                                                 
1504                                                 Argument a = (Argument) Arguments [j];
1505
1506                                                 x = Badness (a, pd.ParameterType (j));
1507                                                 
1508                                                 if (x < 0){
1509                                                         badness = best_match;
1510                                                         continue;
1511                                                 }
1512                                                 
1513                                                 badness += x;
1514                                         }
1515                                         
1516                                         if (badness < best_match){
1517                                                 best_match = badness;
1518                                                 method = me.Methods [i];
1519                                                 best_match_idx = i;
1520                                         }
1521                                 }
1522                         }
1523
1524                         if (best_match_idx == -1)
1525                                 return null;
1526                         
1527                         return method;
1528                 }
1529
1530                         
1531                 public override Expression Resolve (TypeContainer tc)
1532                 {
1533                         //
1534                         // First, resolve the expression that is used to
1535                         // trigger the invocation
1536                         //
1537                         this.expr = expr.Resolve (tc);
1538                         if (this.expr == null)
1539                                 return null;
1540
1541                         if (!(this.expr is MethodGroupExpr)){
1542                                 tc.RootContext.Report.Error (118,
1543                                        "Denotes an " + this.expr.ExprClass + " while a method was expected");
1544                                 return null;
1545                         }
1546
1547                         if (method_parameter_cache == null)
1548                                 method_parameter_cache = new Hashtable ();
1549
1550                         //
1551                         // Next, evaluate all the expressions in the argument list
1552                         //
1553                         if (Arguments != null){
1554                                 for (int i = Arguments.Count; i > 0;){
1555                                         --i;
1556                                         Argument a = (Argument) Arguments [i];
1557
1558                                         if (!a.Resolve (tc))
1559                                                 return null;
1560                                 }
1561                         }
1562
1563                         method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments);
1564
1565                         if (method == null){
1566                                 tc.RootContext.Report.Error (-6,
1567                                 "Figure out error: Can not find a good function for this argument list");
1568                                 return null;
1569                         }
1570
1571                         type = method.ReturnType;
1572                         return this;
1573                 }
1574
1575                 public override void Emit (EmitContext ec)
1576                 {
1577                         int top = Arguments.Count;
1578
1579                         for (int i = 0; i < top; i++){
1580                                 Argument a = (Argument) Arguments [i];
1581
1582                                 a.Emit (ec);
1583                         }
1584
1585                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
1586                 }
1587         }
1588
1589         public class New : Expression {
1590
1591                 public enum NType {
1592                         Object,
1593                         Array
1594                 };
1595
1596                 public readonly NType     NewType;
1597                 public readonly ArrayList Arguments;
1598                 public readonly string    RequestedType;
1599                 // These are for the case when we have an array
1600                 public readonly string    Rank;
1601                 public readonly ArrayList Indices;
1602                 public readonly ArrayList Initializers;
1603                 
1604
1605                 public New (string requested_type, ArrayList arguments)
1606                 {
1607                         RequestedType = requested_type;
1608                         Arguments = arguments;
1609                         NewType = NType.Object;
1610                 }
1611
1612                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
1613                 {
1614                         RequestedType = requested_type;
1615                         Indices       = exprs;
1616                         Rank          = rank;
1617                         Initializers  = initializers;
1618                         NewType       = NType.Array;
1619                 }
1620                 
1621                 public override Expression Resolve (TypeContainer tc)
1622                 {
1623                         // FIXME: Implement;
1624                         return this;
1625                 }
1626
1627                 public override void Emit (EmitContext ec)
1628                 {
1629                 }
1630         }
1631
1632         public class This : Expression {
1633                 public override Expression Resolve (TypeContainer tc)
1634                 {
1635                         // FIXME: Implement;
1636                         return this;
1637                 }
1638
1639                 public override void Emit (EmitContext ec)
1640                 {
1641                 }
1642         }
1643
1644         public class TypeOf : Expression {
1645                 public readonly string QueriedType;
1646                 
1647                 public TypeOf (string queried_type)
1648                 {
1649                         QueriedType = queried_type;
1650                 }
1651
1652                 public override Expression Resolve (TypeContainer tc)
1653                 {
1654                         // FIXME: Implement;
1655                         return this;
1656                 }
1657
1658                 public override void Emit (EmitContext ec)
1659                 {
1660                 }
1661         }
1662
1663         public class SizeOf : Expression {
1664                 public readonly string QueriedType;
1665                 
1666                 public SizeOf (string queried_type)
1667                 {
1668                         this.QueriedType = queried_type;
1669                 }
1670
1671                 public override Expression Resolve (TypeContainer tc)
1672                 {
1673                         // FIXME: Implement;
1674                         return this;
1675                 }
1676
1677                 public override void Emit (EmitContext ec)
1678                 {
1679                 }
1680         }
1681
1682         public class MemberAccess : Expression {
1683                 public readonly string Identifier;
1684                 Expression expr;
1685                 
1686                 public MemberAccess (Expression expr, string id)
1687                 {
1688                         this.expr = expr;
1689                         Identifier = id;
1690                 }
1691
1692                 public Expression Expr {
1693                         get {
1694                                 return expr;
1695                         }
1696                 }
1697                 
1698                 public override Expression Resolve (TypeContainer tc)
1699                 {
1700                         // FIXME: Implement;
1701                         return this;
1702                 }
1703
1704                 public override void Emit (EmitContext ec)
1705                 {
1706                 }
1707
1708         }
1709
1710         // <summary>
1711         //   Nodes of type Namespace are created during the semantic
1712         //   analysis to resolve member_access/qualified_identifier/simple_name
1713         //   accesses.
1714         //
1715         //   They are born `resolved'. 
1716         // </summary>
1717         public class NamespaceExpr : Expression {
1718                 public readonly string Name;
1719                 
1720                 public NamespaceExpr (string name)
1721                 {
1722                         Name = name;
1723                         eclass = ExprClass.Namespace;
1724                 }
1725
1726                 public override Expression Resolve (TypeContainer tc)
1727                 {
1728                         return this;
1729                 }
1730
1731                 public override void Emit (EmitContext ec)
1732                 {
1733                 }
1734         }
1735
1736         // <summary>
1737         //   Fully resolved expression that evaluates to a type
1738         // </summary>
1739         public class TypeExpr : Expression {
1740                 public TypeExpr (Type t)
1741                 {
1742                         Type = t;
1743                         eclass = ExprClass.Type;
1744                 }
1745
1746                 override public Expression Resolve (TypeContainer tc)
1747                 {
1748                         return this;
1749                 }
1750
1751                 override public void Emit (EmitContext ec)
1752                 {
1753                         
1754                 }
1755         }
1756
1757         // <summary>
1758         //   Fully resolved expression that evaluates to a type
1759         // </summary>
1760         public class MethodGroupExpr : Expression {
1761                 public readonly MethodInfo [] Methods;
1762                 
1763                 public MethodGroupExpr (MemberInfo [] mi)
1764                 {
1765                         Methods = new MethodInfo [mi.Length];
1766                         mi.CopyTo (Methods, 0);
1767                         eclass = ExprClass.MethodGroup;
1768                 }
1769
1770                 override public Expression Resolve (TypeContainer tc)
1771                 {
1772                         return this;
1773                 }
1774
1775                 override public void Emit (EmitContext ec)
1776                 {
1777                         
1778                 }
1779         }
1780         
1781         public class BuiltinTypeAccess : Expression {
1782                 public readonly string AccessBase;
1783                 public readonly string Method;
1784                 
1785                 public BuiltinTypeAccess (string type, string method)
1786                 {
1787                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
1788                         AccessBase = type;
1789                         Method = method;
1790                 }
1791
1792                 public override Expression Resolve (TypeContainer tc)
1793                 {
1794                         // FIXME: Implement;
1795                         return this;
1796                 }
1797
1798                 public override void Emit (EmitContext ec)
1799                 {
1800                 }
1801         }
1802
1803
1804         //   Fully resolved expression that evaluates to a Field
1805         // </summary>
1806         public class FieldExpr : Expression {
1807                 public readonly FieldInfo FieldInfo;
1808
1809                 public FieldExpr (FieldInfo fi)
1810                 {
1811                         FieldInfo = fi;
1812                         eclass = ExprClass.Variable;
1813                 }
1814
1815                 override public Expression Resolve (TypeContainer tc)
1816                 {
1817                         // We are born in resolved state. 
1818                         return this;
1819                 }
1820
1821                 override public void Emit (EmitContext ec)
1822                 {
1823                         // FIXME: Assert that this should not be reached?
1824                 }
1825         }
1826         
1827         // <summary>
1828         //   Fully resolved expression that evaluates to a Property
1829         // </summary>
1830         public class PropertyExpr : Expression {
1831                 public readonly PropertyInfo PropertyInfo;
1832                 public readonly bool IsStatic;
1833                 
1834                 public PropertyExpr (PropertyInfo pi)
1835                 {
1836                         PropertyInfo = pi;
1837                         eclass = ExprClass.PropertyAccess;
1838                         IsStatic = false;
1839                                 
1840                         MethodInfo [] acc = pi.GetAccessors ();
1841
1842                         for (int i = 0; i < acc.Length; i++)
1843                                 if (acc [i].IsStatic)
1844                                         IsStatic = true;
1845                 }
1846
1847                 override public Expression Resolve (TypeContainer tc)
1848                 {
1849                         // We are born in resolved state. 
1850                         return this;
1851                 }
1852
1853                 override public void Emit (EmitContext ec)
1854                 {
1855                         // FIXME: Implement.
1856                 }
1857         }
1858
1859         // <summary>
1860         //   Fully resolved expression that evaluates to a Property
1861         // </summary>
1862         public class EventExpr : Expression {
1863                 public readonly EventInfo EventInfo;
1864                 
1865                 public EventExpr (EventInfo ei)
1866                 {
1867                         EventInfo = ei;
1868                         eclass = ExprClass.EventAccess;
1869                 }
1870
1871                 override public Expression Resolve (TypeContainer tc)
1872                 {
1873                         // We are born in resolved state. 
1874                         return this;
1875                 }
1876
1877                 override public void Emit (EmitContext ec)
1878                 {
1879                         // FIXME: Implement.
1880                 }
1881         }
1882         
1883         public class CheckedExpr : Expression {
1884
1885                 public readonly Expression Expr;
1886
1887                 public CheckedExpr (Expression e)
1888                 {
1889                         Expr = e;
1890                 }
1891
1892                 public override Expression Resolve (TypeContainer tc)
1893                 {
1894                         // FIXME : Implement !
1895                         return this;
1896                 }
1897
1898                 public override void Emit (EmitContext ec)
1899                 {
1900                 }
1901                 
1902         }
1903
1904         public class UnCheckedExpr : Expression {
1905
1906                 public readonly Expression Expr;
1907
1908                 public UnCheckedExpr (Expression e)
1909                 {
1910                         Expr = e;
1911                 }
1912
1913                 public override Expression Resolve (TypeContainer tc)
1914                 {
1915                         // FIXME : Implement !
1916                         return this;
1917                 }
1918
1919                 public override void Emit (EmitContext ec)
1920                 {
1921                 }
1922                 
1923         }
1924
1925                 public class ElementAccess : Expression {
1926
1927                 public readonly ArrayList  Arguments;
1928                 public readonly Expression Expr;
1929
1930                 public ElementAccess (Expression e, ArrayList e_list)
1931                 {
1932                         Expr = e;
1933                         Arguments = e_list;
1934                 }
1935
1936                 public override Expression Resolve (TypeContainer tc)
1937                 {
1938                         // FIXME : Implement
1939                         return this;
1940                 }
1941
1942                 public override void Emit (EmitContext ec)
1943                 {
1944                         // FIXME : Implement !
1945                 }
1946
1947         }
1948
1949         public class BaseAccess : Expression {
1950
1951                 public enum BaseAccessType {
1952                         Member,
1953                         Indexer
1954                 };
1955                 
1956                 public readonly BaseAccessType BAType;
1957                 public readonly string         Member;
1958                 public readonly ArrayList      Arguments;
1959
1960                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
1961                 {
1962                         BAType = t;
1963                         Member = member;
1964                         Arguments = args;
1965                         
1966                 }
1967
1968                 public override Expression Resolve (TypeContainer tc)
1969                 {
1970                         // FIXME : Implement !
1971                         return this;
1972                 }
1973
1974                 public override void Emit (EmitContext ec)
1975                 {
1976                 }
1977         }
1978 }