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