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