2001-12-25 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / expression.cs
1 //
2 // expression.cs: Expression representation for the IL tree.
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.
8 //
9 //
10 #define USE_OLD
11
12 namespace Mono.CSharp {
13         using System;
14         using System.Collections;
15         using System.Diagnostics;
16         using System.Reflection;
17         using System.Reflection.Emit;
18         using System.Text;
19
20         /// <summary>
21         ///   This is just a helper class, it is generated by Unary, UnaryMutator
22         ///   when an overloaded method has been found.  It just emits the code for a
23         ///   static call.
24         /// </summary>
25         public class StaticCallExpr : ExpressionStatement {
26                 ArrayList args;
27                 MethodInfo mi;
28
29                 StaticCallExpr (MethodInfo m, ArrayList a)
30                 {
31                         mi = m;
32                         args = a;
33
34                         type = m.ReturnType;
35                         eclass = ExprClass.Value;
36                 }
37
38                 public override Expression DoResolve (EmitContext ec)
39                 {
40                         //
41                         // We are born fully resolved
42                         //
43                         return this;
44                 }
45
46                 public override void Emit (EmitContext ec)
47                 {
48                         if (args != null) 
49                                 Invocation.EmitArguments (ec, mi, args);
50
51                         ec.ig.Emit (OpCodes.Call, mi);
52                         return;
53                 }
54                 
55                 static public Expression MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
56                                                          Expression e, Location loc)
57                 {
58                         ArrayList args;
59                         MethodBase method;
60                         
61                         args = new ArrayList (1);
62                         args.Add (new Argument (e, Argument.AType.Expression));
63                         method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg, args, loc);
64
65                         if (method == null)
66                                 return null;
67
68                         return new StaticCallExpr ((MethodInfo) method, args);
69                 }
70
71                 public override void EmitStatement (EmitContext ec)
72                 {
73                         Emit (ec);
74                         if (type != TypeManager.void_type)
75                                 ec.ig.Emit (OpCodes.Pop);
76                 }
77         }
78         
79         /// <summary>
80         ///   Unary expressions.  
81         /// </summary>
82         ///
83         /// <remarks>
84         ///   Unary implements unary expressions.   It derives from
85         ///   ExpressionStatement becuase the pre/post increment/decrement
86         ///   operators can be used in a statement context.
87         /// </remarks>
88         public class Unary : Expression {
89                 public enum Operator : byte {
90                         UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
91                         Indirection, AddressOf,  TOP
92                 }
93
94                 Operator   oper;
95                 Expression expr;
96                 Location   loc;
97                 
98                 public Unary (Operator op, Expression expr, Location loc)
99                 {
100                         this.oper = op;
101                         this.expr = expr;
102                         this.loc = loc;
103                 }
104
105                 public Expression Expr {
106                         get {
107                                 return expr;
108                         }
109
110                         set {
111                                 expr = value;
112                         }
113                 }
114
115                 public Operator Oper {
116                         get {
117                                 return oper;
118                         }
119
120                         set {
121                                 oper = value;
122                         }
123                 }
124
125                 /// <summary>
126                 ///   Returns a stringified representation of the Operator
127                 /// </summary>
128                 string OperName ()
129                 {
130                         switch (oper){
131                         case Operator.UnaryPlus:
132                                 return "+";
133                         case Operator.UnaryNegation:
134                                 return "-";
135                         case Operator.LogicalNot:
136                                 return "!";
137                         case Operator.OnesComplement:
138                                 return "~";
139                         case Operator.AddressOf:
140                                 return "&";
141                         case Operator.Indirection:
142                                 return "*";
143                         }
144
145                         return oper.ToString ();
146                 }
147
148                 static string [] oper_names;
149
150                 static Unary ()
151                 {
152                         oper_names = new string [(int)Operator.TOP];
153
154                         oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";
155                         oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
156                         oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
157                         oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
158                         oper_names [(int) Operator.Indirection] = "op_Indirection";
159                         oper_names [(int) Operator.AddressOf] = "op_AddressOf";
160                 }
161
162                 void error23 (Type t)
163                 {
164                         Report.Error (
165                                 23, loc, "Operator " + OperName () +
166                                 " cannot be applied to operand of type `" +
167                                 TypeManager.CSharpName (t) + "'");
168                 }
169
170                 /// <remarks>
171                 ///   The result has been already resolved:
172                 ///
173                 ///   FIXME: a minus constant -128 sbyte cant be turned into a
174                 ///   constant byte.
175                 /// </remarks>
176                 static Expression TryReduceNegative (Expression expr)
177                 {
178                         Expression e = null;
179                         
180                         if (expr is IntConstant)
181                                 e = new IntConstant (-((IntConstant) expr).Value);
182                         else if (expr is UIntConstant)
183                                 e = new LongConstant (-((UIntConstant) expr).Value);
184                         else if (expr is LongConstant)
185                                 e = new LongConstant (-((LongConstant) expr).Value);
186                         else if (expr is FloatConstant)
187                                 e = new FloatConstant (-((FloatConstant) expr).Value);
188                         else if (expr is DoubleConstant)
189                                 e = new DoubleConstant (-((DoubleConstant) expr).Value);
190                         else if (expr is DecimalConstant)
191                                 e = new DecimalConstant (-((DecimalConstant) expr).Value);
192                         else if (expr is ShortConstant)
193                                 e = new IntConstant (-((ShortConstant) expr).Value);
194                         else if (expr is UShortConstant)
195                                 e = new IntConstant (-((UShortConstant) expr).Value);
196
197                         return e;
198                 }
199                 
200                 Expression Reduce (EmitContext ec, Expression e)
201                 {
202                         Type expr_type = e.Type;
203                         
204                         switch (oper){
205                         case Operator.UnaryPlus:
206                                 return e;
207                                 
208                         case Operator.UnaryNegation:
209                                 return TryReduceNegative (e);
210                                 
211                         case Operator.LogicalNot:
212                                 if (expr_type != TypeManager.bool_type) {
213                                         error23 (expr_type);
214                                         return null;
215                                 }
216                                 
217                                 BoolConstant b = (BoolConstant) e;
218                                 return new BoolConstant (!(b.Value));
219                                 
220                         case Operator.OnesComplement:
221                                 if (!((expr_type == TypeManager.int32_type) ||
222                                       (expr_type == TypeManager.uint32_type) ||
223                                       (expr_type == TypeManager.int64_type) ||
224                                       (expr_type == TypeManager.uint64_type) ||
225                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
226                                         error23 (expr_type);
227                                         return null;
228                                 }
229
230                                 if (e is EnumConstant){
231                                         EnumConstant enum_constant = (EnumConstant) e;
232                                         
233                                         Expression reduced = Reduce (ec, enum_constant.Child);
234
235                                         return new EnumConstant ((Constant) reduced, enum_constant.Type);
236                                 }
237
238                                 if (expr_type == TypeManager.int32_type)
239                                         return new IntConstant (~ ((IntConstant) e).Value);
240                                 if (expr_type == TypeManager.uint32_type)
241                                         return new UIntConstant (~ ((UIntConstant) e).Value);
242                                 if (expr_type == TypeManager.int64_type)
243                                         return new LongConstant (~ ((LongConstant) e).Value);
244                                 if (expr_type == TypeManager.uint64_type)
245                                         return new ULongConstant (~ ((ULongConstant) e).Value);
246
247                                 throw new Exception (
248                                         "FIXME: Implement constant OnesComplement of:" +
249                                         expr_type);
250                         }
251                         throw new Exception ("Can not constant fold");
252                 }
253
254                 Expression ResolveOperator (EmitContext ec)
255                 {
256                         Type expr_type = expr.Type;
257
258                         //
259                         // Step 1: Perform Operator Overload location
260                         //
261                         Expression mg;
262                         string op_name;
263                         
264                         op_name = oper_names [(int) oper];
265
266                         mg = MemberLookup (ec, expr_type, op_name, false, loc);
267                         
268                         if (mg == null && expr_type.BaseType != null)
269                                 mg = MemberLookup (ec, expr_type.BaseType, op_name, false, loc);
270                         
271                         if (mg != null) {
272                                 Expression e = StaticCallExpr.MakeSimpleCall (
273                                         ec, (MethodGroupExpr) mg, expr, loc);
274
275                                 if (e == null){
276                                         error23 (expr_type);
277                                         return null;
278                                 }
279                                 
280                                 return e;
281                         }
282
283                         // Only perform numeric promotions on:
284                         // +, - 
285
286                         if (expr_type == null)
287                                 return null;
288                         
289                         //
290                         // Step 2: Default operations on CLI native types.
291                         //
292                         if (expr is Constant)
293                                 return Reduce (ec, expr);
294
295                         if (oper == Operator.LogicalNot){
296                                 if (expr_type != TypeManager.bool_type) {
297                                         error23 (expr.Type);
298                                         return null;
299                                 }
300                                 
301                                 type = TypeManager.bool_type;
302                                 return this;
303                         }
304
305                         if (oper == Operator.OnesComplement) {
306                                 if (!((expr_type == TypeManager.int32_type) ||
307                                       (expr_type == TypeManager.uint32_type) ||
308                                       (expr_type == TypeManager.int64_type) ||
309                                       (expr_type == TypeManager.uint64_type) ||
310                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
311                                         error23 (expr.Type);
312                                         return null;
313                                 }
314                                 type = expr_type;
315                                 return this;
316                         }
317
318                         if (oper == Operator.UnaryPlus) {
319                                 //
320                                 // A plus in front of something is just a no-op, so return the child.
321                                 //
322                                 return expr;
323                         }
324
325                         //
326                         // Deals with -literals
327                         // int     operator- (int x)
328                         // long    operator- (long x)
329                         // float   operator- (float f)
330                         // double  operator- (double d)
331                         // decimal operator- (decimal d)
332                         //
333                         if (oper == Operator.UnaryNegation){
334                                 //
335                                 // Fold a "- Constant" into a negative constant
336                                 //
337                         
338                                 Expression e = null;
339
340                                 //
341                                 // Not a constant we can optimize, perform numeric 
342                                 // promotions to int, long, double.
343                                 //
344                                 //
345                                 // The following is inneficient, because we call
346                                 // ConvertImplicit too many times.
347                                 //
348                                 // It is also not clear if we should convert to Float
349                                 // or Double initially.
350                                 //
351                                 if (expr_type == TypeManager.uint32_type){
352                                         //
353                                         // FIXME: handle exception to this rule that
354                                         // permits the int value -2147483648 (-2^31) to
355                                         // bt wrote as a decimal interger literal
356                                         //
357                                         type = TypeManager.int64_type;
358                                         expr = ConvertImplicit (ec, expr, type, loc);
359                                         return this;
360                                 }
361
362                                 if (expr_type == TypeManager.uint64_type){
363                                         //
364                                         // FIXME: Handle exception of `long value'
365                                         // -92233720368547758087 (-2^63) to be wrote as
366                                         // decimal integer literal.
367                                         //
368                                         error23 (expr_type);
369                                         return null;
370                                 }
371
372                                 e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);
373                                 if (e != null){
374                                         expr = e;
375                                         type = e.Type;
376                                         return this;
377                                 } 
378
379                                 e = ConvertImplicit (ec, expr, TypeManager.int64_type, loc);
380                                 if (e != null){
381                                         expr = e;
382                                         type = e.Type;
383                                         return this;
384                                 }
385
386                                 e = ConvertImplicit (ec, expr, TypeManager.double_type, loc);
387                                 if (e != null){
388                                         expr = e;
389                                         type = e.Type;
390                                         return this;
391                                 }
392
393                                 error23 (expr_type);
394                                 return null;
395                         }
396
397                         if (oper == Operator.AddressOf){
398                                 if (expr.eclass != ExprClass.Variable){
399                                         Error (211, loc, "Cannot take the address of non-variables");
400                                         return null;
401                                 }
402                                 type = Type.GetType (expr.Type.ToString () + "*");
403
404                                 return this;
405                         }
406                         
407                         Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
408                                TypeManager.CSharpName (expr_type) + "'");
409                         return null;
410                 }
411
412                 public override Expression DoResolve (EmitContext ec)
413                 {
414                         expr = expr.Resolve (ec);
415                         
416                         if (expr == null)
417                                 return null;
418
419                         eclass = ExprClass.Value;
420                         return ResolveOperator (ec);
421                 }
422
423                 public override void Emit (EmitContext ec)
424                 {
425                         ILGenerator ig = ec.ig;
426                         Type expr_type = expr.Type;
427                         
428                         switch (oper) {
429                         case Operator.UnaryPlus:
430                                 throw new Exception ("This should be caught by Resolve");
431                                 
432                         case Operator.UnaryNegation:
433                                 expr.Emit (ec);
434                                 ig.Emit (OpCodes.Neg);
435                                 break;
436                                 
437                         case Operator.LogicalNot:
438                                 expr.Emit (ec);
439                                 ig.Emit (OpCodes.Ldc_I4_0);
440                                 ig.Emit (OpCodes.Ceq);
441                                 break;
442                                 
443                         case Operator.OnesComplement:
444                                 expr.Emit (ec);
445                                 ig.Emit (OpCodes.Not);
446                                 break;
447                                 
448                         case Operator.AddressOf:
449                                 ((IMemoryLocation)expr).AddressOf (ec);
450                                 break;
451                                 
452                         case Operator.Indirection:
453                                 throw new Exception ("Not implemented yet");
454                                 
455                         default:
456                                 throw new Exception ("This should not happen: Operator = "
457                                                      + oper.ToString ());
458                         }
459                 }
460
461                 /// <summary>
462                 ///   This will emit the child expression for `ec' avoiding the logical
463                 ///   not.  The parent will take care of changing brfalse/brtrue
464                 /// </summary>
465                 public void EmitLogicalNot (EmitContext ec)
466                 {
467                         if (oper != Operator.LogicalNot)
468                                 throw new Exception ("EmitLogicalNot can only be called with !expr");
469
470                         expr.Emit (ec);
471                 }
472                 
473         }
474
475         /// <summary>
476         ///   Unary Mutator expressions (pre and post ++ and --)
477         /// </summary>
478         ///
479         /// <remarks>
480         ///   UnaryMutator implements ++ and -- expressions.   It derives from
481         ///   ExpressionStatement becuase the pre/post increment/decrement
482         ///   operators can be used in a statement context.
483         ///
484         /// FIXME: Idea, we could split this up in two classes, one simpler
485         /// for the common case, and one with the extra fields for more complex
486         /// classes (indexers require temporary access;  overloaded require method)
487         ///
488         /// Maybe we should have classes PreIncrement, PostIncrement, PreDecrement,
489         /// PostDecrement, that way we could save the `Mode' byte as well.  
490         /// </remarks>
491         public class UnaryMutator : ExpressionStatement {
492                 public enum Mode : byte {
493                         PreIncrement, PreDecrement, PostIncrement, PostDecrement
494                 }
495                 
496                 Mode mode;
497                 Location loc;
498                 Expression expr;
499                 LocalTemporary temp_storage;
500
501                 //
502                 // This is expensive for the simplest case.
503                 //
504                 Expression method;
505                         
506                 public UnaryMutator (Mode m, Expression e, Location l)
507                 {
508                         mode = m;
509                         loc = l;
510                         expr = e;
511                 }
512
513                 string OperName ()
514                 {
515                         return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
516                                 "++" : "--";
517                 }
518                 
519                 void error23 (Type t)
520                 {
521                         Report.Error (
522                                 23, loc, "Operator " + OperName () + 
523                                 " cannot be applied to operand of type `" +
524                                 TypeManager.CSharpName (t) + "'");
525                 }
526
527                 /// <summary>
528                 ///   Returns whether an object of type `t' can be incremented
529                 ///   or decremented with add/sub (ie, basically whether we can
530                 ///   use pre-post incr-decr operations on it, but it is not a
531                 ///   System.Decimal, which we require operator overloading to catch)
532                 /// </summary>
533                 static bool IsIncrementableNumber (Type t)
534                 {
535                         return (t == TypeManager.sbyte_type) ||
536                                 (t == TypeManager.byte_type) ||
537                                 (t == TypeManager.short_type) ||
538                                 (t == TypeManager.ushort_type) ||
539                                 (t == TypeManager.int32_type) ||
540                                 (t == TypeManager.uint32_type) ||
541                                 (t == TypeManager.int64_type) ||
542                                 (t == TypeManager.uint64_type) ||
543                                 (t == TypeManager.char_type) ||
544                                 (t.IsSubclassOf (TypeManager.enum_type)) ||
545                                 (t == TypeManager.float_type) ||
546                                 (t == TypeManager.double_type);
547                 }
548
549                 Expression ResolveOperator (EmitContext ec)
550                 {
551                         Type expr_type = expr.Type;
552
553                         //
554                         // Step 1: Perform Operator Overload location
555                         //
556                         Expression mg;
557                         string op_name;
558                         
559                         if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
560                                 op_name = "op_Increment";
561                         else 
562                                 op_name = "op_Decrement";
563
564                         mg = MemberLookup (ec, expr_type, op_name, false, loc);
565
566                         if (mg == null && expr_type.BaseType != null)
567                                 mg = MemberLookup (ec, expr_type.BaseType, op_name, false, loc);
568                         
569                         if (mg != null) {
570                                 method = StaticCallExpr.MakeSimpleCall (
571                                         ec, (MethodGroupExpr) mg, expr, loc);
572
573                                 type = method.Type;
574                                 return this;
575                         }
576
577                         //
578                         // The operand of the prefix/postfix increment decrement operators
579                         // should be an expression that is classified as a variable,
580                         // a property access or an indexer access
581                         //
582                         type = expr_type;
583                         if (expr.eclass == ExprClass.Variable){
584                                 if (IsIncrementableNumber (expr_type) ||
585                                     expr_type == TypeManager.decimal_type){
586                                         return this;
587                                 }
588                         } else if (expr.eclass == ExprClass.IndexerAccess){
589                                 IndexerAccess ia = (IndexerAccess) expr;
590                                 
591                                 temp_storage = new LocalTemporary (ec, expr.Type);
592                                 
593                                 expr = ia.ResolveLValue (ec, temp_storage);
594                                 if (expr == null)
595                                         return null;
596
597                                 return this;
598                         } else if (expr.eclass == ExprClass.PropertyAccess){
599                                 PropertyExpr pe = (PropertyExpr) expr;
600
601                                 if (pe.VerifyAssignable ())
602                                         return this;
603
604                                 return null;
605                         } else {
606                                 report118 (loc, expr, "variable, indexer or property access");
607                                 return null;
608                         }
609
610                         Error (187, loc, "No such operator '" + OperName () + "' defined for type '" +
611                                TypeManager.CSharpName (expr_type) + "'");
612                         return null;
613                 }
614
615                 public override Expression DoResolve (EmitContext ec)
616                 {
617                         expr = expr.Resolve (ec);
618                         
619                         if (expr == null)
620                                 return null;
621
622                         eclass = ExprClass.Value;
623                         return ResolveOperator (ec);
624                 }
625                 
626
627                 //
628                 // FIXME: We need some way of avoiding the use of temp_storage
629                 // for some types of storage (parameters, local variables,
630                 // static fields) and single-dimension array access.
631                 //
632                 void EmitCode (EmitContext ec, bool is_expr)
633                 {
634                         ILGenerator ig = ec.ig;
635                         IAssignMethod ia = (IAssignMethod) expr;
636
637                         if (temp_storage == null)
638                                 temp_storage = new LocalTemporary (ec, expr.Type);
639                         
640                         switch (mode){
641                         case Mode.PreIncrement:
642                         case Mode.PreDecrement:
643                                 if (method == null){
644                                         expr.Emit (ec);
645
646                                         ig.Emit (OpCodes.Ldc_I4_1);
647                                 
648                                         if (mode == Mode.PreDecrement)
649                                                 ig.Emit (OpCodes.Sub);
650                                         else
651                                                 ig.Emit (OpCodes.Add);
652                                 } else
653                                         method.Emit (ec);
654                                 
655                                 temp_storage.Store (ec);
656                                 ia.EmitAssign (ec, temp_storage);
657                                 if (is_expr)
658                                         temp_storage.Emit (ec);
659                                 break;
660                                 
661                         case Mode.PostIncrement:
662                         case Mode.PostDecrement:
663                                 if (is_expr)
664                                         expr.Emit (ec);
665                                 
666                                 if (method == null){
667                                         if (!is_expr)
668                                                 expr.Emit (ec);
669                                         else
670                                                 ig.Emit (OpCodes.Dup);
671
672                                         ig.Emit (OpCodes.Ldc_I4_1);
673                                 
674                                         if (mode == Mode.PostDecrement)
675                                                 ig.Emit (OpCodes.Sub);
676                                         else
677                                                 ig.Emit (OpCodes.Add);
678                                 } else {
679                                         method.Emit (ec);
680                                 }
681                                 
682                                 temp_storage.Store (ec);
683                                 ia.EmitAssign (ec, temp_storage);
684                                 break;
685                         }
686                 }
687
688                 public override void Emit (EmitContext ec)
689                 {
690                         EmitCode (ec, true);
691                         
692                 }
693                 
694                 public override void EmitStatement (EmitContext ec)
695                 {
696                         EmitCode (ec, false);
697                 }
698
699         }
700
701         /// <summary>
702         ///   Base class for the `Is' and `As' classes. 
703         /// </summary>
704         ///
705         /// <remarks>
706         ///   FIXME: Split this in two, and we get to save the `Operator' Oper
707         ///   size. 
708         /// </remarks>
709         public abstract class Probe : Expression {
710                 public readonly string ProbeType;
711                 protected Expression expr;
712                 protected Type probe_type;
713                 Location loc;
714                 
715                 public Probe (Expression expr, string probe_type, Location l)
716                 {
717                         ProbeType = probe_type;
718                         loc = l;
719                         this.expr = expr;
720                 }
721
722                 public Expression Expr {
723                         get {
724                                 return expr;
725                         }
726                 }
727
728                 public override Expression DoResolve (EmitContext ec)
729                 {
730                         probe_type = RootContext.LookupType (ec.TypeContainer, ProbeType, false, loc);
731
732                         if (probe_type == null)
733                                 return null;
734
735                         expr = expr.Resolve (ec);
736                         
737                         return this;
738                 }
739         }
740
741         /// <summary>
742         ///   Implementation of the `is' operator.
743         /// </summary>
744         public class Is : Probe {
745                 public Is (Expression expr, string probe_type, Location l)
746                         : base (expr, probe_type, l)
747                 {
748                 }
749
750                 public override void Emit (EmitContext ec)
751                 {
752                         ILGenerator ig = ec.ig;
753                         
754                         expr.Emit (ec);
755                         
756                         ig.Emit (OpCodes.Isinst, probe_type);
757                         ig.Emit (OpCodes.Ldnull);
758                         ig.Emit (OpCodes.Cgt_Un);
759                 }
760
761                 public override Expression DoResolve (EmitContext ec)
762                 {
763                         Expression e = base.DoResolve (ec);
764
765                         if (e == null)
766                                 return null;
767
768                         type = TypeManager.bool_type;
769                         eclass = ExprClass.Value;
770
771                         return this;
772                 }                               
773         }
774
775         /// <summary>
776         ///   Implementation of the `as' operator.
777         /// </summary>
778         public class As : Probe {
779                 public As (Expression expr, string probe_type, Location l)
780                         : base (expr, probe_type, l)
781                 {
782                 }
783
784                 public override void Emit (EmitContext ec)
785                 {
786                         ILGenerator ig = ec.ig;
787
788                         expr.Emit (ec);
789                         ig.Emit (OpCodes.Isinst, probe_type);
790                 }
791
792                 public override Expression DoResolve (EmitContext ec)
793                 {
794                         Expression e = base.DoResolve (ec);
795
796                         if (e == null)
797                                 return null;
798
799                         type = probe_type;
800                         eclass = ExprClass.Value;
801
802                         return this;
803                 }                               
804         }
805         
806         /// <summary>
807         ///   This represents a typecast in the source language.
808         ///
809         ///   FIXME: Cast expressions have an unusual set of parsing
810         ///   rules, we need to figure those out.
811         /// </summary>
812         public class Cast : Expression {
813                 Expression target_type;
814                 Expression expr;
815                 Location   loc;
816                         
817                 public Cast (Expression cast_type, Expression expr, Location loc)
818                 {
819                         this.target_type = cast_type;
820                         this.expr = expr;
821                         this.loc = loc;
822                 }
823
824                 public Expression TargetType {
825                         get {
826                                 return target_type;
827                         }
828                 }
829
830                 public Expression Expr {
831                         get {
832                                 return expr;
833                         }
834                         set {
835                                 expr = value;
836                         }
837                 }
838
839                 /// <summary>
840                 ///   Attempts to do a compile-time folding of a constant cast.
841                 /// </summary>
842                 Expression TryReduce (EmitContext ec, Type target_type)
843                 {
844                         if (expr is ByteConstant){
845                                 byte v = ((ByteConstant) expr).Value;
846         
847                                 if (target_type == TypeManager.sbyte_type)
848                                         return new SByteConstant ((sbyte) v);
849                                 if (target_type == TypeManager.short_type)
850                                         return new ShortConstant ((short) v);
851                                 if (target_type == TypeManager.ushort_type)
852                                         return new UShortConstant ((ushort) v);
853                                 if (target_type == TypeManager.int32_type)
854                                         return new IntConstant ((int) v);
855                                 if (target_type == TypeManager.uint32_type)
856                                         return new UIntConstant ((uint) v);
857                                 if (target_type == TypeManager.int64_type)
858                                         return new LongConstant ((long) v);
859                                 if (target_type == TypeManager.uint64_type)
860                                         return new ULongConstant ((ulong) v);
861                                 if (target_type == TypeManager.float_type)
862                                         return new FloatConstant ((float) v);
863                                 if (target_type == TypeManager.double_type)
864                                         return new DoubleConstant ((double) v);
865                         }
866                         if (expr is SByteConstant){
867                                 sbyte v = ((SByteConstant) expr).Value;
868         
869                                 if (target_type == TypeManager.byte_type)
870                                         return new ByteConstant ((byte) v);
871                                 if (target_type == TypeManager.short_type)
872                                         return new ShortConstant ((short) v);
873                                 if (target_type == TypeManager.ushort_type)
874                                         return new UShortConstant ((ushort) v);
875                                 if (target_type == TypeManager.int32_type)
876                                         return new IntConstant ((int) v);
877                                 if (target_type == TypeManager.uint32_type)
878                                         return new UIntConstant ((uint) v);
879                                 if (target_type == TypeManager.int64_type)
880                                         return new LongConstant ((long) v);
881                                 if (target_type == TypeManager.uint64_type)
882                                         return new ULongConstant ((ulong) v);
883                                 if (target_type == TypeManager.float_type)
884                                         return new FloatConstant ((float) v);
885                                 if (target_type == TypeManager.double_type)
886                                         return new DoubleConstant ((double) v);
887                         }
888                         if (expr is ShortConstant){
889                                 short v = ((ShortConstant) expr).Value;
890         
891                                 if (target_type == TypeManager.byte_type)
892                                         return new ByteConstant ((byte) v);
893                                 if (target_type == TypeManager.sbyte_type)
894                                         return new SByteConstant ((sbyte) v);
895                                 if (target_type == TypeManager.ushort_type)
896                                         return new UShortConstant ((ushort) v);
897                                 if (target_type == TypeManager.int32_type)
898                                         return new IntConstant ((int) v);
899                                 if (target_type == TypeManager.uint32_type)
900                                         return new UIntConstant ((uint) v);
901                                 if (target_type == TypeManager.int64_type)
902                                         return new LongConstant ((long) v);
903                                 if (target_type == TypeManager.uint64_type)
904                                         return new ULongConstant ((ulong) v);
905                                 if (target_type == TypeManager.float_type)
906                                         return new FloatConstant ((float) v);
907                                 if (target_type == TypeManager.double_type)
908                                         return new DoubleConstant ((double) v);
909                         }
910                         if (expr is UShortConstant){
911                                 ushort v = ((UShortConstant) expr).Value;
912         
913                                 if (target_type == TypeManager.byte_type)
914                                         return new ByteConstant ((byte) v);
915                                 if (target_type == TypeManager.sbyte_type)
916                                         return new SByteConstant ((sbyte) v);
917                                 if (target_type == TypeManager.short_type)
918                                         return new ShortConstant ((short) v);
919                                 if (target_type == TypeManager.int32_type)
920                                         return new IntConstant ((int) v);
921                                 if (target_type == TypeManager.uint32_type)
922                                         return new UIntConstant ((uint) v);
923                                 if (target_type == TypeManager.int64_type)
924                                         return new LongConstant ((long) v);
925                                 if (target_type == TypeManager.uint64_type)
926                                         return new ULongConstant ((ulong) v);
927                                 if (target_type == TypeManager.float_type)
928                                         return new FloatConstant ((float) v);
929                                 if (target_type == TypeManager.double_type)
930                                         return new DoubleConstant ((double) v);
931                         }
932                         if (expr is IntConstant){
933                                 int v = ((IntConstant) expr).Value;
934         
935                                 if (target_type == TypeManager.byte_type)
936                                         return new ByteConstant ((byte) v);
937                                 if (target_type == TypeManager.sbyte_type)
938                                         return new SByteConstant ((sbyte) v);
939                                 if (target_type == TypeManager.short_type)
940                                         return new ShortConstant ((short) v);
941                                 if (target_type == TypeManager.ushort_type)
942                                         return new UShortConstant ((ushort) v);
943                                 if (target_type == TypeManager.uint32_type)
944                                         return new UIntConstant ((uint) v);
945                                 if (target_type == TypeManager.int64_type)
946                                         return new LongConstant ((long) v);
947                                 if (target_type == TypeManager.uint64_type)
948                                         return new ULongConstant ((ulong) v);
949                                 if (target_type == TypeManager.float_type)
950                                         return new FloatConstant ((float) v);
951                                 if (target_type == TypeManager.double_type)
952                                         return new DoubleConstant ((double) v);
953                         }
954                         if (expr is UIntConstant){
955                                 uint v = ((UIntConstant) expr).Value;
956         
957                                 if (target_type == TypeManager.byte_type)
958                                         return new ByteConstant ((byte) v);
959                                 if (target_type == TypeManager.sbyte_type)
960                                         return new SByteConstant ((sbyte) v);
961                                 if (target_type == TypeManager.short_type)
962                                         return new ShortConstant ((short) v);
963                                 if (target_type == TypeManager.ushort_type)
964                                         return new UShortConstant ((ushort) v);
965                                 if (target_type == TypeManager.int32_type)
966                                         return new IntConstant ((int) v);
967                                 if (target_type == TypeManager.int64_type)
968                                         return new LongConstant ((long) v);
969                                 if (target_type == TypeManager.uint64_type)
970                                         return new ULongConstant ((ulong) v);
971                                 if (target_type == TypeManager.float_type)
972                                         return new FloatConstant ((float) v);
973                                 if (target_type == TypeManager.double_type)
974                                         return new DoubleConstant ((double) v);
975                         }
976                         if (expr is LongConstant){
977                                 long v = ((LongConstant) expr).Value;
978         
979                                 if (target_type == TypeManager.byte_type)
980                                         return new ByteConstant ((byte) v);
981                                 if (target_type == TypeManager.sbyte_type)
982                                         return new SByteConstant ((sbyte) v);
983                                 if (target_type == TypeManager.short_type)
984                                         return new ShortConstant ((short) v);
985                                 if (target_type == TypeManager.ushort_type)
986                                         return new UShortConstant ((ushort) v);
987                                 if (target_type == TypeManager.int32_type)
988                                         return new IntConstant ((int) v);
989                                 if (target_type == TypeManager.uint32_type)
990                                         return new UIntConstant ((uint) v);
991                                 if (target_type == TypeManager.uint64_type)
992                                         return new ULongConstant ((ulong) v);
993                                 if (target_type == TypeManager.float_type)
994                                         return new FloatConstant ((float) v);
995                                 if (target_type == TypeManager.double_type)
996                                         return new DoubleConstant ((double) v);
997                         }
998                         if (expr is ULongConstant){
999                                 ulong v = ((ULongConstant) expr).Value;
1000         
1001                                 if (target_type == TypeManager.byte_type)
1002                                         return new ByteConstant ((byte) v);
1003                                 if (target_type == TypeManager.sbyte_type)
1004                                         return new SByteConstant ((sbyte) v);
1005                                 if (target_type == TypeManager.short_type)
1006                                         return new ShortConstant ((short) v);
1007                                 if (target_type == TypeManager.ushort_type)
1008                                         return new UShortConstant ((ushort) v);
1009                                 if (target_type == TypeManager.int32_type)
1010                                         return new IntConstant ((int) v);
1011                                 if (target_type == TypeManager.uint32_type)
1012                                         return new UIntConstant ((uint) v);
1013                                 if (target_type == TypeManager.int64_type)
1014                                         return new LongConstant ((long) v);
1015                                 if (target_type == TypeManager.float_type)
1016                                         return new FloatConstant ((float) v);
1017                                 if (target_type == TypeManager.double_type)
1018                                         return new DoubleConstant ((double) v);
1019                         }
1020                         if (expr is FloatConstant){
1021                                 float v = ((FloatConstant) expr).Value;
1022         
1023                                 if (target_type == TypeManager.byte_type)
1024                                         return new ByteConstant ((byte) v);
1025                                 if (target_type == TypeManager.sbyte_type)
1026                                         return new SByteConstant ((sbyte) v);
1027                                 if (target_type == TypeManager.short_type)
1028                                         return new ShortConstant ((short) v);
1029                                 if (target_type == TypeManager.ushort_type)
1030                                         return new UShortConstant ((ushort) v);
1031                                 if (target_type == TypeManager.int32_type)
1032                                         return new IntConstant ((int) v);
1033                                 if (target_type == TypeManager.uint32_type)
1034                                         return new UIntConstant ((uint) v);
1035                                 if (target_type == TypeManager.int64_type)
1036                                         return new LongConstant ((long) v);
1037                                 if (target_type == TypeManager.uint64_type)
1038                                         return new ULongConstant ((ulong) v);
1039                                 if (target_type == TypeManager.double_type)
1040                                         return new DoubleConstant ((double) v);
1041                         }
1042                         if (expr is DoubleConstant){
1043                                 double v = ((DoubleConstant) expr).Value;
1044         
1045                                 if (target_type == TypeManager.byte_type)
1046                                         return new ByteConstant ((byte) v);
1047                                 if (target_type == TypeManager.sbyte_type)
1048                                         return new SByteConstant ((sbyte) v);
1049                                 if (target_type == TypeManager.short_type)
1050                                         return new ShortConstant ((short) v);
1051                                 if (target_type == TypeManager.ushort_type)
1052                                         return new UShortConstant ((ushort) v);
1053                                 if (target_type == TypeManager.int32_type)
1054                                         return new IntConstant ((int) v);
1055                                 if (target_type == TypeManager.uint32_type)
1056                                         return new UIntConstant ((uint) v);
1057                                 if (target_type == TypeManager.int64_type)
1058                                         return new LongConstant ((long) v);
1059                                 if (target_type == TypeManager.uint64_type)
1060                                         return new ULongConstant ((ulong) v);
1061                                 if (target_type == TypeManager.float_type)
1062                                         return new FloatConstant ((float) v);
1063                         }
1064
1065                         return null;
1066                 }
1067                 
1068                 public override Expression DoResolve (EmitContext ec)
1069                 {
1070                         expr = expr.Resolve (ec);
1071                         if (expr == null)
1072                                 return null;
1073
1074                         target_type = target_type.Resolve (ec);
1075                         if (target_type == null)
1076                                 return null;
1077
1078                         if (target_type.eclass != ExprClass.Type){
1079                                 report118 (loc, target_type, "class");
1080                                 return null;
1081                         }
1082                         
1083                         type = target_type.Type;
1084                         eclass = ExprClass.Value;
1085                         
1086                         if (type == null)
1087                                 return null;
1088
1089                         if (expr is Constant){
1090                                 Expression e = TryReduce (ec, type);
1091
1092                                 if (e != null)
1093                                         return e;
1094                         }
1095                         
1096                         expr = ConvertExplicit (ec, expr, type, loc);
1097                         return expr;
1098                 }
1099
1100                 public override void Emit (EmitContext ec)
1101                 {
1102                         //
1103                         // This one will never happen
1104                         //
1105                         throw new Exception ("Should not happen");
1106                 }
1107         }
1108
1109         /// <summary>
1110         ///   Binary operators
1111         /// </summary>
1112         public class Binary : Expression {
1113                 public enum Operator : byte {
1114                         Multiply, Division, Modulus,
1115                         Addition, Subtraction,
1116                         LeftShift, RightShift,
1117                         LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
1118                         Equality, Inequality,
1119                         BitwiseAnd,
1120                         ExclusiveOr,
1121                         BitwiseOr,
1122                         LogicalAnd,
1123                         LogicalOr
1124                 }
1125
1126                 Operator oper;
1127                 Expression left, right;
1128                 MethodBase method;
1129                 ArrayList  Arguments;
1130                 Location   loc;
1131
1132                 bool DelegateOperation;
1133
1134                 public Binary (Operator oper, Expression left, Expression right, Location loc)
1135                 {
1136                         this.oper = oper;
1137                         this.left = left;
1138                         this.right = right;
1139                         this.loc = loc;
1140                 }
1141
1142                 public Operator Oper {
1143                         get {
1144                                 return oper;
1145                         }
1146                         set {
1147                                 oper = value;
1148                         }
1149                 }
1150                 
1151                 public Expression Left {
1152                         get {
1153                                 return left;
1154                         }
1155                         set {
1156                                 left = value;
1157                         }
1158                 }
1159
1160                 public Expression Right {
1161                         get {
1162                                 return right;
1163                         }
1164                         set {
1165                                 right = value;
1166                         }
1167                 }
1168
1169
1170                 /// <summary>
1171                 ///   Returns a stringified representation of the Operator
1172                 /// </summary>
1173                 string OperName ()
1174                 {
1175                         switch (oper){
1176                         case Operator.Multiply:
1177                                 return "*";
1178                         case Operator.Division:
1179                                 return "/";
1180                         case Operator.Modulus:
1181                                 return "%";
1182                         case Operator.Addition:
1183                                 return "+";
1184                         case Operator.Subtraction:
1185                                 return "-";
1186                         case Operator.LeftShift:
1187                                 return "<<";
1188                         case Operator.RightShift:
1189                                 return ">>";
1190                         case Operator.LessThan:
1191                                 return "<";
1192                         case Operator.GreaterThan:
1193                                 return ">";
1194                         case Operator.LessThanOrEqual:
1195                                 return "<=";
1196                         case Operator.GreaterThanOrEqual:
1197                                 return ">=";
1198                         case Operator.Equality:
1199                                 return "==";
1200                         case Operator.Inequality:
1201                                 return "!=";
1202                         case Operator.BitwiseAnd:
1203                                 return "&";
1204                         case Operator.BitwiseOr:
1205                                 return "|";
1206                         case Operator.ExclusiveOr:
1207                                 return "^";
1208                         case Operator.LogicalOr:
1209                                 return "||";
1210                         case Operator.LogicalAnd:
1211                                 return "&&";
1212                         }
1213
1214                         return oper.ToString ();
1215                 }
1216
1217                 Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
1218                 {
1219                         if (expr.Type == target_type)
1220                                 return expr;
1221
1222                         return ConvertImplicit (ec, expr, target_type, new Location (-1));
1223                 }
1224                 
1225                 //
1226                 // Note that handling the case l == Decimal || r == Decimal
1227                 // is taken care of by the Step 1 Operator Overload resolution.
1228                 //
1229                 bool DoNumericPromotions (EmitContext ec, Type l, Type r)
1230                 {
1231                         if (l == TypeManager.double_type || r == TypeManager.double_type){
1232                                 //
1233                                 // If either operand is of type double, the other operand is
1234                                 // conveted to type double.
1235                                 //
1236                                 if (r != TypeManager.double_type)
1237                                         right = ConvertImplicit (ec, right, TypeManager.double_type, loc);
1238                                 if (l != TypeManager.double_type)
1239                                         left = ConvertImplicit (ec, left, TypeManager.double_type, loc);
1240                                 
1241                                 type = TypeManager.double_type;
1242                         } else if (l == TypeManager.float_type || r == TypeManager.float_type){
1243                                 //
1244                                 // if either operand is of type float, th eother operand is
1245                                 // converd to type float.
1246                                 //
1247                                 if (r != TypeManager.double_type)
1248                                         right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
1249                                 if (l != TypeManager.double_type)
1250                                         left = ConvertImplicit (ec, left, TypeManager.float_type, loc);
1251                                 type = TypeManager.float_type;
1252                         } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
1253                                 Expression e;
1254                                 Type other;
1255                                 //
1256                                 // If either operand is of type ulong, the other operand is
1257                                 // converted to type ulong.  or an error ocurrs if the other
1258                                 // operand is of type sbyte, short, int or long
1259                                 //
1260                                 
1261                                 if (l == TypeManager.uint64_type){
1262                                         if (r != TypeManager.uint64_type){
1263                                                 if (right is IntConstant){
1264                                                         e = TryImplicitIntConversion(l, (IntConstant) right);
1265                                                         if (e != null)
1266                                                                 right = e;
1267                                                 } else if (right is LongConstant){
1268                                                         long ll = ((LongConstant) right).Value;
1269
1270                                                         if (ll > 0)
1271                                                                 right = new ULongConstant ((ulong) ll);
1272                                                 }
1273                                         }
1274                                         other = right.Type;
1275                                 } else {
1276                                         if (left is IntConstant){
1277                                                 e = TryImplicitIntConversion (r, (IntConstant) left);
1278                                                 if (e != null)
1279                                                         left = e;
1280                                         } else if (left is LongConstant){
1281                                                 long ll = ((LongConstant) left).Value;
1282
1283                                                 if (ll > 0)
1284                                                         left = new ULongConstant ((ulong) ll);
1285                                         }
1286                                         other = left.Type;
1287                                 }
1288
1289                                 if ((other == TypeManager.sbyte_type) ||
1290                                     (other == TypeManager.short_type) ||
1291                                     (other == TypeManager.int32_type) ||
1292                                     (other == TypeManager.int64_type)){
1293                                         string oper = OperName ();
1294                                         
1295                                         Error (34, loc, "Operator `" + OperName ()
1296                                                + "' is ambiguous on operands of type `"
1297                                                + TypeManager.CSharpName (l) + "' "
1298                                                + "and `" + TypeManager.CSharpName (r)
1299                                                + "'");
1300                                 }
1301                                 type = TypeManager.uint64_type;
1302                         } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
1303                                 //
1304                                 // If either operand is of type long, the other operand is converted
1305                                 // to type long.
1306                                 //
1307                                 if (l != TypeManager.int64_type)
1308                                         left = ConvertImplicit (ec, left, TypeManager.int64_type, loc);
1309                                 if (r != TypeManager.int64_type)
1310                                         right = ConvertImplicit (ec, right, TypeManager.int64_type, loc);
1311
1312                                 type = TypeManager.int64_type;
1313                         } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
1314                                 //
1315                                 // If either operand is of type uint, and the other
1316                                 // operand is of type sbyte, short or int, othe operands are
1317                                 // converted to type long.
1318                                 //
1319                                 Type other = null;
1320                                 
1321                                 if (l == TypeManager.uint32_type)
1322                                         other = r;
1323                                 else if (r == TypeManager.uint32_type)
1324                                         other = l;
1325
1326                                 if ((other == TypeManager.sbyte_type) ||
1327                                     (other == TypeManager.short_type) ||
1328                                     (other == TypeManager.int32_type)){
1329                                         left = ForceConversion (ec, left, TypeManager.int64_type);
1330                                         right = ForceConversion (ec, right, TypeManager.int64_type);
1331                                         type = TypeManager.int64_type;
1332                                 } else {
1333                                         //
1334                                         // if either operand is of type uint, the other
1335                                         // operand is converd to type uint
1336                                         //
1337                                         left = ForceConversion (ec, left, TypeManager.uint32_type);
1338                                         right = ForceConversion (ec, right, TypeManager.uint32_type);
1339                                         type = TypeManager.uint32_type;
1340                                 } 
1341                         } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
1342                                 if (l != TypeManager.decimal_type)
1343                                         left = ConvertImplicit (ec, left, TypeManager.decimal_type, loc);
1344                                 if (r != TypeManager.decimal_type)
1345                                         right = ConvertImplicit (ec, right, TypeManager.decimal_type, loc);
1346
1347                                 type = TypeManager.decimal_type;
1348                         } else {
1349                                 Expression l_tmp, r_tmp;
1350
1351                                 l_tmp = ForceConversion (ec, left, TypeManager.int32_type);
1352                                 if (l_tmp == null)
1353                                         return false;
1354                                 
1355                                 r_tmp = ForceConversion (ec, right, TypeManager.int32_type);
1356                                 if (r_tmp == null)
1357                                         return false;
1358
1359                                 left = l_tmp;
1360                                 right = r_tmp;
1361                                 
1362                                 type = TypeManager.int32_type;
1363                         }
1364
1365                         return true;
1366                 }
1367
1368                 void error19 ()
1369                 {
1370                         Error (19, loc,
1371                                "Operator " + OperName () + " cannot be applied to operands of type `" +
1372                                TypeManager.CSharpName (left.Type) + "' and `" +
1373                                TypeManager.CSharpName (right.Type) + "'");
1374                                                      
1375                 }
1376                 
1377                 Expression CheckShiftArguments (EmitContext ec)
1378                 {
1379                         Expression e;
1380                         Type l = left.Type;
1381                         Type r = right.Type;
1382
1383                         e = ForceConversion (ec, right, TypeManager.int32_type);
1384                         if (e == null){
1385                                 error19 ();
1386                                 return null;
1387                         }
1388                         right = e;
1389
1390                         if (((e = ConvertImplicit (ec, left, TypeManager.int32_type, loc)) != null) ||
1391                             ((e = ConvertImplicit (ec, left, TypeManager.uint32_type, loc)) != null) ||
1392                             ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) ||
1393                             ((e = ConvertImplicit (ec, left, TypeManager.uint64_type, loc)) != null)){
1394                                 left = e;
1395                                 type = e.Type;
1396
1397                                 return this;
1398                         }
1399                         error19 ();
1400                         return null;
1401                 }
1402                 
1403                 Expression ResolveOperator (EmitContext ec)
1404                 {
1405                         Type l = left.Type;
1406                         Type r = right.Type;
1407
1408                         //
1409                         // Step 1: Perform Operator Overload location
1410                         //
1411                         Expression left_expr, right_expr;
1412                         
1413                         string op = "op_" + oper;
1414
1415                         left_expr = MemberLookup (ec, l, op, false, loc);
1416                         if (left_expr == null && l.BaseType != null)
1417                                 left_expr = MemberLookup (ec, l.BaseType, op, false, loc);
1418                         
1419                         right_expr = MemberLookup (ec, r, op, false, loc);
1420                         if (right_expr == null && r.BaseType != null)
1421                                 right_expr = MemberLookup (ec, r.BaseType, op, false, loc);
1422                         
1423                         MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
1424                         
1425                         if (union != null) {
1426                                 Arguments = new ArrayList ();
1427                                 Arguments.Add (new Argument (left, Argument.AType.Expression));
1428                                 Arguments.Add (new Argument (right, Argument.AType.Expression));
1429
1430                                 method = Invocation.OverloadResolve (ec, union, Arguments, loc);
1431                                 if (method != null) {
1432                                         MethodInfo mi = (MethodInfo) method;
1433                                         type = mi.ReturnType;
1434                                         return this;
1435                                 } else {
1436                                         error19 ();
1437                                         return null;
1438                                 }
1439                         }       
1440
1441                         //
1442                         // Step 2: Default operations on CLI native types.
1443                         //
1444
1445                         // Only perform numeric promotions on:
1446                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
1447                         //
1448                         if (oper == Operator.Addition){
1449                                 //
1450                                 // If any of the arguments is a string, cast to string
1451                                 //
1452                                 if (l == TypeManager.string_type){
1453                                         if (r == TypeManager.string_type){
1454                                                 if (left is Constant && right is Constant){
1455                                                         StringConstant ls = (StringConstant) left;
1456                                                         StringConstant rs = (StringConstant) right;
1457                                                         
1458                                                         return new StringConstant (
1459                                                                 ls.Value + rs.Value);
1460                                                 }
1461                                                 
1462                                                 // string + string
1463                                                 method = TypeManager.string_concat_string_string;
1464                                         } else {
1465                                                 // string + object
1466                                                 method = TypeManager.string_concat_object_object;
1467                                                 right = ConvertImplicit (ec, right,
1468                                                                          TypeManager.object_type, loc);
1469                                         }
1470                                         type = TypeManager.string_type;
1471
1472                                         Arguments = new ArrayList ();
1473                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
1474                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
1475
1476                                         return this;
1477                                         
1478                                 } else if (r == TypeManager.string_type){
1479                                         // object + string
1480                                         method = TypeManager.string_concat_object_object;
1481                                         Arguments = new ArrayList ();
1482                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
1483                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
1484
1485                                         left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
1486                                         type = TypeManager.string_type;
1487
1488                                         return this;
1489                                 }
1490                         }
1491
1492                         if (oper == Operator.Addition || oper == Operator.Subtraction) {
1493                                 if (l.IsSubclassOf (TypeManager.delegate_type) &&
1494                                     r.IsSubclassOf (TypeManager.delegate_type)) {
1495                                         
1496                                         Arguments = new ArrayList ();
1497                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
1498                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
1499                                         
1500                                         if (oper == Operator.Addition)
1501                                                 method = TypeManager.delegate_combine_delegate_delegate;
1502                                         else
1503                                                 method = TypeManager.delegate_remove_delegate_delegate;
1504                                         
1505                                         DelegateOperation = true;
1506                                         type = l;
1507                                         return this;
1508                                 }
1509                         }
1510                         
1511                         //
1512                         // Enumeration operators
1513                         //
1514                         bool lie = TypeManager.IsEnumType (l);
1515                         bool rie = TypeManager.IsEnumType (r);
1516                         if (lie || rie){
1517                                 Expression temp;
1518
1519                                 if (!rie){
1520                                         temp = ConvertImplicit (ec, right, l, loc);
1521                                         if (temp != null)
1522                                                 right = temp;
1523                                 } if (!lie){
1524                                         temp = ConvertImplicit (ec, left, r, loc);
1525                                         if (temp != null){
1526                                                 left = temp;
1527                                                 l = r;
1528                                         }
1529                                 }
1530                                 
1531                                 if (oper == Operator.Equality || oper == Operator.Inequality ||
1532                                     oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||
1533                                     oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){
1534                                         type = TypeManager.bool_type;
1535                                         return this;
1536                                 }
1537
1538                                 if (oper == Operator.BitwiseAnd ||
1539                                     oper == Operator.BitwiseOr ||
1540                                     oper == Operator.ExclusiveOr){
1541                                         type = l;
1542                                         return this;
1543                                 }
1544                         }
1545                         
1546                         if (oper == Operator.LeftShift || oper == Operator.RightShift)
1547                                 return CheckShiftArguments (ec);
1548
1549                         if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
1550                                 if (l != TypeManager.bool_type || r != TypeManager.bool_type){
1551                                         error19 ();
1552                                         return null;
1553                                 }
1554
1555                                 type = TypeManager.bool_type;
1556                                 return this;
1557                         } 
1558
1559                         if (oper == Operator.Equality || oper == Operator.Inequality){
1560                                 if (l == TypeManager.bool_type || r == TypeManager.bool_type){
1561                                         if (r != TypeManager.bool_type || l != TypeManager.bool_type){
1562                                                 error19 ();
1563                                                 return null;
1564                                         }
1565                                         
1566                                         type = TypeManager.bool_type;
1567                                         return this;
1568                                 }
1569
1570                                 //
1571                                 // operator != (object a, object b)
1572                                 // operator == (object a, object b)
1573                                 //
1574                                 // For this to be used, both arguments have to be reference-types.
1575                                 // Read the rationale on the spec (14.9.6)
1576                                 //
1577                                 // Also, if at compile time we know that the classes do not inherit
1578                                 // one from the other, then we catch the error there.
1579                                 //
1580                                 if (!(l.IsValueType || r.IsValueType)){
1581                                         type = TypeManager.bool_type;
1582
1583                                         if (l == r)
1584                                                 return this;
1585                                         
1586                                         if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
1587                                                 return this;
1588                                 }
1589                         }
1590
1591                         //
1592                         // We are dealing with numbers
1593                         //
1594
1595                         if (!DoNumericPromotions (ec, l, r)){
1596                                 error19 ();
1597                                 return null;
1598                         }
1599
1600                         if (left == null || right == null)
1601                                 return null;
1602
1603                         //
1604                         // reload our cached types if required
1605                         //
1606                         l = left.Type;
1607                         r = right.Type;
1608                         
1609                         if (oper == Operator.BitwiseAnd ||
1610                             oper == Operator.BitwiseOr ||
1611                             oper == Operator.ExclusiveOr){
1612                                 if (l == r){
1613                                         if (!((l == TypeManager.int32_type) ||
1614                                               (l == TypeManager.uint32_type) ||
1615                                               (l == TypeManager.int64_type) ||
1616                                               (l == TypeManager.uint64_type)))
1617                                                 type = l;
1618                                 } else {
1619                                         error19 ();
1620                                         return null;
1621                                 }
1622                         }
1623
1624                         if (oper == Operator.Equality ||
1625                             oper == Operator.Inequality ||
1626                             oper == Operator.LessThanOrEqual ||
1627                             oper == Operator.LessThan ||
1628                             oper == Operator.GreaterThanOrEqual ||
1629                             oper == Operator.GreaterThan){
1630                                 type = TypeManager.bool_type;
1631                         }
1632
1633                         return this;
1634                 }
1635
1636                 /// <summary>
1637                 ///   Constant expression reducer for binary operations
1638                 /// </summary>
1639                 public Expression ConstantFold (EmitContext ec)
1640                 {
1641                         object l = ((Constant) left).GetValue ();
1642                         object r = ((Constant) right).GetValue ();
1643                         
1644                         if (l is string && r is string)
1645                                 return new StringConstant ((string) l + (string) r);
1646
1647                         Type result_type = null;
1648
1649                         //
1650                         // Enumerator folding
1651                         //
1652                         if (left.Type == right.Type && left is EnumConstant)
1653                                 result_type = left.Type;
1654
1655                         switch (oper){
1656                         case Operator.BitwiseOr:
1657                                 if ((l is int) && (r is int)){
1658                                         IntConstant v;
1659                                         int res = (int)l | (int)r;
1660                                         
1661                                         v = new IntConstant (res);
1662                                         if (result_type == null)
1663                                                 return v;
1664                                         else
1665                                                 return new EnumConstant (v, result_type);
1666                                 }
1667                                 break;
1668                                 
1669                         case Operator.BitwiseAnd:
1670                                 if ((l is int) && (r is int)){
1671                                         IntConstant v;
1672                                         int res = (int)l & (int)r;
1673                                         
1674                                         v = new IntConstant (res);
1675                                         if (result_type == null)
1676                                                 return v;
1677                                         else
1678                                                 return new EnumConstant (v, result_type);
1679                                 }
1680                                 break;
1681                         }
1682                                         
1683                         return null;
1684                 }
1685                 
1686                 public override Expression DoResolve (EmitContext ec)
1687                 {
1688                         left = left.Resolve (ec);
1689                         right = right.Resolve (ec);
1690
1691                         if (left == null || right == null)
1692                                 return null;
1693
1694                         if (left.Type == null)
1695                                 throw new Exception (
1696                                         "Resolve returned non null, but did not set the type! (" +
1697                                         left + ") at Line: " + loc.Row);
1698                         if (right.Type == null)
1699                                 throw new Exception (
1700                                         "Resolve returned non null, but did not set the type! (" +
1701                                         right + ") at Line: "+ loc.Row);
1702
1703                         eclass = ExprClass.Value;
1704
1705                         if (left is Constant && right is Constant){
1706                                 //
1707                                 // This is temporary until we do the full folding
1708                                 //
1709                                 Expression e = ConstantFold (ec);
1710                                 if (e != null)
1711                                         return e;
1712                         }
1713
1714                         return ResolveOperator (ec);
1715                 }
1716
1717                 public bool IsBranchable ()
1718                 {
1719                         if (oper == Operator.Equality ||
1720                             oper == Operator.Inequality ||
1721                             oper == Operator.LessThan ||
1722                             oper == Operator.GreaterThan ||
1723                             oper == Operator.LessThanOrEqual ||
1724                             oper == Operator.GreaterThanOrEqual){
1725                                 return true;
1726                         } else
1727                                 return false;
1728                 }
1729
1730                 /// <summary>
1731                 ///   This entry point is used by routines that might want
1732                 ///   to emit a brfalse/brtrue after an expression, and instead
1733                 ///   they could use a more compact notation.
1734                 ///
1735                 ///   Typically the code would generate l.emit/r.emit, followed
1736                 ///   by the comparission and then a brtrue/brfalse.  The comparissions
1737                 ///   are sometimes inneficient (there are not as complete as the branches
1738                 ///   look for the hacks in Emit using double ceqs).
1739                 ///
1740                 ///   So for those cases we provide EmitBranchable that can emit the
1741                 ///   branch with the test
1742                 /// </summary>
1743                 public void EmitBranchable (EmitContext ec, int target)
1744                 {
1745                         OpCode opcode;
1746                         bool close_target = false;
1747                         ILGenerator ig = ec.ig;
1748                                 
1749                         //
1750                         // short-circuit operators
1751                         //
1752                         if (oper == Operator.LogicalAnd){
1753                                 left.Emit (ec);
1754                                 ig.Emit (OpCodes.Brfalse, target);
1755                                 right.Emit (ec);
1756                                 ig.Emit (OpCodes.Brfalse, target);
1757                         } else if (oper == Operator.LogicalOr){
1758                                 left.Emit (ec);
1759                                 ig.Emit (OpCodes.Brtrue, target);
1760                                 right.Emit (ec);
1761                                 ig.Emit (OpCodes.Brfalse, target);
1762                         }
1763                                 
1764                         left.Emit (ec);
1765                         right.Emit (ec);
1766                         
1767                         switch (oper){
1768                         case Operator.Equality:
1769                                 if (close_target)
1770                                         opcode = OpCodes.Beq_S;
1771                                 else
1772                                         opcode = OpCodes.Beq;
1773                                 break;
1774
1775                         case Operator.Inequality:
1776                                 if (close_target)
1777                                         opcode = OpCodes.Bne_Un_S;
1778                                 else
1779                                         opcode = OpCodes.Bne_Un;
1780                                 break;
1781
1782                         case Operator.LessThan:
1783                                 if (close_target)
1784                                         opcode = OpCodes.Blt_S;
1785                                 else
1786                                         opcode = OpCodes.Blt;
1787                                 break;
1788
1789                         case Operator.GreaterThan:
1790                                 if (close_target)
1791                                         opcode = OpCodes.Bgt_S;
1792                                 else
1793                                         opcode = OpCodes.Bgt;
1794                                 break;
1795
1796                         case Operator.LessThanOrEqual:
1797                                 if (close_target)
1798                                         opcode = OpCodes.Ble_S;
1799                                 else
1800                                         opcode = OpCodes.Ble;
1801                                 break;
1802
1803                         case Operator.GreaterThanOrEqual:
1804                                 if (close_target)
1805                                         opcode = OpCodes.Bge_S;
1806                                 else
1807                                         opcode = OpCodes.Ble;
1808                                 break;
1809
1810                         default:
1811                                 throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
1812                                                      + oper.ToString ());
1813                         }
1814
1815                         ig.Emit (opcode, target);
1816                 }
1817                 
1818                 public override void Emit (EmitContext ec)
1819                 {
1820                         ILGenerator ig = ec.ig;
1821                         Type l = left.Type;
1822                         Type r = right.Type;
1823                         OpCode opcode;
1824
1825                         if (method != null) {
1826
1827                                 // Note that operators are static anyway
1828                                 
1829                                 if (Arguments != null) 
1830                                         Invocation.EmitArguments (ec, method, Arguments);
1831                                 
1832                                 if (method is MethodInfo)
1833                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
1834                                 else
1835                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1836
1837                                 if (DelegateOperation)
1838                                         ig.Emit (OpCodes.Castclass, type);
1839                                         
1840                                 return;
1841                         }
1842
1843                         //
1844                         // Handle short-circuit operators differently
1845                         // than the rest
1846                         //
1847                         if (oper == Operator.LogicalAnd){
1848                                 Label load_zero = ig.DefineLabel ();
1849                                 Label end = ig.DefineLabel ();
1850                                 
1851                                 left.Emit (ec);
1852                                 ig.Emit (OpCodes.Brfalse, load_zero);
1853                                 right.Emit (ec);
1854                                 ig.Emit (OpCodes.Br, end);
1855                                 ig.MarkLabel (load_zero);
1856                                 ig.Emit (OpCodes.Ldc_I4_0);
1857                                 ig.MarkLabel (end);
1858                                 return;
1859                         } else if (oper == Operator.LogicalOr){
1860                                 Label load_one = ig.DefineLabel ();
1861                                 Label end = ig.DefineLabel ();
1862                                 
1863                                 left.Emit (ec);
1864                                 ig.Emit (OpCodes.Brtrue, load_one);
1865                                 right.Emit (ec);
1866                                 ig.Emit (OpCodes.Br, end);
1867                                 ig.MarkLabel (load_one);
1868                                 ig.Emit (OpCodes.Ldc_I4_1);
1869                                 ig.MarkLabel (end);
1870                                 return;
1871                         }
1872                         
1873                         left.Emit (ec);
1874                         right.Emit (ec);
1875
1876                         switch (oper){
1877                         case Operator.Multiply:
1878                                 if (ec.CheckState){
1879                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1880                                                 opcode = OpCodes.Mul_Ovf;
1881                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1882                                                 opcode = OpCodes.Mul_Ovf_Un;
1883                                         else
1884                                                 opcode = OpCodes.Mul;
1885                                 } else
1886                                         opcode = OpCodes.Mul;
1887
1888                                 break;
1889
1890                         case Operator.Division:
1891                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1892                                         opcode = OpCodes.Div_Un;
1893                                 else
1894                                         opcode = OpCodes.Div;
1895                                 break;
1896
1897                         case Operator.Modulus:
1898                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1899                                         opcode = OpCodes.Rem_Un;
1900                                 else
1901                                         opcode = OpCodes.Rem;
1902                                 break;
1903
1904                         case Operator.Addition:
1905                                 if (ec.CheckState){
1906                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1907                                                 opcode = OpCodes.Add_Ovf;
1908                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1909                                                 opcode = OpCodes.Add_Ovf_Un;
1910                                         else
1911                                                 opcode = OpCodes.Mul;
1912                                 } else
1913                                         opcode = OpCodes.Add;
1914                                 break;
1915
1916                         case Operator.Subtraction:
1917                                 if (ec.CheckState){
1918                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1919                                                 opcode = OpCodes.Sub_Ovf;
1920                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1921                                                 opcode = OpCodes.Sub_Ovf_Un;
1922                                         else
1923                                                 opcode = OpCodes.Sub;
1924                                 } else
1925                                         opcode = OpCodes.Sub;
1926                                 break;
1927
1928                         case Operator.RightShift:
1929                                 opcode = OpCodes.Shr;
1930                                 break;
1931                                 
1932                         case Operator.LeftShift:
1933                                 opcode = OpCodes.Shl;
1934                                 break;
1935
1936                         case Operator.Equality:
1937                                 opcode = OpCodes.Ceq;
1938                                 break;
1939
1940                         case Operator.Inequality:
1941                                 ec.ig.Emit (OpCodes.Ceq);
1942                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1943                                 
1944                                 opcode = OpCodes.Ceq;
1945                                 break;
1946
1947                         case Operator.LessThan:
1948                                 opcode = OpCodes.Clt;
1949                                 break;
1950
1951                         case Operator.GreaterThan:
1952                                 opcode = OpCodes.Cgt;
1953                                 break;
1954
1955                         case Operator.LessThanOrEqual:
1956                                 ec.ig.Emit (OpCodes.Cgt);
1957                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1958                                 
1959                                 opcode = OpCodes.Ceq;
1960                                 break;
1961
1962                         case Operator.GreaterThanOrEqual:
1963                                 ec.ig.Emit (OpCodes.Clt);
1964                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
1965                                 
1966                                 opcode = OpCodes.Sub;
1967                                 break;
1968
1969                         case Operator.BitwiseOr:
1970                                 opcode = OpCodes.Or;
1971                                 break;
1972
1973                         case Operator.BitwiseAnd:
1974                                 opcode = OpCodes.And;
1975                                 break;
1976
1977                         case Operator.ExclusiveOr:
1978                                 opcode = OpCodes.Xor;
1979                                 break;
1980
1981                         default:
1982                                 throw new Exception ("This should not happen: Operator = "
1983                                                      + oper.ToString ());
1984                         }
1985
1986                         ig.Emit (opcode);
1987                 }
1988         }
1989
1990         /// <summary>
1991         ///   Implements the ternary conditiona operator (?:)
1992         /// </summary>
1993         public class Conditional : Expression {
1994                 Expression expr, trueExpr, falseExpr;
1995                 Location loc;
1996                 
1997                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
1998                 {
1999                         this.expr = expr;
2000                         this.trueExpr = trueExpr;
2001                         this.falseExpr = falseExpr;
2002                         this.loc = l;
2003                 }
2004
2005                 public Expression Expr {
2006                         get {
2007                                 return expr;
2008                         }
2009                 }
2010
2011                 public Expression TrueExpr {
2012                         get {
2013                                 return trueExpr;
2014                         }
2015                 }
2016
2017                 public Expression FalseExpr {
2018                         get {
2019                                 return falseExpr;
2020                         }
2021                 }
2022
2023                 public override Expression DoResolve (EmitContext ec)
2024                 {
2025                         expr = expr.Resolve (ec);
2026
2027                         if (expr.Type != TypeManager.bool_type)
2028                                 expr = Expression.ConvertImplicitRequired (
2029                                         ec, expr, TypeManager.bool_type, loc);
2030                         
2031                         trueExpr = trueExpr.Resolve (ec);
2032                         falseExpr = falseExpr.Resolve (ec);
2033
2034                         if (expr == null || trueExpr == null || falseExpr == null)
2035                                 return null;
2036
2037                         if (trueExpr.Type == falseExpr.Type)
2038                                 type = trueExpr.Type;
2039                         else {
2040                                 Expression conv;
2041
2042                                 //
2043                                 // First, if an implicit conversion exists from trueExpr
2044                                 // to falseExpr, then the result type is of type falseExpr.Type
2045                                 //
2046                                 conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
2047                                 if (conv != null){
2048                                         type = falseExpr.Type;
2049                                         trueExpr = conv;
2050                                 } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
2051                                         type = trueExpr.Type;
2052                                         falseExpr = conv;
2053                                 } else {
2054                                         Error (173, loc, "The type of the conditional expression can " +
2055                                                "not be computed because there is no implicit conversion" +
2056                                                " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
2057                                                " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
2058                                         return null;
2059                                 }
2060                         }
2061
2062                         if (expr is BoolConstant){
2063                                 BoolConstant bc = (BoolConstant) expr;
2064
2065                                 if (bc.Value)
2066                                         return trueExpr;
2067                                 else
2068                                         return falseExpr;
2069                         }
2070
2071                         eclass = ExprClass.Value;
2072                         return this;
2073                 }
2074
2075                 public override void Emit (EmitContext ec)
2076                 {
2077                         ILGenerator ig = ec.ig;
2078                         Label false_target = ig.DefineLabel ();
2079                         Label end_target = ig.DefineLabel ();
2080
2081                         expr.Emit (ec);
2082                         ig.Emit (OpCodes.Brfalse, false_target);
2083                         trueExpr.Emit (ec);
2084                         ig.Emit (OpCodes.Br, end_target);
2085                         ig.MarkLabel (false_target);
2086                         falseExpr.Emit (ec);
2087                         ig.MarkLabel (end_target);
2088                 }
2089
2090         }
2091
2092         /// <summary>
2093         ///   Local variables
2094         /// </summary>
2095         public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation {
2096                 public readonly string Name;
2097                 public readonly Block Block;
2098                 Location loc;
2099                 VariableInfo variable_info;
2100                 
2101                 public LocalVariableReference (Block block, string name, Location l)
2102                 {
2103                         Block = block;
2104                         Name = name;
2105                         loc = l;
2106                         eclass = ExprClass.Variable;
2107                 }
2108
2109                 public VariableInfo VariableInfo {
2110                         get {
2111                                 if (variable_info == null)
2112                                         variable_info = Block.GetVariableInfo (Name);
2113                                 return variable_info;
2114                         }
2115                 }
2116                 
2117                 public override Expression DoResolve (EmitContext ec)
2118                 {
2119                         VariableInfo vi = VariableInfo;
2120
2121                         if (Block.IsConstant (Name)) {
2122                                 Expression e = Block.GetConstantExpression (Name);
2123
2124                                 e = e.Resolve (ec);
2125                                 if (e == null)  
2126                                         return null;
2127
2128                                 if (!(e is Constant)) {
2129                                         Report.Error (150, loc, "A constant value is expected");
2130                                         return null;
2131                                 }
2132
2133                                 vi.Used = true;
2134                                 return e;
2135                         }
2136
2137                         type = vi.VariableType;
2138                         return this;
2139                 }
2140
2141                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
2142                 {
2143                         Expression e = DoResolve (ec);
2144
2145                         if (e == null)
2146                                 return null;
2147
2148                         VariableInfo vi = VariableInfo;
2149                         
2150                         if (vi.ReadOnly){
2151                                 if (vi.Assigned){
2152                                         Report.Error (
2153                                                 1604, loc,
2154                                                 "cannot assign to `" + Name + "' because it is readonly");
2155                                         return null;
2156                                 }
2157                         }
2158                         
2159                         return this;
2160                 }
2161
2162                 public override void Emit (EmitContext ec)
2163                 {
2164                         VariableInfo vi = VariableInfo;
2165                         ILGenerator ig = ec.ig;
2166                         int idx = vi.Idx;
2167
2168                         vi.Used = true;
2169
2170                         switch (idx){
2171                         case 0:
2172                                 ig.Emit (OpCodes.Ldloc_0);
2173                                 break;
2174                                 
2175                         case 1:
2176                                 ig.Emit (OpCodes.Ldloc_1);
2177                                 break;
2178                                 
2179                         case 2:
2180                                 ig.Emit (OpCodes.Ldloc_2);
2181                                 break;
2182                                 
2183                         case 3:
2184                                 ig.Emit (OpCodes.Ldloc_3);
2185                                 break;
2186                                 
2187                         default:
2188                                 if (idx <= 255)
2189                                         ig.Emit (OpCodes.Ldloc_S, (byte) idx);
2190                                 else
2191                                         ig.Emit (OpCodes.Ldloc, idx);
2192                                 break;
2193                         }
2194                 }
2195                 
2196                 public static void Store (ILGenerator ig, int idx)
2197                 {
2198                         switch (idx){
2199                         case 0:
2200                                 ig.Emit (OpCodes.Stloc_0);
2201                                 break;
2202                                 
2203                         case 1:
2204                                 ig.Emit (OpCodes.Stloc_1);
2205                                 break;
2206                                 
2207                         case 2:
2208                                 ig.Emit (OpCodes.Stloc_2);
2209                                 break;
2210                                 
2211                         case 3:
2212                                 ig.Emit (OpCodes.Stloc_3);
2213                                 break;
2214                                 
2215                         default:
2216                                 if (idx <= 255)
2217                                         ig.Emit (OpCodes.Stloc_S, (byte) idx);
2218                                 else
2219                                         ig.Emit (OpCodes.Stloc, idx);
2220                                 break;
2221                         }
2222                 }
2223
2224                 public void EmitAssign (EmitContext ec, Expression source)
2225                 {
2226                         ILGenerator ig = ec.ig;
2227                         VariableInfo vi = VariableInfo;
2228
2229                         vi.Assigned = true;
2230
2231                         source.Emit (ec);
2232                         
2233                         // Funny seems the code below generates optimal code for us, but
2234                         // seems to take too long to generate what we need.
2235                         // ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
2236
2237                         Store (ig, vi.Idx);
2238                 }
2239                 
2240                 public void AddressOf (EmitContext ec)
2241                 {
2242                         VariableInfo vi = VariableInfo;
2243                         int idx = vi.Idx;
2244
2245                         vi.Used = true;
2246                         vi.Assigned = true;
2247                         
2248                         if (idx <= 255)
2249                                 ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
2250                         else
2251                                 ec.ig.Emit (OpCodes.Ldloca, idx);
2252                 }
2253         }
2254
2255         /// <summary>
2256         ///   This represents a reference to a parameter in the intermediate
2257         ///   representation.
2258         /// </summary>
2259         public class ParameterReference : Expression, IAssignMethod, IMemoryLocation {
2260                 Parameters pars;
2261                 String name;
2262                 int idx;
2263                 bool is_ref;
2264                 
2265                 public ParameterReference (Parameters pars, int idx, string name)
2266                 {
2267                         this.pars = pars;
2268                         this.idx  = idx;
2269                         this.name = name;
2270                         eclass = ExprClass.Variable;
2271                 }
2272
2273                 //
2274                 // Notice that for ref/out parameters, the type exposed is not the
2275                 // same type exposed externally.
2276                 //
2277                 // for "ref int a":
2278                 //   externally we expose "int&"
2279                 //   here we expose       "int".
2280                 //
2281                 // We record this in "is_ref".  This means that the type system can treat
2282                 // the type as it is expected, but when we generate the code, we generate
2283                 // the alternate kind of code.
2284                 //
2285                 public override Expression DoResolve (EmitContext ec)
2286                 {
2287                         type = pars.GetParameterInfo (ec.TypeContainer, idx, out is_ref);
2288                         eclass = ExprClass.Variable;
2289                         
2290                         return this;
2291                 }
2292
2293                 public override void Emit (EmitContext ec)
2294                 {
2295                         ILGenerator ig = ec.ig;
2296                         int arg_idx = idx;
2297
2298                         if (!ec.IsStatic)
2299                                 arg_idx++;
2300                         
2301                         if (arg_idx <= 255)
2302                                 ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
2303                         else
2304                                 ig.Emit (OpCodes.Ldarg, arg_idx);
2305
2306                         if (!is_ref)
2307                                 return;
2308
2309                         //
2310                         // If we are a reference, we loaded on the stack a pointer
2311                         // Now lets load the real value
2312                         //
2313
2314                         if (type == TypeManager.int32_type)
2315                                 ig.Emit (OpCodes.Ldind_I4);
2316                         else if (type == TypeManager.uint32_type)
2317                                 ig.Emit (OpCodes.Ldind_U4);
2318                         else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
2319                                 ig.Emit (OpCodes.Ldind_I8);
2320                         else if (type == TypeManager.char_type)
2321                                 ig.Emit (OpCodes.Ldind_U2);
2322                         else if (type == TypeManager.short_type)
2323                                 ig.Emit (OpCodes.Ldind_I2);
2324                         else if (type == TypeManager.ushort_type)
2325                                 ig.Emit (OpCodes.Ldind_U2);
2326                         else if (type == TypeManager.float_type)
2327                                 ig.Emit (OpCodes.Ldind_R4);
2328                         else if (type == TypeManager.double_type)
2329                                 ig.Emit (OpCodes.Ldind_R8);
2330                         else if (type == TypeManager.byte_type)
2331                                 ig.Emit (OpCodes.Ldind_U1);
2332                         else if (type == TypeManager.sbyte_type)
2333                                 ig.Emit (OpCodes.Ldind_I1);
2334                         else if (type == TypeManager.intptr_type)
2335                                 ig.Emit (OpCodes.Ldind_I);
2336                         else
2337                                 ig.Emit (OpCodes.Ldind_Ref);
2338                 }
2339
2340                 public void EmitAssign (EmitContext ec, Expression source)
2341                 {
2342                         ILGenerator ig = ec.ig;
2343                         int arg_idx = idx;
2344
2345                         if (!ec.IsStatic)
2346                                 arg_idx++;
2347
2348                         if (is_ref){
2349                                 // Load the pointer
2350                                 if (arg_idx <= 255)
2351                                         ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
2352                                 else
2353                                         ig.Emit (OpCodes.Ldarg, arg_idx);
2354                         }
2355                         
2356                         source.Emit (ec);
2357
2358                         if (is_ref){
2359                                 if (type == TypeManager.int32_type || type == TypeManager.uint32_type)
2360                                         ig.Emit (OpCodes.Stind_I4);
2361                                 else if (type == TypeManager.int64_type || type == TypeManager.uint64_type)
2362                                         ig.Emit (OpCodes.Stind_I8);
2363                                 else if (type == TypeManager.char_type || type == TypeManager.short_type ||
2364                                         type == TypeManager.ushort_type)
2365                                         ig.Emit (OpCodes.Stind_I2);
2366                                 else if (type == TypeManager.float_type)
2367                                         ig.Emit (OpCodes.Stind_R4);
2368                                 else if (type == TypeManager.double_type)
2369                                         ig.Emit (OpCodes.Stind_R8);
2370                                 else if (type == TypeManager.byte_type || type == TypeManager.sbyte_type)
2371                                         ig.Emit (OpCodes.Stind_I1);
2372                                 else if (type == TypeManager.intptr_type)
2373                                         ig.Emit (OpCodes.Stind_I);
2374                                 else
2375                                         ig.Emit (OpCodes.Stind_Ref);
2376                         } else {
2377                                 if (arg_idx <= 255)
2378                                         ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
2379                                 else
2380                                         ig.Emit (OpCodes.Starg, arg_idx);
2381                         }
2382                         
2383                 }
2384
2385                 public void AddressOf (EmitContext ec)
2386                 {
2387                         int arg_idx = idx;
2388
2389                         if (!ec.IsStatic)
2390                                 arg_idx++;
2391
2392                         if (arg_idx <= 255)
2393                                 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
2394                         else
2395                                 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
2396                 }
2397         }
2398         
2399         /// <summary>
2400         ///   Used for arguments to New(), Invocation()
2401         /// </summary>
2402         public class Argument {
2403                 public enum AType : byte {
2404                         Expression,
2405                         Ref,
2406                         Out
2407                 };
2408
2409                 public readonly AType ArgType;
2410                 public Expression expr;
2411                 
2412                 public Argument (Expression expr, AType type)
2413                 {
2414                         this.expr = expr;
2415                         this.ArgType = type;
2416                 }
2417
2418                 public Expression Expr {
2419                         get {
2420                                 return expr;
2421                         }
2422
2423                         set {
2424                                 expr = value;
2425                         }
2426                 }
2427
2428                 public Type Type {
2429                         get {
2430                                 return expr.Type;
2431                         }
2432                 }
2433
2434                 public Parameter.Modifier GetParameterModifier ()
2435                 {
2436                         if (ArgType == AType.Ref)
2437                                 return Parameter.Modifier.REF;
2438
2439                         if (ArgType == AType.Out)
2440                                 return Parameter.Modifier.OUT;
2441
2442                         return Parameter.Modifier.NONE;
2443                 }
2444
2445                 public static string FullDesc (Argument a)
2446                 {
2447                         return (a.ArgType == AType.Ref ? "ref " :
2448                                 (a.ArgType == AType.Out ? "out " : "")) +
2449                                 TypeManager.CSharpName (a.Expr.Type);
2450                 }
2451                 
2452                 public bool Resolve (EmitContext ec, Location loc)
2453                 {
2454                         expr = expr.Resolve (ec);
2455
2456                         if (ArgType == AType.Expression)
2457                                 return expr != null;
2458
2459                         if (expr.eclass != ExprClass.Variable){
2460                                 Report.Error (206, loc,
2461                                               "A property or indexer can not be passed as an out or ref " +
2462                                               "parameter");
2463                                 return false;
2464                         }
2465                                 
2466                         return expr != null;
2467                 }
2468
2469                 public void Emit (EmitContext ec)
2470                 {
2471                         if (ArgType == AType.Ref || ArgType == AType.Out)
2472                                 ((IMemoryLocation)expr).AddressOf (ec);
2473                         else
2474                                 expr.Emit (ec);
2475                 }
2476         }
2477
2478         /// <summary>
2479         ///   Invocation of methods or delegates.
2480         /// </summary>
2481         public class Invocation : ExpressionStatement {
2482                 public readonly ArrayList Arguments;
2483                 Location loc;
2484
2485                 Expression expr;
2486                 MethodBase method = null;
2487                         
2488                 static Hashtable method_parameter_cache;
2489
2490                 static Invocation ()
2491                 {
2492                         method_parameter_cache = new PtrHashtable ();
2493                 }
2494                         
2495                 //
2496                 // arguments is an ArrayList, but we do not want to typecast,
2497                 // as it might be null.
2498                 //
2499                 // FIXME: only allow expr to be a method invocation or a
2500                 // delegate invocation (7.5.5)
2501                 //
2502                 public Invocation (Expression expr, ArrayList arguments, Location l)
2503                 {
2504                         this.expr = expr;
2505                         Arguments = arguments;
2506                         loc = l;
2507                 }
2508
2509                 public Expression Expr {
2510                         get {
2511                                 return expr;
2512                         }
2513                 }
2514
2515                 /// <summary>
2516                 ///   Returns the Parameters (a ParameterData interface) for the
2517                 ///   Method `mb'
2518                 /// </summary>
2519                 public static ParameterData GetParameterData (MethodBase mb)
2520                 {
2521                         object pd = method_parameter_cache [mb];
2522                         object ip;
2523                         
2524                         if (pd != null)
2525                                 return (ParameterData) pd;
2526
2527                         
2528                         ip = TypeManager.LookupParametersByBuilder (mb);
2529                         if (ip != null){
2530                                 method_parameter_cache [mb] = ip;
2531
2532                                 return (ParameterData) ip;
2533                         } else {
2534                                 ParameterInfo [] pi = mb.GetParameters ();
2535                                 ReflectionParameters rp = new ReflectionParameters (pi);
2536                                 method_parameter_cache [mb] = rp;
2537
2538                                 return (ParameterData) rp;
2539                         }
2540                 }
2541
2542                 /// <summary>
2543                 ///   Tells whether a user defined conversion from Type `from' to
2544                 ///   Type `to' exists.
2545                 ///
2546                 ///   FIXME: we could implement a cache here. 
2547                 /// </summary>
2548                 static bool ConversionExists (EmitContext ec, Type from, Type to, Location loc)
2549                 {
2550                         // Locate user-defined implicit operators
2551
2552                         Expression mg;
2553                         
2554                         mg = MemberLookup (ec, to, "op_Implicit", false, loc);
2555
2556                         if (mg != null) {
2557                                 MethodGroupExpr me = (MethodGroupExpr) mg;
2558                                 
2559                                 for (int i = me.Methods.Length; i > 0;) {
2560                                         i--;
2561                                         MethodBase mb = me.Methods [i];
2562                                         ParameterData pd = GetParameterData (mb);
2563                                         
2564                                         if (from == pd.ParameterType (0))
2565                                                 return true;
2566                                 }
2567                         }
2568
2569                         mg = MemberLookup (ec, from, "op_Implicit", false, loc);
2570
2571                         if (mg != null) {
2572                                 MethodGroupExpr me = (MethodGroupExpr) mg;
2573
2574                                 for (int i = me.Methods.Length; i > 0;) {
2575                                         i--;
2576                                         MethodBase mb = me.Methods [i];
2577                                         MethodInfo mi = (MethodInfo) mb;
2578                                         
2579                                         if (mi.ReturnType == to)
2580                                                 return true;
2581                                 }
2582                         }
2583                         
2584                         return false;
2585                 }
2586                 
2587                 /// <summary>
2588                 ///  Determines "better conversion" as specified in 7.4.2.3
2589                 ///  Returns : 1 if a->p is better
2590                 ///            0 if a->q or neither is better 
2591                 /// </summary>
2592                 static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, bool use_standard,
2593                                              Location loc)
2594                 {
2595                         Type argument_type = a.Type;
2596                         Expression argument_expr = a.Expr;
2597
2598                         if (argument_type == null)
2599                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
2600
2601                         if (p == q)
2602                                 return 0;
2603                         
2604                         if (argument_type == p)
2605                                 return 1;
2606
2607                         if (argument_type == q)
2608                                 return 0;
2609
2610                         //
2611                         // Now probe whether an implicit constant expression conversion
2612                         // can be used.
2613                         //
2614                         // An implicit constant expression conversion permits the following
2615                         // conversions:
2616                         //
2617                         //    * A constant-expression of type `int' can be converted to type
2618                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
2619                         //      of the expression is withing the range of the destination type.
2620                         //
2621                         //    * A constant-expression of type long can be converted to type
2622                         //      ulong, provided the value of the constant expression is not negative
2623                         //
2624                         // FIXME: Note that this assumes that constant folding has
2625                         // taken place.  We dont do constant folding yet.
2626                         //
2627
2628                         if (argument_expr is IntConstant){
2629                                 IntConstant ei = (IntConstant) argument_expr;
2630                                 int value = ei.Value;
2631                                 
2632                                 if (p == TypeManager.sbyte_type){
2633                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
2634                                                 return 1;
2635                                 } else if (p == TypeManager.byte_type){
2636                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
2637                                                 return 1;
2638                                 } else if (p == TypeManager.short_type){
2639                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
2640                                                 return 1;
2641                                 } else if (p == TypeManager.ushort_type){
2642                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
2643                                                 return 1;
2644                                 } else if (p == TypeManager.uint32_type){
2645                                         //
2646                                         // we can optimize this case: a positive int32
2647                                         // always fits on a uint32
2648                                         //
2649                                         if (value >= 0)
2650                                                 return 1;
2651                                 } else if (p == TypeManager.uint64_type){
2652                                         //
2653                                         // we can optimize this case: a positive int32
2654                                         // always fits on a uint64
2655                                         //
2656                                         if (value >= 0)
2657                                                 return 1;
2658                                 }
2659                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){
2660                                 LongConstant lc = (LongConstant) argument_expr;
2661                                 
2662                                 if (p == TypeManager.uint64_type){
2663                                         if (lc.Value > 0)
2664                                                 return 1;
2665                                 }
2666                         }
2667
2668                         if (q == null) {
2669
2670                                 Expression tmp;
2671
2672                                 if (use_standard)
2673                                         tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
2674                                 else
2675                                         tmp = ConvertImplicit (ec, argument_expr, p, loc);
2676
2677                                 if (tmp != null)
2678                                         return 1;
2679                                 else
2680                                         return 0;
2681
2682                         }
2683
2684                         if (ConversionExists (ec, p, q, loc) == true &&
2685                             ConversionExists (ec, q, p, loc) == false)
2686                                 return 1;
2687
2688                         if (p == TypeManager.sbyte_type)
2689                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
2690                                     q == TypeManager.uint32_type || q == TypeManager.uint64_type)
2691                                         return 1;
2692
2693                         if (p == TypeManager.short_type)
2694                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
2695                                     q == TypeManager.uint64_type)
2696                                         return 1;
2697
2698                         if (p == TypeManager.int32_type)
2699                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
2700                                         return 1;
2701
2702                         if (p == TypeManager.int64_type)
2703                                 if (q == TypeManager.uint64_type)
2704                                         return 1;
2705
2706                         return 0;
2707                 }
2708                 
2709                 /// <summary>
2710                 ///  Determines "Better function"
2711                 /// </summary>
2712                 /// <remarks>
2713                 ///    and returns an integer indicating :
2714                 ///    0 if candidate ain't better
2715                 ///    1 if candidate is better than the current best match
2716                 /// </remarks>
2717                 static int BetterFunction (EmitContext ec, ArrayList args,
2718                                            MethodBase candidate, MethodBase best,
2719                                            bool use_standard, Location loc)
2720                 {
2721                         ParameterData candidate_pd = GetParameterData (candidate);
2722                         ParameterData best_pd;
2723                         int argument_count;
2724
2725                         if (args == null)
2726                                 argument_count = 0;
2727                         else
2728                                 argument_count = args.Count;
2729
2730                         if (candidate_pd.Count == 0 && argument_count == 0)
2731                                 return 1;
2732
2733                         if (best == null) {
2734                                 if (candidate_pd.Count == argument_count) {
2735                                         int x = 0;
2736                                         for (int j = argument_count; j > 0;) {
2737                                                 j--;
2738                                                 
2739                                                 Argument a = (Argument) args [j];
2740                                                 
2741                                                 x = BetterConversion (
2742                                                         ec, a, candidate_pd.ParameterType (j), null,
2743                                                         use_standard, loc);
2744                                                 
2745                                                 if (x <= 0)
2746                                                         break;
2747                                         }
2748                                         
2749                                         if (x > 0)
2750                                                 return 1;
2751                                         else
2752                                                 return 0;
2753                                         
2754                                 } else
2755                                         return 0;
2756                         }
2757
2758                         best_pd = GetParameterData (best);
2759
2760                         if (candidate_pd.Count == argument_count && best_pd.Count == argument_count) {
2761                                 int rating1 = 0, rating2 = 0;
2762                                 
2763                                 for (int j = argument_count; j > 0;) {
2764                                         j--;
2765                                         int x, y;
2766                                         
2767                                         Argument a = (Argument) args [j];
2768
2769                                         x = BetterConversion (ec, a, candidate_pd.ParameterType (j),
2770                                                               best_pd.ParameterType (j), use_standard, loc);
2771                                         y = BetterConversion (ec, a, best_pd.ParameterType (j),
2772                                                               candidate_pd.ParameterType (j), use_standard,
2773                                                               loc);
2774                                         
2775                                         rating1 += x;
2776                                         rating2 += y;
2777                                 }
2778
2779                                 if (rating1 > rating2)
2780                                         return 1;
2781                                 else
2782                                         return 0;
2783                         } else
2784                                 return 0;
2785                         
2786                 }
2787
2788                 public static string FullMethodDesc (MethodBase mb)
2789                 {
2790                         StringBuilder sb = new StringBuilder (mb.Name);
2791                         ParameterData pd = GetParameterData (mb);
2792
2793                         int count = pd.Count;
2794                         sb.Append (" (");
2795                         
2796                         for (int i = count; i > 0; ) {
2797                                 i--;
2798
2799                                 sb.Append (pd.ParameterDesc (count - i - 1));
2800                                 if (i != 0)
2801                                         sb.Append (", ");
2802                         }
2803                         
2804                         sb.Append (")");
2805                         return sb.ToString ();
2806                 }
2807
2808                 public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2)
2809                 {
2810                         MemberInfo [] miset;
2811                         MethodGroupExpr union;
2812                         
2813                         if (mg1 != null && mg2 != null) {
2814                                 
2815                                 MethodGroupExpr left_set = null, right_set = null;
2816                                 int length1 = 0, length2 = 0;
2817                                 
2818                                 left_set = (MethodGroupExpr) mg1;
2819                                 length1 = left_set.Methods.Length;
2820                                 
2821                                 right_set = (MethodGroupExpr) mg2;
2822                                 length2 = right_set.Methods.Length;
2823
2824                                 ArrayList common = new ArrayList ();
2825                                 
2826                                 for (int i = 0; i < left_set.Methods.Length; i++) {
2827                                         for (int j = 0; j < right_set.Methods.Length; j++) {
2828                                                 if (left_set.Methods [i] == right_set.Methods [j]) 
2829                                                         common.Add (left_set.Methods [i]);
2830                                         }
2831                                 }
2832                                 
2833                                 miset = new MemberInfo [length1 + length2 - common.Count];
2834
2835                                 left_set.Methods.CopyTo (miset, 0);
2836
2837                                 int k = 0;
2838                                 
2839                                 for (int j = 0; j < right_set.Methods.Length; j++)
2840                                         if (!common.Contains (right_set.Methods [j]))
2841                                                 miset [length1 + k++] = right_set.Methods [j];
2842                                 
2843                                 union = new MethodGroupExpr (miset);
2844
2845                                 return union;
2846
2847                         } else if (mg1 == null && mg2 != null) {
2848                                 
2849                                 MethodGroupExpr me = (MethodGroupExpr) mg2; 
2850                                 
2851                                 miset = new MemberInfo [me.Methods.Length];
2852                                 me.Methods.CopyTo (miset, 0);
2853
2854                                 union = new MethodGroupExpr (miset);
2855                                 
2856                                 return union;
2857
2858                         } else if (mg2 == null && mg1 != null) {
2859                                 
2860                                 MethodGroupExpr me = (MethodGroupExpr) mg1; 
2861                                 
2862                                 miset = new MemberInfo [me.Methods.Length];
2863                                 me.Methods.CopyTo (miset, 0);
2864
2865                                 union = new MethodGroupExpr (miset);
2866                                 
2867                                 return union;
2868                         }
2869                         
2870                         return null;
2871                 }
2872
2873                 /// <summary>
2874                 ///  Determines is the candidate method, if a params method, is applicable
2875                 ///  in its expanded form to the given set of arguments
2876                 /// </summary>
2877                 static bool IsParamsMethodApplicable (ArrayList arguments, MethodBase candidate)
2878                 {
2879                         int arg_count;
2880                         
2881                         if (arguments == null)
2882                                 arg_count = 0;
2883                         else
2884                                 arg_count = arguments.Count;
2885                         
2886                         ParameterData pd = GetParameterData (candidate);
2887                         
2888                         int pd_count = pd.Count;
2889
2890                         if (pd_count == 0)
2891                                 return false;
2892                         
2893                         if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
2894                                 return false;
2895
2896                         if (pd_count - 1 > arg_count)
2897                                 return false;
2898
2899                         // If we have come this far, the case which remains is when the number of parameters
2900                         // is less than or equal to the argument count. So, we now check if the element type
2901                         // of the params array is compatible with each argument type
2902                         //
2903
2904                         Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
2905
2906                         for (int i = pd_count - 1; i < arg_count - 1; i++) {
2907                                 Argument a = (Argument) arguments [i];
2908                                 if (!StandardConversionExists (a.Type, element_type))
2909                                         return false;
2910                         }
2911                         
2912                         return true;
2913                 }
2914
2915                 /// <summary>
2916                 ///  Determines if the candidate method is applicable (section 14.4.2.1)
2917                 ///  to the given set of arguments
2918                 /// </summary>
2919                 static bool IsApplicable (ArrayList arguments, MethodBase candidate)
2920                 {
2921                         int arg_count;
2922
2923                         if (arguments == null)
2924                                 arg_count = 0;
2925                         else
2926                                 arg_count = arguments.Count;
2927
2928                         ParameterData pd = GetParameterData (candidate);
2929
2930                         int pd_count = pd.Count;
2931
2932                         if (arg_count != pd.Count)
2933                                 return false;
2934
2935                         for (int i = arg_count; i > 0; ) {
2936                                 i--;
2937
2938                                 Argument a = (Argument) arguments [i];
2939
2940                                 Parameter.Modifier a_mod = a.GetParameterModifier ();
2941                                 Parameter.Modifier p_mod = pd.ParameterModifier (i);
2942
2943                                 if (a_mod == p_mod) {
2944                                         
2945                                         if (a_mod == Parameter.Modifier.NONE)
2946                                                 if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
2947                                                         return false;
2948                                         
2949                                         if (a_mod == Parameter.Modifier.REF ||
2950                                             a_mod == Parameter.Modifier.OUT)
2951                                                 if (pd.ParameterType (i) != a.Type)
2952                                                         return false;
2953                                 } else
2954                                         return false;
2955                         }
2956
2957                         return true;
2958                 }
2959                 
2960                 
2961
2962                 /// <summary>
2963                 ///   Find the Applicable Function Members (7.4.2.1)
2964                 ///
2965                 ///   me: Method Group expression with the members to select.
2966                 ///       it might contain constructors or methods (or anything
2967                 ///       that maps to a method).
2968                 ///
2969                 ///   Arguments: ArrayList containing resolved Argument objects.
2970                 ///
2971                 ///   loc: The location if we want an error to be reported, or a Null
2972                 ///        location for "probing" purposes.
2973                 ///
2974                 ///   use_standard: controls whether OverloadResolve should use the 
2975                 ///   ConvertImplicit or ConvertImplicitStandard during overload resolution.
2976                 ///
2977                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
2978                 ///            that is the best match of me on Arguments.
2979                 ///
2980                 /// </summary>
2981                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
2982                                                           ArrayList Arguments, Location loc,
2983                                                           bool use_standard)
2984                 {
2985                         ArrayList afm = new ArrayList ();
2986                         int best_match_idx = -1;
2987                         MethodBase method = null;
2988                         int argument_count;
2989                         ArrayList candidates = new ArrayList ();
2990                         
2991                         for (int i = me.Methods.Length; i > 0; ){
2992                                 i--;
2993                                 MethodBase candidate  = me.Methods [i];
2994                                 int x;
2995
2996                                 // Check if candidate is applicable (section 14.4.2.1)
2997                                 if (!IsApplicable (Arguments, candidate))
2998                                         continue;
2999
3000                                 candidates.Add (candidate);
3001                                 x = BetterFunction (ec, Arguments, candidate, method, use_standard, loc);
3002                                 
3003                                 if (x == 0)
3004                                         continue;
3005                                 else {
3006                                         best_match_idx = i;
3007                                         method = me.Methods [best_match_idx];
3008                                 }
3009                         }
3010
3011                         if (Arguments == null)
3012                                 argument_count = 0;
3013                         else
3014                                 argument_count = Arguments.Count;
3015                         
3016                         //
3017                         // Now we see if we can find params functions, applicable in their expanded form
3018                         // since if they were applicable in their normal form, they would have been selected
3019                         // above anyways
3020                         //
3021                         if (best_match_idx == -1) {
3022
3023                                 for (int i = me.Methods.Length; i > 0; ) {
3024                                         i--;
3025                                         MethodBase candidate = me.Methods [i];
3026
3027                                         if (IsParamsMethodApplicable (Arguments, candidate)) {
3028                                                 best_match_idx = i;
3029                                                 method = me.Methods [best_match_idx];
3030                                                 break;
3031                                         }
3032                                 }
3033                         }
3034
3035                         //
3036                         // Now we see if we can at least find a method with the same number of arguments
3037                         //
3038                         ParameterData pd;
3039                         int method_count = 0;
3040
3041                         if (best_match_idx == -1) {
3042                                 
3043                                 for (int i = me.Methods.Length; i > 0;) {
3044                                         i--;
3045                                         MethodBase mb = me.Methods [i];
3046                                         pd = GetParameterData (mb);
3047                                         
3048                                         if (pd.Count == argument_count) {
3049                                                 best_match_idx = i;
3050                                                 method = me.Methods [best_match_idx];
3051                                                 method_count++;
3052                                         } else
3053                                                 continue;
3054                                 }
3055                         }
3056
3057                         if (method == null)
3058                                 return null;
3059
3060                         //
3061                         // Now check that there are no ambiguities i.e the selected method
3062                         // should be better than all the others
3063                         //
3064
3065                         for (int i = candidates.Count; i > 0; ) {
3066                                 i--;
3067                                 MethodBase candidate = (MethodBase) candidates [i];
3068                                 int x;
3069
3070                                 if (candidate == method)
3071                                         continue;
3072
3073                                 x = BetterFunction (ec, Arguments, method, candidate, use_standard, loc);
3074                                 
3075                                 if (x != 1) {
3076                                         Report.Error (
3077                                                 121, loc,
3078                                                 "Ambiguous call when selecting function due to implicit casts");
3079                                         return null;
3080                                 }
3081                         }
3082
3083                         
3084                         // And now convert implicitly, each argument to the required type
3085                         
3086                         pd = GetParameterData (method);
3087                         int pd_count = pd.Count;
3088
3089                         for (int j = 0; j < argument_count; j++) {
3090                                 Argument a = (Argument) Arguments [j];
3091                                 Expression a_expr = a.Expr;
3092                                 Type parameter_type = pd.ParameterType (j);
3093
3094                                 //
3095                                 // Note that we need to compare against the element type
3096                                 // when we have a params method
3097                                 //
3098                                 if (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS) {
3099                                         if (j >= pd_count - 1) 
3100                                                 parameter_type = pd.ParameterType (pd_count - 1).GetElementType ();
3101                                 }
3102
3103                                 if (a.Type != parameter_type){
3104                                         Expression conv;
3105                                         
3106                                         if (use_standard)
3107                                                 conv = ConvertImplicitStandard (
3108                                                         ec, a_expr, parameter_type, Location.Null);
3109                                         else
3110                                                 conv = ConvertImplicit (
3111                                                         ec, a_expr, parameter_type, Location.Null);
3112
3113                                         if (conv == null) {
3114                                                 if (!Location.IsNull (loc)) {
3115                                                         Error (1502, loc,
3116                                                                "The best overloaded match for method '" +
3117                                                                FullMethodDesc (method) +
3118                                                                "' has some invalid arguments");
3119                                                         Error (1503, loc,
3120                                                          "Argument " + (j+1) +
3121                                                          ": Cannot convert from '" + Argument.FullDesc (a) 
3122                                                          + "' to '" + pd.ParameterDesc (j) + "'");
3123                                                 }
3124                                                 return null;
3125                                         }
3126                                         
3127                         
3128                                         
3129                                         //
3130                                         // Update the argument with the implicit conversion
3131                                         //
3132                                         if (a_expr != conv)
3133                                                 a.Expr = conv;
3134
3135                                         // FIXME : For the case of params methods, we need to actually instantiate
3136                                         // an array and initialize it with the argument values etc etc.
3137
3138                                 }
3139                                 
3140                                 if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
3141                                     pd.ParameterModifier (j) != Parameter.Modifier.PARAMS) {
3142                                         if (!Location.IsNull (loc)) {
3143                                                 Error (1502, loc,
3144                                                        "The best overloaded match for method '" + FullMethodDesc (method)+
3145                                                        "' has some invalid arguments");
3146                                                 Error (1503, loc,
3147                                                        "Argument " + (j+1) +
3148                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
3149                                                        + "' to '" + pd.ParameterDesc (j) + "'");
3150                                         }
3151                                         return null;
3152                                 }
3153                                 
3154                                 
3155                         }
3156                         
3157                         return method;
3158                 }
3159                 
3160                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
3161                                                           ArrayList Arguments, Location loc)
3162                 {
3163                         return OverloadResolve (ec, me, Arguments, loc, false);
3164                 }
3165                         
3166                 public override Expression DoResolve (EmitContext ec)
3167                 {
3168                         //
3169                         // First, resolve the expression that is used to
3170                         // trigger the invocation
3171                         //
3172                         expr = expr.Resolve (ec);
3173                         if (expr == null)
3174                                 return null;
3175
3176                         if (!(expr is MethodGroupExpr)) {
3177                                 Type expr_type = expr.Type;
3178
3179                                 if (expr_type != null){
3180                                         bool IsDelegate = TypeManager.IsDelegateType (expr_type);
3181                                         if (IsDelegate)
3182                                                 return (new DelegateInvocation (
3183                                                         this.expr, Arguments, loc)).Resolve (ec);
3184                                 }
3185                         }
3186
3187                         if (!(expr is MethodGroupExpr)){
3188                                 report118 (loc, this.expr, "method group");
3189                                 return null;
3190                         }
3191
3192                         //
3193                         // Next, evaluate all the expressions in the argument list
3194                         //
3195                         if (Arguments != null){
3196                                 for (int i = Arguments.Count; i > 0;){
3197                                         --i;
3198                                         Argument a = (Argument) Arguments [i];
3199
3200                                         if (!a.Resolve (ec, loc))
3201                                                 return null;
3202                                 }
3203                         }
3204
3205                         method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments, loc);
3206
3207                         if (method == null){
3208                                 Error (-6, loc,
3209                                        "Could not find any applicable function for this argument list");
3210                                 return null;
3211                         }
3212
3213                         if (method is MethodInfo)
3214                                 type = ((MethodInfo)method).ReturnType;
3215
3216                         eclass = ExprClass.Value;
3217                         return this;
3218                 }
3219
3220                 // <summary>
3221                 //   Emits the list of arguments as an array
3222                 // </summary>
3223                 static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
3224                 {
3225                         ILGenerator ig = ec.ig;
3226                         int count = arguments.Count - idx;
3227                         Argument a = (Argument) arguments [idx];
3228                         Type t = a.expr.Type;
3229                         string array_type = t.FullName + "[]";
3230                         LocalBuilder array;
3231                         
3232                         array = ig.DeclareLocal (Type.GetType (array_type));
3233                         IntConstant.EmitInt (ig, count);
3234                         ig.Emit (OpCodes.Newarr, t);
3235                         ig.Emit (OpCodes.Stloc, array);
3236
3237                         int top = arguments.Count;
3238                         for (int j = idx; j < top; j++){
3239                                 a = (Argument) arguments [j];
3240                                 
3241                                 ig.Emit (OpCodes.Ldloc, array);
3242                                 IntConstant.EmitInt (ig, j - idx);
3243                                 a.Emit (ec);
3244                                 
3245                                 ArrayAccess.EmitStoreOpcode (ig, t);
3246                         }
3247                         ig.Emit (OpCodes.Ldloc, array);
3248                 }
3249                 
3250                 /// <summary>
3251                 ///   Emits a list of resolved Arguments that are in the arguments
3252                 ///   ArrayList.
3253                 /// 
3254                 ///   The MethodBase argument might be null if the
3255                 ///   emission of the arguments is known not to contain
3256                 ///   a `params' field (for example in constructors or other routines
3257                 ///   that keep their arguments in this structure
3258                 /// </summary>
3259                 public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
3260                 {
3261                         ParameterData pd = null;
3262                         int top;
3263
3264                         if (arguments != null)
3265                                 top = arguments.Count;
3266                         else
3267                                 top = 0;
3268
3269                         if (mb != null)
3270                                  pd = GetParameterData (mb);
3271
3272                         for (int i = 0; i < top; i++){
3273                                 Argument a = (Argument) arguments [i];
3274
3275                                 if (pd != null){
3276                                         if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
3277                                                 EmitParams (ec, i, arguments);
3278                                                 return;
3279                                         }
3280                                 }
3281                                             
3282                                 a.Emit (ec);
3283                         }
3284                 }
3285
3286                 public static void EmitCall (EmitContext ec,
3287                                              bool is_static, Expression instance_expr,
3288                                              MethodBase method, ArrayList Arguments)
3289                 {
3290                         ILGenerator ig = ec.ig;
3291                         bool struct_call = false;
3292                                 
3293                         if (!is_static){
3294                                 //
3295                                 // If this is ourselves, push "this"
3296                                 //
3297                                 if (instance_expr == null){
3298                                         ig.Emit (OpCodes.Ldarg_0);
3299                                 } else {
3300                                         //
3301                                         // Push the instance expression
3302                                         //
3303                                         if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
3304
3305                                                 struct_call = true;
3306
3307                                                 //
3308                                                 // If the expression implements IMemoryLocation, then
3309                                                 // we can optimize and use AddressOf on the
3310                                                 // return.
3311                                                 //
3312                                                 // If not we have to use some temporary storage for
3313                                                 // it.
3314                                                 if (instance_expr is IMemoryLocation)
3315                                                         ((IMemoryLocation) instance_expr).AddressOf (ec);
3316                                                 else {
3317                                                         Type t = instance_expr.Type;
3318                                                         
3319                                                         instance_expr.Emit (ec);
3320                                                         LocalBuilder temp = ig.DeclareLocal (t);
3321                                                         ig.Emit (OpCodes.Stloc, temp);
3322                                                         ig.Emit (OpCodes.Ldloca, temp);
3323                                                 }
3324                                         } else 
3325                                                 instance_expr.Emit (ec);
3326                                 }
3327                         }
3328
3329                         if (Arguments != null)
3330                                 EmitArguments (ec, method, Arguments);
3331
3332                         if (is_static || struct_call){
3333                                 if (method is MethodInfo)
3334                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
3335                                 else
3336                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
3337                         } else {
3338                                 if (method is MethodInfo)
3339                                         ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
3340                                 else
3341                                         ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
3342                         }
3343                 }
3344                 
3345                 public override void Emit (EmitContext ec)
3346                 {
3347                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
3348                         EmitCall (ec, method.IsStatic, mg.InstanceExpression, method, Arguments);
3349                 }
3350                 
3351                 public override void EmitStatement (EmitContext ec)
3352                 {
3353                         Emit (ec);
3354
3355                         // 
3356                         // Pop the return value if there is one
3357                         //
3358                         if (method is MethodInfo){
3359                                 if (((MethodInfo)method).ReturnType != TypeManager.void_type)
3360                                         ec.ig.Emit (OpCodes.Pop);
3361                         }
3362                 }
3363         }
3364
3365         /// <summary>
3366         ///    Implements the new expression 
3367         /// </summary>
3368         public class New : ExpressionStatement {
3369                 public readonly ArrayList Arguments;
3370                 public readonly string    RequestedType;
3371
3372                 Location loc;
3373                 MethodBase method = null;
3374
3375                 //
3376                 // If set, the new expression is for a value_target, and
3377                 // we will not leave anything on the stack.
3378                 //
3379                 Expression value_target;
3380                 
3381                 public New (string requested_type, ArrayList arguments, Location l)
3382                 {
3383                         RequestedType = requested_type;
3384                         Arguments = arguments;
3385                         loc = l;
3386                 }
3387
3388                 public Expression ValueTypeVariable {
3389                         get {
3390                                 return value_target;
3391                         }
3392
3393                         set {
3394                                 value_target = value;
3395                         }
3396                 }
3397
3398                 public override Expression DoResolve (EmitContext ec)
3399                 {
3400                         type = RootContext.LookupType (ec.TypeContainer, RequestedType, false, loc);
3401                         
3402                         if (type == null)
3403                                 return null;
3404                         
3405                         bool IsDelegate = TypeManager.IsDelegateType (type);
3406                         
3407                         if (IsDelegate)
3408                                 return (new NewDelegate (type, Arguments, loc)).Resolve (ec);
3409                         
3410                         bool is_struct = false;
3411                         is_struct = type.IsSubclassOf (TypeManager.value_type);
3412                         eclass = ExprClass.Value;
3413
3414                         //
3415                         // SRE returns a match for .ctor () on structs (the object constructor), 
3416                         // so we have to manually ignore it.
3417                         //
3418                         if (is_struct && Arguments == null)
3419                                 return this;
3420                         
3421                         Expression ml;
3422                         ml = MemberLookup (ec, type, ".ctor", false,
3423                                            MemberTypes.Constructor, AllBindingFlags, loc);
3424                         
3425                         if (! (ml is MethodGroupExpr)){
3426                                 if (!is_struct){
3427                                         report118 (loc, ml, "method group");
3428                                         return null;
3429                                 }
3430                         }
3431                         
3432                         if (ml != null) {
3433                                 if (Arguments != null){
3434                                         for (int i = Arguments.Count; i > 0;){
3435                                                 --i;
3436                                                 Argument a = (Argument) Arguments [i];
3437                                                 
3438                                                 if (!a.Resolve (ec, loc))
3439                                                         return null;
3440                                         }
3441                                 }
3442                                 
3443                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
3444                                                                      Arguments, loc);
3445                         }
3446                         
3447                         if (method == null && !is_struct) {
3448                                 Error (-6, loc,
3449                                        "New invocation: Can not find a constructor for " +
3450                                        "this argument list");
3451                                 return null;
3452                         }
3453                         return this;
3454                 }
3455
3456                 //
3457                 // This DoEmit can be invoked in two contexts:
3458                 //    * As a mechanism that will leave a value on the stack (new object)
3459                 //    * As one that wont (init struct)
3460                 //
3461                 // You can control whether a value is required on the stack by passing
3462                 // need_value_on_stack.  The code *might* leave a value on the stack
3463                 // so it must be popped manually
3464                 //
3465                 // If we are dealing with a ValueType, we have a few
3466                 // situations to deal with:
3467                 //
3468                 //    * The target is a ValueType, and we have been provided
3469                 //      the instance (this is easy, we are being assigned).
3470                 //
3471                 //    * The target of New is being passed as an argument,
3472                 //      to a boxing operation or a function that takes a
3473                 //      ValueType.
3474                 //
3475                 //      In this case, we need to create a temporary variable
3476                 //      that is the argument of New.
3477                 //
3478                 // Returns whether a value is left on the stack
3479                 //
3480                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
3481                 {
3482                         if (method == null){
3483                                 IMemoryLocation ml;
3484
3485                                 if (value_target == null)
3486                                         value_target = new LocalTemporary (ec, type);
3487                                                 
3488                                 ml = (IMemoryLocation) value_target;
3489                                 ml.AddressOf (ec);
3490                         } else {
3491                                 Invocation.EmitArguments (ec, method, Arguments);
3492                                 ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
3493                                 return true;
3494                         }
3495
3496                         //
3497                         // It must be a value type, sanity check
3498                         //
3499                         if (value_target != null){
3500                                 ec.ig.Emit (OpCodes.Initobj, type);
3501
3502                                 if (need_value_on_stack){
3503                                         value_target.Emit (ec);
3504                                         return true;
3505                                 }
3506                                 return false;
3507                         }
3508
3509                         throw new Exception ("No method and no value type");
3510                 }
3511
3512                 public override void Emit (EmitContext ec)
3513                 {
3514                         DoEmit (ec, true);
3515                 }
3516                 
3517                 public override void EmitStatement (EmitContext ec)
3518                 {
3519                         if (DoEmit (ec, false))
3520                                 ec.ig.Emit (OpCodes.Pop);
3521                 }
3522         }
3523
3524         /// <summary>
3525         ///   Represents an array creation expression.
3526         /// </summary>
3527         ///
3528         /// <remarks>
3529         ///   There are two possible scenarios here: one is an array creation
3530         ///   expression that specifies the dimensions and optionally the
3531         ///   initialization data and the other which does not need dimensions
3532         ///   specified but where initialization data is mandatory.
3533         /// </remarks>
3534         public class ArrayCreation : ExpressionStatement {
3535                 string RequestedType;
3536                 string Rank;
3537                 ArrayList Initializers;
3538                 Location  loc;
3539                 ArrayList Arguments;
3540                 
3541                 MethodBase method = null;
3542                 Type array_element_type;
3543                 bool IsOneDimensional = false;
3544                 bool IsBuiltinType = false;
3545                 bool ExpectInitializers = false;
3546
3547                 int dimensions = 0;
3548                 Type underlying_type;
3549
3550                 ArrayList ArrayData;
3551
3552                 Hashtable Bounds;
3553
3554                 public ArrayCreation (string requested_type, ArrayList exprs,
3555                                       string rank, ArrayList initializers, Location l)
3556                 {
3557                         RequestedType = requested_type;
3558                         Rank          = rank;
3559                         Initializers  = initializers;
3560                         loc = l;
3561
3562                         Arguments = new ArrayList ();
3563
3564                         foreach (Expression e in exprs)
3565                                 Arguments.Add (new Argument (e, Argument.AType.Expression));
3566
3567                 }
3568
3569                 public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
3570                 {
3571                         RequestedType = requested_type;
3572                         Initializers = initializers;
3573                         loc = l;
3574
3575                         Rank = rank.Substring (0, rank.LastIndexOf ("["));
3576
3577                         string tmp = rank.Substring (rank.LastIndexOf ("["));
3578
3579                         dimensions = tmp.Length - 1;
3580                         ExpectInitializers = true;
3581                 }
3582
3583                 public static string FormArrayType (string base_type, int idx_count, string rank)
3584                 {
3585                         StringBuilder sb = new StringBuilder (base_type);
3586
3587                         sb.Append (rank);
3588                         
3589                         sb.Append ("[");
3590                         for (int i = 1; i < idx_count; i++)
3591                                 sb.Append (",");
3592                         sb.Append ("]");
3593                         
3594                         return sb.ToString ();
3595                 }
3596
3597                 public static string FormElementType (string base_type, int idx_count, string rank)
3598                 {
3599                         StringBuilder sb = new StringBuilder (base_type);
3600                         
3601                         sb.Append ("[");
3602                         for (int i = 1; i < idx_count; i++)
3603                                 sb.Append (",");
3604                         sb.Append ("]");
3605
3606                         sb.Append (rank);
3607
3608                         string val = sb.ToString ();
3609
3610                         return val.Substring (0, val.LastIndexOf ("["));
3611                 }
3612
3613                 void error178 ()
3614                 {
3615                         Report.Error (178, loc, "Incorrectly structured array initializer");
3616                 }
3617                 
3618                 public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
3619                 {
3620                         if (specified_dims) { 
3621                                 Argument a = (Argument) Arguments [idx];
3622                                 
3623                                 if (!a.Resolve (ec, loc))
3624                                         return false;
3625                                 
3626                                 if (!(a.Expr is Constant)) {
3627                                         Report.Error (150, loc, "A constant value is expected");
3628                                         return false;
3629                                 }
3630                                 
3631                                 int value = (int) ((Constant) a.Expr).GetValue ();
3632                                 
3633                                 if (value != probe.Count) {
3634                                         error178 ();
3635                                         return false;
3636                                 }
3637                                 
3638                                 Bounds [idx] = value;
3639                         }
3640                         
3641                         foreach (object o in probe) {
3642                                 if (o is ArrayList) {
3643                                         bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
3644                                         if (!ret)
3645                                                 return false;
3646                                 } else {
3647                                         Expression tmp = (Expression) o;
3648                                         tmp = tmp.Resolve (ec);
3649                                         if (tmp == null)
3650                                                 continue;
3651                                         
3652                                         // Handle initialization from vars, fields etc.
3653
3654                                         Expression conv = ConvertImplicitRequired (
3655                                                 ec, tmp, underlying_type, loc);
3656                                         
3657                                         if (conv == null) 
3658                                                 return false;
3659
3660                                         if (conv is StringConstant)
3661                                                 ArrayData.Add (conv);
3662                                         else if (conv is Constant)
3663                                                 ArrayData.Add (((Constant) conv).GetValue ());
3664                                         else
3665                                                 ArrayData.Add (conv);
3666                                 }
3667                         }
3668
3669                         return true;
3670                 }
3671                 
3672                 public void UpdateIndices (EmitContext ec)
3673                 {
3674                         int i = 0;
3675                         for (ArrayList probe = Initializers; probe != null;) {
3676                                 
3677                                 if (probe [0] is ArrayList) {
3678                                         Expression e = new IntConstant (probe.Count);
3679                                         Arguments.Add (new Argument (e, Argument.AType.Expression));
3680
3681                                         Bounds [i++] =  probe.Count;
3682                                         
3683                                         probe = (ArrayList) probe [0];
3684                                         
3685                                 } else {
3686                                         Expression e = new IntConstant (probe.Count);
3687                                         Arguments.Add (new Argument (e, Argument.AType.Expression));
3688
3689                                         Bounds [i++] = probe.Count;
3690                                         probe = null;
3691                                 }
3692                         }
3693
3694                 }
3695                 
3696                 public bool ValidateInitializers (EmitContext ec)
3697                 {
3698                         if (Initializers == null) {
3699                                 if (ExpectInitializers)
3700                                         return false;
3701                                 else
3702                                         return true;
3703                         }
3704                         
3705                         underlying_type = RootContext.LookupType (
3706                                 ec.TypeContainer, RequestedType, false, loc);
3707                         
3708                         //
3709                         // We use this to store all the date values in the order in which we
3710                         // will need to store them in the byte blob later
3711                         //
3712                         ArrayData = new ArrayList ();
3713                         Bounds = new Hashtable ();
3714                         
3715                         bool ret;
3716
3717                         if (Arguments != null) {
3718                                 ret = CheckIndices (ec, Initializers, 0, true);
3719                                 return ret;
3720                                 
3721                         } else {
3722                                 Arguments = new ArrayList ();
3723
3724                                 ret = CheckIndices (ec, Initializers, 0, false);
3725                                 
3726                                 if (!ret)
3727                                         return false;
3728                                 
3729                                 UpdateIndices (ec);
3730                                 
3731                                 if (Arguments.Count != dimensions) {
3732                                         error178 ();
3733                                         return false;
3734                                 }
3735
3736                                 return ret;
3737                         }
3738                 }
3739                 
3740                 public override Expression DoResolve (EmitContext ec)
3741                 {
3742                         int arg_count;
3743
3744                         if (!ValidateInitializers (ec))
3745                                 return null;
3746
3747                         if (Arguments == null)
3748                                 arg_count = 0;
3749                         else {
3750                                 arg_count = Arguments.Count;
3751                                 for (int i = arg_count; i > 0;){
3752                                         --i;
3753                                         Argument a = (Argument) Arguments [i];
3754                                         
3755                                         if (!a.Resolve (ec, loc))
3756                                                 return null;
3757                                 }
3758                         }
3759                         
3760                         string array_type = FormArrayType (RequestedType, arg_count, Rank);
3761                         string element_type = FormElementType (RequestedType, arg_count, Rank);
3762
3763                         type = RootContext.LookupType (ec.TypeContainer, array_type, false, loc);
3764                         
3765                         array_element_type = RootContext.LookupType (
3766                                 ec.TypeContainer, element_type, false, loc);
3767                         
3768                         if (type == null)
3769                                 return null;
3770                         
3771                         if (arg_count == 1) {
3772                                 IsOneDimensional = true;
3773                                 eclass = ExprClass.Value;
3774                                 return this;
3775                         }
3776
3777                         IsBuiltinType = TypeManager.IsBuiltinType (type);
3778                         
3779                         if (IsBuiltinType) {
3780                                 
3781                                 Expression ml;
3782                                 
3783                                 ml = MemberLookup (ec, type, ".ctor", false, MemberTypes.Constructor,
3784                                                    AllBindingFlags, loc);
3785                                 
3786                                 if (!(ml is MethodGroupExpr)){
3787                                         report118 (loc, ml, "method group");
3788                                         return null;
3789                                 }
3790                                 
3791                                 if (ml == null) {
3792                                         Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
3793                                                       "this argument list");
3794                                         return null;
3795                                 }
3796                                 
3797                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, loc);
3798                                 
3799                                 if (method == null) {
3800                                         Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
3801                                                       "this argument list");
3802                                         return null;
3803                                 }
3804                                 
3805                                 eclass = ExprClass.Value;
3806                                 return this;
3807                                 
3808                         } else {
3809                                 ModuleBuilder mb = RootContext.ModuleBuilder;
3810
3811                                 ArrayList args = new ArrayList ();
3812                                 if (Arguments != null){
3813                                         for (int i = arg_count; i > 0;){
3814                                                 --i;
3815                                                 Argument a = (Argument) Arguments [i];
3816                                                 
3817                                                 args.Add (a.Type);
3818                                         }
3819                                 }
3820                                 
3821                                 Type [] arg_types = null;
3822                                 
3823                                 if (args.Count > 0)
3824                                         arg_types = new Type [args.Count];
3825                                 
3826                                 args.CopyTo (arg_types, 0);
3827                                 
3828                                 method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
3829                                                             arg_types);
3830                                 
3831                                 if (method == null) {
3832                                         Report.Error (-6, loc, "New invocation: Can not find a constructor for " +
3833                                                       "this argument list");
3834                                         return null;
3835                                 }
3836                                 
3837                                 eclass = ExprClass.Value;
3838                                 return this;
3839                                 
3840                         }
3841                 }
3842
3843                 public static byte [] MakeByteBlob (ArrayList ArrayData, Type underlying_type, Location loc)
3844                 {
3845                         int factor;
3846                         byte [] data;
3847
3848                         int count = ArrayData.Count;
3849
3850                         if (underlying_type == TypeManager.int32_type ||
3851                             underlying_type == TypeManager.uint32_type ||
3852                             underlying_type == TypeManager.float_type)
3853                                 factor = 4;
3854                         else if (underlying_type == TypeManager.int64_type ||
3855                                  underlying_type == TypeManager.uint64_type ||
3856                                  underlying_type == TypeManager.double_type)
3857                                 factor = 8;
3858                         else if (underlying_type == TypeManager.byte_type ||
3859                                  underlying_type == TypeManager.sbyte_type ||
3860                                  underlying_type == TypeManager.bool_type)      
3861                                 factor = 1;
3862                         else if (underlying_type == TypeManager.short_type ||
3863                                  underlying_type == TypeManager.char_type ||
3864                                  underlying_type == TypeManager.ushort_type)
3865                                 factor = 2;
3866                         else {
3867                                 Report.Error (-100, loc, "Unhandled type in MakeByteBlob!!");
3868                                 return null;
3869                         }
3870
3871                         data = new byte [count * factor];
3872                         int idx = 0;
3873                         
3874                         for (int i = 0; i < count; ++i) {
3875                                 object v = ArrayData [i];
3876
3877                                 if (v is EnumConstant)
3878                                         v = ((EnumConstant) v).Child;
3879
3880                                 if (underlying_type == TypeManager.int64_type ||
3881                                     underlying_type == TypeManager.uint64_type){
3882                                         long val = 0;
3883                                         if (!(v is Expression))
3884                                                 val = (long) v;
3885
3886                                         for (int j = 0; j < factor; ++j) {
3887                                                 data [idx + j] = (byte) (val & 0xFF);
3888                                                 val = (val >> 8);
3889                                         }
3890                                 } else if (underlying_type == TypeManager.float_type) {
3891 #if __MonoCS__
3892 #else
3893                                         unsafe {
3894                                                 float val = 0;
3895
3896                                                 if (!(v is Expression))
3897                                                         val = (float) v;
3898
3899                                                 byte *ptr = (byte *) &val;
3900                                                 
3901                                                 for (int j = 0; j < factor; ++j)
3902                                                         data [idx + j] = (byte) ptr [j];
3903                                         }
3904 #endif
3905                                 } else if (underlying_type == TypeManager.double_type) {
3906 #if __MonoCS__
3907 #else
3908                                         unsafe {
3909                                                 double val = 0;
3910
3911                                                 if (!(v is Expression))
3912                                                         val = (double) v;
3913
3914                                                 byte *ptr = (byte *) &val;
3915                                                 
3916                                                 for (int j = 0; j < factor; ++j)
3917                                                         data [idx + j] = (byte) ptr [j];
3918                                         }
3919 #endif
3920                                 } else if (underlying_type == TypeManager.char_type){
3921                                         int val = (char) 0;
3922
3923                                         if (!(v is Expression))
3924                                                 v = (int) ((char) v);
3925                                         
3926                                         data [idx] = (byte) (val & 0xff);
3927                                         data [idx+1] = (byte) (val >> 8);
3928
3929                                 } else if (underlying_type == TypeManager.int32_type) {
3930                                         int val = 0;
3931                                         
3932                                         if (!(v is Expression))
3933                                                 val = (int) v;
3934                                         
3935                                         data [idx]   = (byte) (val & 0xff);
3936                                         data [idx+1] = (byte) ((val >> 8) & 0xff);
3937                                         data [idx+2] = (byte) ((val >> 16) & 0xff);
3938                                         data [idx+3] = (byte) (val >> 24);
3939                                 } else
3940                                         throw new Exception ("Unrecognized type in MakeByteBlob");
3941
3942                                 idx += factor;
3943                         }
3944
3945                         return data;
3946                 }
3947
3948                 //
3949                 // Emits the initializers for the array
3950                 //
3951                 void EmitStaticInitializers (EmitContext ec, bool is_expression)
3952                 {
3953                         //
3954                         // First, the static data
3955                         //
3956                         FieldBuilder fb;
3957                         ILGenerator ig = ec.ig;
3958                         
3959                         byte [] data = MakeByteBlob (ArrayData, underlying_type, loc);
3960                         
3961                         if (data != null) {
3962                                 fb = RootContext.MakeStaticData (data);
3963                                 
3964                                 if (is_expression)
3965                                         ig.Emit (OpCodes.Dup);
3966                                 ig.Emit (OpCodes.Ldtoken, fb);
3967                                 ig.Emit (OpCodes.Call,
3968                                          TypeManager.void_initializearray_array_fieldhandle);
3969                         }
3970                 }
3971                 
3972                 //
3973                 // Emits pieces of the array that can not be computed at compile
3974                 // time (variables and string locations).
3975                 //
3976                 // This always expect the top value on the stack to be the array
3977                 //
3978                 void EmitDynamicInitializers (EmitContext ec, bool is_expression)
3979                 {
3980                         ILGenerator ig = ec.ig;
3981                         int dims = Bounds.Count;
3982                         int [] current_pos = new int [dims];
3983                         int top = ArrayData.Count;
3984                         LocalBuilder temp = ig.DeclareLocal (type);
3985
3986                         ig.Emit (OpCodes.Stloc, temp);
3987
3988                         MethodInfo set = null;
3989
3990                         if (dims != 1){
3991                                 Type [] args;
3992                                 ModuleBuilder mb = null;
3993                                 mb = RootContext.ModuleBuilder;
3994                                 args = new Type [dims + 1];
3995
3996                                 int j;
3997                                 for (j = 0; j < dims; j++)
3998                                         args [j] = TypeManager.int32_type;
3999
4000                                 args [j] = array_element_type;
4001                                 
4002                                 set = mb.GetArrayMethod (
4003                                         type, "Set",
4004                                         CallingConventions.HasThis | CallingConventions.Standard,
4005                                         TypeManager.void_type, args);
4006                         }
4007                         
4008                         for (int i = 0; i < top; i++){
4009
4010                                 Expression e = null;
4011
4012                                 if (ArrayData [i] is Expression)
4013                                         e = (Expression) ArrayData [i];
4014
4015                                 if (e != null) {
4016                                         //
4017                                         // Basically we do this for string literals and
4018                                         // other non-literal expressions
4019                                         //
4020                                         if (e is StringConstant || !(e is Constant)) {
4021
4022                                                 ig.Emit (OpCodes.Ldloc, temp);
4023
4024                                                 for (int idx = dims; idx > 0; ) {
4025                                                         idx--;
4026                                                         IntConstant.EmitInt (ig, current_pos [idx]);
4027                                                 }
4028
4029                                                 e.Emit (ec);
4030                                                 
4031                                                 if (dims == 1)
4032                                                         ArrayAccess.EmitStoreOpcode (ig, array_element_type);
4033                                                 else 
4034                                                         ig.Emit (OpCodes.Call, set);
4035                                                 
4036                                         }
4037                                 }
4038                                 
4039                                 //
4040                                 // Advance counter
4041                                 //
4042                                 for (int j = 0; j < dims; j++){
4043                                         current_pos [j]++;
4044                                         if (current_pos [j] < (int) Bounds [j])
4045                                                 break;
4046                                         current_pos [j] = 0;
4047                                 }
4048                         }
4049
4050                         if (is_expression)
4051                                 ig.Emit (OpCodes.Ldloc, temp);
4052                 }
4053
4054                 void DoEmit (EmitContext ec, bool is_statement)
4055                 {
4056                         ILGenerator ig = ec.ig;
4057                         
4058                         if (IsOneDimensional) {
4059                                 Invocation.EmitArguments (ec, null, Arguments);
4060                                 ig.Emit (OpCodes.Newarr, array_element_type);
4061                                 
4062                         } else {
4063                                 Invocation.EmitArguments (ec, null, Arguments);
4064
4065                                 if (IsBuiltinType)
4066                                         ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
4067                                 else
4068                                         ig.Emit (OpCodes.Newobj, (MethodInfo) method);
4069                         }
4070
4071                         if (Initializers != null){
4072                                 //
4073                                 // FIXME: Set this variable correctly.
4074                                 // 
4075                                 bool dynamic_initializers = true;
4076
4077                                 if (underlying_type != TypeManager.string_type &&
4078                                     underlying_type != TypeManager.object_type)
4079                                         EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
4080                                 
4081                                 if (dynamic_initializers)
4082                                         EmitDynamicInitializers (ec, !is_statement);
4083                         }
4084                 }
4085                 
4086                 public override void Emit (EmitContext ec)
4087                 {
4088                         DoEmit (ec, false);
4089                 }
4090
4091                 public override void EmitStatement (EmitContext ec)
4092                 {
4093                         DoEmit (ec, true);
4094                 }
4095                 
4096         }
4097         
4098         /// <summary>
4099         ///   Represents the `this' construct
4100         /// </summary>
4101         public class This : Expression, IAssignMethod, IMemoryLocation {
4102                 Location loc;
4103                 
4104                 public This (Location loc)
4105                 {
4106                         this.loc = loc;
4107                 }
4108
4109                 public override Expression DoResolve (EmitContext ec)
4110                 {
4111                         eclass = ExprClass.Variable;
4112                         type = ec.TypeContainer.TypeBuilder;
4113
4114                         if (ec.IsStatic){
4115                                 Report.Error (26, loc,
4116                                               "Keyword this not valid in static code");
4117                                 return null;
4118                         }
4119                         
4120                         return this;
4121                 }
4122
4123                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
4124                 {
4125                         DoResolve (ec);
4126                         
4127                         if (ec.TypeContainer is Class){
4128                                 Report.Error (1604, loc, "Cannot assign to `this'");
4129                                 return null;
4130                         }
4131
4132                         return this;
4133                 }
4134
4135                 public override void Emit (EmitContext ec)
4136                 {
4137                         ec.ig.Emit (OpCodes.Ldarg_0);
4138                 }
4139
4140                 public void EmitAssign (EmitContext ec, Expression source)
4141                 {
4142                         source.Emit (ec);
4143                         ec.ig.Emit (OpCodes.Starg, 0);
4144                 }
4145
4146                 public void AddressOf (EmitContext ec)
4147                 {
4148                         ec.ig.Emit (OpCodes.Ldarg_0);
4149
4150                         // FIMXE
4151                         // FIGURE OUT WHY LDARG_S does not work
4152                         //
4153                         // consider: struct X { int val; int P { set { val = value; }}}
4154                         //
4155                         // Yes, this looks very bad. Look at `NOTAS' for
4156                         // an explanation.
4157                         // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
4158                 }
4159         }
4160
4161         /// <summary>
4162         ///   Implements the typeof operator
4163         /// </summary>
4164         public class TypeOf : Expression {
4165                 public readonly string QueriedType;
4166                 Type typearg;
4167                 Location loc;
4168                 
4169                 public TypeOf (string queried_type, Location l)
4170                 {
4171                         QueriedType = queried_type;
4172                         loc = l;
4173                 }
4174
4175                 public override Expression DoResolve (EmitContext ec)
4176                 {
4177                         typearg = RootContext.LookupType (
4178                                 ec.TypeContainer, QueriedType, false, loc);
4179
4180                         if (typearg == null)
4181                                 return null;
4182
4183                         type = TypeManager.type_type;
4184                         eclass = ExprClass.Type;
4185                         return this;
4186                 }
4187
4188                 public override void Emit (EmitContext ec)
4189                 {
4190                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
4191                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
4192                 }
4193         }
4194
4195         /// <summary>
4196         ///   Implements the sizeof expression
4197         /// </summary>
4198         public class SizeOf : Expression {
4199                 public readonly string QueriedType;
4200                 
4201                 public SizeOf (string queried_type)
4202                 {
4203                         this.QueriedType = queried_type;
4204                 }
4205
4206                 public override Expression DoResolve (EmitContext ec)
4207                 {
4208                         // FIXME: Implement;
4209                         throw new Exception ("Unimplemented");
4210                         // return this;
4211                 }
4212
4213                 public override void Emit (EmitContext ec)
4214                 {
4215                         throw new Exception ("Implement me");
4216                 }
4217         }
4218
4219         /// <summary>
4220         ///   Implements the member access expression
4221         /// </summary>
4222         public class MemberAccess : Expression {
4223                 public readonly string Identifier;
4224                 Expression expr;
4225                 Expression member_lookup;
4226                 Location loc;
4227                 
4228                 public MemberAccess (Expression expr, string id, Location l)
4229                 {
4230                         this.expr = expr;
4231                         Identifier = id;
4232                         loc = l;
4233                 }
4234
4235                 public Expression Expr {
4236                         get {
4237                                 return expr;
4238                         }
4239                 }
4240
4241                 static void error176 (Location loc, string name)
4242                 {
4243                         Report.Error (176, loc, "Static member `" +
4244                                       name + "' cannot be accessed " +
4245                                       "with an instance reference, qualify with a " +
4246                                       "type name instead");
4247                 }
4248
4249 #if USE_OLD
4250                 public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
4251                                                               Expression left, Location loc)
4252                 {
4253                         //
4254                         // Method Groups
4255                         //
4256                         if (member_lookup is MethodGroupExpr){
4257                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
4258
4259                                 //
4260                                 // Type.MethodGroup
4261                                 //
4262                                 if (left is TypeExpr){
4263                                         if (!mg.RemoveInstanceMethods ()){
4264                                                 SimpleName.Error120 (loc, mg.Methods [0].Name); 
4265                                                 return null;
4266                                         }
4267
4268                                         return member_lookup;
4269                                 }
4270
4271                                 //
4272                                 // Instance.MethodGroup
4273                                 //
4274                                 if (!mg.RemoveStaticMethods ()){
4275                                         error176 (loc, mg.Methods [0].Name);
4276                                         return null;
4277                                 }
4278                                 
4279                                 mg.InstanceExpression = left;
4280                                         
4281                                 return member_lookup;
4282                         }
4283
4284                         if (member_lookup is FieldExpr){
4285                                 FieldExpr fe = (FieldExpr) member_lookup;
4286                                 FieldInfo fi = fe.FieldInfo;
4287
4288                                 if (fi is FieldBuilder) {
4289                                         Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
4290                                         
4291                                         if (c != null) {
4292                                                 object o = c.LookupConstantValue (ec);
4293                                                 return Constantify (o, fi.FieldType);
4294                                         }
4295                                 }
4296
4297                                 if (fi.IsLiteral) {
4298                                         Type t = fi.FieldType;
4299                                         Type decl_type = fi.DeclaringType;
4300                                         object o;
4301
4302                                         if (fi is FieldBuilder)
4303                                                 o = TypeManager.GetValue ((FieldBuilder) fi);
4304                                         else
4305                                                 o = fi.GetValue (fi);
4306                                         
4307                                         if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
4308                                                 Expression enum_member = MemberLookup (ec, decl_type, "value__",
4309                                                                                        false, loc); 
4310
4311                                                 Enum en = TypeManager.LookupEnum (decl_type);
4312
4313                                                 Constant c;
4314                                                 if (en != null)
4315                                                         c = Constantify (o, en.UnderlyingType);
4316                                                 else 
4317                                                         c = Constantify (o, enum_member.Type);
4318                                                 
4319                                                 return new EnumConstant (c, decl_type);
4320                                         }
4321                                         
4322                                         Expression exp = Constantify (o, t);
4323
4324                                         if (!(left is TypeExpr)) {
4325                                                 error176 (loc, fe.FieldInfo.Name);
4326                                                 return null;
4327                                         }
4328                                         
4329                                         return exp;
4330                                 }
4331                                 
4332                                 if (left is TypeExpr){
4333                                         if (!fe.FieldInfo.IsStatic){
4334                                                 error176 (loc, fe.FieldInfo.Name);
4335                                                 return null;
4336                                         }
4337                                         return member_lookup;
4338                                 } else {
4339                                         if (fe.FieldInfo.IsStatic){
4340                                                 error176 (loc, fe.FieldInfo.Name);
4341                                                 return null;
4342                                         }
4343                                         fe.InstanceExpression = left;
4344
4345                                         return fe;
4346                                 }
4347                         }
4348
4349                         if (member_lookup is PropertyExpr){
4350                                 PropertyExpr pe = (PropertyExpr) member_lookup;
4351
4352                                 if (left is TypeExpr){
4353                                         if (!pe.IsStatic){
4354                                                 SimpleName.Error120 (loc, pe.PropertyInfo.Name);
4355                                                 return null;
4356                                         }
4357                                         return pe;
4358                                 } else {
4359                                         if (pe.IsStatic){
4360                                                 error176 (loc, pe.PropertyInfo.Name);
4361                                                 return null;
4362                                         }
4363                                         pe.InstanceExpression = left;
4364                                         
4365                                         return pe;
4366                                 }
4367                         }
4368
4369                         if (member_lookup is EventExpr) {
4370
4371                                 EventExpr ee = (EventExpr) member_lookup;
4372                                 
4373                                 //
4374                                 // If the event is local to this class, we transform ourselves into
4375                                 // a FieldExpr
4376                                 //
4377
4378                                 Expression ml = MemberLookup (ec, ec.TypeContainer.TypeBuilder, ee.EventInfo.Name,
4379                                                               true, MemberTypes.Event, AllBindingFlags, loc);
4380
4381                                 if (ml != null) {
4382                                         MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
4383
4384                                         ml = ExprClassFromMemberInfo (ec, mi, loc);
4385                                         
4386                                         if (ml == null) {
4387                                                 Report.Error (-200, loc, "Internal error!!");
4388                                                 return null;
4389                                         }
4390
4391                                         return ResolveMemberAccess (ec, ml, left, loc);
4392                                 }
4393
4394                                 if (left is TypeExpr) {
4395                                         if (!ee.IsStatic) {
4396                                                 SimpleName.Error120 (loc, ee.EventInfo.Name);
4397                                                 return null;
4398                                         }
4399
4400                                         return ee;
4401
4402                                 } else {
4403                                         if (ee.IsStatic) {
4404                                                 error176 (loc, ee.EventInfo.Name);
4405                                                 return null;
4406                                         }
4407
4408                                         ee.InstanceExpression = left;
4409
4410                                         return ee;
4411                                 }
4412                         }
4413
4414                         if (member_lookup is TypeExpr){
4415                                 member_lookup.Resolve (ec);
4416                                 return member_lookup;
4417                         }
4418                         
4419                         Console.WriteLine ("Left is: " + left);
4420                         Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
4421                         Environment.Exit (0);
4422                         return null;
4423                 }
4424                 
4425                 public override Expression DoResolve (EmitContext ec)
4426                 {
4427                         //
4428                         // We are the sole users of ResolveWithSimpleName (ie, the only
4429                         // ones that can cope with it
4430                         //
4431                         expr = expr.ResolveWithSimpleName (ec);
4432
4433                         if (expr == null)
4434                                 return null;
4435
4436                         if (expr is SimpleName){
4437                                 SimpleName child_expr = (SimpleName) expr;
4438                                 
4439                                 expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
4440
4441                                 return expr.ResolveWithSimpleName (ec);
4442                         }
4443                                         
4444                         //
4445                         // Handle enums here when they are in transit.
4446                         // Note that we cannot afford to hit MemberLookup in this case because
4447                         // it will fail to find any members at all
4448                         //
4449
4450                         Type expr_type = expr.Type;
4451                         if (expr_type.IsSubclassOf (TypeManager.enum_type)) {
4452                                 
4453                                 Enum en = TypeManager.LookupEnum (expr_type);
4454                                 
4455                                 if (en != null) {
4456                                         object value = en.LookupEnumValue (ec, Identifier, loc);
4457
4458                                         if (value == null)
4459                                                 return null;
4460                                         
4461                                         Constant c = Constantify (value, en.UnderlyingType);
4462                                         return new EnumConstant (c, expr_type);
4463                                 }
4464                         }
4465
4466                         member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
4467
4468                         if (member_lookup == null)
4469                                 return null;
4470
4471                         return ResolveMemberAccess (ec, member_lookup, expr, loc);
4472                 }
4473
4474 #else
4475
4476                 bla bla bla
4477                 //
4478                 // This code is more conformant to the spec (it follows it step by step),
4479                 // but it has not been tested yet, and there is nothing here that is not
4480                 // caught by the above code.  But it might be a better foundation to improve
4481                 // on in the future
4482                 //
4483                 public ResolveTypeMemberAccess (EmitContext ec, Expression member_lookup,
4484                                                 Expression left, Location loc)
4485                 {
4486                         if (member_lookup is TypeExpr){
4487                                 member_lookup.Resolve (ec);
4488                                 return member_lookup;
4489                         }
4490                         
4491                         if (member_lookup is MethodGroupExpr){
4492                                 if (!mg.RemoveStaticMethods ()){
4493                                         SimpleName.Error120 (loc, mg.Methods [0].Name); 
4494                                         return null;
4495                                 }
4496                                 
4497                                 return member_lookup;
4498                         }
4499                         
4500                         if (member_lookup is PropertyExpr){
4501                                 PropertyExpr pe = (PropertyExpr) member_lookup;
4502                                         
4503                                         if (!pe.IsStatic){
4504                                                 SimpleName.Error120 (loc, pe.PropertyInfo.Name);
4505                                                 return null;
4506                                         }
4507                                         return pe;
4508                         }
4509                         
4510                         if (member_lookup is FieldExpr){
4511                                 FieldExpr fe = (FieldExpr) member_lookup;
4512                                 FieldInfo fi = fe.FieldInfo;
4513                                 
4514                                 if (fi is FieldBuilder) {
4515                                         Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
4516                                         
4517                                         if (c != null) {
4518                                                 object o = c.LookupConstantValue (ec);
4519                                                 return Constantify (o, fi.FieldType);
4520                                         }
4521                                 }
4522                                 
4523                                 if (fi.IsLiteral) {
4524                                         Type t = fi.FieldType;
4525                                         Type decl_type = fi.DeclaringType;
4526                                         object o;
4527                                         
4528                                         if (fi is FieldBuilder)
4529                                                 o = TypeManager.GetValue ((FieldBuilder) fi);
4530                                         else
4531                                                 o = fi.GetValue (fi);
4532                                         
4533                                         if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
4534                                                 Expression enum_member = MemberLookup (
4535                                                         ec, decl_type, "value__",
4536                                                         false, loc); 
4537                                                 
4538                                                 Enum en = TypeManager.LookupEnum (decl_type);
4539                                                 
4540                                                 Constant c;
4541                                                 if (en != null)
4542                                                         c = Constantify (o, en.UnderlyingType);
4543                                                 else 
4544                                                         c = Constantify (o, enum_member.Type);
4545                                                 
4546                                                 return new EnumConstant (c, decl_type);
4547                                         }
4548                                         
4549                                         Expression exp = Constantify (o, t);
4550                                         
4551                                         return exp;
4552                                 }
4553
4554                                 if (!fe.FieldInfo.IsStatic){
4555                                         error176 (loc, fe.FieldInfo.Name);
4556                                         return null;
4557                                 }
4558                                 return member_lookup;
4559                         }
4560
4561                         if (member_lookup is EventExpr){
4562
4563                                 EventExpr ee = (EventExpr) member_lookup;
4564                                 
4565                                 //
4566                                 // If the event is local to this class, we transform ourselves into
4567                                 // a FieldExpr
4568                                 //
4569
4570                                 Expression ml = MemberLookup (
4571                                         ec, ec.TypeContainer.TypeBuilder, ee.EventInfo.Name,
4572                                         true, MemberTypes.Event, AllBindingFlags, loc);
4573
4574                                 if (ml != null) {
4575                                         MemberInfo mi = ec.TypeContainer.GetFieldFromEvent ((EventExpr) ml);
4576
4577                                         ml = ExprClassFromMemberInfo (ec, mi, loc);
4578                                         
4579                                         if (ml == null) {
4580                                                 Report.Error (-200, loc, "Internal error!!");
4581                                                 return null;
4582                                         }
4583
4584                                         return ResolveMemberAccess (ec, ml, left, loc);
4585                                 }
4586
4587                                 if (!ee.IsStatic) {
4588                                         SimpleName.Error120 (loc, ee.EventInfo.Name);
4589                                         return null;
4590                                 }
4591                                 
4592                                 return ee;
4593                         }
4594
4595                         Console.WriteLine ("Left is: " + left);
4596                         Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
4597                         Environment.Exit (0);
4598
4599                         return null;
4600                 }
4601                 
4602                 public ResolveInstanceMemberAccess (EmitContext ec, Expression member_lookup,
4603                                                     Expression left, Location loc)
4604                 {
4605                         if (member_lookup is MethodGroupExpr){
4606                                 //
4607                                 // Instance.MethodGroup
4608                                 //
4609                                 if (!mg.RemoveStaticMethods ()){
4610                                         error176 (loc, mg.Methods [0].Name);
4611                                         return null;
4612                                 }
4613                                 
4614                                 mg.InstanceExpression = left;
4615                                         
4616                                 return member_lookup;
4617                         }
4618
4619                         if (member_lookup is PropertyExpr){
4620                                 PropertyExpr pe = (PropertyExpr) member_lookup;
4621
4622                                 if (pe.IsStatic){
4623                                         error176 (loc, pe.PropertyInfo.Name);
4624                                         return null;
4625                                 }
4626                                 pe.InstanceExpression = left;
4627                                 
4628                                 return pe;
4629                         }
4630
4631                         Type left_type = left.type;
4632
4633                         if (left_type.IsValueType){
4634                         } else {
4635                                 
4636                         }
4637                 }
4638                 
4639                 public override Expression DoResolve (EmitContext ec)
4640                 {
4641                         //
4642                         // We are the sole users of ResolveWithSimpleName (ie, the only
4643                         // ones that can cope with it
4644                         //
4645                         expr = expr.ResolveWithSimpleName (ec);
4646
4647                         if (expr == null)
4648                                 return null;
4649
4650                         if (expr is SimpleName){
4651                                 SimpleName child_expr = (SimpleName) expr;
4652                                 
4653                                 expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
4654
4655                                 return expr.ResolveWithSimpleName (ec);
4656                         }
4657
4658                         //
4659                         // Handle enums here when they are in transit.
4660                         // Note that we cannot afford to hit MemberLookup in this case because
4661                         // it will fail to find any members at all (Why?)
4662                         //
4663
4664                         Type expr_type = expr.Type;
4665                         if (expr_type.IsSubclassOf (TypeManager.enum_type)) {
4666                                 
4667                                 Enum en = TypeManager.LookupEnum (expr_type);
4668                                 
4669                                 if (en != null) {
4670                                         object value = en.LookupEnumValue (ec, Identifier, loc);
4671
4672                                         if (value == null)
4673                                                 return null;
4674                                         
4675                                         Constant c = Constantify (value, en.UnderlyingType);
4676                                         return new EnumConstant (c, expr_type);
4677                                 }
4678                         }
4679
4680                         member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
4681
4682                         if (member_lookup == null)
4683                                 return null;
4684
4685                         if (expr is TypeExpr)
4686                                 return ResolveTypeMemberAccess (ec, member_lookup, expr, loc);
4687                         else
4688                                 return ResolveInstanceMemberAccess (ec, member_lookup, expr, loc);
4689                 }
4690 #endif
4691                 public override void Emit (EmitContext ec)
4692                 {
4693                         throw new Exception ("Should not happen I think");
4694                 }
4695         }
4696
4697         /// <summary>
4698         ///   Implements checked expressions
4699         /// </summary>
4700         public class CheckedExpr : Expression {
4701
4702                 public Expression Expr;
4703
4704                 public CheckedExpr (Expression e)
4705                 {
4706                         Expr = e;
4707                 }
4708
4709                 public override Expression DoResolve (EmitContext ec)
4710                 {
4711                         Expr = Expr.Resolve (ec);
4712
4713                         if (Expr == null)
4714                                 return null;
4715
4716                         eclass = Expr.eclass;
4717                         type = Expr.Type;
4718                         return this;
4719                 }
4720
4721                 public override void Emit (EmitContext ec)
4722                 {
4723                         bool last_check = ec.CheckState;
4724                         
4725                         ec.CheckState = true;
4726                         Expr.Emit (ec);
4727                         ec.CheckState = last_check;
4728                 }
4729                 
4730         }
4731
4732         /// <summary>
4733         ///   Implements the unchecked expression
4734         /// </summary>
4735         public class UnCheckedExpr : Expression {
4736
4737                 public Expression Expr;
4738
4739                 public UnCheckedExpr (Expression e)
4740                 {
4741                         Expr = e;
4742                 }
4743
4744                 public override Expression DoResolve (EmitContext ec)
4745                 {
4746                         Expr = Expr.Resolve (ec);
4747
4748                         if (Expr == null)
4749                                 return null;
4750
4751                         eclass = Expr.eclass;
4752                         type = Expr.Type;
4753                         return this;
4754                 }
4755
4756                 public override void Emit (EmitContext ec)
4757                 {
4758                         bool last_check = ec.CheckState;
4759                         
4760                         ec.CheckState = false;
4761                         Expr.Emit (ec);
4762                         ec.CheckState = last_check;
4763                 }
4764                 
4765         }
4766
4767         /// <summary>
4768         ///   An Element Access expression.
4769         ///
4770         ///   During semantic analysis these are transformed into 
4771         ///   IndexerAccess or ArrayAccess 
4772         /// </summary>
4773         public class ElementAccess : Expression {
4774                 public ArrayList  Arguments;
4775                 public Expression Expr;
4776                 public Location   loc;
4777                 
4778                 public ElementAccess (Expression e, ArrayList e_list, Location l)
4779                 {
4780                         Expr = e;
4781
4782                         loc  = l;
4783                         
4784                         if (e_list == null)
4785                                 return;
4786                         
4787                         Arguments = new ArrayList ();
4788                         foreach (Expression tmp in e_list)
4789                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
4790                         
4791                 }
4792
4793                 bool CommonResolve (EmitContext ec)
4794                 {
4795                         Expr = Expr.Resolve (ec);
4796
4797                         if (Expr == null) 
4798                                 return false;
4799
4800                         if (Arguments == null)
4801                                 return false;
4802
4803                         for (int i = Arguments.Count; i > 0;){
4804                                 --i;
4805                                 Argument a = (Argument) Arguments [i];
4806                                 
4807                                 if (!a.Resolve (ec, loc))
4808                                         return false;
4809                         }
4810
4811                         return true;
4812                 }
4813                                 
4814                 public override Expression DoResolve (EmitContext ec)
4815                 {
4816                         if (!CommonResolve (ec))
4817                                 return null;
4818
4819                         //
4820                         // We perform some simple tests, and then to "split" the emit and store
4821                         // code we create an instance of a different class, and return that.
4822                         //
4823                         // I am experimenting with this pattern.
4824                         //
4825                         if (Expr.Type.IsSubclassOf (TypeManager.array_type))
4826                                 return (new ArrayAccess (this)).Resolve (ec);
4827                         else
4828                                 return (new IndexerAccess (this)).Resolve (ec);
4829                 }
4830
4831                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
4832                 {
4833                         if (!CommonResolve (ec))
4834                                 return null;
4835
4836                         if (Expr.Type.IsSubclassOf (TypeManager.array_type))
4837                                 return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
4838                         else
4839                                 return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
4840                 }
4841                 
4842                 public override void Emit (EmitContext ec)
4843                 {
4844                         throw new Exception ("Should never be reached");
4845                 }
4846         }
4847
4848         /// <summary>
4849         ///   Implements array access 
4850         /// </summary>
4851         public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
4852                 //
4853                 // Points to our "data" repository
4854                 //
4855                 ElementAccess ea;
4856                 
4857                 public ArrayAccess (ElementAccess ea_data)
4858                 {
4859                         ea = ea_data;
4860                         eclass = ExprClass.Variable;
4861                 }
4862
4863                 public override Expression DoResolve (EmitContext ec)
4864                 {
4865                         if (ea.Expr.eclass != ExprClass.Variable) {
4866                                 report118 (ea.loc, ea.Expr, "variable");
4867                                 return null;
4868                         }
4869
4870                         Type t = ea.Expr.Type;
4871
4872                         if (t.GetArrayRank () != ea.Arguments.Count){
4873                                 Report.Error (22, ea.loc,
4874                                               "Incorrect number of indexes for array " +
4875                                               " expected: " + t.GetArrayRank () + " got: " +
4876                                               ea.Arguments.Count);
4877                                 return null;
4878                         }
4879                         type = t.GetElementType ();
4880                         eclass = ExprClass.Variable;
4881
4882                         return this;
4883                 }
4884
4885                 /// <summary>
4886                 ///    Emits the right opcode to load an object of Type `t'
4887                 ///    from an array of T
4888                 /// </summary>
4889                 static public void EmitLoadOpcode (ILGenerator ig, Type type)
4890                 {
4891                         if (type == TypeManager.byte_type)
4892                                 ig.Emit (OpCodes.Ldelem_I1);
4893                         else if (type == TypeManager.sbyte_type)
4894                                 ig.Emit (OpCodes.Ldelem_U1);
4895                         else if (type == TypeManager.short_type)
4896                                 ig.Emit (OpCodes.Ldelem_I2);
4897                         else if (type == TypeManager.ushort_type)
4898                                 ig.Emit (OpCodes.Ldelem_U2);
4899                         else if (type == TypeManager.int32_type)
4900                                 ig.Emit (OpCodes.Ldelem_I4);
4901                         else if (type == TypeManager.uint32_type)
4902                                 ig.Emit (OpCodes.Ldelem_U4);
4903                         else if (type == TypeManager.uint64_type)
4904                                 ig.Emit (OpCodes.Ldelem_I8);
4905                         else if (type == TypeManager.int64_type)
4906                                 ig.Emit (OpCodes.Ldelem_I8);
4907                         else if (type == TypeManager.float_type)
4908                                 ig.Emit (OpCodes.Ldelem_R4);
4909                         else if (type == TypeManager.double_type)
4910                                 ig.Emit (OpCodes.Ldelem_R8);
4911                         else if (type == TypeManager.intptr_type)
4912                                 ig.Emit (OpCodes.Ldelem_I);
4913                         else if (type.IsValueType)
4914                                 ig.Emit (OpCodes.Ldelema, type);
4915                         else 
4916                                 ig.Emit (OpCodes.Ldelem_Ref);
4917                 }
4918
4919                 /// <summary>
4920                 ///    Emits the right opcode to store an object of Type `t'
4921                 ///    from an array of T.  
4922                 /// </summary>
4923                 static public void EmitStoreOpcode (ILGenerator ig, Type t)
4924                 {
4925                         if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
4926                                 ig.Emit (OpCodes.Stelem_I1);
4927                         else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
4928                                 ig.Emit (OpCodes.Stelem_I2);
4929                         else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
4930                                 ig.Emit (OpCodes.Stelem_I4);
4931                         else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
4932                                 ig.Emit (OpCodes.Stelem_I8);
4933                         else if (t == TypeManager.float_type)
4934                                 ig.Emit (OpCodes.Stelem_R4);
4935                         else if (t == TypeManager.double_type)
4936                                 ig.Emit (OpCodes.Stelem_R8);
4937                         else if (t == TypeManager.intptr_type)
4938                                 ig.Emit (OpCodes.Stelem_I);
4939                         else
4940                                 ig.Emit (OpCodes.Stelem_Ref);
4941                 }
4942
4943                 MethodInfo FetchGetMethod ()
4944                 {
4945                         ModuleBuilder mb = RootContext.ModuleBuilder;
4946                         Type [] args = new Type [ea.Arguments.Count];
4947                         MethodInfo get;
4948                         
4949                         int i = 0;
4950                                 
4951                         foreach (Argument a in ea.Arguments)
4952                                 args [i++] = a.Type;
4953                         
4954                         get = mb.GetArrayMethod (
4955                                 ea.Expr.Type, "Get",
4956                                 CallingConventions.HasThis |
4957                                 CallingConventions.Standard,
4958                                 type, args);
4959                         return get;
4960                 }
4961                                 
4962
4963                 MethodInfo FetchAddressMethod ()
4964                 {
4965                         ModuleBuilder mb = RootContext.ModuleBuilder;
4966                         Type [] args = new Type [ea.Arguments.Count];
4967                         MethodInfo address;
4968                         string ptr_type_name;
4969                         Type ret_type;
4970                         int i = 0;
4971                         
4972                         ptr_type_name = type.FullName + "&";
4973                         ret_type = Type.GetType (ptr_type_name);
4974                         
4975                         //
4976                         // It is a type defined by the source code we are compiling
4977                         //
4978                         if (ret_type == null){
4979                                 ret_type = mb.GetType (ptr_type_name);
4980                         }
4981                         
4982                         foreach (Argument a in ea.Arguments)
4983                                 args [i++] = a.Type;
4984                         
4985                         address = mb.GetArrayMethod (
4986                                 ea.Expr.Type, "Address",
4987                                 CallingConventions.HasThis |
4988                                 CallingConventions.Standard,
4989                                 ret_type, args);
4990
4991                         return address;
4992                 }
4993                 
4994                 public override void Emit (EmitContext ec)
4995                 {
4996                         int rank = ea.Expr.Type.GetArrayRank ();
4997                         ILGenerator ig = ec.ig;
4998
4999                         ea.Expr.Emit (ec);
5000
5001                         foreach (Argument a in ea.Arguments)
5002                                 a.Expr.Emit (ec);
5003
5004                         if (rank == 1)
5005                                 EmitLoadOpcode (ig, type);
5006                         else {
5007                                 MethodInfo method;
5008                                 
5009                                 method = FetchGetMethod ();
5010                                 ig.Emit (OpCodes.Call, method);
5011                         }
5012                 }
5013
5014                 public void EmitAssign (EmitContext ec, Expression source)
5015                 {
5016                         int rank = ea.Expr.Type.GetArrayRank ();
5017                         ILGenerator ig = ec.ig;
5018
5019                         ea.Expr.Emit (ec);
5020
5021                         foreach (Argument a in ea.Arguments)
5022                                 a.Expr.Emit (ec);
5023
5024                         source.Emit (ec);
5025
5026                         Type t = source.Type;
5027
5028                         if (rank == 1)
5029                                 EmitStoreOpcode (ig, t);
5030                         else {
5031                                 ModuleBuilder mb = RootContext.ModuleBuilder;
5032                                 Type [] args = new Type [ea.Arguments.Count + 1];
5033                                 MethodInfo set;
5034                                 
5035                                 int i = 0;
5036                                 
5037                                 foreach (Argument a in ea.Arguments)
5038                                         args [i++] = a.Type;
5039
5040                                 args [i] = type;
5041                                 
5042                                 set = mb.GetArrayMethod (
5043                                         ea.Expr.Type, "Set",
5044                                         CallingConventions.HasThis |
5045                                         CallingConventions.Standard,
5046                                         TypeManager.void_type, args);
5047                                 
5048                                 ig.Emit (OpCodes.Call, set);
5049                         }
5050                 }
5051
5052                 public void AddressOf (EmitContext ec)
5053                 {
5054                         int rank = ea.Expr.Type.GetArrayRank ();
5055                         ILGenerator ig = ec.ig;
5056                         
5057                         ea.Expr.Emit (ec);
5058
5059                         foreach (Argument a in ea.Arguments)
5060                                 a.Expr.Emit (ec);
5061
5062                         if (rank == 1){
5063                                 ig.Emit (OpCodes.Ldelema, type);
5064                         } else {
5065                                 MethodInfo address = FetchAddressMethod ();
5066                                 ig.Emit (OpCodes.Call, address);
5067                         }
5068                 }
5069         }
5070
5071         
5072         class Indexers {
5073                 public ArrayList getters, setters;
5074                 static Hashtable map;
5075
5076                 static Indexers ()
5077                 {
5078                         map = new Hashtable ();
5079                 }
5080
5081                 Indexers (MemberInfo [] mi)
5082                 {
5083                         foreach (PropertyInfo property in mi){
5084                                 MethodInfo get, set;
5085                                 
5086                                 get = property.GetGetMethod (true);
5087                                 if (get != null){
5088                                         if (getters == null)
5089                                                 getters = new ArrayList ();
5090
5091                                         getters.Add (get);
5092                                 }
5093                                 
5094                                 set = property.GetSetMethod (true);
5095                                 if (set != null){
5096                                         if (setters == null)
5097                                                 setters = new ArrayList ();
5098                                         setters.Add (set);
5099                                 }
5100                         }
5101                 }
5102                 
5103                 static public Indexers GetIndexersForType (Type t, TypeManager tm, Location loc) 
5104                 {
5105                         Indexers ix = (Indexers) map [t];
5106                         string p_name = TypeManager.IndexerPropertyName (t);
5107                         
5108                         if (ix != null)
5109                                 return ix;
5110
5111                         MemberInfo [] mi = tm.FindMembers (
5112                                 t, MemberTypes.Property,
5113                                 BindingFlags.Public | BindingFlags.Instance,
5114                                 Type.FilterName, p_name);
5115
5116                         if (mi == null || mi.Length == 0){
5117                                 Report.Error (21, loc,
5118                                               "Type `" + TypeManager.CSharpName (t) + "' does not have " +
5119                                               "any indexers defined");
5120                                 return null;
5121                         }
5122                         
5123                         ix = new Indexers (mi);
5124                         map [t] = ix;
5125
5126                         return ix;
5127                 }
5128         }
5129
5130         /// <summary>
5131         ///   Expressions that represent an indexer call.
5132         /// </summary>
5133         public class IndexerAccess : Expression, IAssignMethod {
5134                 //
5135                 // Points to our "data" repository
5136                 //
5137                 ElementAccess ea;
5138                 MethodInfo get, set;
5139                 Indexers ilist;
5140                 ArrayList set_arguments;
5141                 
5142                 public IndexerAccess (ElementAccess ea_data)
5143                 {
5144                         ea = ea_data;
5145                         eclass = ExprClass.Value;
5146                 }
5147
5148                 public override Expression DoResolve (EmitContext ec)
5149                 {
5150                         Type indexer_type = ea.Expr.Type;
5151                         
5152                         //
5153                         // Step 1: Query for all `Item' *properties*.  Notice
5154                         // that the actual methods are pointed from here.
5155                         //
5156                         // This is a group of properties, piles of them.  
5157
5158                         if (ilist == null)
5159                                 ilist = Indexers.GetIndexersForType (
5160                                         indexer_type, RootContext.TypeManager, ea.loc);
5161
5162
5163                         //
5164                         // Step 2: find the proper match
5165                         //
5166                         if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)
5167                                 get = (MethodInfo) Invocation.OverloadResolve (
5168                                         ec, new MethodGroupExpr (ilist.getters), ea.Arguments, ea.loc);
5169
5170                         if (get == null){
5171                                 Report.Error (154, ea.loc,
5172                                               "indexer can not be used in this context, because " +
5173                                               "it lacks a `get' accessor");
5174                                 return null;
5175                         }
5176
5177                         type = get.ReturnType;
5178                         eclass = ExprClass.IndexerAccess;
5179                         return this;
5180                 }
5181
5182                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
5183                 {
5184                         Type indexer_type = ea.Expr.Type;
5185                         Type right_type = right_side.Type;
5186
5187                         if (ilist == null)
5188                                 ilist = Indexers.GetIndexersForType (
5189                                         indexer_type, RootContext.TypeManager, ea.loc);
5190
5191                         if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
5192                                 set_arguments = (ArrayList) ea.Arguments.Clone ();
5193                                 set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
5194
5195                                 set = (MethodInfo) Invocation.OverloadResolve (
5196                                         ec, new MethodGroupExpr (ilist.setters), set_arguments, ea.loc);
5197                         }
5198                         
5199                         if (set == null){
5200                                 Report.Error (200, ea.loc,
5201                                               "indexer X.this [" + TypeManager.CSharpName (right_type) +
5202                                               "] lacks a `set' accessor");
5203                                         return null;
5204                         }
5205
5206                         type = TypeManager.void_type;
5207                         eclass = ExprClass.IndexerAccess;
5208                         return this;
5209                 }
5210                 
5211                 public override void Emit (EmitContext ec)
5212                 {
5213                         Invocation.EmitCall (ec, false, ea.Expr, get, ea.Arguments);
5214                 }
5215
5216                 //
5217                 // source is ignored, because we already have a copy of it from the
5218                 // LValue resolution and we have already constructed a pre-cached
5219                 // version of the arguments (ea.set_arguments);
5220                 //
5221                 public void EmitAssign (EmitContext ec, Expression source)
5222                 {
5223                         Invocation.EmitCall (ec, false, ea.Expr, set, set_arguments);
5224                 }
5225         }
5226
5227         /// <summary>
5228         ///   The base operator for method names
5229         /// </summary>
5230         public class BaseAccess : Expression {
5231                 string member;
5232                 Location loc;
5233                 
5234                 public BaseAccess (string member, Location l)
5235                 {
5236                         this.member = member;
5237                         loc = l;
5238                 }
5239
5240                 public override Expression DoResolve (EmitContext ec)
5241                 {
5242                         Expression member_lookup;
5243                         Type current_type = ec.TypeContainer.TypeBuilder;
5244                         Type base_type = current_type.BaseType;
5245                         
5246                         member_lookup = MemberLookup (ec, base_type, member, false, loc);
5247                         if (member_lookup == null)
5248                                 return null;
5249
5250                         Expression left;
5251                         
5252                         if (ec.IsStatic)
5253                                 left = new TypeExpr (base_type);
5254                         else
5255                                 left = new This (loc).Resolve (ec);
5256                         
5257                         return MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc);
5258                 }
5259
5260                 public override void Emit (EmitContext ec)
5261                 {
5262                         throw new Exception ("Should never be called"); 
5263                 }
5264         }
5265
5266         /// <summary>
5267         ///   The base indexer operator
5268         /// </summary>
5269         public class BaseIndexerAccess : Expression {
5270                 ArrayList Arguments;
5271
5272                 public BaseIndexerAccess (ArrayList args)
5273                 {
5274                         Arguments = args;
5275                 }
5276
5277                 public override Expression DoResolve (EmitContext ec)
5278                 {
5279                         // FIXME: Implement;
5280                         throw new Exception ("Unimplemented");
5281                         // return this;
5282                 }
5283
5284                 public override void Emit (EmitContext ec)
5285                 {
5286                         throw new Exception ("Unimplemented");
5287                 }
5288         }
5289         
5290         /// <summary>
5291         ///   This class exists solely to pass the Type around and to be a dummy
5292         ///   that can be passed to the conversion functions (this is used by
5293         ///   foreach implementation to typecast the object return value from
5294         ///   get_Current into the proper type.  All code has been generated and
5295         ///   we only care about the side effect conversions to be performed
5296         /// </summary>
5297         public class EmptyExpression : Expression {
5298                 public EmptyExpression ()
5299                 {
5300                         type = TypeManager.object_type;
5301                         eclass = ExprClass.Value;
5302                 }
5303
5304                 public EmptyExpression (Type t)
5305                 {
5306                         type = t;
5307                         eclass = ExprClass.Value;
5308                 }
5309                 
5310                 public override Expression DoResolve (EmitContext ec)
5311                 {
5312                         return this;
5313                 }
5314
5315                 public override void Emit (EmitContext ec)
5316                 {
5317                         // nothing, as we only exist to not do anything.
5318                 }
5319
5320                 //
5321                 // This is just because we might want to reuse this bad boy
5322                 // instead of creating gazillions of EmptyExpressions.
5323                 // (CanConvertImplicit uses it)
5324                 //
5325                 public void SetType (Type t)
5326                 {
5327                         type = t;
5328                 }
5329         }
5330
5331         public class UserCast : Expression {
5332                 MethodBase method;
5333                 Expression source;
5334                 
5335                 public UserCast (MethodInfo method, Expression source)
5336                 {
5337                         this.method = method;
5338                         this.source = source;
5339                         type = method.ReturnType;
5340                         eclass = ExprClass.Value;
5341                 }
5342
5343                 public override Expression DoResolve (EmitContext ec)
5344                 {
5345                         //
5346                         // We are born fully resolved
5347                         //
5348                         return this;
5349                 }
5350
5351                 public override void Emit (EmitContext ec)
5352                 {
5353                         ILGenerator ig = ec.ig;
5354
5355                         source.Emit (ec);
5356                         
5357                         if (method is MethodInfo)
5358                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
5359                         else
5360                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5361
5362                 }
5363
5364         }
5365
5366         // <summary>
5367         //   This class is used to "construct" the type during a typecast
5368         //   operation.  Since the Type.GetType class in .NET can parse
5369         //   the type specification, we just use this to construct the type
5370         //   one bit at a time.
5371         // </summary>
5372         public class ComposedCast : Expression {
5373                 Expression left;
5374                 string dim;
5375                 Location loc;
5376                 
5377                 public ComposedCast (Expression left, string dim, Location l)
5378                 {
5379                         this.left = left;
5380                         this.dim = dim;
5381                         loc = l;
5382                 }
5383
5384                 public override Expression DoResolve (EmitContext ec)
5385                 {
5386                         left = left.Resolve (ec);
5387                         if (left == null)
5388                                 return null;
5389
5390                         if (left.eclass != ExprClass.Type){
5391                                 report118 (loc, left, "type");
5392                                 return null;
5393                         }
5394                         
5395                         type = RootContext.LookupType (
5396                                 ec.TypeContainer, left.Type.FullName + dim, false, loc);
5397                         if (type == null)
5398                                 return null;
5399
5400                         eclass = ExprClass.Type;
5401                         return this;
5402                 }
5403
5404                 public override void Emit (EmitContext ec)
5405                 {
5406                         throw new Exception ("This should never be called");
5407                 }
5408         }
5409 }