2001-09-08 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 namespace CIR {
10         using System.Collections;
11         using System.Diagnostics;
12         using System;
13         using System.Reflection;
14         using System.Reflection.Emit;
15
16         // <remarks>
17         //   The ExprClass class contains the is used to pass the 
18         //   classification of an expression (value, variable, namespace,
19         //   type, method group, property access, event access, indexer access,
20         //   nothing).
21         // </remarks>
22         public enum ExprClass {
23                 Invalid,
24                 
25                 Value, Variable, Namespace, Type,
26                 MethodGroup, PropertyAccess,
27                 EventAccess, IndexerAccess, Nothing, 
28         }
29
30         // <remarks>
31         //   Base class for expressions
32         // </remarks>
33         public abstract class Expression {
34                 protected ExprClass eclass;
35                 protected Type      type;
36                 
37                 public Type Type {
38                         get {
39                                 return type;
40                         }
41
42                         set {
43                                 type = value;
44                         }
45                 }
46
47                 public ExprClass ExprClass {
48                         get {
49                                 return eclass;
50                         }
51
52                         set {
53                                 eclass = value;
54                         }
55                 }
56
57                 public abstract Expression Resolve (TypeContainer tc);
58                 public abstract void Emit (EmitContext ec);
59                 
60                 // <summary>
61                 //   Protected constructor.  Only derivate types should
62                 //   be able to be created
63                 // </summary>
64
65                 protected Expression ()
66                 {
67                         eclass = ExprClass.Invalid;
68                         type = null;
69                 }
70
71                 // 
72                 // Returns a fully formed expression after a MemberLookup
73                 //
74                 static Expression ExprClassFromMemberInfo (MemberInfo mi)
75                 {
76                         if (mi is EventInfo){
77                                 // FIXME: Implement
78                                 return null;
79                         } else if (mi is FieldInfo){
80                                 return new FieldExpr ((FieldInfo) mi);
81                         } else if (mi is PropertyInfo){
82                                 return new PropertyExpr ((PropertyInfo) mi);
83                         } else if (mi is Type)
84                                 return new TypeExpr ((Type) mi);
85
86                         return null;
87                 }
88                 
89                 //
90                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
91                 //
92                 // FIXME: We need to cope with access permissions here, or this wont
93                 // work!
94                 //
95                 // This code could use some optimizations, but we need to do some
96                 // measurements.  For example, we could use a delegate to `flag' when
97                 // something can not any longer be a method-group (because it is something
98                 // else).
99                 //
100                 // Return values:
101                 //     If the return value is an Array, then it is an array of
102                 //     MethodInfos
103                 //   
104                 //     If the return value is an MemberInfo, it is anything, but a Method
105                 //
106                 //     null on error.
107                 //
108                 // FIXME: When calling MemberLookup inside an `Invocation', we should pass
109                 // the arguments here and have MemberLookup return only the methods that
110                 // match the argument count/type, unlike we are doing now (we delay this
111                 // decision).
112                 //
113                 // This is so we can catch correctly attempts to invoke instance methods
114                 // from a static body (scan for error 120 in ResolveSimpleName).
115                 // 
116                 protected static Expression MemberLookup (Report r, Type t, string name, bool same_type)
117                 {
118                         MemberTypes mt =
119                                 // MemberTypes.Constructor |
120                                 MemberTypes.Event       |
121                                 MemberTypes.Field       |
122                                 MemberTypes.Method      |
123                                 MemberTypes.NestedType  |
124                                 MemberTypes.Property;
125                         
126                         BindingFlags bf =
127                                 BindingFlags.Public |
128                                 BindingFlags.Static |
129                                 BindingFlags.Instance;
130                         
131                         if (same_type)
132                                 bf |= BindingFlags.NonPublic;
133
134                         
135                         MemberInfo [] mi = t.FindMembers (mt, bf, Type.FilterName, name);
136
137                         if (mi.Length == 1 && !(mi [0] is MethodInfo))
138                                 return Expression.ExprClassFromMemberInfo (mi [0]);
139
140                         for (int i = 0; i < mi.Length; i++)
141                                 if (!(mi [i] is MethodInfo)){
142                                         r.Error (-5, "Do not know how to reproduce this case: Methods and non-Method with the same name, report this please");
143                                         
144                                 }
145
146                         return new MethodGroupExpr (mi);
147                 }
148                 
149                 // <summary>
150                 //   Resolves the E in `E.I' side for a member_access
151                 //
152                 // This is suboptimal and should be merged with ResolveMemberAccess
153                 static Expression ResolvePrimary (TypeContainer tc, string name)
154                 {
155                         int dot_pos = name.LastIndexOf (".");
156
157                         if (tc.RootContext.IsNamespace (name))
158                                 return new NamespaceExpr (name);
159
160                         if (dot_pos != -1){
161                         } else {
162                                 Type t = tc.LookupType (name, false);
163
164                                 if (t != null)
165                                         return new TypeExpr (t);
166                         }
167
168                         return null;
169                 }
170                         
171                 static public Expression ResolveMemberAccess (TypeContainer tc, string name)
172                 {
173                         Expression left_e;
174                         int dot_pos = name.LastIndexOf (".");
175                         string left = name.Substring (0, dot_pos);
176                         string right = name.Substring (dot_pos + 1);
177
178                         left_e = ResolvePrimary (tc, left);
179                         if (left_e == null)
180                                 return null;
181
182                         switch (left_e.ExprClass){
183                         case ExprClass.Type:
184                                 return  MemberLookup (tc.RootContext.Report,
185                                                       left_e.Type, right,
186                                                       left_e.Type == tc.TypeBuilder);
187                                 
188                         case ExprClass.Namespace:
189                         case ExprClass.PropertyAccess:
190                         case ExprClass.IndexerAccess:
191                         case ExprClass.Variable:
192                         case ExprClass.Value:
193                         case ExprClass.Nothing:
194                         case ExprClass.EventAccess:
195                         case ExprClass.MethodGroup:
196                         case ExprClass.Invalid:
197                                 tc.RootContext.Report.Error (-1000,
198                                                              "Internal compiler error, should have " +
199                                                              "got these handled before");
200                                 break;
201                         }
202                         
203                         return null;
204                 }
205                 
206         }
207
208         public class Unary : Expression {
209                 public enum Operator {
210                         Plus, Minus, Negate, BitComplement,
211                         Indirection, AddressOf, PreIncrement,
212                         PreDecrement, PostIncrement, PostDecrement
213                 }
214
215                 Operator   oper;
216                 Expression expr;
217                 
218                 public Unary (Operator op, Expression expr)
219                 {
220                         this.oper = op;
221                         this.expr = expr;
222                 }
223
224                 public Expression Expr {
225                         get {
226                                 return expr;
227                         }
228
229                         set {
230                                 expr = value;
231                         }
232                 }
233
234                 public Operator Oper {
235                         get {
236                                 return oper;
237                         }
238
239                         set {
240                                 oper = value;
241                         }
242                 }
243
244                 public override Expression Resolve (TypeContainer tc)
245                 {
246                         // FIXME: Implement;
247                         return this;
248                 }
249
250                 public override void Emit (EmitContext ec)
251                 {
252                 }
253         }
254
255         public class Probe : Expression {
256                 string probe_type;
257                 Expression expr;
258                 Operator oper;
259
260                 public enum Operator {
261                         Is, As
262                 }
263                 
264                 public Probe (Operator oper, Expression expr, string probe_type)
265                 {
266                         this.oper = oper;
267                         this.probe_type = probe_type;
268                         this.expr = expr;
269                 }
270
271                 public Operator Oper {
272                         get {
273                                 return oper;
274                         }
275                 }
276
277                 public Expression Expr {
278                         get {
279                                 return expr;
280                         }
281                 }
282
283                 public string ProbeType {
284                         get {
285                                 return probe_type;
286                         }
287                 }
288
289                 public override Expression Resolve (TypeContainer tc)
290                 {
291                         // FIXME: Implement;
292                         return this;
293                 }
294
295                 public override void Emit (EmitContext ec)
296                 {
297                 }
298         }
299         
300         public class Cast : Expression {
301                 string target_type;
302                 Expression expr;
303                 
304                 public Cast (string cast_type, Expression expr)
305                 {
306                         this.target_type = target_type;
307                         this.expr = expr;
308                 }
309
310                 public string TargetType {
311                         get {
312                                 return target_type;
313                         }
314                 }
315
316                 public Expression Expr {
317                         get {
318                                 return expr;
319                         }
320                         set {
321                                 expr = value;
322                         }
323                 }
324                 
325                 public override Expression Resolve (TypeContainer tc)
326                 {
327                         // FIXME: Implement;
328                         return this;
329                 }
330
331                 public override void Emit (EmitContext ec)
332                 {
333                 }
334         }
335
336         public class Binary : Expression {
337                 public enum Operator {
338                         Multiply, Divide, Modulo,
339                         Add, Substract,
340                         ShiftLeft, ShiftRight,
341                         LessThan, GreatherThan, LessOrEqual, GreatherOrEqual, 
342                         Equal, NotEqual,
343                         BitwiseAnd,
344                         ExclusiveOr,
345                         BitwiseOr,
346                         LogicalAnd,
347                         LogicalOr
348                 }
349
350                 Operator oper;
351                 Expression left, right;
352                 
353                 public Binary (Operator oper, Expression left, Expression right)
354                 {
355                         this.oper = oper;
356                         this.left = left;
357                         this.right = right;
358                 }
359
360                 public Operator Oper {
361                         get {
362                                 return oper;
363                         }
364                         set {
365                                 oper = value;
366                         }
367                 }
368                 
369                 public Expression Left {
370                         get {
371                                 return left;
372                         }
373                         set {
374                                 left = value;
375                         }
376                 }
377
378                 public Expression Right {
379                         get {
380                                 return right;
381                         }
382                         set {
383                                 right = value;
384                         }
385                 }
386
387                 public override Expression Resolve (TypeContainer tc)
388                 {
389                         // FIXME: implement me
390                         return this;
391                 }
392
393                 public override void Emit (EmitContext ec)
394                 {
395                 }
396         }
397
398         public class Conditional : Expression {
399                 Expression expr, trueExpr, falseExpr;
400                 
401                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
402                 {
403                         this.expr = expr;
404                         this.trueExpr = trueExpr;
405                         this.falseExpr = falseExpr;
406                 }
407
408                 public Expression Expr {
409                         get {
410                                 return expr;
411                         }
412                 }
413
414                 public Expression TrueExpr {
415                         get {
416                                 return trueExpr;
417                         }
418                 }
419
420                 public Expression FalseExpr {
421                         get {
422                                 return falseExpr;
423                         }
424                 }
425
426                 public override Expression Resolve (TypeContainer tc)
427                 {
428                         // FIXME: Implement;
429                         return this;
430                 }
431
432                 public override void Emit (EmitContext ec)
433                 {
434                 }
435         }
436
437         public class SimpleName : Expression {
438                 string name;
439                 
440                 public SimpleName (string name)
441                 {
442                         this.name = name;
443                 }
444
445                 public string Name {
446                         get {
447                                 return name;
448                         }
449                 }
450
451                 //
452                 // Checks whether we are trying to access an instance
453                 // property, method or field from a static body.
454                 //
455                 Expression MemberStaticCheck (Report r, Expression e)
456                 {
457                         if (e is FieldExpr){
458                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
459                                 
460                                 if (!fi.IsStatic){
461                                         r.Error (120,
462                                                  "An object reference is required " +
463                                                  "for the non-static field `"+name+"'");
464                                         return null;
465                                 }
466                         } else if (e is MethodGroupExpr){
467                                 // FIXME: Pending reorganization of MemberLookup
468                                 // Basically at this point we should have the
469                                 // best match already selected for us, and
470                                 // we should only have to check a *single*
471                                 // Method for its static on/off bit.
472                                 return e;
473                         } else if (e is PropertyExpr){
474                                 if (!((PropertyExpr) e).IsStatic){
475                                         r.Error (120,
476                                                  "An object reference is required " +
477                                                  "for the non-static property access `"+
478                                                  name+"'");
479                                         return null;
480                                 }
481                         }
482
483                         return e;
484                 }
485                 
486                 //
487                 // 7.5.2: Simple Names. 
488                 //
489                 // Local Variables and Parameters are handled at
490                 // parse time, so they never occur as SimpleNames.
491                 //
492                 Expression ResolveSimpleName (TypeContainer tc)
493                 {
494                         Expression e;
495                         Report r = tc.RootContext.Report;
496
497                         e = MemberLookup (tc.RootContext.Report, tc.TypeBuilder, name, true);
498                         if (e != null){
499                                 if (e is TypeExpr)
500                                         return e;
501                                 if ((tc.ModFlags & Modifiers.STATIC) != 0)
502                                         return MemberStaticCheck (r, e);
503                                 else
504                                         return e;
505                         }
506
507                         //
508                         // Do step 3 of the Simple Name resolution.
509                         //
510                         // FIXME: implement me.
511                         
512                         return this;
513                 }
514                 
515                 //
516                 // SimpleName needs to handle a multitude of cases:
517                 //
518                 // simple_names and qualified_identifiers are placed on
519                 // the tree equally.
520                 //
521                 public override Expression Resolve (TypeContainer tc)
522                 {
523                         if (name.IndexOf (".") != -1)
524                                 return ResolveMemberAccess (tc, name);
525                         else
526                                 return ResolveSimpleName (tc);
527                 }
528
529                 public override void Emit (EmitContext ec)
530                 {
531                 }
532         }
533         
534         public class LocalVariableReference : Expression {
535                 public readonly string Name;
536                 public readonly Block Block;
537                 
538                 public LocalVariableReference (Block block, string name)
539                 {
540                         Block = block;
541                         Name = name;
542                         eclass = ExprClass.Variable;
543                 }
544
545                 public VariableInfo VariableInfo {
546                         get {
547                                 return (VariableInfo) Block.GetVariableInfo (Name);
548                         }
549                 }
550                 
551                 public override Expression Resolve (TypeContainer tc)
552                 {
553                         return this;
554                 }
555
556                 public override void Emit (EmitContext ec)
557                 {
558                         Console.WriteLine ("Internal compiler error, LocalVariableReference should not be emitted");
559                 }
560         }
561
562         public class ParameterReference : Expression {
563                 public readonly Parameters Pars;
564                 public readonly String Name;
565                 public readonly int Idx;
566                 
567                 public ParameterReference (Parameters pars, int idx, string name)
568                 {
569                         Pars = pars;
570                         Idx  = idx;
571                         Name = name;
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         // <summary>
586         //   Used for arguments to New(), Invocation()
587         // </summary>
588         public class Argument {
589                 public enum AType {
590                         Expression,
591                         Ref,
592                         Out
593                 };
594
595                 public readonly AType Type;
596                 Expression expr;
597
598                 public Argument (Expression expr, AType type)
599                 {
600                         this.expr = expr;
601                         this.Type = type;
602                 }
603
604                 public Expression Expr {
605                         get {
606                                 return expr;
607                         }
608                 }
609
610                 public bool Resolve (TypeContainer tc)
611                 {
612                         expr = expr.Resolve (tc);
613                         return expr != null;
614                 }
615
616                 public void Emit (EmitContext ec)
617                 {
618                         expr.Emit (ec);
619                 }
620         }
621
622         // <summary>
623         //   Invocation of methods or delegates.
624         // </summary>
625         public class Invocation : Expression {
626                 public readonly ArrayList Arguments;
627                 Expression expr;
628                 MethodInfo method = null;
629                 
630                 //
631                 // arguments is an ArrayList, but we do not want to typecast,
632                 // as it might be null.
633                 //
634                 // FIXME: only allow expr to be a method invocation or a
635                 // delegate invocation (7.5.5)
636                 //
637                 public Invocation (Expression expr, ArrayList arguments)
638                 {
639                         this.expr = expr;
640                         Arguments = arguments;
641                 }
642
643                 public Expression Expr {
644                         get {
645                                 return expr;
646                         }
647                 }
648
649                 /// <summary>
650                 ///   Computes whether Argument `a' and the ParameterInfo `pi' are
651                 ///   compatible, and if so, how good is the match (in terms of
652                 ///   "better conversions" (7.4.2.3).
653                 ///
654                 ///   0   is the best possible match.
655                 ///   -1  represents a type mismatch.
656                 ///   -2  represents a ref/out mismatch.
657                 /// </summary>
658                 static int Badness (Argument a, ParameterInfo pi)
659                 {
660                         if (pi.ParameterType == a.Expr.Type)
661                                 return 0;
662
663                         // FIXME: Implement implicit conversions here.
664                         // FIXME: Implement better conversion here.
665                         
666                         return -1;
667                 }
668                 
669                 public override Expression Resolve (TypeContainer tc)
670                 {
671                         //
672                         // First, resolve the expression that is used to
673                         // trigger the invocation
674                         //
675                         this.expr = expr.Resolve (tc);
676                         if (this.expr == null)
677                                 return null;
678
679                         if (!(this.expr is MethodGroupExpr)){
680                                 tc.RootContext.Report.Error (118,
681                                        "Denotes an " + this.expr.ExprClass + " while a method was expected");
682                                 return null;
683                         }
684
685                         //
686                         // Next, evaluate all the expressions in the argument list
687                         //
688                         if (Arguments != null){
689                                 for (int i = Arguments.Count; i > 0;){
690                                         --i;
691                                         Argument a = (Argument) Arguments [i];
692
693                                         if (!a.Resolve (tc))
694                                                 return null;
695                                 }
696                         }
697
698                         //
699                         // Find the Applicable Function Members (7.4.2.1)
700                         //
701                         MethodGroupExpr me = (MethodGroupExpr) this.expr;
702                         ArrayList afm = new ArrayList ();
703                         int best_match = 10000;
704                         int best_match_idx = -1;
705                         
706                         for (int i = me.Methods.Length; i > 0; ){
707                                 i--;
708                                 ParameterInfo [] pi = me.Methods [i].GetParameters ();
709
710                                 //
711                                 // Compute how good this is
712                                 //
713                                 if (pi.Length == Arguments.Count){
714                                         int badness = 0;
715                                         
716                                         for (int j = Arguments.Count; j > 0;){
717                                                 int x;
718                                                 j--;
719
720                                                 Argument a = (Argument) Arguments [j];
721
722                                                 x = Badness (a, pi [j]);
723
724                                                 if (x < 0){
725                                                         // FIXME: report nice error.
726                                                 } else
727                                                         badness += x;
728                                         }
729
730                                         if (badness < best_match){
731                                                 best_match = badness;
732                                                 method = me.Methods [i];
733                                                 best_match_idx = i;
734                                         }
735                                 }
736                         }
737
738                         if (method == null){
739                                 tc.RootContext.Report.Error (-6,
740                                 "Figure out error: Can not find a good function for this argument list");
741                                 return null;
742                         }
743
744                         Console.WriteLine ("Found a method! " + method);
745
746                         return this;
747                 }
748
749                 public override void Emit (EmitContext ec)
750                 {
751                         int top = Arguments.Count;
752
753                         for (int i = 0; i < top; i++){
754                                 Argument a = (Argument) Arguments [i];
755
756                                 a.Emit (ec);
757                         }
758
759                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
760                 }
761         }
762
763         public class New : Expression {
764
765                 public enum NType {
766                         Object,
767                         Array
768                 };
769
770                 public readonly NType     NewType;
771                 public readonly ArrayList Arguments;
772                 public readonly string    RequestedType;
773                 // These are for the case when we have an array
774                 public readonly string    Rank;
775                 public readonly ArrayList Indices;
776                 public readonly ArrayList Initializers;
777                 
778
779                 public New (string requested_type, ArrayList arguments)
780                 {
781                         RequestedType = requested_type;
782                         Arguments = arguments;
783                         NewType = NType.Object;
784                 }
785
786                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
787                 {
788                         RequestedType = requested_type;
789                         Indices       = exprs;
790                         Rank          = rank;
791                         Initializers  = initializers;
792                         NewType       = NType.Array;
793                 }
794                 
795                 public override Expression Resolve (TypeContainer tc)
796                 {
797                         // FIXME: Implement;
798                         return this;
799                 }
800
801                 public override void Emit (EmitContext ec)
802                 {
803                 }
804         }
805
806         public class This : Expression {
807                 public override Expression Resolve (TypeContainer tc)
808                 {
809                         // FIXME: Implement;
810                         return this;
811                 }
812
813                 public override void Emit (EmitContext ec)
814                 {
815                 }
816         }
817
818         public class TypeOf : Expression {
819                 public readonly string QueriedType;
820                 
821                 public TypeOf (string queried_type)
822                 {
823                         QueriedType = queried_type;
824                 }
825
826                 public override Expression Resolve (TypeContainer tc)
827                 {
828                         // FIXME: Implement;
829                         return this;
830                 }
831
832                 public override void Emit (EmitContext ec)
833                 {
834                 }
835         }
836
837         public class SizeOf : Expression {
838                 public readonly string QueriedType;
839                 
840                 public SizeOf (string queried_type)
841                 {
842                         this.QueriedType = queried_type;
843                 }
844
845                 public override Expression Resolve (TypeContainer tc)
846                 {
847                         // FIXME: Implement;
848                         return this;
849                 }
850
851                 public override void Emit (EmitContext ec)
852                 {
853                 }
854         }
855
856         public class MemberAccess : Expression {
857                 public readonly string Identifier;
858                 Expression expr;
859                 
860                 public MemberAccess (Expression expr, string id)
861                 {
862                         this.expr = expr;
863                         Identifier = id;
864                 }
865
866                 public Expression Expr {
867                         get {
868                                 return expr;
869                         }
870                 }
871                 
872                 public override Expression Resolve (TypeContainer tc)
873                 {
874                         // FIXME: Implement;
875                         return this;
876                 }
877
878                 public override void Emit (EmitContext ec)
879                 {
880                 }
881
882         }
883
884         // <summary>
885         //   Nodes of type Namespace are created during the semantic
886         //   analysis to resolve member_access/qualified_identifier/simple_name
887         //   accesses.
888         //
889         //   They are born `resolved'. 
890         // </summary>
891         public class NamespaceExpr : Expression {
892                 public readonly string Name;
893                 
894                 public NamespaceExpr (string name)
895                 {
896                         Name = name;
897                         eclass = ExprClass.Namespace;
898                 }
899
900                 public override Expression Resolve (TypeContainer tc)
901                 {
902                         return this;
903                 }
904
905                 public override void Emit (EmitContext ec)
906                 {
907                 }
908         }
909
910         // <summary>
911         //   Fully resolved expression that evaluates to a type
912         // </summary>
913         public class TypeExpr : Expression {
914                 public TypeExpr (Type t)
915                 {
916                         Type = t;
917                         eclass = ExprClass.Type;
918                 }
919
920                 override public Expression Resolve (TypeContainer tc)
921                 {
922                         return this;
923                 }
924
925                 override public void Emit (EmitContext ec)
926                 {
927                         
928                 }
929         }
930
931         // <summary>
932         //   Fully resolved expression that evaluates to a type
933         // </summary>
934         public class MethodGroupExpr : Expression {
935                 public readonly MethodInfo [] Methods;
936                 
937                 public MethodGroupExpr (MemberInfo [] mi)
938                 {
939                         Methods = new MethodInfo [mi.Length];
940                         mi.CopyTo (Methods, 0);
941                         eclass = ExprClass.MethodGroup;
942                 }
943
944                 override public Expression Resolve (TypeContainer tc)
945                 {
946                         return this;
947                 }
948
949                 override public void Emit (EmitContext ec)
950                 {
951                         
952                 }
953         }
954         
955         public class BuiltinTypeAccess : Expression {
956                 public readonly string AccessBase;
957                 public readonly string Method;
958                 
959                 public BuiltinTypeAccess (string type, string method)
960                 {
961                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
962                         AccessBase = type;
963                         Method = method;
964                 }
965
966                 public override Expression Resolve (TypeContainer tc)
967                 {
968                         // FIXME: Implement;
969                         return this;
970                 }
971
972                 public override void Emit (EmitContext ec)
973                 {
974                 }
975         }
976
977
978         //   Fully resolved expression that evaluates to a Field
979         // </summary>
980         public class FieldExpr : Expression {
981                 public readonly FieldInfo FieldInfo;
982
983                 public FieldExpr (FieldInfo fi)
984                 {
985                         FieldInfo = fi;
986                         eclass = ExprClass.Variable;
987                 }
988
989                 override public Expression Resolve (TypeContainer tc)
990                 {
991                         // We are born in resolved state. 
992                         return this;
993                 }
994
995                 override public void Emit (EmitContext ec)
996                 {
997                         // FIXME: Assert that this should not be reached?
998                 }
999         }
1000         
1001         // <summary>
1002         //   Fully resolved expression that evaluates to a Property
1003         // </summary>
1004         public class PropertyExpr : Expression {
1005                 public readonly PropertyInfo PropertyInfo;
1006                 public readonly bool IsStatic;
1007                 
1008                 public PropertyExpr (PropertyInfo pi)
1009                 {
1010                         PropertyInfo = pi;
1011                         eclass = ExprClass.PropertyAccess;
1012                         IsStatic = false;
1013                                 
1014                         MethodInfo [] acc = pi.GetAccessors ();
1015
1016                         for (int i = 0; i < acc.Length; i++)
1017                                 if (acc [i].IsStatic)
1018                                         IsStatic = true;
1019                 }
1020
1021                 override public Expression Resolve (TypeContainer tc)
1022                 {
1023                         // We are born in resolved state. 
1024                         return this;
1025                 }
1026
1027                 override public void Emit (EmitContext ec)
1028                 {
1029                         // FIXME: Implement.
1030                 }
1031         }
1032
1033         public class CheckedExpr : Expression {
1034
1035                 public readonly Expression Expr;
1036
1037                 public CheckedExpr (Expression e)
1038                 {
1039                         Expr = e;
1040                 }
1041
1042                 public override Expression Resolve (TypeContainer tc)
1043                 {
1044                         // FIXME : Implement !
1045                         return this;
1046                 }
1047
1048                 public override void Emit (EmitContext ec)
1049                 {
1050                 }
1051                 
1052         }
1053
1054         public class UnCheckedExpr : Expression {
1055
1056                 public readonly Expression Expr;
1057
1058                 public UnCheckedExpr (Expression e)
1059                 {
1060                         Expr = e;
1061                 }
1062
1063                 public override Expression Resolve (TypeContainer tc)
1064                 {
1065                         // FIXME : Implement !
1066                         return this;
1067                 }
1068
1069                 public override void Emit (EmitContext ec)
1070                 {
1071                 }
1072                 
1073         }
1074
1075                 public class ElementAccess : Expression {
1076
1077                 public readonly ArrayList  Arguments;
1078                 public readonly Expression Expr;
1079
1080                 public ElementAccess (Expression e, ArrayList e_list)
1081                 {
1082                         Expr = e;
1083                         Arguments = e_list;
1084                 }
1085
1086                 public override Expression Resolve (TypeContainer tc)
1087                 {
1088                         // FIXME : Implement
1089                         return this;
1090                 }
1091
1092                 public override void Emit (EmitContext ec)
1093                 {
1094                         // FIXME : Implement !
1095                 }
1096
1097         }
1098
1099         public class BaseAccess : Expression {
1100
1101                 public enum BaseAccessType {
1102                         Member,
1103                         Indexer
1104                 };
1105                 
1106                 public readonly BaseAccessType BAType;
1107                 public readonly string         Member;
1108                 public readonly ArrayList      Arguments;
1109
1110                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
1111                 {
1112                         BAType = t;
1113                         Member = member;
1114                         Arguments = args;
1115                         
1116                 }
1117
1118                 public override Expression Resolve (TypeContainer tc)
1119                 {
1120                         // FIXME : Implement !
1121                         return this;
1122                 }
1123
1124                 public override void Emit (EmitContext ec)
1125                 {
1126                 }
1127         }
1128 }