2001-09-12 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                 
458                 public OpcodeCast (Expression child, Type return_type, OpCode op)
459                         : base (child, return_type)
460                         
461                 {
462                         this.op = op;
463                         this.op2 = OpCodes.Nop;
464                 }
465
466                 public OpcodeCast (Expression child, Type return_type, OpCode op, OpCode op2)
467                         : base (child, return_type)
468                         
469                 {
470                         this.op = op;
471                         this.op2 = op2;
472                 }
473
474                 public override Expression Resolve (TypeContainer tc)
475                 {
476                         // This should never be invoked, we are born in fully
477                         // initialized state.
478
479                         return this;
480                 }
481
482                 public override void Emit (EmitContext ec)
483                 {
484                         base.Emit (ec);
485                         ec.ig.Emit (op);
486                         
487                         if (!op2.Equals (OpCodes.Nop))
488                                 ec.ig.Emit (op2);
489                 }                       
490                 
491         }
492         
493         public class Unary : Expression {
494                 public enum Operator {
495                         Plus, Minus, Negate, BitComplement,
496                         Indirection, AddressOf, PreIncrement,
497                         PreDecrement, PostIncrement, PostDecrement
498                 }
499
500                 Operator   oper;
501                 Expression expr;
502                 
503                 public Unary (Operator op, Expression expr)
504                 {
505                         this.oper = op;
506                         this.expr = expr;
507                 }
508
509                 public Expression Expr {
510                         get {
511                                 return expr;
512                         }
513
514                         set {
515                                 expr = value;
516                         }
517                 }
518
519                 public Operator Oper {
520                         get {
521                                 return oper;
522                         }
523
524                         set {
525                                 oper = value;
526                         }
527                 }
528
529                 public override Expression Resolve (TypeContainer tc)
530                 {
531                         // FIXME: Implement;
532                         return this;
533                 }
534
535                 public override void Emit (EmitContext ec)
536                 {
537                 }
538         }
539
540         public class Probe : Expression {
541                 string probe_type;
542                 Expression expr;
543                 Operator oper;
544
545                 public enum Operator {
546                         Is, As
547                 }
548                 
549                 public Probe (Operator oper, Expression expr, string probe_type)
550                 {
551                         this.oper = oper;
552                         this.probe_type = probe_type;
553                         this.expr = expr;
554                 }
555
556                 public Operator Oper {
557                         get {
558                                 return oper;
559                         }
560                 }
561
562                 public Expression Expr {
563                         get {
564                                 return expr;
565                         }
566                 }
567
568                 public string ProbeType {
569                         get {
570                                 return probe_type;
571                         }
572                 }
573
574                 public override Expression Resolve (TypeContainer tc)
575                 {
576                         // FIXME: Implement;
577                         return this;
578                 }
579
580                 public override void Emit (EmitContext ec)
581                 {
582                 }
583         }
584         
585         public class Cast : Expression {
586                 string target_type;
587                 Expression expr;
588                 
589                 public Cast (string cast_type, Expression expr)
590                 {
591                         this.target_type = target_type;
592                         this.expr = expr;
593                 }
594
595                 public string TargetType {
596                         get {
597                                 return target_type;
598                         }
599                 }
600
601                 public Expression Expr {
602                         get {
603                                 return expr;
604                         }
605                         set {
606                                 expr = value;
607                         }
608                 }
609                 
610                 public override Expression Resolve (TypeContainer tc)
611                 {
612                         // FIXME: Implement;
613                         return this;
614                 }
615
616                 public override void Emit (EmitContext ec)
617                 {
618                 }
619         }
620
621         public class Binary : Expression {
622                 public enum Operator {
623                         Multiply, Divide, Modulo,
624                         Add, Substract,
625                         ShiftLeft, ShiftRight,
626                         LessThan, GreatherThan, LessOrEqual, GreatherOrEqual, 
627                         Equal, NotEqual,
628                         BitwiseAnd,
629                         ExclusiveOr,
630                         BitwiseOr,
631                         LogicalAnd,
632                         LogicalOr
633                 }
634
635                 Operator oper;
636                 Expression left, right;
637
638                 public Binary (Operator oper, Expression left, Expression right)
639                 {
640                         this.oper = oper;
641                         this.left = left;
642                         this.right = right;
643                 }
644
645                 public Operator Oper {
646                         get {
647                                 return oper;
648                         }
649                         set {
650                                 oper = value;
651                         }
652                 }
653                 
654                 public Expression Left {
655                         get {
656                                 return left;
657                         }
658                         set {
659                                 left = value;
660                         }
661                 }
662
663                 public Expression Right {
664                         get {
665                                 return right;
666                         }
667                         set {
668                                 right = value;
669                         }
670                 }
671
672
673                 // <summary>
674                 //   Retruns a stringified representation of the Operator
675                 // </summary>
676                 string OperName ()
677                 {
678                         switch (oper){
679                         case Operator.Multiply:
680                                 return "*";
681                         case Operator.Divide:
682                                 return "/";
683                         case Operator.Modulo:
684                                 return "%";
685                         case Operator.Add:
686                                 return "+";
687                         case Operator.Substract:
688                                 return "-";
689                         case Operator.ShiftLeft:
690                                 return "<<";
691                         case Operator.ShiftRight:
692                                 return ">>";
693                         case Operator.LessThan:
694                                 return "<";
695                         case Operator.GreatherThan:
696                                 return ">";
697                         case Operator.LessOrEqual:
698                                 return "<=";
699                         case Operator.GreatherOrEqual:
700                                 return ">=";
701                         case Operator.Equal:
702                                 return "==";
703                         case Operator.NotEqual:
704                                 return "!=";
705                         case Operator.BitwiseAnd:
706                                 return "&";
707                         case Operator.BitwiseOr:
708                                 return "|";
709                         case Operator.ExclusiveOr:
710                                 return "^";
711                         case Operator.LogicalOr:
712                                 return "||";
713                         case Operator.LogicalAnd:
714                                 return "&&";
715                         }
716
717                         return oper.ToString ();
718                 }
719
720                 Expression ForceConversion (Expression expr, Type target_type)
721                 {
722                         if (expr.Type == target_type)
723                                 return expr;
724
725                         return ConvertImplicit (expr, target_type);
726                 }
727                 
728                 //
729                 // Note that handling the case l == Decimal || r == Decimal
730                 // is taken care of by the Step 1 Operator Overload resolution.
731                 //
732                 void DoNumericPromotions (TypeContainer tc, Type l, Type r)
733                 {
734                         if (l == TypeManager.double_type || r == TypeManager.double_type){
735                                 //
736                                 // If either operand is of type double, the other operand is
737                                 // conveted to type double.
738                                 //
739                                 if (r != TypeManager.double_type)
740                                         right = ConvertImplicit (right, TypeManager.double_type);
741                                 if (l != TypeManager.double_type)
742                                         left = ConvertImplicit (left, TypeManager.double_type);
743                                 
744                                 type = TypeManager.double_type;
745                         } else if (l == TypeManager.float_type || r == TypeManager.float_type){
746                                 //
747                                 // if either operand is of type float, th eother operand is
748                                 // converd to type float.
749                                 //
750                                 if (r != TypeManager.double_type)
751                                         right = ConvertImplicit (right, TypeManager.float_type);
752                                 if (l != TypeManager.double_type)
753                                         left = ConvertImplicit (left, TypeManager.float_type);
754                                 type = TypeManager.float_type;
755                         } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
756                                 //
757                                 // If either operand is of type ulong, the other operand is
758                                 // converted to type ulong.  or an error ocurrs if the other
759                                 // operand is of type sbyte, short, int or long
760                                 //
761                                 Type other = null;
762                                 
763                                 if (l == TypeManager.uint64_type)
764                                         other = r;
765                                 else if (r == TypeManager.uint64_type)
766                                         other = l;
767
768                                 if ((other == TypeManager.sbyte_type) ||
769                                     (other == TypeManager.short_type) ||
770                                     (other == TypeManager.int32_type) ||
771                                     (other == TypeManager.int64_type)){
772                                         string oper = OperName ();
773                                         
774                                         tc.RootContext.Report.Error (34, "Operator `" + OperName ()
775                                                                      + "' is ambiguous on operands of type `"
776                                                                      + TypeManager.CSharpName (l) + "' "
777                                                                      + "and `" + TypeManager.CSharpName (r)
778                                                                      + "'");
779                                 }
780                                 type = TypeManager.uint64_type;
781                         } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
782                                 //
783                                 // If either operand is of type long, the other operand is converted
784                                 // to type long.
785                                 //
786                                 if (l != TypeManager.int64_type)
787                                         left = ConvertImplicit (left, TypeManager.int64_type);
788                                 if (r != TypeManager.int64_type)
789                                         right = ConvertImplicit (right, TypeManager.int64_type);
790
791                                 type = TypeManager.int64_type;
792                         } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
793                                 //
794                                 // If either operand is of type uint, and the other
795                                 // operand is of type sbyte, short or int, othe operands are
796                                 // converted to type long.
797                                 //
798                                 Type other = null;
799                                 
800                                 if (l == TypeManager.uint32_type)
801                                         other = r;
802                                 else if (r == TypeManager.uint32_type)
803                                         other = l;
804
805                                 if ((other == TypeManager.sbyte_type) ||
806                                     (other == TypeManager.short_type) ||
807                                     (other == TypeManager.int32_type)){
808                                         left = ForceConversion (left, TypeManager.int64_type);
809                                         right = ForceConversion (right, TypeManager.int64_type);
810                                         type = TypeManager.int64_type;
811                                 } else {
812                                         //
813                                         // if either operand is of type uint, the other
814                                         // operand is converd to type uint
815                                         //
816                                         left = ForceConversion (left, TypeManager.uint32_type);
817                                         right = ForceConversion (left, TypeManager.uint32_type);
818                                         type = TypeManager.uint32_type;
819                                 } 
820                         } else {
821                                 left = ForceConversion (left, TypeManager.int32_type);
822                                 right = ForceConversion (right, TypeManager.int32_type);
823                         }
824                 }
825
826                 void error19 (TypeContainer tc)
827                 {
828                         tc.RootContext.Report.Error (
829                                 19,
830                                 "Operator " + OperName () + " cannot be applied to operands of type `" +
831                                 TypeManager.CSharpName (left.Type) + "' and `" +
832                                 TypeManager.CSharpName (right.Type) + "'");
833                                                      
834                 }
835                 
836                 Expression CheckShiftArguments (TypeContainer tc)
837                 {
838                         Expression e;
839                         Type l = left.Type;
840                         Type r = right.Type;
841
842                         e = ForceConversion (right, TypeManager.int32_type);
843                         if (e == null){
844                                 error19 (tc);
845                                 return null;
846                         }
847                         right = e;
848
849                         if (((e = ConvertImplicit (left, TypeManager.int32_type)) != null) ||
850                             ((e = ConvertImplicit (left, TypeManager.uint32_type)) != null) ||
851                             ((e = ConvertImplicit (left, TypeManager.int64_type)) != null) ||
852                             ((e = ConvertImplicit (left, TypeManager.uint64_type)) != null)){
853                                 left = e;
854
855                                 return this;
856                         }
857                         error19 (tc);
858                         return null;
859                 }
860                 
861                 Expression ResolveOperator (TypeContainer tc)
862                 {
863                         Type l = left.Type;
864                         Type r = right.Type;
865
866                         //
867                         // Step 1: Perform Operator Overload location
868                         //
869
870                         
871                         //
872                         // Step 2: Default operations on CLI native types.
873                         //
874
875                         // Only perform numeric promotions on:
876                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
877                         //
878                         if (oper == Operator.ShiftLeft || oper == Operator.ShiftRight){
879                                 return CheckShiftArguments (tc);
880                         } else if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
881
882                                 if (l != TypeManager.bool_type || r != TypeManager.bool_type)
883                                         error19 (tc);
884                         } else
885                                 DoNumericPromotions (tc, l, r);
886
887                         if (oper == Operator.BitwiseAnd ||
888                             oper == Operator.BitwiseOr ||
889                             oper == Operator.ExclusiveOr){
890                                 if (!((l == TypeManager.int32_type) ||
891                                       (l == TypeManager.uint32_type) ||
892                                       (l == TypeManager.int64_type) ||
893                                       (l == TypeManager.uint64_type))){
894                                         error19 (tc);
895                                         return null;
896                                 }
897                         } else 
898                         
899                         if (left == null || right == null)
900                                 return null;
901
902                         return this;
903                 }
904                 
905                 public override Expression Resolve (TypeContainer tc)
906                 {
907                         left = left.Resolve (tc);
908                         right = right.Resolve (tc);
909
910                         if (left == null || right == null)
911                                 return null;
912                                         
913                         return ResolveOperator (tc);
914                 }
915
916                 public bool IsBranchable ()
917                 {
918                         if (oper == Operator.Equal ||
919                             oper == Operator.NotEqual ||
920                             oper == Operator.LessThan ||
921                             oper == Operator.GreatherThan ||
922                             oper == Operator.LessOrEqual ||
923                             oper == Operator.GreatherOrEqual){
924                                 return true;
925                         } else
926                                 return false;
927                 }
928
929                 // <summary>
930                 //   This entry point is used by routines that might want
931                 //   to emit a brfalse/brtrue after an expression, and instead
932                 //   they could use a more compact notation.
933                 //
934                 //   Typically the code would generate l.emit/r.emit, followed
935                 //   by the comparission and then a brtrue/brfalse.  The comparissions
936                 //   are sometimes inneficient (there are not as complete as the branches
937                 //   look for the hacks in Emit using double ceqs).
938                 //
939                 //   So for those cases we provide EmitBranchable that can emit the
940                 //   branch with the test
941                 // </summary>
942                 public void EmitBranchable (EmitContext ec, int target)
943                 {
944                         OpCode opcode;
945                         bool close_target = false;
946                         
947                         left.Emit (ec);
948                         right.Emit (ec);
949                         
950                         switch (oper){
951                         case Operator.Equal:
952                                 if (close_target)
953                                         opcode = OpCodes.Beq_S;
954                                 else
955                                         opcode = OpCodes.Beq;
956                                 break;
957
958                         case Operator.NotEqual:
959                                 if (close_target)
960                                         opcode = OpCodes.Bne_Un_S;
961                                 else
962                                         opcode = OpCodes.Bne_Un;
963                                 break;
964
965                         case Operator.LessThan:
966                                 if (close_target)
967                                         opcode = OpCodes.Blt_S;
968                                 else
969                                         opcode = OpCodes.Blt;
970                                 break;
971
972                         case Operator.GreatherThan:
973                                 if (close_target)
974                                         opcode = OpCodes.Bgt_S;
975                                 else
976                                         opcode = OpCodes.Bgt;
977                                 break;
978
979                         case Operator.LessOrEqual:
980                                 if (close_target)
981                                         opcode = OpCodes.Ble_S;
982                                 else
983                                         opcode = OpCodes.Ble;
984                                 break;
985
986                         case Operator.GreatherOrEqual:
987                                 if (close_target)
988                                         opcode = OpCodes.Bge_S;
989                                 else
990                                         opcode = OpCodes.Ble;
991                                 break;
992
993                         default:
994                                 Console.WriteLine ("EmitBranchable called for non-EmitBranchable operator: "
995                                                    + oper.ToString ());
996                                 opcode = OpCodes.Nop;
997                                 break;
998                         }
999
1000                         ec.ig.Emit (opcode, target);
1001                 }
1002                 
1003                 public override void Emit (EmitContext ec)
1004                 {
1005                         ILGenerator ig = ec.ig;
1006                         Type l = left.Type;
1007                         Type r = right.Type;
1008                         OpCode opcode;
1009                         
1010                         left.Emit (ec);
1011                         right.Emit (ec);
1012
1013                         switch (oper){
1014                         case Operator.Multiply:
1015                                 if (ec.CheckState){
1016                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1017                                                 opcode = OpCodes.Mul_Ovf;
1018                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1019                                                 opcode = OpCodes.Mul_Ovf_Un;
1020                                         else
1021                                                 opcode = OpCodes.Mul;
1022                                 } else
1023                                         opcode = OpCodes.Mul;
1024
1025                                 break;
1026
1027                         case Operator.Divide:
1028                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1029                                         opcode = OpCodes.Div_Un;
1030                                 else
1031                                         opcode = OpCodes.Div;
1032                                 break;
1033
1034                         case Operator.Modulo:
1035                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1036                                         opcode = OpCodes.Rem_Un;
1037                                 else
1038                                         opcode = OpCodes.Rem;
1039                                 break;
1040
1041                         case Operator.Add:
1042                                 if (ec.CheckState){
1043                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1044                                                 opcode = OpCodes.Add_Ovf;
1045                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1046                                                 opcode = OpCodes.Add_Ovf_Un;
1047                                         else
1048                                                 opcode = OpCodes.Mul;
1049                                 } else
1050                                         opcode = OpCodes.Add;
1051                                 break;
1052
1053                         case Operator.Substract:
1054                                 if (ec.CheckState){
1055                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1056                                                 opcode = OpCodes.Sub_Ovf;
1057                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1058                                                 opcode = OpCodes.Sub_Ovf_Un;
1059                                         else
1060                                                 opcode = OpCodes.Sub;
1061                                 } else
1062                                         opcode = OpCodes.Sub;
1063                                 break;
1064
1065                         case Operator.ShiftRight:
1066                                 opcode = OpCodes.Shr;
1067                                 break;
1068                                 
1069                         case Operator.ShiftLeft:
1070                                 opcode = OpCodes.Shl;
1071                                 break;
1072
1073                         case Operator.Equal:
1074                                 opcode = OpCodes.Ceq;
1075                                 break;
1076
1077                         case Operator.NotEqual:
1078                                 ec.ig.Emit (OpCodes.Ceq);
1079                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1080                                 
1081                                 opcode = OpCodes.Ceq;
1082                                 break;
1083
1084                         case Operator.LessThan:
1085                                 opcode = OpCodes.Clt;
1086                                 break;
1087
1088                         case Operator.GreatherThan:
1089                                 opcode = OpCodes.Cgt;
1090                                 break;
1091
1092                         case Operator.LessOrEqual:
1093                                 ec.ig.Emit (OpCodes.Cgt);
1094                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1095                                 
1096                                 opcode = OpCodes.Ceq;
1097                                 break;
1098
1099                         case Operator.GreatherOrEqual:
1100                                 ec.ig.Emit (OpCodes.Clt);
1101                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
1102                                 
1103                                 opcode = OpCodes.Sub;
1104                                 break;
1105
1106                         case Operator.LogicalOr:
1107                         case Operator.BitwiseOr:
1108                                 opcode = OpCodes.Or;
1109                                 break;
1110
1111                         case Operator.LogicalAnd:
1112                         case Operator.BitwiseAnd:
1113                                 opcode = OpCodes.And;
1114                                 break;
1115
1116                         case Operator.ExclusiveOr:
1117                                 opcode = OpCodes.Xor;
1118                                 break;
1119
1120                         default:
1121                                 Console.WriteLine ("This should not happen: Operator = " + oper.ToString ());
1122                                 opcode = OpCodes.Nop;
1123                                 break;
1124                         }
1125
1126                         ec.ig.Emit (opcode);
1127                 }
1128         }
1129
1130         public class Conditional : Expression {
1131                 Expression expr, trueExpr, falseExpr;
1132                 
1133                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
1134                 {
1135                         this.expr = expr;
1136                         this.trueExpr = trueExpr;
1137                         this.falseExpr = falseExpr;
1138                 }
1139
1140                 public Expression Expr {
1141                         get {
1142                                 return expr;
1143                         }
1144                 }
1145
1146                 public Expression TrueExpr {
1147                         get {
1148                                 return trueExpr;
1149                         }
1150                 }
1151
1152                 public Expression FalseExpr {
1153                         get {
1154                                 return falseExpr;
1155                         }
1156                 }
1157
1158                 public override Expression Resolve (TypeContainer tc)
1159                 {
1160                         // FIXME: Implement;
1161                         return this;
1162                 }
1163
1164                 public override void Emit (EmitContext ec)
1165                 {
1166                 }
1167         }
1168
1169         public class SimpleName : Expression {
1170                 string name;
1171                 
1172                 public SimpleName (string name)
1173                 {
1174                         this.name = name;
1175                 }
1176
1177                 public string Name {
1178                         get {
1179                                 return name;
1180                         }
1181                 }
1182
1183                 //
1184                 // Checks whether we are trying to access an instance
1185                 // property, method or field from a static body.
1186                 //
1187                 Expression MemberStaticCheck (Report r, Expression e)
1188                 {
1189                         if (e is FieldExpr){
1190                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
1191                                 
1192                                 if (!fi.IsStatic){
1193                                         r.Error (120,
1194                                                  "An object reference is required " +
1195                                                  "for the non-static field `"+name+"'");
1196                                         return null;
1197                                 }
1198                         } else if (e is MethodGroupExpr){
1199                                 // FIXME: Pending reorganization of MemberLookup
1200                                 // Basically at this point we should have the
1201                                 // best match already selected for us, and
1202                                 // we should only have to check a *single*
1203                                 // Method for its static on/off bit.
1204                                 return e;
1205                         } else if (e is PropertyExpr){
1206                                 if (!((PropertyExpr) e).IsStatic){
1207                                         r.Error (120,
1208                                                  "An object reference is required " +
1209                                                  "for the non-static property access `"+
1210                                                  name+"'");
1211                                         return null;
1212                                 }
1213                         }
1214
1215                         return e;
1216                 }
1217                 
1218                 //
1219                 // 7.5.2: Simple Names. 
1220                 //
1221                 // Local Variables and Parameters are handled at
1222                 // parse time, so they never occur as SimpleNames.
1223                 //
1224                 Expression ResolveSimpleName (TypeContainer tc)
1225                 {
1226                         Expression e;
1227                         Report r = tc.RootContext.Report;
1228
1229                         e = MemberLookup (tc.RootContext, tc.TypeBuilder, name, true);
1230                         if (e != null){
1231                                 if (e is TypeExpr)
1232                                         return e;
1233                                 if ((tc.ModFlags & Modifiers.STATIC) != 0)
1234                                         return MemberStaticCheck (r, e);
1235                                 else
1236                                         return e;
1237                         }
1238
1239                         //
1240                         // Do step 3 of the Simple Name resolution.
1241                         //
1242                         // FIXME: implement me.
1243                         
1244                         return this;
1245                 }
1246                 
1247                 //
1248                 // SimpleName needs to handle a multitude of cases:
1249                 //
1250                 // simple_names and qualified_identifiers are placed on
1251                 // the tree equally.
1252                 //
1253                 public override Expression Resolve (TypeContainer tc)
1254                 {
1255                         if (name.IndexOf (".") != -1)
1256                                 return ResolveMemberAccess (tc, name);
1257                         else
1258                                 return ResolveSimpleName (tc);
1259                 }
1260
1261                 public override void Emit (EmitContext ec)
1262                 {
1263                 }
1264         }
1265         
1266         public class LocalVariableReference : Expression {
1267                 public readonly string Name;
1268                 public readonly Block Block;
1269                 
1270                 public LocalVariableReference (Block block, string name)
1271                 {
1272                         Block = block;
1273                         Name = name;
1274                         eclass = ExprClass.Variable;
1275                 }
1276
1277                 public VariableInfo VariableInfo {
1278                         get {
1279                                 return (VariableInfo) Block.GetVariableInfo (Name);
1280                         }
1281                 }
1282                 
1283                 public override Expression Resolve (TypeContainer tc)
1284                 {
1285                         return this;
1286                 }
1287
1288                 public override void Emit (EmitContext ec)
1289                 {
1290                         Console.WriteLine ("Internal compiler error, LocalVariableReference should not be emitted");
1291                 }
1292         }
1293
1294         public class ParameterReference : Expression {
1295                 public readonly Parameters Pars;
1296                 public readonly String Name;
1297                 public readonly int Idx;
1298                 
1299                 public ParameterReference (Parameters pars, int idx, string name)
1300                 {
1301                         Pars = pars;
1302                         Idx  = idx;
1303                         Name = name;
1304                 }
1305
1306                 public override Expression Resolve (TypeContainer tc)
1307                 {
1308                         // FIXME: Implement;
1309                         return this;
1310                 }
1311
1312                 public override void Emit (EmitContext ec)
1313                 {
1314                 }
1315         }
1316         
1317         // <summary>
1318         //   Used for arguments to New(), Invocation()
1319         // </summary>
1320         public class Argument {
1321                 public enum AType {
1322                         Expression,
1323                         Ref,
1324                         Out
1325                 };
1326
1327                 public readonly AType Type;
1328                 Expression expr;
1329
1330                 public Argument (Expression expr, AType type)
1331                 {
1332                         this.expr = expr;
1333                         this.Type = type;
1334                 }
1335
1336                 public Expression Expr {
1337                         get {
1338                                 return expr;
1339                         }
1340                 }
1341
1342                 public bool Resolve (TypeContainer tc)
1343                 {
1344                         expr = expr.Resolve (tc);
1345                         return expr != null;
1346                 }
1347
1348                 public void Emit (EmitContext ec)
1349                 {
1350                         expr.Emit (ec);
1351                 }
1352         }
1353
1354         // <summary>
1355         //   Invocation of methods or delegates.
1356         // </summary>
1357         public class Invocation : Expression {
1358                 public readonly ArrayList Arguments;
1359                 Expression expr;
1360                 MethodInfo method = null;
1361                 
1362                 //
1363                 // arguments is an ArrayList, but we do not want to typecast,
1364                 // as it might be null.
1365                 //
1366                 // FIXME: only allow expr to be a method invocation or a
1367                 // delegate invocation (7.5.5)
1368                 //
1369                 public Invocation (Expression expr, ArrayList arguments)
1370                 {
1371                         this.expr = expr;
1372                         Arguments = arguments;
1373                 }
1374
1375                 public Expression Expr {
1376                         get {
1377                                 return expr;
1378                         }
1379                 }
1380
1381                 /// <summary>
1382                 ///   Computes whether Argument `a' and the ParameterInfo `pi' are
1383                 ///   compatible, and if so, how good is the match (in terms of
1384                 ///   "better conversions" (7.4.2.3).
1385                 ///
1386                 ///   0   is the best possible match.
1387                 ///   -1  represents a type mismatch.
1388                 ///   -2  represents a ref/out mismatch.
1389                 /// </summary>
1390                 static int Badness (Argument a, ParameterInfo pi)
1391                 {
1392                         if (pi.ParameterType == a.Expr.Type)
1393                                 return 0;
1394
1395                         // FIXME: Implement implicit conversions here.
1396                         // FIXME: Implement better conversion here.
1397                         
1398                         return -1;
1399                 }
1400
1401                 // <summary>
1402                 //   Find the Applicable Function Members (7.4.2.1)
1403                 // </summary>
1404                 static MethodInfo OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
1405                 {
1406                         ArrayList afm = new ArrayList ();
1407                         int best_match = 10000;
1408                         int best_match_idx = -1;
1409                         MethodInfo method = null;
1410                         
1411                         for (int i = me.Methods.Length; i > 0; ){
1412                                 i--;
1413                                 ParameterInfo [] pi = me.Methods [i].GetParameters ();
1414
1415                                 //
1416                                 // Compute how good this is
1417                                 //
1418                                 if (pi.Length == Arguments.Count){
1419                                         int badness = 0;
1420                                         
1421                                         for (int j = Arguments.Count; j > 0;){
1422                                                 int x;
1423                                                 j--;
1424
1425                                                 Argument a = (Argument) Arguments [j];
1426
1427                                                 x = Badness (a, pi [j]);
1428
1429                                                 if (x < 0){
1430                                                         // FIXME: report nice error.
1431                                                 } else
1432                                                         badness += x;
1433                                         }
1434
1435                                         if (badness < best_match){
1436                                                 best_match = badness;
1437                                                 method = me.Methods [i];
1438                                                 best_match_idx = i;
1439                                         }
1440                                 }
1441                         }
1442
1443                         if (best_match_idx == -1)
1444                                 return null;
1445                         
1446                         return method;
1447                 }
1448
1449                         
1450                 public override Expression Resolve (TypeContainer tc)
1451                 {
1452                         //
1453                         // First, resolve the expression that is used to
1454                         // trigger the invocation
1455                         //
1456                         this.expr = expr.Resolve (tc);
1457                         if (this.expr == null)
1458                                 return null;
1459
1460                         if (!(this.expr is MethodGroupExpr)){
1461                                 tc.RootContext.Report.Error (118,
1462                                        "Denotes an " + this.expr.ExprClass + " while a method was expected");
1463                                 return null;
1464                         }
1465
1466                         //
1467                         // Next, evaluate all the expressions in the argument list
1468                         //
1469                         if (Arguments != null){
1470                                 for (int i = Arguments.Count; i > 0;){
1471                                         --i;
1472                                         Argument a = (Argument) Arguments [i];
1473
1474                                         if (!a.Resolve (tc))
1475                                                 return null;
1476                                 }
1477                         }
1478
1479                         method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
1480
1481                         if (method == null){
1482                                 tc.RootContext.Report.Error (-6,
1483                                 "Figure out error: Can not find a good function for this argument list");
1484                                 return null;
1485                         }
1486
1487                         Console.WriteLine ("Found a method! " + method);
1488
1489                         return this;
1490                 }
1491
1492                 public override void Emit (EmitContext ec)
1493                 {
1494                         int top = Arguments.Count;
1495
1496                         for (int i = 0; i < top; i++){
1497                                 Argument a = (Argument) Arguments [i];
1498
1499                                 a.Emit (ec);
1500                         }
1501
1502                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
1503                 }
1504         }
1505
1506         public class New : Expression {
1507
1508                 public enum NType {
1509                         Object,
1510                         Array
1511                 };
1512
1513                 public readonly NType     NewType;
1514                 public readonly ArrayList Arguments;
1515                 public readonly string    RequestedType;
1516                 // These are for the case when we have an array
1517                 public readonly string    Rank;
1518                 public readonly ArrayList Indices;
1519                 public readonly ArrayList Initializers;
1520                 
1521
1522                 public New (string requested_type, ArrayList arguments)
1523                 {
1524                         RequestedType = requested_type;
1525                         Arguments = arguments;
1526                         NewType = NType.Object;
1527                 }
1528
1529                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
1530                 {
1531                         RequestedType = requested_type;
1532                         Indices       = exprs;
1533                         Rank          = rank;
1534                         Initializers  = initializers;
1535                         NewType       = NType.Array;
1536                 }
1537                 
1538                 public override Expression Resolve (TypeContainer tc)
1539                 {
1540                         // FIXME: Implement;
1541                         return this;
1542                 }
1543
1544                 public override void Emit (EmitContext ec)
1545                 {
1546                 }
1547         }
1548
1549         public class This : Expression {
1550                 public override Expression Resolve (TypeContainer tc)
1551                 {
1552                         // FIXME: Implement;
1553                         return this;
1554                 }
1555
1556                 public override void Emit (EmitContext ec)
1557                 {
1558                 }
1559         }
1560
1561         public class TypeOf : Expression {
1562                 public readonly string QueriedType;
1563                 
1564                 public TypeOf (string queried_type)
1565                 {
1566                         QueriedType = queried_type;
1567                 }
1568
1569                 public override Expression Resolve (TypeContainer tc)
1570                 {
1571                         // FIXME: Implement;
1572                         return this;
1573                 }
1574
1575                 public override void Emit (EmitContext ec)
1576                 {
1577                 }
1578         }
1579
1580         public class SizeOf : Expression {
1581                 public readonly string QueriedType;
1582                 
1583                 public SizeOf (string queried_type)
1584                 {
1585                         this.QueriedType = queried_type;
1586                 }
1587
1588                 public override Expression Resolve (TypeContainer tc)
1589                 {
1590                         // FIXME: Implement;
1591                         return this;
1592                 }
1593
1594                 public override void Emit (EmitContext ec)
1595                 {
1596                 }
1597         }
1598
1599         public class MemberAccess : Expression {
1600                 public readonly string Identifier;
1601                 Expression expr;
1602                 
1603                 public MemberAccess (Expression expr, string id)
1604                 {
1605                         this.expr = expr;
1606                         Identifier = id;
1607                 }
1608
1609                 public Expression Expr {
1610                         get {
1611                                 return expr;
1612                         }
1613                 }
1614                 
1615                 public override Expression Resolve (TypeContainer tc)
1616                 {
1617                         // FIXME: Implement;
1618                         return this;
1619                 }
1620
1621                 public override void Emit (EmitContext ec)
1622                 {
1623                 }
1624
1625         }
1626
1627         // <summary>
1628         //   Nodes of type Namespace are created during the semantic
1629         //   analysis to resolve member_access/qualified_identifier/simple_name
1630         //   accesses.
1631         //
1632         //   They are born `resolved'. 
1633         // </summary>
1634         public class NamespaceExpr : Expression {
1635                 public readonly string Name;
1636                 
1637                 public NamespaceExpr (string name)
1638                 {
1639                         Name = name;
1640                         eclass = ExprClass.Namespace;
1641                 }
1642
1643                 public override Expression Resolve (TypeContainer tc)
1644                 {
1645                         return this;
1646                 }
1647
1648                 public override void Emit (EmitContext ec)
1649                 {
1650                 }
1651         }
1652
1653         // <summary>
1654         //   Fully resolved expression that evaluates to a type
1655         // </summary>
1656         public class TypeExpr : Expression {
1657                 public TypeExpr (Type t)
1658                 {
1659                         Type = t;
1660                         eclass = ExprClass.Type;
1661                 }
1662
1663                 override public Expression Resolve (TypeContainer tc)
1664                 {
1665                         return this;
1666                 }
1667
1668                 override public void Emit (EmitContext ec)
1669                 {
1670                         
1671                 }
1672         }
1673
1674         // <summary>
1675         //   Fully resolved expression that evaluates to a type
1676         // </summary>
1677         public class MethodGroupExpr : Expression {
1678                 public readonly MethodInfo [] Methods;
1679                 
1680                 public MethodGroupExpr (MemberInfo [] mi)
1681                 {
1682                         Methods = new MethodInfo [mi.Length];
1683                         mi.CopyTo (Methods, 0);
1684                         eclass = ExprClass.MethodGroup;
1685                 }
1686
1687                 override public Expression Resolve (TypeContainer tc)
1688                 {
1689                         return this;
1690                 }
1691
1692                 override public void Emit (EmitContext ec)
1693                 {
1694                         
1695                 }
1696         }
1697         
1698         public class BuiltinTypeAccess : Expression {
1699                 public readonly string AccessBase;
1700                 public readonly string Method;
1701                 
1702                 public BuiltinTypeAccess (string type, string method)
1703                 {
1704                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
1705                         AccessBase = type;
1706                         Method = method;
1707                 }
1708
1709                 public override Expression Resolve (TypeContainer tc)
1710                 {
1711                         // FIXME: Implement;
1712                         return this;
1713                 }
1714
1715                 public override void Emit (EmitContext ec)
1716                 {
1717                 }
1718         }
1719
1720
1721         //   Fully resolved expression that evaluates to a Field
1722         // </summary>
1723         public class FieldExpr : Expression {
1724                 public readonly FieldInfo FieldInfo;
1725
1726                 public FieldExpr (FieldInfo fi)
1727                 {
1728                         FieldInfo = fi;
1729                         eclass = ExprClass.Variable;
1730                 }
1731
1732                 override public Expression Resolve (TypeContainer tc)
1733                 {
1734                         // We are born in resolved state. 
1735                         return this;
1736                 }
1737
1738                 override public void Emit (EmitContext ec)
1739                 {
1740                         // FIXME: Assert that this should not be reached?
1741                 }
1742         }
1743         
1744         // <summary>
1745         //   Fully resolved expression that evaluates to a Property
1746         // </summary>
1747         public class PropertyExpr : Expression {
1748                 public readonly PropertyInfo PropertyInfo;
1749                 public readonly bool IsStatic;
1750                 
1751                 public PropertyExpr (PropertyInfo pi)
1752                 {
1753                         PropertyInfo = pi;
1754                         eclass = ExprClass.PropertyAccess;
1755                         IsStatic = false;
1756                                 
1757                         MethodInfo [] acc = pi.GetAccessors ();
1758
1759                         for (int i = 0; i < acc.Length; i++)
1760                                 if (acc [i].IsStatic)
1761                                         IsStatic = true;
1762                 }
1763
1764                 override public Expression Resolve (TypeContainer tc)
1765                 {
1766                         // We are born in resolved state. 
1767                         return this;
1768                 }
1769
1770                 override public void Emit (EmitContext ec)
1771                 {
1772                         // FIXME: Implement.
1773                 }
1774         }
1775
1776         // <summary>
1777         //   Fully resolved expression that evaluates to a Property
1778         // </summary>
1779         public class EventExpr : Expression {
1780                 public readonly EventInfo EventInfo;
1781                 
1782                 public EventExpr (EventInfo ei)
1783                 {
1784                         EventInfo = ei;
1785                         eclass = ExprClass.EventAccess;
1786                 }
1787
1788                 override public Expression Resolve (TypeContainer tc)
1789                 {
1790                         // We are born in resolved state. 
1791                         return this;
1792                 }
1793
1794                 override public void Emit (EmitContext ec)
1795                 {
1796                         // FIXME: Implement.
1797                 }
1798         }
1799         
1800         public class CheckedExpr : Expression {
1801
1802                 public readonly Expression Expr;
1803
1804                 public CheckedExpr (Expression e)
1805                 {
1806                         Expr = e;
1807                 }
1808
1809                 public override Expression Resolve (TypeContainer tc)
1810                 {
1811                         // FIXME : Implement !
1812                         return this;
1813                 }
1814
1815                 public override void Emit (EmitContext ec)
1816                 {
1817                 }
1818                 
1819         }
1820
1821         public class UnCheckedExpr : Expression {
1822
1823                 public readonly Expression Expr;
1824
1825                 public UnCheckedExpr (Expression e)
1826                 {
1827                         Expr = e;
1828                 }
1829
1830                 public override Expression Resolve (TypeContainer tc)
1831                 {
1832                         // FIXME : Implement !
1833                         return this;
1834                 }
1835
1836                 public override void Emit (EmitContext ec)
1837                 {
1838                 }
1839                 
1840         }
1841
1842                 public class ElementAccess : Expression {
1843
1844                 public readonly ArrayList  Arguments;
1845                 public readonly Expression Expr;
1846
1847                 public ElementAccess (Expression e, ArrayList e_list)
1848                 {
1849                         Expr = e;
1850                         Arguments = e_list;
1851                 }
1852
1853                 public override Expression Resolve (TypeContainer tc)
1854                 {
1855                         // FIXME : Implement
1856                         return this;
1857                 }
1858
1859                 public override void Emit (EmitContext ec)
1860                 {
1861                         // FIXME : Implement !
1862                 }
1863
1864         }
1865
1866         public class BaseAccess : Expression {
1867
1868                 public enum BaseAccessType {
1869                         Member,
1870                         Indexer
1871                 };
1872                 
1873                 public readonly BaseAccessType BAType;
1874                 public readonly string         Member;
1875                 public readonly ArrayList      Arguments;
1876
1877                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
1878                 {
1879                         BAType = t;
1880                         Member = member;
1881                         Arguments = args;
1882                         
1883                 }
1884
1885                 public override Expression Resolve (TypeContainer tc)
1886                 {
1887                         // FIXME : Implement !
1888                         return this;
1889                 }
1890
1891                 public override void Emit (EmitContext ec)
1892                 {
1893                 }
1894         }
1895 }