2001-09-20 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 namespace CIR {
10         using System.Collections;
11         using System.Diagnostics;
12         using System;
13         using System.Reflection;
14         using System.Reflection.Emit;
15
16         // <remarks>
17         //   The ExprClass class contains the is used to pass the 
18         //   classification of an expression (value, variable, namespace,
19         //   type, method group, property access, event access, indexer access,
20         //   nothing).
21         // </remarks>
22         public enum ExprClass {
23                 Invalid,
24                 
25                 Value, Variable, Namespace, Type,
26                 MethodGroup, PropertyAccess,
27                 EventAccess, IndexerAccess, Nothing, 
28         }
29
30         // <remarks>
31         //   Base class for expressions
32         // </remarks>
33         public abstract class Expression {
34                 protected ExprClass eclass;
35                 protected Type      type;
36                 
37                 public Type Type {
38                         get {
39                                 return type;
40                         }
41
42                         set {
43                                 type = value;
44                         }
45                 }
46
47                 public ExprClass ExprClass {
48                         get {
49                                 return eclass;
50                         }
51
52                         set {
53                                 eclass = value;
54                         }
55                 }
56
57                 public abstract Expression Resolve (TypeContainer tc);
58                 public abstract void Emit (EmitContext ec);
59                 
60                 // <summary>
61                 //   Protected constructor.  Only derivate types should
62                 //   be able to be created
63                 // </summary>
64
65                 protected Expression ()
66                 {
67                         eclass = ExprClass.Invalid;
68                         type = null;
69                 }
70
71                 // 
72                 // Returns a fully formed expression after a MemberLookup
73                 //
74                 static Expression ExprClassFromMemberInfo (MemberInfo mi)
75                 {
76                         if (mi is EventInfo){
77                                 return new EventExpr ((EventInfo) mi);
78                         } else if (mi is FieldInfo){
79                                 return new FieldExpr ((FieldInfo) mi);
80                         } else if (mi is PropertyInfo){
81                                 return new PropertyExpr ((PropertyInfo) mi);
82                         } else if (mi is Type)
83                                 return new TypeExpr ((Type) mi);
84
85                         return null;
86                 }
87                 
88                 //
89                 // FIXME: Probably implement a cache for (t,name,current_access_set)?
90                 //
91                 // FIXME: We need to cope with access permissions here, or this wont
92                 // work!
93                 //
94                 // This code could use some optimizations, but we need to do some
95                 // measurements.  For example, we could use a delegate to `flag' when
96                 // something can not any longer be a method-group (because it is something
97                 // else).
98                 //
99                 // Return values:
100                 //     If the return value is an Array, then it is an array of
101                 //     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                                 method = Invocation.OverloadResolve (union, Arguments);
1135                                 if (method != null)
1136                                         return this;
1137
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
1453                         return this;
1454                 }
1455
1456                 public override void Emit (EmitContext ec)
1457                 {
1458                 }
1459         }
1460
1461         public class SimpleName : Expression {
1462                 public readonly string Name;
1463                 public readonly Location Location;
1464                 
1465                 public SimpleName (string name, Location l)
1466                 {
1467                         Name = name;
1468                         Location = l;
1469                 }
1470
1471                 //
1472                 // Checks whether we are trying to access an instance
1473                 // property, method or field from a static body.
1474                 //
1475                 Expression MemberStaticCheck (Report r, Expression e)
1476                 {
1477                         if (e is FieldExpr){
1478                                 FieldInfo fi = ((FieldExpr) e).FieldInfo;
1479                                 
1480                                 if (!fi.IsStatic){
1481                                         r.Error (120,
1482                                                  "An object reference is required " +
1483                                                  "for the non-static field `"+Name+"'");
1484                                         return null;
1485                                 }
1486                         } else if (e is MethodGroupExpr){
1487                                 // FIXME: Pending reorganization of MemberLookup
1488                                 // Basically at this point we should have the
1489                                 // best match already selected for us, and
1490                                 // we should only have to check a *single*
1491                                 // Method for its static on/off bit.
1492                                 return e;
1493                         } else if (e is PropertyExpr){
1494                                 if (!((PropertyExpr) e).IsStatic){
1495                                         r.Error (120,
1496                                                  "An object reference is required " +
1497                                                  "for the non-static property access `"+
1498                                                  Name+"'");
1499                                         return null;
1500                                 }
1501                         }
1502
1503                         return e;
1504                 }
1505                 
1506                 //
1507                 // 7.5.2: Simple Names. 
1508                 //
1509                 // Local Variables and Parameters are handled at
1510                 // parse time, so they never occur as SimpleNames.
1511                 //
1512                 Expression ResolveSimpleName (TypeContainer tc)
1513                 {
1514                         Expression e;
1515                         Report r = tc.RootContext.Report;
1516
1517                         e = MemberLookup (tc.RootContext, tc.TypeBuilder, Name, true);
1518                         if (e != null){
1519                                 if (e is TypeExpr)
1520                                         return e;
1521                                 else if (e is FieldExpr){
1522                                         FieldExpr fe = (FieldExpr) e;
1523
1524                                         if (!fe.FieldInfo.IsStatic)
1525                                                 fe.Instance = new This ();
1526                                 }
1527                                 
1528                                 if ((tc.ModFlags & Modifiers.STATIC) != 0)
1529                                         return MemberStaticCheck (r, e);
1530                                 else
1531                                         return e;
1532                         }
1533
1534                         //
1535                         // Do step 3 of the Simple Name resolution.
1536                         //
1537                         // FIXME: implement me.
1538
1539                         r.Error (103, Location, "The name `" + Name + "' does not exist in the class `" +
1540                                  tc.Name + "'");
1541
1542                         return null;
1543                 }
1544                 
1545                 //
1546                 // SimpleName needs to handle a multitude of cases:
1547                 //
1548                 // simple_names and qualified_identifiers are placed on
1549                 // the tree equally.
1550                 //
1551                 public override Expression Resolve (TypeContainer tc)
1552                 {
1553                         if (Name.IndexOf (".") != -1)
1554                                 return ResolveMemberAccess (tc, Name);
1555                         else
1556                                 return ResolveSimpleName (tc);
1557                 }
1558
1559                 public override void Emit (EmitContext ec)
1560                 {
1561                 }
1562         }
1563         
1564         public class LocalVariableReference : Expression {
1565                 public readonly string Name;
1566                 public readonly Block Block;
1567                 
1568                 public LocalVariableReference (Block block, string name)
1569                 {
1570                         Block = block;
1571                         Name = name;
1572                         eclass = ExprClass.Variable;
1573                 }
1574
1575                 public VariableInfo VariableInfo {
1576                         get {
1577                                 return Block.GetVariableInfo (Name);
1578                         }
1579                 }
1580                 
1581                 public override Expression Resolve (TypeContainer tc)
1582                 {
1583                         VariableInfo vi = Block.GetVariableInfo (Name);
1584
1585                         type = vi.VariableType;
1586                         return this;
1587                 }
1588
1589                 public override void Emit (EmitContext ec)
1590                 {
1591                         VariableInfo vi = VariableInfo;
1592                         ILGenerator ig = ec.ig;
1593                         int idx = vi.Idx;
1594
1595                         Console.WriteLine ("Variable: " + vi);
1596                         switch (idx){
1597                         case 0:
1598                                 ig.Emit (OpCodes.Ldloc_0);
1599                                 break;
1600                                 
1601                         case 1:
1602                                 ig.Emit (OpCodes.Ldloc_1);
1603                                 break;
1604
1605                         case 2:
1606                                 ig.Emit (OpCodes.Ldloc_2);
1607                                 break;
1608
1609                         case 3:
1610                                 ig.Emit (OpCodes.Ldloc_3);
1611                                 break;
1612
1613                         default:
1614                                 if (idx < 255)
1615                                         ig.Emit (OpCodes.Ldloc_S, idx);
1616                                 else
1617                                         ig.Emit (OpCodes.Ldloc, idx);
1618                                 break;
1619                         }
1620                 }
1621         }
1622
1623         public class ParameterReference : Expression {
1624                 public readonly Parameters Pars;
1625                 public readonly String Name;
1626                 public readonly int Idx;
1627                 
1628                 public ParameterReference (Parameters pars, int idx, string name)
1629                 {
1630                         Pars = pars;
1631                         Idx  = idx;
1632                         Name = name;
1633                 }
1634
1635                 public override Expression Resolve (TypeContainer tc)
1636                 {
1637                         Type [] types = Pars.GetParameterInfo (tc);
1638
1639                         type = types [Idx];
1640                         
1641                         return this;
1642                 }
1643
1644                 public override void Emit (EmitContext ec)
1645                 {
1646                         if (Idx < 255)
1647                                 ec.ig.Emit (OpCodes.Ldarg_S, Idx);
1648                         else
1649                                 ec.ig.Emit (OpCodes.Ldarg, Idx);
1650                 }
1651         }
1652         
1653         // <summary>
1654         //   Used for arguments to New(), Invocation()
1655         // </summary>
1656         public class Argument {
1657                 public enum AType {
1658                         Expression,
1659                         Ref,
1660                         Out
1661                 };
1662
1663                 public readonly AType Type;
1664                 Expression expr;
1665
1666                 public Argument (Expression expr, AType type)
1667                 {
1668                         this.expr = expr;
1669                         this.Type = type;
1670                 }
1671
1672                 public Expression Expr {
1673                         get {
1674                                 return expr;
1675                         }
1676                 }
1677
1678                 public bool Resolve (TypeContainer tc)
1679                 {
1680                         expr = expr.Resolve (tc);
1681
1682                         return expr != null;
1683                 }
1684
1685                 public void Emit (EmitContext ec)
1686                 {
1687                         expr.Emit (ec);
1688                 }
1689         }
1690
1691         // <summary>
1692         //   Invocation of methods or delegates.
1693         // </summary>
1694         public class Invocation : Expression {
1695                 public readonly ArrayList Arguments;
1696                 public readonly Location Location;
1697                 
1698                 Expression expr;
1699                 MethodBase method = null;
1700                         
1701                 static Hashtable method_parameter_cache;
1702
1703                 static Invocation ()
1704                 {
1705                         method_parameter_cache = new Hashtable ();
1706                 }
1707                         
1708                 //
1709                 // arguments is an ArrayList, but we do not want to typecast,
1710                 // as it might be null.
1711                 //
1712                 // FIXME: only allow expr to be a method invocation or a
1713                 // delegate invocation (7.5.5)
1714                 //
1715                 public Invocation (Expression expr, ArrayList arguments, Location l)
1716                 {
1717                         this.expr = expr;
1718                         Arguments = arguments;
1719                         Location = l;
1720                 }
1721
1722                 public Expression Expr {
1723                         get {
1724                                 return expr;
1725                         }
1726                 }
1727
1728                 /// <summary>
1729                 ///   Computes whether Argument `a' and the Type t of the  ParameterInfo `pi' are
1730                 ///   compatible, and if so, how good is the match (in terms of
1731                 ///   "better conversions" (7.4.2.3).
1732                 ///
1733                 ///   0   is the best possible match.
1734                 ///   -1  represents a type mismatch.
1735                 ///   -2  represents a ref/out mismatch.
1736                 /// </summary>
1737                 static int Badness (Argument a, Type t)
1738                 {
1739                         Expression argument_expr = a.Expr;
1740                         Type argument_type = argument_expr.Type;
1741
1742                         if (argument_type == null){
1743                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
1744                         }
1745                         
1746                         if (t == argument_type) 
1747                                 return 0;
1748
1749                         //
1750                         // Now probe whether an implicit constant expression conversion
1751                         // can be used.
1752                         //
1753                         // An implicit constant expression conversion permits the following
1754                         // conversions:
1755                         //
1756                         //    * A constant-expression of type `int' can be converted to type
1757                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
1758                         //      of the expression is withing the range of the destination type.
1759                         //
1760                         //    * A constant-expression of type long can be converted to type
1761                         //      ulong, provided the value of the constant expression is not negative
1762                         //
1763                         // FIXME: Note that this assumes that constant folding has
1764                         // taken place.  We dont do constant folding yet.
1765                         //
1766
1767                         if (argument_type == TypeManager.int32_type && argument_expr is IntLiteral){
1768                                 IntLiteral ei = (IntLiteral) argument_expr;
1769                                 int value = ei.Value;
1770                                 
1771                                 if (t == TypeManager.sbyte_type){
1772                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
1773                                                 return 1;
1774                                 } else if (t == TypeManager.byte_type){
1775                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
1776                                                 return 1;
1777                                 } else if (t == TypeManager.short_type){
1778                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
1779                                                 return 1;
1780                                 } else if (t == TypeManager.ushort_type){
1781                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1782                                                 return 1;
1783                                 } else if (t == TypeManager.uint32_type){
1784                                         //
1785                                         // we can optimize this case: a positive int32
1786                                         // always fits on a uint32
1787                                         //
1788                                         if (value >= 0)
1789                                                 return 1;
1790                                 } else if (t == TypeManager.uint64_type){
1791                                         //
1792                                         // we can optimize this case: a positive int32
1793                                         // always fits on a uint64
1794                                         //
1795                                         if (value >= 0)
1796                                                 return 1;
1797                                 }
1798                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
1799                                 LongLiteral ll = (LongLiteral) argument_expr;
1800                                 
1801                                 if (t == TypeManager.uint64_type){
1802                                         if (ll.Value > 0)
1803                                                 return 1;
1804                                 }
1805                         }
1806                         
1807                         // FIXME: Implement user-defined implicit conversions here.
1808                         // FIXME: Implement better conversion here.
1809                         
1810                         return -1;
1811                 }
1812
1813                 // <summary>
1814                 //   Returns the Parameters (a ParameterData interface) for the
1815                 //   Method `mb'
1816                 // </summary>
1817                 static ParameterData GetParameterData (MethodBase mb)
1818                 {
1819                         object pd = method_parameter_cache [mb];
1820
1821                         if (pd != null)
1822                                 return (ParameterData) pd;
1823
1824                         if (mb is MethodBuilder || mb is ConstructorBuilder){
1825                                 MethodCore mc = TypeContainer.LookupMethodByBuilder (mb);
1826
1827                                 InternalParameters ip = mc.ParameterInfo;
1828                                 method_parameter_cache [mb] = ip;
1829
1830                                 return (ParameterData) ip;
1831                         } else {
1832                                 ParameterInfo [] pi = mb.GetParameters ();
1833                                 ReflectionParameters rp = new ReflectionParameters (pi);
1834                                 method_parameter_cache [mb] = rp;
1835
1836                                 return (ParameterData) rp;
1837                         }
1838                 }
1839                 
1840                 // <summary>
1841                 //   Find the Applicable Function Members (7.4.2.1)
1842                 //
1843                 //   me: Method Group expression with the members to select.
1844                 //       it might contain constructors or methods (or anything
1845                 //       that maps to a method).
1846                 //
1847                 //   Arguments: ArrayList containing resolved Argument objects.
1848                 //
1849                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
1850                 //            that is the best match of me on Arguments.
1851                 //
1852                 // </summary>
1853                 public static MethodBase OverloadResolve (MethodGroupExpr me, ArrayList Arguments)
1854                 {
1855                         ArrayList afm = new ArrayList ();
1856                         int best_match = 10000;
1857                         int best_match_idx = -1;
1858                         MethodBase method = null;
1859                         int argument_count;
1860
1861                         if (Arguments == null)
1862                                 argument_count = 0;
1863                         else
1864                                 argument_count = Arguments.Count;
1865
1866                         for (int i = me.Methods.Length; i > 0; ){
1867                                 i--;
1868                                 MethodBase mb = me.Methods [i];
1869                                 ParameterData pd;
1870
1871                                 pd = GetParameterData (mb);
1872
1873                                 // If this is the case, we have a method with no args - presumably
1874                                 if (pd == null && argument_count == 0)
1875                                         return me.Methods [0];
1876
1877                                 //
1878                                 // Compute how good this is
1879                                 //
1880                                 if (pd.Count == argument_count){
1881                                         int badness = 0;
1882                                         
1883                                         for (int j = argument_count; j > 0;){
1884                                                 int x;
1885                                                 j--;
1886                                                 
1887                                                 Argument a = (Argument) Arguments [j];
1888
1889                                                 x = Badness (a, pd.ParameterType (j));
1890
1891                                                 if (x < 0){
1892                                                         badness = best_match;
1893                                                         continue;
1894                                                 }
1895                                                 
1896                                                 badness += x;
1897                                         }
1898                                         
1899                                         if (badness < best_match){
1900                                                 best_match = badness;
1901                                                 method = me.Methods [i];
1902                                                 best_match_idx = i;
1903                                         }
1904                                 }
1905                         }
1906
1907                         if (best_match_idx == -1)
1908                                 return null;
1909                         
1910                         return method;
1911                 }
1912
1913                         
1914                 public override Expression Resolve (TypeContainer tc)
1915                 {
1916                         //
1917                         // First, resolve the expression that is used to
1918                         // trigger the invocation
1919                         //
1920                         this.expr = expr.Resolve (tc);
1921                         if (this.expr == null)
1922                                 return null;
1923
1924                         if (!(this.expr is MethodGroupExpr)){
1925                                 tc.RootContext.Report.Error (118,
1926                                        "Denotes a non-method (Detail: ExprClass=" + this.expr.ExprClass+")");
1927                                 return null;
1928                         }
1929
1930                         //
1931                         // Next, evaluate all the expressions in the argument list
1932                         //
1933                         if (Arguments != null){
1934                                 for (int i = Arguments.Count; i > 0;){
1935                                         --i;
1936                                         Argument a = (Argument) Arguments [i];
1937
1938                                         if (!a.Resolve (tc))
1939                                                 return null;
1940                                 }
1941                         }
1942
1943                         method = OverloadResolve ((MethodGroupExpr) this.expr, Arguments);
1944
1945                         if (method == null){
1946                                 tc.RootContext.Report.Error (-6, Location,
1947                                 "Figure out error: Can not find a good function for this argument list");
1948                                 return null;
1949                         }
1950
1951                         if (method is MethodInfo)
1952                                 type = ((MethodInfo)method).ReturnType;
1953
1954                         return this;
1955                 }
1956
1957                 public static void EmitArguments (EmitContext ec, MethodBase method, ArrayList Arguments)
1958                 {
1959                         int top;
1960
1961                         if (Arguments != null)
1962                                 top = Arguments.Count;
1963                         else
1964                                 top = 0;
1965
1966                         for (int i = 0; i < top; i++){
1967                                 Argument a = (Argument) Arguments [i];
1968
1969                                 Console.WriteLine ("Perform the actual type widening of arguments here for things like: void fn (sbyte s);  ... fn (1)");
1970                                 
1971                                 a.Emit (ec);
1972                         }
1973                 }
1974                 
1975                 public override void Emit (EmitContext ec)
1976                 {
1977                         bool is_static = method.IsStatic;
1978
1979                         if (!is_static){
1980                                 MethodGroupExpr mg = (MethodGroupExpr) this.expr;
1981
1982                                 if (mg.InstanceExpression == null){
1983                                         Console.WriteLine ("Internal compiler error.  Should check in the method groups for static/instance");
1984                                 }
1985
1986                                 mg.InstanceExpression.Emit (ec);
1987                         }
1988
1989                         if (Arguments != null)
1990                                 EmitArguments (ec, method, Arguments);
1991
1992                         if (is_static){
1993                                 if (method is MethodInfo)
1994                                         ec.ig.Emit (OpCodes.Call, (MethodInfo) method);
1995                                 else
1996                                         ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1997                         } else {
1998                                 if (method is MethodInfo)
1999                                         ec.ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
2000                                 else
2001                                         ec.ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
2002                         } 
2003
2004                 }
2005         }
2006
2007         public class New : Expression {
2008
2009                 public enum NType {
2010                         Object,
2011                         Array
2012                 };
2013
2014                 public readonly NType     NewType;
2015                 public readonly ArrayList Arguments;
2016                 public readonly string    RequestedType;
2017                 // These are for the case when we have an array
2018                 public readonly string    Rank;
2019                 public readonly ArrayList Indices;
2020                 public readonly ArrayList Initializers;
2021                 
2022                 MethodBase method = null;
2023
2024                 public New (string requested_type, ArrayList arguments)
2025                 {
2026                         RequestedType = requested_type;
2027                         Arguments = arguments;
2028                         NewType = NType.Object;
2029                 }
2030
2031                 public New (string requested_type, ArrayList exprs, string rank, ArrayList initializers)
2032                 {
2033                         RequestedType = requested_type;
2034                         Indices       = exprs;
2035                         Rank          = rank;
2036                         Initializers  = initializers;
2037                         NewType       = NType.Array;
2038                 }
2039                 
2040                 public override Expression Resolve (TypeContainer tc)
2041                 {
2042                         type = tc.LookupType (RequestedType, false);
2043
2044                         if (type == null)
2045                                 return null;
2046
2047                         Expression ml;
2048
2049                         ml = MemberLookup (tc.RootContext, type, ".ctor", false,
2050                                            MemberTypes.Constructor, AllBindingsFlags);
2051
2052                         if (! (ml is MethodGroupExpr)){
2053                                 //
2054                                 // FIXME: Find proper error
2055                                 //
2056                                 tc.RootContext.Report.Error (118, "Did find something that is not a method");
2057                                 return null;
2058                         }
2059                         
2060                         if (Arguments != null){
2061                                 for (int i = Arguments.Count; i > 0;){
2062                                         --i;
2063                                         Argument a = (Argument) Arguments [i];
2064
2065                                         if (!a.Resolve (tc))
2066                                                 return null;
2067                                 }
2068                         }
2069
2070                         method = Invocation.OverloadResolve ((MethodGroupExpr) ml, Arguments);
2071
2072                         if (method == null) {
2073                                 tc.RootContext.Report.Error (-6,
2074                                 "New invocation: Can not find a constructor for this argument list");
2075                                 return null;
2076                         }
2077
2078                         return this;
2079                 }
2080
2081                 public override void Emit (EmitContext ec)
2082                 {
2083                         Invocation.EmitArguments (ec, method, Arguments);
2084                         ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
2085                 }
2086         }
2087
2088         //
2089         // Represents the `this' construct
2090         //
2091         public class This : Expression {
2092                 public override Expression Resolve (TypeContainer tc)
2093                 {
2094                         eclass = ExprClass.Variable;
2095                         type = tc.TypeBuilder;
2096                         
2097                         return this;
2098                 }
2099
2100                 public override void Emit (EmitContext ec)
2101                 {
2102                         ec.ig.Emit (OpCodes.Ldarg_0);
2103                 }
2104         }
2105
2106         public class TypeOf : Expression {
2107                 public readonly string QueriedType;
2108                 
2109                 public TypeOf (string queried_type)
2110                 {
2111                         QueriedType = queried_type;
2112                 }
2113
2114                 public override Expression Resolve (TypeContainer tc)
2115                 {
2116                         type = tc.LookupType (QueriedType, false);
2117
2118                         if (type == null)
2119                                 return null;
2120                         
2121                         eclass = ExprClass.Type;
2122                         return this;
2123                 }
2124
2125                 public override void Emit (EmitContext ec)
2126                 {
2127                         // FIXME: Implement.
2128                 }
2129         }
2130
2131         public class SizeOf : Expression {
2132                 public readonly string QueriedType;
2133                 
2134                 public SizeOf (string queried_type)
2135                 {
2136                         this.QueriedType = queried_type;
2137                 }
2138
2139                 public override Expression Resolve (TypeContainer tc)
2140                 {
2141                         // FIXME: Implement;
2142                         throw new Exception ("Unimplemented");
2143
2144                         return this;
2145                 }
2146
2147                 public override void Emit (EmitContext ec)
2148                 {
2149                 }
2150         }
2151
2152         public class MemberAccess : Expression {
2153                 public readonly string Identifier;
2154                 Expression expr;
2155                 Expression member_lookup;
2156                 
2157                 public MemberAccess (Expression expr, string id)
2158                 {
2159                         this.expr = expr;
2160                         Identifier = id;
2161                 }
2162
2163                 public Expression Expr {
2164                         get {
2165                                 return expr;
2166                         }
2167                 }
2168                 
2169                 public override Expression Resolve (TypeContainer tc)
2170                 {
2171                         Expression new_expression = expr.Resolve (tc);
2172
2173                         if (new_expression == null)
2174                                 return null;
2175
2176                         Console.WriteLine ("This is what I figured: " + expr.Type + "/" + expr.ExprClass);
2177
2178                         member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
2179
2180                         if (member_lookup is MethodGroupExpr){
2181                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
2182
2183                                 //
2184                                 // Bind the instance expression to it
2185                                 //
2186                                 // FIXME: This is a horrible way of detecting if it is
2187                                 // an instance expression.  Figure out how to fix this.
2188                                 //
2189
2190                                 if (expr is LocalVariableReference ||
2191                                     expr is ParameterReference ||
2192                                     expr is FieldExpr)
2193                                         mg.InstanceExpression = expr;
2194                                         
2195                                 return member_lookup;
2196                         } else if (member_lookup is FieldExpr){
2197                                 FieldExpr fe = (FieldExpr) member_lookup;
2198
2199                                 fe.Instance = expr;
2200
2201                                 return member_lookup;
2202                         } else
2203                                 //
2204                                 // FIXME: This should generate the proper node
2205                                 // ie, for a Property Access, it should like call it
2206                                 // and stuff.
2207
2208                                 return member_lookup;
2209                 }
2210
2211                 public override void Emit (EmitContext ec)
2212                 {
2213                 }
2214
2215         }
2216
2217         // <summary>
2218         //   Nodes of type Namespace are created during the semantic
2219         //   analysis to resolve member_access/qualified_identifier/simple_name
2220         //   accesses.
2221         //
2222         //   They are born `resolved'. 
2223         // </summary>
2224         public class NamespaceExpr : Expression {
2225                 public readonly string Name;
2226                 
2227                 public NamespaceExpr (string name)
2228                 {
2229                         Name = name;
2230                         eclass = ExprClass.Namespace;
2231                 }
2232
2233                 public override Expression Resolve (TypeContainer tc)
2234                 {
2235                         return this;
2236                 }
2237
2238                 public override void Emit (EmitContext ec)
2239                 {
2240                 }
2241         }
2242
2243         // <summary>
2244         //   Fully resolved expression that evaluates to a type
2245         // </summary>
2246         public class TypeExpr : Expression {
2247                 public TypeExpr (Type t)
2248                 {
2249                         Type = t;
2250                         eclass = ExprClass.Type;
2251                 }
2252
2253                 override public Expression Resolve (TypeContainer tc)
2254                 {
2255                         return this;
2256                 }
2257
2258                 override public void Emit (EmitContext ec)
2259                 {
2260                         
2261                 }
2262         }
2263
2264         // <summary>
2265         //   MethodGroup Expression.
2266         //  
2267         //   This is a fully resolved expression that evaluates to a type
2268         // </summary>
2269         public class MethodGroupExpr : Expression {
2270                 public readonly MethodBase [] Methods;
2271                 Expression instance_expression = null;
2272                 
2273                 public MethodGroupExpr (MemberInfo [] mi)
2274                 {
2275                         Methods = new MethodBase [mi.Length];
2276                         mi.CopyTo (Methods, 0);
2277                         eclass = ExprClass.MethodGroup;
2278                 }
2279
2280                 //
2281                 // `A method group may have associated an instance expression' 
2282                 // 
2283                 public Expression InstanceExpression {
2284                         get {
2285                                 return instance_expression;
2286                         }
2287
2288                         set {
2289                                 instance_expression = value;
2290                         }
2291                 }
2292                 
2293                 override public Expression Resolve (TypeContainer tc)
2294                 {
2295                         return this;
2296                 }
2297
2298                 override public void Emit (EmitContext ec)
2299                 {
2300                         
2301                 }
2302         }
2303         
2304         public class BuiltinTypeAccess : Expression {
2305                 public readonly string AccessBase;
2306                 public readonly string Method;
2307                 
2308                 public BuiltinTypeAccess (string type, string method)
2309                 {
2310                         System.Console.WriteLine ("DUDE! This type should be fully resolved!");
2311                         AccessBase = type;
2312                         Method = method;
2313                 }
2314
2315                 public override Expression Resolve (TypeContainer tc)
2316                 {
2317                         // FIXME: Implement;
2318                         throw new Exception ("Unimplemented");
2319
2320                         return this;
2321                 }
2322
2323                 public override void Emit (EmitContext ec)
2324                 {
2325                 }
2326         }
2327
2328
2329         //   Fully resolved expression that evaluates to a Field
2330         // </summary>
2331         public class FieldExpr : Expression {
2332                 public readonly FieldInfo FieldInfo;
2333                 public Expression Instance;
2334                         
2335                 public FieldExpr (FieldInfo fi)
2336                 {
2337                         FieldInfo = fi;
2338                         eclass = ExprClass.Variable;
2339                         type = fi.FieldType;
2340                 }
2341
2342                 override public Expression Resolve (TypeContainer tc)
2343                 {
2344                         if (!FieldInfo.IsStatic){
2345                                 if (Instance == null){
2346                                         throw new Exception ("non-static FieldExpr without instance var\n" +
2347                                                              "You have to assign the Instance variable\n" +
2348                                                              "Of the FieldExpr to set this\n");
2349                                 }
2350
2351                                 Instance = Instance.Resolve (tc);
2352                                 if (Instance == null)
2353                                         return null;
2354                                 
2355                         }
2356                         return this;
2357                 }
2358
2359                 override public void Emit (EmitContext ec)
2360                 {
2361                         ILGenerator ig = ec.ig;
2362
2363                         if (FieldInfo.IsStatic)
2364                                 ig.Emit (OpCodes.Ldsfld, FieldInfo);
2365                         else {
2366                                 Instance.Emit (ec);
2367                                 
2368                                 ig.Emit (OpCodes.Ldfld, FieldInfo);
2369                         }
2370                 }
2371         }
2372         
2373         // <summary>
2374         //   Fully resolved expression that evaluates to a Property
2375         // </summary>
2376         public class PropertyExpr : Expression {
2377                 public readonly PropertyInfo PropertyInfo;
2378                 public readonly bool IsStatic;
2379                 
2380                 public PropertyExpr (PropertyInfo pi)
2381                 {
2382                         PropertyInfo = pi;
2383                         eclass = ExprClass.PropertyAccess;
2384                         IsStatic = false;
2385                                 
2386                         MethodBase [] acc = pi.GetAccessors ();
2387
2388                         for (int i = 0; i < acc.Length; i++)
2389                                 if (acc [i].IsStatic)
2390                                         IsStatic = true;
2391
2392                         type = pi.PropertyType;
2393                 }
2394
2395                 override public Expression Resolve (TypeContainer tc)
2396                 {
2397                         // We are born in resolved state. 
2398                         return this;
2399                 }
2400
2401                 override public void Emit (EmitContext ec)
2402                 {
2403                         // FIXME: Implement;
2404                         throw new Exception ("Unimplemented");
2405                 }
2406         }
2407
2408         // <summary>
2409         //   Fully resolved expression that evaluates to a Property
2410         // </summary>
2411         public class EventExpr : Expression {
2412                 public readonly EventInfo EventInfo;
2413                 
2414                 public EventExpr (EventInfo ei)
2415                 {
2416                         EventInfo = ei;
2417                         eclass = ExprClass.EventAccess;
2418                 }
2419
2420                 override public Expression Resolve (TypeContainer tc)
2421                 {
2422                         // We are born in resolved state. 
2423                         return this;
2424                 }
2425
2426                 override public void Emit (EmitContext ec)
2427                 {
2428                         // FIXME: Implement.
2429                 }
2430         }
2431         
2432         public class CheckedExpr : Expression {
2433
2434                 public Expression Expr;
2435
2436                 public CheckedExpr (Expression e)
2437                 {
2438                         Expr = e;
2439                 }
2440
2441                 public override Expression Resolve (TypeContainer tc)
2442                 {
2443                         Expr = Expr.Resolve (tc);
2444
2445                         if (Expr == null)
2446                                 return null;
2447
2448                         eclass = Expr.ExprClass;
2449                         type = Expr.Type;
2450                         return this;
2451                 }
2452
2453                 public override void Emit (EmitContext ec)
2454                 {
2455                         bool last_check = ec.CheckState;
2456
2457                         ec.CheckState = true;
2458                         
2459                         Expr.Emit (ec);
2460
2461                         ec.CheckState = last_check;
2462                 }
2463                 
2464         }
2465
2466         public class UnCheckedExpr : Expression {
2467
2468                 public Expression Expr;
2469
2470                 public UnCheckedExpr (Expression e)
2471                 {
2472                         Expr = e;
2473                 }
2474
2475                 public override Expression Resolve (TypeContainer tc)
2476                 {
2477                         Expr = Expr.Resolve (tc);
2478
2479                         if (Expr == null)
2480                                 return null;
2481
2482                         eclass = Expr.ExprClass;
2483                         type = Expr.Type;
2484                         return this;
2485                 }
2486
2487                 public override void Emit (EmitContext ec)
2488                 {
2489                         bool last_check = ec.CheckState;
2490
2491                         ec.CheckState = false;
2492                         
2493                         Expr.Emit (ec);
2494
2495                         ec.CheckState = last_check;
2496                 }
2497                 
2498         }
2499         
2500         public class ElementAccess : Expression {
2501                 
2502                 public readonly ArrayList  Arguments;
2503                 public readonly Expression Expr;
2504                 
2505                 public ElementAccess (Expression e, ArrayList e_list)
2506                 {
2507                         Expr = e;
2508                         Arguments = e_list;
2509                 }
2510
2511                 public override Expression Resolve (TypeContainer tc)
2512                 {
2513                         // FIXME: Implement;
2514                         throw new Exception ("Unimplemented");
2515
2516                         return this;
2517                 }
2518                 
2519                 public override void Emit (EmitContext ec)
2520                 {
2521                         // FIXME : Implement !
2522                 }
2523                 
2524         }
2525         
2526         public class BaseAccess : Expression {
2527
2528                 public enum BaseAccessType {
2529                         Member,
2530                         Indexer
2531                 };
2532                 
2533                 public readonly BaseAccessType BAType;
2534                 public readonly string         Member;
2535                 public readonly ArrayList      Arguments;
2536
2537                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
2538                 {
2539                         BAType = t;
2540                         Member = member;
2541                         Arguments = args;
2542                         
2543                 }
2544
2545                 public override Expression Resolve (TypeContainer tc)
2546                 {
2547                         // FIXME: Implement;
2548                         throw new Exception ("Unimplemented");
2549
2550                         return this;
2551                 }
2552
2553                 public override void Emit (EmitContext ec)
2554                 {
2555                 }
2556         }
2557 }