2004-05-27 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / gmcs / 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, 2002, 2003 Ximian, Inc.
8 // (C) 2003, 2004 Novell, Inc.
9 //
10 #define USE_OLD
11
12 namespace Mono.CSharp {
13         using System;
14         using System.Collections;
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                 public StaticCallExpr (MethodInfo m, ArrayList a, Location l)
29                 {
30                         mi = m;
31                         args = a;
32
33                         type = m.ReturnType;
34                         eclass = ExprClass.Value;
35                         loc = l;
36                 }
37
38                 public override Expression DoResolve (EmitContext ec)
39                 {
40                         //
41                         // We are born fully resolved
42                         //
43                         return this;
44                 }
45
46                 public override void Emit (EmitContext ec)
47                 {
48                         if (args != null) 
49                                 Invocation.EmitArguments (ec, mi, args);
50
51                         ec.ig.Emit (OpCodes.Call, mi);
52                         return;
53                 }
54                 
55                 static public Expression MakeSimpleCall (EmitContext ec, MethodGroupExpr mg,
56                                                          Expression e, Location loc)
57                 {
58                         ArrayList args;
59                         MethodBase method;
60                         
61                         args = new ArrayList (1);
62                         Argument a = new Argument (e, Argument.AType.Expression);
63
64                         // We need to resolve the arguments before sending them in !
65                         if (!a.Resolve (ec, loc))
66                                 return null;
67
68                         args.Add (a);
69                         method = Invocation.OverloadResolve (
70                                 ec, (MethodGroupExpr) mg, args, false, loc);
71
72                         if (method == null)
73                                 return null;
74
75                         return new StaticCallExpr ((MethodInfo) method, args, loc);
76                 }
77
78                 public override void EmitStatement (EmitContext ec)
79                 {
80                         Emit (ec);
81                         if (TypeManager.TypeToCoreType (type) != TypeManager.void_type)
82                                 ec.ig.Emit (OpCodes.Pop);
83                 }
84         }
85
86         public class ParenthesizedExpression : Expression
87         {
88                 public Expression Expr;
89
90                 public ParenthesizedExpression (Expression expr, Location loc)
91                 {
92                         this.Expr = expr;
93                         this.loc = loc;
94                 }
95
96                 public override Expression DoResolve (EmitContext ec)
97                 {
98                         Expr = Expr.Resolve (ec);
99                         return Expr;
100                 }
101
102                 public override void Emit (EmitContext ec)
103                 {
104                         throw new Exception ("Should not happen");
105                 }
106         }
107         
108         /// <summary>
109         ///   Unary expressions.  
110         /// </summary>
111         ///
112         /// <remarks>
113         ///   Unary implements unary expressions.   It derives from
114         ///   ExpressionStatement becuase the pre/post increment/decrement
115         ///   operators can be used in a statement context.
116         /// </remarks>
117         public class Unary : Expression {
118                 public enum Operator : byte {
119                         UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
120                         Indirection, AddressOf,  TOP
121                 }
122
123                 public Operator Oper;
124                 public Expression Expr;
125                 
126                 public Unary (Operator op, Expression expr, Location loc)
127                 {
128                         this.Oper = op;
129                         this.Expr = expr;
130                         this.loc = loc;
131                 }
132
133                 /// <summary>
134                 ///   Returns a stringified representation of the Operator
135                 /// </summary>
136                 static public string OperName (Operator oper)
137                 {
138                         switch (oper){
139                         case Operator.UnaryPlus:
140                                 return "+";
141                         case Operator.UnaryNegation:
142                                 return "-";
143                         case Operator.LogicalNot:
144                                 return "!";
145                         case Operator.OnesComplement:
146                                 return "~";
147                         case Operator.AddressOf:
148                                 return "&";
149                         case Operator.Indirection:
150                                 return "*";
151                         }
152
153                         return oper.ToString ();
154                 }
155
156                 public static readonly string [] oper_names;
157
158                 static Unary ()
159                 {
160                         oper_names = new string [(int)Operator.TOP];
161
162                         oper_names [(int) Operator.UnaryPlus] = "op_UnaryPlus";
163                         oper_names [(int) Operator.UnaryNegation] = "op_UnaryNegation";
164                         oper_names [(int) Operator.LogicalNot] = "op_LogicalNot";
165                         oper_names [(int) Operator.OnesComplement] = "op_OnesComplement";
166                         oper_names [(int) Operator.Indirection] = "op_Indirection";
167                         oper_names [(int) Operator.AddressOf] = "op_AddressOf";
168                 }
169
170                 void Error23 (Type t)
171                 {
172                         Error (
173                                 23, "Operator " + OperName (Oper) +
174                                 " cannot be applied to operand of type `" +
175                                 TypeManager.CSharpName (t) + "'");
176                 }
177
178                 /// <remarks>
179                 ///   The result has been already resolved:
180                 ///
181                 ///   FIXME: a minus constant -128 sbyte cant be turned into a
182                 ///   constant byte.
183                 /// </remarks>
184                 static Expression TryReduceNegative (Constant expr)
185                 {
186                         Expression e = null;
187
188                         if (expr is IntConstant)
189                                 e = new IntConstant (-((IntConstant) expr).Value);
190                         else if (expr is UIntConstant){
191                                 uint value = ((UIntConstant) expr).Value;
192
193                                 if (value < 2147483649)
194                                         return new IntConstant (-(int)value);
195                                 else
196                                         e = new LongConstant (-value);
197                         }
198                         else if (expr is LongConstant)
199                                 e = new LongConstant (-((LongConstant) expr).Value);
200                         else if (expr is ULongConstant){
201                                 ulong value = ((ULongConstant) expr).Value;
202
203                                 if (value < 9223372036854775809)
204                                         return new LongConstant(-(long)value);
205                         }
206                         else if (expr is FloatConstant)
207                                 e = new FloatConstant (-((FloatConstant) expr).Value);
208                         else if (expr is DoubleConstant)
209                                 e = new DoubleConstant (-((DoubleConstant) expr).Value);
210                         else if (expr is DecimalConstant)
211                                 e = new DecimalConstant (-((DecimalConstant) expr).Value);
212                         else if (expr is ShortConstant)
213                                 e = new IntConstant (-((ShortConstant) expr).Value);
214                         else if (expr is UShortConstant)
215                                 e = new IntConstant (-((UShortConstant) expr).Value);
216                         return e;
217                 }
218
219                 // <summary>
220                 //   This routine will attempt to simplify the unary expression when the
221                 //   argument is a constant.  The result is returned in `result' and the
222                 //   function returns true or false depending on whether a reduction
223                 //   was performed or not
224                 // </summary>
225                 bool Reduce (EmitContext ec, Constant e, out Expression result)
226                 {
227                         Type expr_type = e.Type;
228                         
229                         switch (Oper){
230                         case Operator.UnaryPlus:
231                                 result = e;
232                                 return true;
233                                 
234                         case Operator.UnaryNegation:
235                                 result = TryReduceNegative (e);
236                                 return true;
237                                 
238                         case Operator.LogicalNot:
239                                 if (expr_type != TypeManager.bool_type) {
240                                         result = null;
241                                         Error23 (expr_type);
242                                         return false;
243                                 }
244                                 
245                                 BoolConstant b = (BoolConstant) e;
246                                 result = new BoolConstant (!(b.Value));
247                                 return true;
248                                 
249                         case Operator.OnesComplement:
250                                 if (!((expr_type == TypeManager.int32_type) ||
251                                       (expr_type == TypeManager.uint32_type) ||
252                                       (expr_type == TypeManager.int64_type) ||
253                                       (expr_type == TypeManager.uint64_type) ||
254                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
255
256                                         result = null;
257                                         if (Convert.ImplicitConversionExists (ec, e, TypeManager.int32_type)){
258                                                 result = new Cast (new TypeExpression (TypeManager.int32_type, loc), e, loc);
259                                                 result = result.Resolve (ec);
260                                         } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint32_type)){
261                                                 result = new Cast (new TypeExpression (TypeManager.uint32_type, loc), e, loc);
262                                                 result = result.Resolve (ec);
263                                         } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.int64_type)){
264                                                 result = new Cast (new TypeExpression (TypeManager.int64_type, loc), e, loc);
265                                                 result = result.Resolve (ec);
266                                         } else if (Convert.ImplicitConversionExists (ec, e, TypeManager.uint64_type)){
267                                                 result = new Cast (new TypeExpression (TypeManager.uint64_type, loc), e, loc);
268                                                 result = result.Resolve (ec);
269                                         }
270
271                                         if (result == null || !(result is Constant)){
272                                                 result = null;
273                                                 Error23 (expr_type);
274                                                 return false;
275                                         }
276
277                                         expr_type = result.Type;
278                                         e = (Constant) result;
279                                 }
280
281                                 if (e is EnumConstant){
282                                         EnumConstant enum_constant = (EnumConstant) e;
283                                         Expression reduced;
284                                         
285                                         if (Reduce (ec, enum_constant.Child, out reduced)){
286                                                 result = new EnumConstant ((Constant) reduced, enum_constant.Type);
287                                                 return true;
288                                         } else {
289                                                 result = null;
290                                                 return false;
291                                         }
292                                 }
293
294                                 if (expr_type == TypeManager.int32_type){
295                                         result = new IntConstant (~ ((IntConstant) e).Value);
296                                 } else if (expr_type == TypeManager.uint32_type){
297                                         result = new UIntConstant (~ ((UIntConstant) e).Value);
298                                 } else if (expr_type == TypeManager.int64_type){
299                                         result = new LongConstant (~ ((LongConstant) e).Value);
300                                 } else if (expr_type == TypeManager.uint64_type){
301                                         result = new ULongConstant (~ ((ULongConstant) e).Value);
302                                 } else {
303                                         result = null;
304                                         Error23 (expr_type);
305                                         return false;
306                                 }
307                                 return true;
308
309                         case Operator.AddressOf:
310                                 result = this;
311                                 return false;
312
313                         case Operator.Indirection:
314                                 result = this;
315                                 return false;
316                         }
317                         throw new Exception ("Can not constant fold: " + Oper.ToString());
318                 }
319
320                 Expression ResolveOperator (EmitContext ec)
321                 {
322                         Type expr_type = Expr.Type;
323
324                         //
325                         // Step 1: Perform Operator Overload location
326                         //
327                         Expression mg;
328                         string op_name;
329                         
330                         op_name = oper_names [(int) Oper];
331
332                         mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
333                         
334                         if (mg != null) {
335                                 Expression e = StaticCallExpr.MakeSimpleCall (
336                                         ec, (MethodGroupExpr) mg, Expr, loc);
337
338                                 if (e == null){
339                                         Error23 (expr_type);
340                                         return null;
341                                 }
342                                 
343                                 return e;
344                         }
345
346                         // Only perform numeric promotions on:
347                         // +, - 
348
349                         if (expr_type == null)
350                                 return null;
351                         
352                         //
353                         // Step 2: Default operations on CLI native types.
354                         //
355
356                         // Attempt to use a constant folding operation.
357                         if (Expr is Constant){
358                                 Expression result;
359                                 
360                                 if (Reduce (ec, (Constant) Expr, out result))
361                                         return result;
362                         }
363
364                         switch (Oper){
365                         case Operator.LogicalNot:
366                                 if (expr_type != TypeManager.bool_type) {
367                                         Expr = ResolveBoolean (ec, Expr, loc);
368                                         if (Expr == null){
369                                                 Error23 (expr_type);
370                                                 return null;
371                                         }
372                                 }
373                                 
374                                 type = TypeManager.bool_type;
375                                 return this;
376
377                         case Operator.OnesComplement:
378                                 if (!((expr_type == TypeManager.int32_type) ||
379                                       (expr_type == TypeManager.uint32_type) ||
380                                       (expr_type == TypeManager.int64_type) ||
381                                       (expr_type == TypeManager.uint64_type) ||
382                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
383                                         Expression e;
384
385                                         e = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
386                                         if (e != null){
387                                                 type = TypeManager.int32_type;
388                                                 return this;
389                                         }
390                                         e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint32_type, loc);
391                                         if (e != null){
392                                                 type = TypeManager.uint32_type;
393                                                 return this;
394                                         }
395                                         e = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
396                                         if (e != null){
397                                                 type = TypeManager.int64_type;
398                                                 return this;
399                                         }
400                                         e = Convert.ImplicitConversion (ec, Expr, TypeManager.uint64_type, loc);
401                                         if (e != null){
402                                                 type = TypeManager.uint64_type;
403                                                 return this;
404                                         }
405                                         Error23 (expr_type);
406                                         return null;
407                                 }
408                                 type = expr_type;
409                                 return this;
410
411                         case Operator.AddressOf:
412                                 if (Expr.eclass != ExprClass.Variable){
413                                         Error (211, "Cannot take the address of non-variables");
414                                         return null;
415                                 }
416                                 
417                                 if (!ec.InUnsafe) {
418                                         UnsafeError (loc); 
419                                         return null;
420                                 }
421                                 
422                                 if (!TypeManager.VerifyUnManaged (Expr.Type, loc)){
423                                         return null;
424                                 }
425
426                                 IVariable variable = Expr as IVariable;
427                                 if (!ec.InFixedInitializer && ((variable == null) || !variable.VerifyFixed (false))) {
428                                         Error (212, "You can only take the address of an unfixed expression inside " +
429                                                "of a fixed statement initializer");
430                                         return null;
431                                 }
432
433                                 if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
434                                         Error (213, "You can not fix an already fixed expression");
435                                         return null;
436                                 }
437
438                                 // According to the specs, a variable is considered definitely assigned if you take
439                                 // its address.
440                                 if ((variable != null) && (variable.VariableInfo != null))
441                                         variable.VariableInfo.SetAssigned (ec);
442
443                                 type = TypeManager.GetPointerType (Expr.Type);
444                                 return this;
445
446                         case Operator.Indirection:
447                                 if (!ec.InUnsafe){
448                                         UnsafeError (loc);
449                                         return null;
450                                 }
451                                 
452                                 if (!expr_type.IsPointer){
453                                         Error (193, "The * or -> operator can only be applied to pointers");
454                                         return null;
455                                 }
456                                 
457                                 //
458                                 // We create an Indirection expression, because
459                                 // it can implement the IMemoryLocation.
460                                 // 
461                                 return new Indirection (Expr, loc);
462                         
463                         case Operator.UnaryPlus:
464                                 //
465                                 // A plus in front of something is just a no-op, so return the child.
466                                 //
467                                 return Expr;
468
469                         case Operator.UnaryNegation:
470                                 //
471                                 // Deals with -literals
472                                 // int     operator- (int x)
473                                 // long    operator- (long x)
474                                 // float   operator- (float f)
475                                 // double  operator- (double d)
476                                 // decimal operator- (decimal d)
477                                 //
478                                 Expression expr = null;
479
480                                 //
481                                 // transform - - expr into expr
482                                 //
483                                 if (Expr is Unary){
484                                         Unary unary = (Unary) Expr;
485                                         
486                                         if (unary.Oper == Operator.UnaryNegation)
487                                                 return unary.Expr;
488                                 }
489
490                                 //
491                                 // perform numeric promotions to int,
492                                 // long, double.
493                                 //
494                                 //
495                                 // The following is inneficient, because we call
496                                 // ImplicitConversion too many times.
497                                 //
498                                 // It is also not clear if we should convert to Float
499                                 // or Double initially.
500                                 //
501                                 if (expr_type == TypeManager.uint32_type){
502                                         //
503                                         // FIXME: handle exception to this rule that
504                                         // permits the int value -2147483648 (-2^31) to
505                                         // bt wrote as a decimal interger literal
506                                         //
507                                         type = TypeManager.int64_type;
508                                         Expr = Convert.ImplicitConversion (ec, Expr, type, loc);
509                                         return this;
510                                 }
511
512                                 if (expr_type == TypeManager.uint64_type){
513                                         //
514                                         // FIXME: Handle exception of `long value'
515                                         // -92233720368547758087 (-2^63) to be wrote as
516                                         // decimal integer literal.
517                                         //
518                                         Error23 (expr_type);
519                                         return null;
520                                 }
521
522                                 if (expr_type == TypeManager.float_type){
523                                         type = expr_type;
524                                         return this;
525                                 }
526                                 
527                                 expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int32_type, loc);
528                                 if (expr != null){
529                                         Expr = expr;
530                                         type = expr.Type;
531                                         return this;
532                                 } 
533
534                                 expr = Convert.ImplicitConversion (ec, Expr, TypeManager.int64_type, loc);
535                                 if (expr != null){
536                                         Expr = expr;
537                                         type = expr.Type;
538                                         return this;
539                                 }
540
541                                 expr = Convert.ImplicitConversion (ec, Expr, TypeManager.double_type, loc);
542                                 if (expr != null){
543                                         Expr = expr;
544                                         type = expr.Type;
545                                         return this;
546                                 }
547                                 
548                                 Error23 (expr_type);
549                                 return null;
550                         }
551
552                         Error (187, "No such operator '" + OperName (Oper) + "' defined for type '" +
553                                TypeManager.CSharpName (expr_type) + "'");
554                         return null;
555                 }
556
557                 public override Expression DoResolve (EmitContext ec)
558                 {
559                         if (Oper == Operator.AddressOf)
560                                 Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
561                         else
562                                 Expr = Expr.Resolve (ec);
563                         
564                         if (Expr == null)
565                                 return null;
566
567                         eclass = ExprClass.Value;
568                         return ResolveOperator (ec);
569                 }
570
571                 public override Expression DoResolveLValue (EmitContext ec, Expression right)
572                 {
573                         if (Oper == Operator.Indirection)
574                                 return base.DoResolveLValue (ec, right);
575
576                         Error (131, "The left-hand side of an assignment must be a " +
577                                "variable, property or indexer");
578                         return null;
579                 }
580
581                 public override void Emit (EmitContext ec)
582                 {
583                         ILGenerator ig = ec.ig;
584                         
585                         switch (Oper) {
586                         case Operator.UnaryPlus:
587                                 throw new Exception ("This should be caught by Resolve");
588                                 
589                         case Operator.UnaryNegation:
590                                 if (ec.CheckState) {
591                                         ig.Emit (OpCodes.Ldc_I4_0);
592                                         if (type == TypeManager.int64_type)
593                                                 ig.Emit (OpCodes.Conv_U8);
594                                         Expr.Emit (ec);
595                                         ig.Emit (OpCodes.Sub_Ovf);
596                                 } else {
597                                 Expr.Emit (ec);
598                                 ig.Emit (OpCodes.Neg);
599                                 }
600                                 
601                                 break;
602                                 
603                         case Operator.LogicalNot:
604                                 Expr.Emit (ec);
605                                 ig.Emit (OpCodes.Ldc_I4_0);
606                                 ig.Emit (OpCodes.Ceq);
607                                 break;
608                                 
609                         case Operator.OnesComplement:
610                                 Expr.Emit (ec);
611                                 ig.Emit (OpCodes.Not);
612                                 break;
613                                 
614                         case Operator.AddressOf:
615                                 ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore);
616                                 break;
617                                 
618                         default:
619                                 throw new Exception ("This should not happen: Operator = "
620                                                      + Oper.ToString ());
621                         }
622                 }
623
624                 public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
625                 {
626                         if (Oper == Operator.LogicalNot)
627                                 Expr.EmitBranchable (ec, target, !onTrue);
628                         else
629                                 base.EmitBranchable (ec, target, onTrue);
630                 }
631
632                 public override string ToString ()
633                 {
634                         return "Unary (" + Oper + ", " + Expr + ")";
635                 }
636                 
637         }
638
639         //
640         // Unary operators are turned into Indirection expressions
641         // after semantic analysis (this is so we can take the address
642         // of an indirection).
643         //
644         public class Indirection : Expression, IMemoryLocation, IAssignMethod {
645                 Expression expr;
646                 LocalTemporary temporary;
647                 bool have_temporary;
648                 
649                 public Indirection (Expression expr, Location l)
650                 {
651                         this.expr = expr;
652                         this.type = TypeManager.GetElementType (expr.Type);
653                         eclass = ExprClass.Variable;
654                         loc = l;
655                 }
656
657                 void LoadExprValue (EmitContext ec)
658                 {
659                 }
660                 
661                 public override void Emit (EmitContext ec)
662                 {
663                         ILGenerator ig = ec.ig;
664
665                         if (temporary != null){
666                                 if (have_temporary) {
667                                         temporary.Emit (ec);
668                                 } else {
669                                 expr.Emit (ec);
670                                 ec.ig.Emit (OpCodes.Dup);
671                                 temporary.Store (ec);
672                                 have_temporary = true;
673                                 }
674                         } else
675                                 expr.Emit (ec);
676                         
677                         LoadFromPtr (ig, Type);
678                 }
679
680                 public void EmitAssign (EmitContext ec, Expression source)
681                 {
682                         if (temporary != null){
683                                 if (have_temporary)
684                                         temporary.Emit (ec);
685                                 else {
686                                         expr.Emit (ec);
687                                         ec.ig.Emit (OpCodes.Dup);
688                                         temporary.Store (ec);
689                                         have_temporary = true;
690                                 }
691                         } else 
692                                 expr.Emit (ec);
693
694                         source.Emit (ec);
695                         StoreFromPtr (ec.ig, type);
696                 }
697                 
698                 public void AddressOf (EmitContext ec, AddressOp Mode)
699                 {
700                         if (temporary != null){
701                                 if (have_temporary){
702                                         temporary.Emit (ec);
703                                         return;
704                                 }
705                                 expr.Emit (ec);
706                                 ec.ig.Emit (OpCodes.Dup);
707                                 temporary.Store (ec);
708                                 have_temporary = true;
709                         } else
710                                 expr.Emit (ec);
711                 }
712
713                 public override Expression DoResolve (EmitContext ec)
714                 {
715                         //
716                         // Born fully resolved
717                         //
718                         return this;
719                 }
720
721                 public new void CacheTemporaries (EmitContext ec)
722                 {
723                         temporary = new LocalTemporary (ec, expr.Type);
724                 }
725
726                 public override string ToString ()
727                 {
728                         return "*(" + expr + ")";
729                 }
730         }
731         
732         /// <summary>
733         ///   Unary Mutator expressions (pre and post ++ and --)
734         /// </summary>
735         ///
736         /// <remarks>
737         ///   UnaryMutator implements ++ and -- expressions.   It derives from
738         ///   ExpressionStatement becuase the pre/post increment/decrement
739         ///   operators can be used in a statement context.
740         ///
741         /// FIXME: Idea, we could split this up in two classes, one simpler
742         /// for the common case, and one with the extra fields for more complex
743         /// classes (indexers require temporary access;  overloaded require method)
744         ///
745         /// </remarks>
746         public class UnaryMutator : ExpressionStatement {
747                 [Flags]
748                 public enum Mode : byte {
749                         IsIncrement    = 0,
750                         IsDecrement    = 1,
751                         IsPre          = 0,
752                         IsPost         = 2,
753                         
754                         PreIncrement   = 0,
755                         PreDecrement   = IsDecrement,
756                         PostIncrement  = IsPost,
757                         PostDecrement  = IsPost | IsDecrement
758                 }
759                 
760                 Mode mode;
761                 Expression expr;
762                 LocalTemporary temp_storage;
763
764                 //
765                 // This is expensive for the simplest case.
766                 //
767                 Expression method;
768                         
769                 public UnaryMutator (Mode m, Expression e, Location l)
770                 {
771                         mode = m;
772                         loc = l;
773                         expr = e;
774                 }
775
776                 static string OperName (Mode mode)
777                 {
778                         return (mode == Mode.PreIncrement || mode == Mode.PostIncrement) ?
779                                 "++" : "--";
780                 }
781                 
782                 void Error23 (Type t)
783                 {
784                         Error (
785                                 23, "Operator " + OperName (mode) + 
786                                 " cannot be applied to operand of type `" +
787                                 TypeManager.CSharpName (t) + "'");
788                 }
789
790                 /// <summary>
791                 ///   Returns whether an object of type `t' can be incremented
792                 ///   or decremented with add/sub (ie, basically whether we can
793                 ///   use pre-post incr-decr operations on it, but it is not a
794                 ///   System.Decimal, which we require operator overloading to catch)
795                 /// </summary>
796                 static bool IsIncrementableNumber (Type t)
797                 {
798                         return (t == TypeManager.sbyte_type) ||
799                                 (t == TypeManager.byte_type) ||
800                                 (t == TypeManager.short_type) ||
801                                 (t == TypeManager.ushort_type) ||
802                                 (t == TypeManager.int32_type) ||
803                                 (t == TypeManager.uint32_type) ||
804                                 (t == TypeManager.int64_type) ||
805                                 (t == TypeManager.uint64_type) ||
806                                 (t == TypeManager.char_type) ||
807                                 (t.IsSubclassOf (TypeManager.enum_type)) ||
808                                 (t == TypeManager.float_type) ||
809                                 (t == TypeManager.double_type) ||
810                                 (t.IsPointer && t != TypeManager.void_ptr_type);
811                 }
812
813                 Expression ResolveOperator (EmitContext ec)
814                 {
815                         Type expr_type = expr.Type;
816
817                         //
818                         // Step 1: Perform Operator Overload location
819                         //
820                         Expression mg;
821                         string op_name;
822                         
823                         if (mode == Mode.PreIncrement || mode == Mode.PostIncrement)
824                                 op_name = "op_Increment";
825                         else 
826                                 op_name = "op_Decrement";
827
828                         mg = MemberLookup (ec, expr_type, op_name, MemberTypes.Method, AllBindingFlags, loc);
829
830                         if (mg == null && expr_type.BaseType != null)
831                                 mg = MemberLookup (ec, expr_type.BaseType, op_name,
832                                                    MemberTypes.Method, AllBindingFlags, loc);
833                         
834                         if (mg != null) {
835                                 method = StaticCallExpr.MakeSimpleCall (
836                                         ec, (MethodGroupExpr) mg, expr, loc);
837
838                                 type = method.Type;
839                                 return this;
840                         }
841
842                         //
843                         // The operand of the prefix/postfix increment decrement operators
844                         // should be an expression that is classified as a variable,
845                         // a property access or an indexer access
846                         //
847                         type = expr_type;
848                         if (expr.eclass == ExprClass.Variable){
849                                 LocalVariableReference var = expr as LocalVariableReference;
850                                 if ((var != null) && var.IsReadOnly)
851                                         Error (1604, "cannot assign to `" + var.Name + "' because it is readonly");
852                                 if (IsIncrementableNumber (expr_type) ||
853                                     expr_type == TypeManager.decimal_type){
854                                         return this;
855                                 }
856                         } else if (expr.eclass == ExprClass.IndexerAccess){
857                                 IndexerAccess ia = (IndexerAccess) expr;
858                                 
859                                 temp_storage = new LocalTemporary (ec, expr.Type);
860                                 
861                                 expr = ia.ResolveLValue (ec, temp_storage);
862                                 if (expr == null)
863                                         return null;
864
865                                 return this;
866                         } else if (expr.eclass == ExprClass.PropertyAccess){
867                                 PropertyExpr pe = (PropertyExpr) expr;
868
869                                 if (pe.VerifyAssignable ())
870                                         return this;
871
872                                 return null;
873                         } else {
874                                 expr.Error_UnexpectedKind ("variable, indexer or property access");
875                                 return null;
876                         }
877
878                         Error (187, "No such operator '" + OperName (mode) + "' defined for type '" +
879                                TypeManager.CSharpName (expr_type) + "'");
880                         return null;
881                 }
882
883                 public override Expression DoResolve (EmitContext ec)
884                 {
885                         expr = expr.Resolve (ec);
886                         
887                         if (expr == null)
888                                 return null;
889
890                         eclass = ExprClass.Value;
891                         return ResolveOperator (ec);
892                 }
893
894                 static int PtrTypeSize (Type t)
895                 {
896                         return GetTypeSize (TypeManager.GetElementType (t));
897                 }
898
899                 //
900                 // Loads the proper "1" into the stack based on the type, then it emits the
901                 // opcode for the operation requested
902                 //
903                 void LoadOneAndEmitOp (EmitContext ec, Type t)
904                 {
905                         //
906                         // Measure if getting the typecode and using that is more/less efficient
907                         // that comparing types.  t.GetTypeCode() is an internal call.
908                         //
909                         ILGenerator ig = ec.ig;
910                                                      
911                         if (t == TypeManager.uint64_type || t == TypeManager.int64_type)
912                                 LongConstant.EmitLong (ig, 1);
913                         else if (t == TypeManager.double_type)
914                                 ig.Emit (OpCodes.Ldc_R8, 1.0);
915                         else if (t == TypeManager.float_type)
916                                 ig.Emit (OpCodes.Ldc_R4, 1.0F);
917                         else if (t.IsPointer){
918                                 int n = PtrTypeSize (t);
919                                 
920                                 if (n == 0)
921                                         ig.Emit (OpCodes.Sizeof, t);
922                                 else
923                                         IntConstant.EmitInt (ig, n);
924                         } else 
925                                 ig.Emit (OpCodes.Ldc_I4_1);
926
927                         //
928                         // Now emit the operation
929                         //
930                         if (ec.CheckState){
931                                 if (t == TypeManager.int32_type ||
932                                     t == TypeManager.int64_type){
933                                         if ((mode & Mode.IsDecrement) != 0)
934                                                 ig.Emit (OpCodes.Sub_Ovf);
935                                         else
936                                                 ig.Emit (OpCodes.Add_Ovf);
937                                 } else if (t == TypeManager.uint32_type ||
938                                            t == TypeManager.uint64_type){
939                                         if ((mode & Mode.IsDecrement) != 0)
940                                                 ig.Emit (OpCodes.Sub_Ovf_Un);
941                                         else
942                                                 ig.Emit (OpCodes.Add_Ovf_Un);
943                                 } else {
944                                         if ((mode & Mode.IsDecrement) != 0)
945                                                 ig.Emit (OpCodes.Sub_Ovf);
946                                         else
947                                                 ig.Emit (OpCodes.Add_Ovf);
948                                 }
949                         } else {
950                                 if ((mode & Mode.IsDecrement) != 0)
951                                         ig.Emit (OpCodes.Sub);
952                                 else
953                                         ig.Emit (OpCodes.Add);
954                         }
955
956                         if (t == TypeManager.sbyte_type){
957                                 if (ec.CheckState)
958                                         ig.Emit (OpCodes.Conv_Ovf_I1);
959                                 else
960                                         ig.Emit (OpCodes.Conv_I1);
961                         } else if (t == TypeManager.byte_type){
962                                 if (ec.CheckState)
963                                         ig.Emit (OpCodes.Conv_Ovf_U1);
964                                 else
965                                         ig.Emit (OpCodes.Conv_U1);
966                         } else if (t == TypeManager.short_type){
967                                 if (ec.CheckState)
968                                         ig.Emit (OpCodes.Conv_Ovf_I2);
969                                 else
970                                         ig.Emit (OpCodes.Conv_I2);
971                         } else if (t == TypeManager.ushort_type || t == TypeManager.char_type){
972                                 if (ec.CheckState)
973                                         ig.Emit (OpCodes.Conv_Ovf_U2);
974                                 else
975                                         ig.Emit (OpCodes.Conv_U2);
976                         }
977                         
978                 }
979
980                 static EmptyExpression empty_expr;
981                 
982                 void EmitCode (EmitContext ec, bool is_expr)
983                 {
984                         ILGenerator ig = ec.ig;
985                         IAssignMethod ia = (IAssignMethod) expr;
986                         Type expr_type = expr.Type;
987
988                         ia.CacheTemporaries (ec);
989
990                         //
991                         // NOTE: We should probably handle three cases:
992                         //
993                         //     * method invocation required.
994                         //     * direct stack manipulation possible
995                         //     * the object requires an "instance" field
996                         //
997                         if (temp_storage == null){
998                                 //
999                                 // Temporary improvement: if we are dealing with something that does
1000                                 // not require complicated instance setup, avoid using a temporary
1001                                 //
1002                                 // For now: only localvariables when not remapped
1003                                 //
1004
1005                                 if (method == null &&
1006                                     ((expr is LocalVariableReference) ||(expr is FieldExpr && ((FieldExpr) expr).FieldInfo.IsStatic))){
1007                                         if (empty_expr == null)
1008                                                 empty_expr = new EmptyExpression ();
1009                                         
1010                                         switch (mode){
1011                                         case Mode.PreIncrement:
1012                                         case Mode.PreDecrement:
1013                                                 expr.Emit (ec);
1014                                         
1015                                                 LoadOneAndEmitOp (ec, expr_type);
1016                                                 if (is_expr)
1017                                                         ig.Emit (OpCodes.Dup);
1018                                                 ia.EmitAssign (ec, empty_expr);
1019                                                 break;
1020                                                 
1021                                         case Mode.PostIncrement:
1022                                         case Mode.PostDecrement:
1023                                                 expr.Emit (ec);
1024                                                 if (is_expr)
1025                                                         ig.Emit (OpCodes.Dup);
1026                                                 
1027                                                 LoadOneAndEmitOp (ec, expr_type);
1028                                                 ia.EmitAssign (ec, empty_expr);
1029                                                 break;
1030                                         }
1031                                         return;
1032                                 }
1033                                 temp_storage = new LocalTemporary (ec, expr_type);
1034                         }
1035                         
1036                         switch (mode){
1037                         case Mode.PreIncrement:
1038                         case Mode.PreDecrement:
1039                                 if (method == null){
1040                                         expr.Emit (ec);
1041                                         
1042                                         LoadOneAndEmitOp (ec, expr_type);
1043                                 } else 
1044                                         method.Emit (ec);
1045                                 
1046                                 temp_storage.Store (ec);
1047                                 ia.EmitAssign (ec, temp_storage);
1048                                 if (is_expr)
1049                                         temp_storage.Emit (ec);
1050                                 break;
1051                                 
1052                         case Mode.PostIncrement:
1053                         case Mode.PostDecrement:
1054                                 if (is_expr)
1055                                         expr.Emit (ec);
1056                                 
1057                                 if (method == null){
1058                                         if (!is_expr)
1059                                                 expr.Emit (ec);
1060                                         else
1061                                                 ig.Emit (OpCodes.Dup);
1062                                         
1063                                         LoadOneAndEmitOp (ec, expr_type);
1064                                 } else {
1065                                         method.Emit (ec);
1066                                 }
1067                                 
1068                                 temp_storage.Store (ec);
1069                                 ia.EmitAssign (ec, temp_storage);
1070                                 break;
1071                         }
1072
1073                         temp_storage.Release (ec);
1074                 }
1075
1076                 public override void Emit (EmitContext ec)
1077                 {
1078                         EmitCode (ec, true);
1079                         
1080                 }
1081                 
1082                 public override void EmitStatement (EmitContext ec)
1083                 {
1084                         EmitCode (ec, false);
1085                 }
1086
1087         }
1088
1089         /// <summary>
1090         ///   Base class for the `Is' and `As' classes. 
1091         /// </summary>
1092         ///
1093         /// <remarks>
1094         ///   FIXME: Split this in two, and we get to save the `Operator' Oper
1095         ///   size. 
1096         /// </remarks>
1097         public abstract class Probe : Expression {
1098                 public readonly Expression ProbeType;
1099                 protected Expression expr;
1100                 protected Type probe_type;
1101                 
1102                 public Probe (Expression expr, Expression probe_type, Location l)
1103                 {
1104                         ProbeType = probe_type;
1105                         loc = l;
1106                         this.expr = expr;
1107                 }
1108
1109                 public Expression Expr {
1110                         get {
1111                                 return expr;
1112                         }
1113                 }
1114
1115                 public override Expression DoResolve (EmitContext ec)
1116                 {
1117                         probe_type = ec.DeclSpace.ResolveType (ProbeType, false, loc);
1118
1119                         if (probe_type == null)
1120                                 return null;
1121
1122                         expr = expr.Resolve (ec);
1123                         if (expr == null)
1124                                 return null;
1125                         
1126                         return this;
1127                 }
1128         }
1129
1130         /// <summary>
1131         ///   Implementation of the `is' operator.
1132         /// </summary>
1133         public class Is : Probe {
1134                 public Is (Expression expr, Expression probe_type, Location l)
1135                         : base (expr, probe_type, l)
1136                 {
1137                 }
1138
1139                 enum Action {
1140                         AlwaysTrue, AlwaysNull, AlwaysFalse, LeaveOnStack, Probe
1141                 }
1142
1143                 Action action;
1144                 
1145                 public override void Emit (EmitContext ec)
1146                 {
1147                         ILGenerator ig = ec.ig;
1148
1149                         expr.Emit (ec);
1150
1151                         switch (action){
1152                         case Action.AlwaysFalse:
1153                                 ig.Emit (OpCodes.Pop);
1154                                 IntConstant.EmitInt (ig, 0);
1155                                 return;
1156                         case Action.AlwaysTrue:
1157                                 ig.Emit (OpCodes.Pop);
1158                                 IntConstant.EmitInt (ig, 1);
1159                                 return;
1160                         case Action.LeaveOnStack:
1161                                 // the `e != null' rule.
1162                                 ig.Emit (OpCodes.Ldnull);
1163                                 ig.Emit (OpCodes.Ceq);
1164                                 ig.Emit (OpCodes.Ldc_I4_0);
1165                                 ig.Emit (OpCodes.Ceq);
1166                                 return;
1167                         case Action.Probe:
1168                                 ig.Emit (OpCodes.Isinst, probe_type);
1169                                 ig.Emit (OpCodes.Ldnull);
1170                                 ig.Emit (OpCodes.Cgt_Un);
1171                                 return;
1172                         }
1173                         throw new Exception ("never reached");
1174                 }
1175
1176                 public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
1177                 {
1178                         ILGenerator ig = ec.ig;
1179
1180                         switch (action){
1181                         case Action.AlwaysFalse:
1182                                 if (! onTrue)
1183                                         ig.Emit (OpCodes.Br, target);
1184                                 
1185                                 return;
1186                         case Action.AlwaysTrue:
1187                                 if (onTrue)
1188                                         ig.Emit (OpCodes.Br, target);
1189                                 
1190                                 return;
1191                         case Action.LeaveOnStack:
1192                                 // the `e != null' rule.
1193                                 expr.Emit (ec);
1194                                 ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
1195                                 return;
1196                         case Action.Probe:
1197                                 expr.Emit (ec);
1198                                 ig.Emit (OpCodes.Isinst, probe_type);
1199                                 ig.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target);
1200                                 return;
1201                         }
1202                         throw new Exception ("never reached");
1203                 }
1204
1205                 public override Expression DoResolve (EmitContext ec)
1206                 {
1207                         Expression e = base.DoResolve (ec);
1208
1209                         if ((e == null) || (expr == null))
1210                                 return null;
1211
1212                         Type etype = expr.Type;
1213                         bool warning_always_matches = false;
1214                         bool warning_never_matches = false;
1215
1216                         type = TypeManager.bool_type;
1217                         eclass = ExprClass.Value;
1218
1219                         //
1220                         // First case, if at compile time, there is an implicit conversion
1221                         // then e != null (objects) or true (value types)
1222                         //
1223                         e = Convert.ImplicitConversionStandard (ec, expr, probe_type, loc);
1224                         if (e != null){
1225                                 expr = e;
1226                                 if (etype.IsValueType)
1227                                         action = Action.AlwaysTrue;
1228                                 else
1229                                         action = Action.LeaveOnStack;
1230
1231                                 warning_always_matches = true;
1232                         } else if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){
1233                                 //
1234                                 // Second case: explicit reference convresion
1235                                 //
1236                                 if (expr is NullLiteral)
1237                                         action = Action.AlwaysFalse;
1238                                 else
1239                                         action = Action.Probe;
1240                         } else {
1241                                 action = Action.AlwaysFalse;
1242                                 warning_never_matches = true;
1243                         }
1244                         
1245                         if (RootContext.WarningLevel >= 1){
1246                                 if (warning_always_matches)
1247                                         Warning (183, "The expression is always of type `" +
1248                                                  TypeManager.CSharpName (probe_type) + "'");
1249                                 else if (warning_never_matches){
1250                                         if (!(probe_type.IsInterface || expr.Type.IsInterface))
1251                                                 Warning (184,
1252                                                          "The expression is never of type `" +
1253                                                          TypeManager.CSharpName (probe_type) + "'");
1254                                 }
1255                         }
1256
1257                         return this;
1258                 }                               
1259         }
1260
1261         /// <summary>
1262         ///   Implementation of the `as' operator.
1263         /// </summary>
1264         public class As : Probe {
1265                 public As (Expression expr, Expression probe_type, Location l)
1266                         : base (expr, probe_type, l)
1267                 {
1268                 }
1269
1270                 bool do_isinst = false;
1271                 
1272                 public override void Emit (EmitContext ec)
1273                 {
1274                         ILGenerator ig = ec.ig;
1275
1276                         expr.Emit (ec);
1277
1278                         if (do_isinst)
1279                                 ig.Emit (OpCodes.Isinst, probe_type);
1280                 }
1281
1282                 static void Error_CannotConvertType (Type source, Type target, Location loc)
1283                 {
1284                         Report.Error (
1285                                 39, loc, "as operator can not convert from `" +
1286                                 TypeManager.CSharpName (source) + "' to `" +
1287                                 TypeManager.CSharpName (target) + "'");
1288                 }
1289                 
1290                 public override Expression DoResolve (EmitContext ec)
1291                 {
1292                         Expression e = base.DoResolve (ec);
1293
1294                         if (e == null)
1295                                 return null;
1296
1297                         type = probe_type;
1298                         eclass = ExprClass.Value;
1299                         Type etype = expr.Type;
1300
1301                         if (TypeManager.IsValueType (probe_type)){
1302                                 Report.Error (77, loc, "The as operator should be used with a reference type only (" +
1303                                               TypeManager.CSharpName (probe_type) + " is a value type)");
1304                                 return null;
1305                         
1306                         }
1307                         
1308                         e = Convert.ImplicitConversion (ec, expr, probe_type, loc);
1309                         if (e != null){
1310                                 expr = e;
1311                                 do_isinst = false;
1312                                 return this;
1313                         }
1314
1315                         if (Convert.ExplicitReferenceConversionExists (etype, probe_type)){
1316                                 do_isinst = true;
1317                                 return this;
1318                         }
1319
1320                         Error_CannotConvertType (etype, probe_type, loc);
1321                         return null;
1322                 }                               
1323         }
1324         
1325         /// <summary>
1326         ///   This represents a typecast in the source language.
1327         ///
1328         ///   FIXME: Cast expressions have an unusual set of parsing
1329         ///   rules, we need to figure those out.
1330         /// </summary>
1331         public class Cast : Expression {
1332                 Expression target_type;
1333                 Expression expr;
1334                         
1335                 public Cast (Expression cast_type, Expression expr, Location loc)
1336                 {
1337                         this.target_type = cast_type;
1338                         this.expr = expr;
1339                         this.loc = loc;
1340                 }
1341
1342                 public Expression TargetType {
1343                         get {
1344                                 return target_type;
1345                         }
1346                 }
1347
1348                 public Expression Expr {
1349                         get {
1350                                 return expr;
1351                         }
1352                         set {
1353                                 expr = value;
1354                         }
1355                 }
1356
1357                 bool CheckRange (EmitContext ec, long value, Type type, long min, long max)
1358                 {
1359                         if (!ec.ConstantCheckState)
1360                                 return true;
1361
1362                         if ((value < min) || (value > max)) {
1363                                 Error (221, "Constant value `" + value + "' cannot be converted " +
1364                                        "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " +
1365                                        "syntax to override)");
1366                                 return false;
1367                         }
1368
1369                         return true;
1370                 }
1371
1372                 bool CheckRange (EmitContext ec, ulong value, Type type, ulong max)
1373                 {
1374                         if (!ec.ConstantCheckState)
1375                                 return true;
1376
1377                         if (value > max) {
1378                                 Error (221, "Constant value `" + value + "' cannot be converted " +
1379                                        "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " +
1380                                        "syntax to override)");
1381                                 return false;
1382                         }
1383
1384                         return true;
1385                 }
1386
1387                 bool CheckUnsigned (EmitContext ec, long value, Type type)
1388                 {
1389                         if (!ec.ConstantCheckState)
1390                                 return true;
1391
1392                         if (value < 0) {
1393                                 Error (221, "Constant value `" + value + "' cannot be converted " +
1394                                        "to a `" + TypeManager.CSharpName (type) + "' (use `unchecked' " +
1395                                        "syntax to override)");
1396                                 return false;
1397                         }
1398
1399                         return true;
1400                 }
1401
1402                 /// <summary>
1403                 ///   Attempts to do a compile-time folding of a constant cast.
1404                 /// </summary>
1405                 Expression TryReduce (EmitContext ec, Type target_type)
1406                 {
1407                         Expression real_expr = expr;
1408                         if (real_expr is EnumConstant)
1409                                 real_expr = ((EnumConstant) real_expr).Child;
1410                                 
1411                         if (real_expr is ByteConstant){
1412                                 byte v = ((ByteConstant) real_expr).Value;
1413         
1414                                 if (target_type == TypeManager.sbyte_type) {
1415                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1416                                                 return null;
1417                                         return new SByteConstant ((sbyte) v);
1418                                 }
1419                                 if (target_type == TypeManager.short_type)
1420                                         return new ShortConstant ((short) v);
1421                                 if (target_type == TypeManager.ushort_type)
1422                                         return new UShortConstant ((ushort) v);
1423                                 if (target_type == TypeManager.int32_type)
1424                                         return new IntConstant ((int) v);
1425                                 if (target_type == TypeManager.uint32_type)
1426                                         return new UIntConstant ((uint) v);
1427                                 if (target_type == TypeManager.int64_type)
1428                                         return new LongConstant ((long) v);
1429                                 if (target_type == TypeManager.uint64_type)
1430                                         return new ULongConstant ((ulong) v);
1431                                 if (target_type == TypeManager.float_type)
1432                                         return new FloatConstant ((float) v);
1433                                 if (target_type == TypeManager.double_type)
1434                                         return new DoubleConstant ((double) v);
1435                                 if (target_type == TypeManager.char_type)
1436                                         return new CharConstant ((char) v);
1437                                 if (target_type == TypeManager.decimal_type)
1438                                         return new DecimalConstant ((decimal) v);
1439                         }
1440                         if (real_expr is SByteConstant){
1441                                 sbyte v = ((SByteConstant) real_expr).Value;
1442         
1443                                 if (target_type == TypeManager.byte_type) {
1444                                         if (!CheckUnsigned (ec, v, target_type))
1445                                                 return null;
1446                                         return new ByteConstant ((byte) v);
1447                                 }
1448                                 if (target_type == TypeManager.short_type)
1449                                         return new ShortConstant ((short) v);
1450                                 if (target_type == TypeManager.ushort_type) {
1451                                         if (!CheckUnsigned (ec, v, target_type))
1452                                                 return null;
1453                                         return new UShortConstant ((ushort) v);
1454                                 } if (target_type == TypeManager.int32_type)
1455                                         return new IntConstant ((int) v);
1456                                 if (target_type == TypeManager.uint32_type) {
1457                                         if (!CheckUnsigned (ec, v, target_type))
1458                                                 return null;
1459                                         return new UIntConstant ((uint) v);
1460                                 } if (target_type == TypeManager.int64_type)
1461                                         return new LongConstant ((long) v);
1462                                 if (target_type == TypeManager.uint64_type) {
1463                                         if (!CheckUnsigned (ec, v, target_type))
1464                                                 return null;
1465                                         return new ULongConstant ((ulong) v);
1466                                 }
1467                                 if (target_type == TypeManager.float_type)
1468                                         return new FloatConstant ((float) v);
1469                                 if (target_type == TypeManager.double_type)
1470                                         return new DoubleConstant ((double) v);
1471                                 if (target_type == TypeManager.char_type) {
1472                                         if (!CheckUnsigned (ec, v, target_type))
1473                                                 return null;
1474                                         return new CharConstant ((char) v);
1475                                 }
1476                                 if (target_type == TypeManager.decimal_type)
1477                                         return new DecimalConstant ((decimal) v);
1478                         }
1479                         if (real_expr is ShortConstant){
1480                                 short v = ((ShortConstant) real_expr).Value;
1481         
1482                                 if (target_type == TypeManager.byte_type) {
1483                                         if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
1484                                                 return null;
1485                                         return new ByteConstant ((byte) v);
1486                                 }
1487                                 if (target_type == TypeManager.sbyte_type) {
1488                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1489                                                 return null;
1490                                         return new SByteConstant ((sbyte) v);
1491                                 }
1492                                 if (target_type == TypeManager.ushort_type) {
1493                                         if (!CheckUnsigned (ec, v, target_type))
1494                                                 return null;
1495                                         return new UShortConstant ((ushort) v);
1496                                 }
1497                                 if (target_type == TypeManager.int32_type)
1498                                         return new IntConstant ((int) v);
1499                                 if (target_type == TypeManager.uint32_type) {
1500                                         if (!CheckUnsigned (ec, v, target_type))
1501                                                 return null;
1502                                         return new UIntConstant ((uint) v);
1503                                 }
1504                                 if (target_type == TypeManager.int64_type)
1505                                         return new LongConstant ((long) v);
1506                                 if (target_type == TypeManager.uint64_type) {
1507                                         if (!CheckUnsigned (ec, v, target_type))
1508                                                 return null;
1509                                         return new ULongConstant ((ulong) v);
1510                                 }
1511                                 if (target_type == TypeManager.float_type)
1512                                         return new FloatConstant ((float) v);
1513                                 if (target_type == TypeManager.double_type)
1514                                         return new DoubleConstant ((double) v);
1515                                 if (target_type == TypeManager.char_type) {
1516                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1517                                                 return null;
1518                                         return new CharConstant ((char) v);
1519                                 }
1520                                 if (target_type == TypeManager.decimal_type)
1521                                         return new DecimalConstant ((decimal) v);
1522                         }
1523                         if (real_expr is UShortConstant){
1524                                 ushort v = ((UShortConstant) real_expr).Value;
1525         
1526                                 if (target_type == TypeManager.byte_type) {
1527                                         if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
1528                                                 return null;
1529                                         return new ByteConstant ((byte) v);
1530                                 }
1531                                 if (target_type == TypeManager.sbyte_type) {
1532                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1533                                                 return null;
1534                                         return new SByteConstant ((sbyte) v);
1535                                 }
1536                                 if (target_type == TypeManager.short_type) {
1537                                         if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
1538                                                 return null;
1539                                         return new ShortConstant ((short) v);
1540                                 }
1541                                 if (target_type == TypeManager.int32_type)
1542                                         return new IntConstant ((int) v);
1543                                 if (target_type == TypeManager.uint32_type)
1544                                         return new UIntConstant ((uint) v);
1545                                 if (target_type == TypeManager.int64_type)
1546                                         return new LongConstant ((long) v);
1547                                 if (target_type == TypeManager.uint64_type)
1548                                         return new ULongConstant ((ulong) v);
1549                                 if (target_type == TypeManager.float_type)
1550                                         return new FloatConstant ((float) v);
1551                                 if (target_type == TypeManager.double_type)
1552                                         return new DoubleConstant ((double) v);
1553                                 if (target_type == TypeManager.char_type) {
1554                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1555                                                 return null;
1556                                         return new CharConstant ((char) v);
1557                                 }
1558                                 if (target_type == TypeManager.decimal_type)
1559                                         return new DecimalConstant ((decimal) v);
1560                         }
1561                         if (real_expr is IntConstant){
1562                                 int v = ((IntConstant) real_expr).Value;
1563         
1564                                 if (target_type == TypeManager.byte_type) {
1565                                         if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
1566                                                 return null;
1567                                         return new ByteConstant ((byte) v);
1568                                 }
1569                                 if (target_type == TypeManager.sbyte_type) {
1570                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1571                                                 return null;
1572                                         return new SByteConstant ((sbyte) v);
1573                                 }
1574                                 if (target_type == TypeManager.short_type) {
1575                                         if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
1576                                                 return null;
1577                                         return new ShortConstant ((short) v);
1578                                 }
1579                                 if (target_type == TypeManager.ushort_type) {
1580                                         if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue))
1581                                                 return null;
1582                                         return new UShortConstant ((ushort) v);
1583                                 }
1584                                 if (target_type == TypeManager.uint32_type) {
1585                                         if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue))
1586                                                 return null;
1587                                         return new UIntConstant ((uint) v);
1588                                 }
1589                                 if (target_type == TypeManager.int64_type)
1590                                         return new LongConstant ((long) v);
1591                                 if (target_type == TypeManager.uint64_type) {
1592                                         if (!CheckUnsigned (ec, v, target_type))
1593                                                 return null;
1594                                         return new ULongConstant ((ulong) v);
1595                                 }
1596                                 if (target_type == TypeManager.float_type)
1597                                         return new FloatConstant ((float) v);
1598                                 if (target_type == TypeManager.double_type)
1599                                         return new DoubleConstant ((double) v);
1600                                 if (target_type == TypeManager.char_type) {
1601                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1602                                                 return null;
1603                                         return new CharConstant ((char) v);
1604                                 }
1605                                 if (target_type == TypeManager.decimal_type)
1606                                         return new DecimalConstant ((decimal) v);
1607                         }
1608                         if (real_expr is UIntConstant){
1609                                 uint v = ((UIntConstant) real_expr).Value;
1610         
1611                                 if (target_type == TypeManager.byte_type) {
1612                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1613                                                 return null;
1614                                         return new ByteConstant ((byte) v);
1615                                 }
1616                                 if (target_type == TypeManager.sbyte_type) {
1617                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1618                                                 return null;
1619                                         return new SByteConstant ((sbyte) v);
1620                                 }
1621                                 if (target_type == TypeManager.short_type) {
1622                                         if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
1623                                                 return null;
1624                                         return new ShortConstant ((short) v);
1625                                 }
1626                                 if (target_type == TypeManager.ushort_type) {
1627                                         if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue))
1628                                                 return null;
1629                                         return new UShortConstant ((ushort) v);
1630                                 }
1631                                 if (target_type == TypeManager.int32_type) {
1632                                         if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue))
1633                                                 return null;
1634                                         return new IntConstant ((int) v);
1635                                 }
1636                                 if (target_type == TypeManager.int64_type)
1637                                         return new LongConstant ((long) v);
1638                                 if (target_type == TypeManager.uint64_type)
1639                                         return new ULongConstant ((ulong) v);
1640                                 if (target_type == TypeManager.float_type)
1641                                         return new FloatConstant ((float) v);
1642                                 if (target_type == TypeManager.double_type)
1643                                         return new DoubleConstant ((double) v);
1644                                 if (target_type == TypeManager.char_type) {
1645                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1646                                                 return null;
1647                                         return new CharConstant ((char) v);
1648                                 }
1649                                 if (target_type == TypeManager.decimal_type)
1650                                         return new DecimalConstant ((decimal) v);
1651                         }
1652                         if (real_expr is LongConstant){
1653                                 long v = ((LongConstant) real_expr).Value;
1654         
1655                                 if (target_type == TypeManager.byte_type) {
1656                                         if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
1657                                                 return null;
1658                                         return new ByteConstant ((byte) v);
1659                                 }
1660                                 if (target_type == TypeManager.sbyte_type) {
1661                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1662                                                 return null;
1663                                         return new SByteConstant ((sbyte) v);
1664                                 }
1665                                 if (target_type == TypeManager.short_type) {
1666                                         if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
1667                                                 return null;
1668                                         return new ShortConstant ((short) v);
1669                                 }
1670                                 if (target_type == TypeManager.ushort_type) {
1671                                         if (!CheckRange (ec, v, target_type, UInt16.MinValue, UInt16.MaxValue))
1672                                                 return null;
1673                                         return new UShortConstant ((ushort) v);
1674                                 }
1675                                 if (target_type == TypeManager.int32_type) {
1676                                         if (!CheckRange (ec, v, target_type, Int32.MinValue, Int32.MaxValue))
1677                                                 return null;
1678                                         return new IntConstant ((int) v);
1679                                 }
1680                                 if (target_type == TypeManager.uint32_type) {
1681                                         if (!CheckRange (ec, v, target_type, UInt32.MinValue, UInt32.MaxValue))
1682                                                 return null;
1683                                         return new UIntConstant ((uint) v);
1684                                 }
1685                                 if (target_type == TypeManager.uint64_type) {
1686                                         if (!CheckUnsigned (ec, v, target_type))
1687                                                 return null;
1688                                         return new ULongConstant ((ulong) v);
1689                                 }
1690                                 if (target_type == TypeManager.float_type)
1691                                         return new FloatConstant ((float) v);
1692                                 if (target_type == TypeManager.double_type)
1693                                         return new DoubleConstant ((double) v);
1694                                 if (target_type == TypeManager.char_type) {
1695                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1696                                                 return null;
1697                                         return new CharConstant ((char) v);
1698                                 }
1699                                 if (target_type == TypeManager.decimal_type)
1700                                         return new DecimalConstant ((decimal) v);
1701                         }
1702                         if (real_expr is ULongConstant){
1703                                 ulong v = ((ULongConstant) real_expr).Value;
1704         
1705                                 if (target_type == TypeManager.byte_type) {
1706                                         if (!CheckRange (ec, v, target_type, Byte.MaxValue))
1707                                                 return null;
1708                                         return new ByteConstant ((byte) v);
1709                                 }
1710                                 if (target_type == TypeManager.sbyte_type) {
1711                                         if (!CheckRange (ec, v, target_type, (ulong) SByte.MaxValue))
1712                                                 return null;
1713                                         return new SByteConstant ((sbyte) v);
1714                                 }
1715                                 if (target_type == TypeManager.short_type) {
1716                                         if (!CheckRange (ec, v, target_type, (ulong) Int16.MaxValue))
1717                                                 return null;
1718                                         return new ShortConstant ((short) v);
1719                                 }
1720                                 if (target_type == TypeManager.ushort_type) {
1721                                         if (!CheckRange (ec, v, target_type, UInt16.MaxValue))
1722                                                 return null;
1723                                         return new UShortConstant ((ushort) v);
1724                                 }
1725                                 if (target_type == TypeManager.int32_type) {
1726                                         if (!CheckRange (ec, v, target_type, Int32.MaxValue))
1727                                                 return null;
1728                                         return new IntConstant ((int) v);
1729                                 }
1730                                 if (target_type == TypeManager.uint32_type) {
1731                                         if (!CheckRange (ec, v, target_type, UInt32.MaxValue))
1732                                                 return null;
1733                                         return new UIntConstant ((uint) v);
1734                                 }
1735                                 if (target_type == TypeManager.int64_type) {
1736                                         if (!CheckRange (ec, v, target_type, (ulong) Int64.MaxValue))
1737                                                 return null;
1738                                         return new LongConstant ((long) v);
1739                                 }
1740                                 if (target_type == TypeManager.float_type)
1741                                         return new FloatConstant ((float) v);
1742                                 if (target_type == TypeManager.double_type)
1743                                         return new DoubleConstant ((double) v);
1744                                 if (target_type == TypeManager.char_type) {
1745                                         if (!CheckRange (ec, v, target_type, Char.MaxValue))
1746                                                 return null;
1747                                         return new CharConstant ((char) v);
1748                                 }
1749                                 if (target_type == TypeManager.decimal_type)
1750                                         return new DecimalConstant ((decimal) v);
1751                         }
1752                         if (real_expr is FloatConstant){
1753                                 float v = ((FloatConstant) real_expr).Value;
1754         
1755                                 if (target_type == TypeManager.byte_type)
1756                                         return new ByteConstant ((byte) v);
1757                                 if (target_type == TypeManager.sbyte_type)
1758                                         return new SByteConstant ((sbyte) v);
1759                                 if (target_type == TypeManager.short_type)
1760                                         return new ShortConstant ((short) v);
1761                                 if (target_type == TypeManager.ushort_type)
1762                                         return new UShortConstant ((ushort) v);
1763                                 if (target_type == TypeManager.int32_type)
1764                                         return new IntConstant ((int) v);
1765                                 if (target_type == TypeManager.uint32_type)
1766                                         return new UIntConstant ((uint) v);
1767                                 if (target_type == TypeManager.int64_type)
1768                                         return new LongConstant ((long) v);
1769                                 if (target_type == TypeManager.uint64_type)
1770                                         return new ULongConstant ((ulong) v);
1771                                 if (target_type == TypeManager.double_type)
1772                                         return new DoubleConstant ((double) v);
1773                                 if (target_type == TypeManager.char_type)
1774                                         return new CharConstant ((char) v);
1775                                 if (target_type == TypeManager.decimal_type)
1776                                         return new DecimalConstant ((decimal) v);
1777                         }
1778                         if (real_expr is DoubleConstant){
1779                                 double v = ((DoubleConstant) real_expr).Value;
1780         
1781                                 if (target_type == TypeManager.byte_type){
1782                                         return new ByteConstant ((byte) v);
1783                                 } if (target_type == TypeManager.sbyte_type)
1784                                         return new SByteConstant ((sbyte) v);
1785                                 if (target_type == TypeManager.short_type)
1786                                         return new ShortConstant ((short) v);
1787                                 if (target_type == TypeManager.ushort_type)
1788                                         return new UShortConstant ((ushort) v);
1789                                 if (target_type == TypeManager.int32_type)
1790                                         return new IntConstant ((int) v);
1791                                 if (target_type == TypeManager.uint32_type)
1792                                         return new UIntConstant ((uint) v);
1793                                 if (target_type == TypeManager.int64_type)
1794                                         return new LongConstant ((long) v);
1795                                 if (target_type == TypeManager.uint64_type)
1796                                         return new ULongConstant ((ulong) v);
1797                                 if (target_type == TypeManager.float_type)
1798                                         return new FloatConstant ((float) v);
1799                                 if (target_type == TypeManager.char_type)
1800                                         return new CharConstant ((char) v);
1801                                 if (target_type == TypeManager.decimal_type)
1802                                         return new DecimalConstant ((decimal) v);
1803                         }
1804
1805                         if (real_expr is CharConstant){
1806                                 char v = ((CharConstant) real_expr).Value;
1807                                 
1808                                 if (target_type == TypeManager.byte_type) {
1809                                         if (!CheckRange (ec, v, target_type, Byte.MinValue, Byte.MaxValue))
1810                                                 return null;
1811                                         return new ByteConstant ((byte) v);
1812                                 }
1813                                 if (target_type == TypeManager.sbyte_type) {
1814                                         if (!CheckRange (ec, v, target_type, SByte.MinValue, SByte.MaxValue))
1815                                                 return null;
1816                                         return new SByteConstant ((sbyte) v);
1817                                 }
1818                                 if (target_type == TypeManager.short_type) {
1819                                         if (!CheckRange (ec, v, target_type, Int16.MinValue, Int16.MaxValue))
1820                                                 return null;
1821                                         return new ShortConstant ((short) v);
1822                                 }
1823                                 if (target_type == TypeManager.int32_type)
1824                                         return new IntConstant ((int) v);
1825                                 if (target_type == TypeManager.uint32_type)
1826                                         return new UIntConstant ((uint) v);
1827                                 if (target_type == TypeManager.int64_type)
1828                                         return new LongConstant ((long) v);
1829                                 if (target_type == TypeManager.uint64_type)
1830                                         return new ULongConstant ((ulong) v);
1831                                 if (target_type == TypeManager.float_type)
1832                                         return new FloatConstant ((float) v);
1833                                 if (target_type == TypeManager.double_type)
1834                                         return new DoubleConstant ((double) v);
1835                                 if (target_type == TypeManager.char_type) {
1836                                         if (!CheckRange (ec, v, target_type, Char.MinValue, Char.MaxValue))
1837                                                 return null;
1838                                         return new CharConstant ((char) v);
1839                                 }
1840                                 if (target_type == TypeManager.decimal_type)
1841                                         return new DecimalConstant ((decimal) v);
1842                         }
1843
1844                         return null;
1845                 }
1846                 
1847                 public override Expression DoResolve (EmitContext ec)
1848                 {
1849                         expr = expr.Resolve (ec);
1850                         if (expr == null)
1851                                 return null;
1852
1853                         type = ec.DeclSpace.ResolveType (target_type, false, Location);
1854                         
1855                         if (type == null)
1856                                 return null;
1857
1858                         eclass = ExprClass.Value;
1859
1860                         if (expr is Constant){
1861                                 Expression e = TryReduce (ec, type);
1862
1863                                 if (e != null)
1864                                         return e;
1865                         }
1866
1867                         expr = Convert.ExplicitConversion (ec, expr, type, loc);
1868                         return expr;
1869                 }
1870
1871                 public override void Emit (EmitContext ec)
1872                 {
1873                         //
1874                         // This one will never happen
1875                         //
1876                         throw new Exception ("Should not happen");
1877                 }
1878         }
1879
1880         /// <summary>
1881         ///   Binary operators
1882         /// </summary>
1883         public class Binary : Expression {
1884                 public enum Operator : byte {
1885                         Multiply, Division, Modulus,
1886                         Addition, Subtraction,
1887                         LeftShift, RightShift,
1888                         LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
1889                         Equality, Inequality,
1890                         BitwiseAnd,
1891                         ExclusiveOr,
1892                         BitwiseOr,
1893                         LogicalAnd,
1894                         LogicalOr,
1895                         TOP
1896                 }
1897
1898                 Operator oper;
1899                 Expression left, right;
1900
1901                 // This must be kept in sync with Operator!!!
1902                 public static readonly string [] oper_names;
1903                 
1904                 static Binary ()
1905                 {
1906                         oper_names = new string [(int) Operator.TOP];
1907
1908                         oper_names [(int) Operator.Multiply] = "op_Multiply";
1909                         oper_names [(int) Operator.Division] = "op_Division";
1910                         oper_names [(int) Operator.Modulus] = "op_Modulus";
1911                         oper_names [(int) Operator.Addition] = "op_Addition";
1912                         oper_names [(int) Operator.Subtraction] = "op_Subtraction";
1913                         oper_names [(int) Operator.LeftShift] = "op_LeftShift";
1914                         oper_names [(int) Operator.RightShift] = "op_RightShift";
1915                         oper_names [(int) Operator.LessThan] = "op_LessThan";
1916                         oper_names [(int) Operator.GreaterThan] = "op_GreaterThan";
1917                         oper_names [(int) Operator.LessThanOrEqual] = "op_LessThanOrEqual";
1918                         oper_names [(int) Operator.GreaterThanOrEqual] = "op_GreaterThanOrEqual";
1919                         oper_names [(int) Operator.Equality] = "op_Equality";
1920                         oper_names [(int) Operator.Inequality] = "op_Inequality";
1921                         oper_names [(int) Operator.BitwiseAnd] = "op_BitwiseAnd";
1922                         oper_names [(int) Operator.BitwiseOr] = "op_BitwiseOr";
1923                         oper_names [(int) Operator.ExclusiveOr] = "op_ExclusiveOr";
1924                         oper_names [(int) Operator.LogicalOr] = "op_LogicalOr";
1925                         oper_names [(int) Operator.LogicalAnd] = "op_LogicalAnd";
1926                 }
1927
1928                 public Binary (Operator oper, Expression left, Expression right, Location loc)
1929                 {
1930                         this.oper = oper;
1931                         this.left = left;
1932                         this.right = right;
1933                         this.loc = loc;
1934                 }
1935
1936                 public Operator Oper {
1937                         get {
1938                                 return oper;
1939                         }
1940                         set {
1941                                 oper = value;
1942                         }
1943                 }
1944                 
1945                 public Expression Left {
1946                         get {
1947                                 return left;
1948                         }
1949                         set {
1950                                 left = value;
1951                         }
1952                 }
1953
1954                 public Expression Right {
1955                         get {
1956                                 return right;
1957                         }
1958                         set {
1959                                 right = value;
1960                         }
1961                 }
1962
1963
1964                 /// <summary>
1965                 ///   Returns a stringified representation of the Operator
1966                 /// </summary>
1967                 static string OperName (Operator oper)
1968                 {
1969                         switch (oper){
1970                         case Operator.Multiply:
1971                                 return "*";
1972                         case Operator.Division:
1973                                 return "/";
1974                         case Operator.Modulus:
1975                                 return "%";
1976                         case Operator.Addition:
1977                                 return "+";
1978                         case Operator.Subtraction:
1979                                 return "-";
1980                         case Operator.LeftShift:
1981                                 return "<<";
1982                         case Operator.RightShift:
1983                                 return ">>";
1984                         case Operator.LessThan:
1985                                 return "<";
1986                         case Operator.GreaterThan:
1987                                 return ">";
1988                         case Operator.LessThanOrEqual:
1989                                 return "<=";
1990                         case Operator.GreaterThanOrEqual:
1991                                 return ">=";
1992                         case Operator.Equality:
1993                                 return "==";
1994                         case Operator.Inequality:
1995                                 return "!=";
1996                         case Operator.BitwiseAnd:
1997                                 return "&";
1998                         case Operator.BitwiseOr:
1999                                 return "|";
2000                         case Operator.ExclusiveOr:
2001                                 return "^";
2002                         case Operator.LogicalOr:
2003                                 return "||";
2004                         case Operator.LogicalAnd:
2005                                 return "&&";
2006                         }
2007
2008                         return oper.ToString ();
2009                 }
2010
2011                 public override string ToString ()
2012                 {
2013                         return "operator " + OperName (oper) + "(" + left.ToString () + ", " +
2014                                 right.ToString () + ")";
2015                 }
2016                 
2017                 Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
2018                 {
2019                         if (expr.Type == target_type)
2020                                 return expr;
2021
2022                         return Convert.ImplicitConversion (ec, expr, target_type, loc);
2023                 }
2024
2025                 public static void Error_OperatorAmbiguous (Location loc, Operator oper, Type l, Type r)
2026                 {
2027                         Report.Error (
2028                                 34, loc, "Operator `" + OperName (oper) 
2029                                 + "' is ambiguous on operands of type `"
2030                                 + TypeManager.CSharpName (l) + "' "
2031                                 + "and `" + TypeManager.CSharpName (r)
2032                                 + "'");
2033                 }
2034
2035                 bool IsOfType (EmitContext ec, Type l, Type r, Type t, bool check_user_conversions)
2036                 {
2037                         if ((l == t) || (r == t))
2038                                 return true;
2039
2040                         if (!check_user_conversions)
2041                                 return false;
2042
2043                         if (Convert.ImplicitUserConversionExists (ec, l, t))
2044                                 return true;
2045                         else if (Convert.ImplicitUserConversionExists (ec, r, t))
2046                                 return true;
2047                         else
2048                                 return false;
2049                 }
2050
2051                 //
2052                 // Note that handling the case l == Decimal || r == Decimal
2053                 // is taken care of by the Step 1 Operator Overload resolution.
2054                 //
2055                 // If `check_user_conv' is true, we also check whether a user-defined conversion
2056                 // exists.  Note that we only need to do this if both arguments are of a user-defined
2057                 // type, otherwise ConvertImplict() already finds the user-defined conversion for us,
2058                 // so we don't explicitly check for performance reasons.
2059                 //
2060                 bool DoNumericPromotions (EmitContext ec, Type l, Type r, bool check_user_conv)
2061                 {
2062                         if (IsOfType (ec, l, r, TypeManager.double_type, check_user_conv)){
2063                                 //
2064                                 // If either operand is of type double, the other operand is
2065                                 // conveted to type double.
2066                                 //
2067                                 if (r != TypeManager.double_type)
2068                                         right = Convert.ImplicitConversion (ec, right, TypeManager.double_type, loc);
2069                                 if (l != TypeManager.double_type)
2070                                         left = Convert.ImplicitConversion (ec, left, TypeManager.double_type, loc);
2071                                 
2072                                 type = TypeManager.double_type;
2073                         } else if (IsOfType (ec, l, r, TypeManager.float_type, check_user_conv)){
2074                                 //
2075                                 // if either operand is of type float, the other operand is
2076                                 // converted to type float.
2077                                 //
2078                                 if (r != TypeManager.double_type)
2079                                         right = Convert.ImplicitConversion (ec, right, TypeManager.float_type, loc);
2080                                 if (l != TypeManager.double_type)
2081                                         left = Convert.ImplicitConversion (ec, left, TypeManager.float_type, loc);
2082                                 type = TypeManager.float_type;
2083                         } else if (IsOfType (ec, l, r, TypeManager.uint64_type, check_user_conv)){
2084                                 Expression e;
2085                                 Type other;
2086                                 //
2087                                 // If either operand is of type ulong, the other operand is
2088                                 // converted to type ulong.  or an error ocurrs if the other
2089                                 // operand is of type sbyte, short, int or long
2090                                 //
2091                                 if (l == TypeManager.uint64_type){
2092                                         if (r != TypeManager.uint64_type){
2093                                                 if (right is IntConstant){
2094                                                         IntConstant ic = (IntConstant) right;
2095                                                         
2096                                                         e = Convert.TryImplicitIntConversion (l, ic);
2097                                                         if (e != null)
2098                                                                 right = e;
2099                                                 } else if (right is LongConstant){
2100                                                         long ll = ((LongConstant) right).Value;
2101
2102                                                         if (ll >= 0)
2103                                                                 right = new ULongConstant ((ulong) ll);
2104                                                 } else {
2105                                                         e = Convert.ImplicitNumericConversion (ec, right, l, loc);
2106                                                         if (e != null)
2107                                                                 right = e;
2108                                                 }
2109                                         }
2110                                         other = right.Type;
2111                                 } else {
2112                                         if (left is IntConstant){
2113                                                 e = Convert.TryImplicitIntConversion (r, (IntConstant) left);
2114                                                 if (e != null)
2115                                                         left = e;
2116                                         } else if (left is LongConstant){
2117                                                 long ll = ((LongConstant) left).Value;
2118                                                 
2119                                                 if (ll > 0)
2120                                                         left = new ULongConstant ((ulong) ll);
2121                                         } else {
2122                                                 e = Convert.ImplicitNumericConversion (ec, left, r, loc);
2123                                                 if (e != null)
2124                                                         left = e;
2125                                         }
2126                                         other = left.Type;
2127                                 }
2128
2129                                 if ((other == TypeManager.sbyte_type) ||
2130                                     (other == TypeManager.short_type) ||
2131                                     (other == TypeManager.int32_type) ||
2132                                     (other == TypeManager.int64_type))
2133                                         Error_OperatorAmbiguous (loc, oper, l, r);
2134                                 type = TypeManager.uint64_type;
2135                         } else if (IsOfType (ec, l, r, TypeManager.int64_type, check_user_conv)){
2136                                 //
2137                                 // If either operand is of type long, the other operand is converted
2138                                 // to type long.
2139                                 //
2140                                 if (l != TypeManager.int64_type)
2141                                         left = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc);
2142                                 if (r != TypeManager.int64_type)
2143                                         right = Convert.ImplicitConversion (ec, right, TypeManager.int64_type, loc);
2144                                 
2145                                 type = TypeManager.int64_type;
2146                         } else if (IsOfType (ec, l, r, TypeManager.uint32_type, check_user_conv)){
2147                                 //
2148                                 // If either operand is of type uint, and the other
2149                                 // operand is of type sbyte, short or int, othe operands are
2150                                 // converted to type long (unless we have an int constant).
2151                                 //
2152                                 Type other = null;
2153                                 
2154                                 if (l == TypeManager.uint32_type){
2155                                         if (right is IntConstant){
2156                                                 IntConstant ic = (IntConstant) right;
2157                                                 int val = ic.Value;
2158                                                 
2159                                                 if (val >= 0){
2160                                                         right = new UIntConstant ((uint) val);
2161                                                         type = l;
2162                                                         
2163                                                         return true;
2164                                                 }
2165                                         }
2166                                         other = r;
2167                                 } else if (r == TypeManager.uint32_type){
2168                                         if (left is IntConstant){
2169                                                 IntConstant ic = (IntConstant) left;
2170                                                 int val = ic.Value;
2171                                                 
2172                                                 if (val >= 0){
2173                                                         left = new UIntConstant ((uint) val);
2174                                                         type = r;
2175                                                         return true;
2176                                                 }
2177                                         }
2178                                         
2179                                         other = l;
2180                                 }
2181
2182                                 if ((other == TypeManager.sbyte_type) ||
2183                                     (other == TypeManager.short_type) ||
2184                                     (other == TypeManager.int32_type)){
2185                                         left = ForceConversion (ec, left, TypeManager.int64_type);
2186                                         right = ForceConversion (ec, right, TypeManager.int64_type);
2187                                         type = TypeManager.int64_type;
2188                                 } else {
2189                                         //
2190                                         // if either operand is of type uint, the other
2191                                         // operand is converd to type uint
2192                                         //
2193                                         left = ForceConversion (ec, left, TypeManager.uint32_type);
2194                                         right = ForceConversion (ec, right, TypeManager.uint32_type);
2195                                         type = TypeManager.uint32_type;
2196                                 } 
2197                         } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
2198                                 if (l != TypeManager.decimal_type)
2199                                         left = Convert.ImplicitConversion (ec, left, TypeManager.decimal_type, loc);
2200
2201                                 if (r != TypeManager.decimal_type)
2202                                         right = Convert.ImplicitConversion (ec, right, TypeManager.decimal_type, loc);
2203                                 type = TypeManager.decimal_type;
2204                         } else {
2205                                 left = ForceConversion (ec, left, TypeManager.int32_type);
2206                                 right = ForceConversion (ec, right, TypeManager.int32_type);
2207
2208                                 type = TypeManager.int32_type;
2209                         }
2210
2211                         return (left != null) && (right != null);
2212                 }
2213
2214                 static public void Error_OperatorCannotBeApplied (Location loc, string name, Type l, Type r)
2215                 {
2216                         Report.Error (19, loc,
2217                                "Operator " + name + " cannot be applied to operands of type `" +
2218                                TypeManager.CSharpName (l) + "' and `" +
2219                                TypeManager.CSharpName (r) + "'");
2220                 }
2221                 
2222                 void Error_OperatorCannotBeApplied ()
2223                 {
2224                         Error_OperatorCannotBeApplied (loc, OperName (oper), left.Type, right.Type);
2225                 }
2226
2227                 static bool is_unsigned (Type t)
2228                 {
2229                         return (t == TypeManager.uint32_type || t == TypeManager.uint64_type ||
2230                                 t == TypeManager.short_type || t == TypeManager.byte_type);
2231                 }
2232
2233                 static bool is_user_defined (Type t)
2234                 {
2235                         if (t.IsSubclassOf (TypeManager.value_type) &&
2236                             (!TypeManager.IsBuiltinType (t) || t == TypeManager.decimal_type))
2237                                 return true;
2238                         else
2239                                 return false;
2240                 }
2241
2242                 Expression Make32or64 (EmitContext ec, Expression e)
2243                 {
2244                         Type t= e.Type;
2245                         
2246                         if (t == TypeManager.int32_type || t == TypeManager.uint32_type ||
2247                             t == TypeManager.int64_type || t == TypeManager.uint64_type)
2248                                 return e;
2249                         Expression ee = Convert.ImplicitConversion (ec, e, TypeManager.int32_type, loc);
2250                         if (ee != null)
2251                                 return ee;
2252                         ee = Convert.ImplicitConversion (ec, e, TypeManager.uint32_type, loc);
2253                         if (ee != null)
2254                                 return ee;
2255                         ee = Convert.ImplicitConversion (ec, e, TypeManager.int64_type, loc);
2256                         if (ee != null)
2257                                 return ee;
2258                         ee = Convert.ImplicitConversion (ec, e, TypeManager.uint64_type, loc);
2259                         if (ee != null)
2260                                 return ee;
2261                         return null;
2262                 }
2263                                         
2264                 Expression CheckShiftArguments (EmitContext ec)
2265                 {
2266                         Expression e;
2267
2268                         e = ForceConversion (ec, right, TypeManager.int32_type);
2269                         if (e == null){
2270                                 Error_OperatorCannotBeApplied ();
2271                                 return null;
2272                         }
2273                         right = e;
2274
2275                         if (((e = Convert.ImplicitConversion (ec, left, TypeManager.int32_type, loc)) != null) ||
2276                             ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint32_type, loc)) != null) ||
2277                             ((e = Convert.ImplicitConversion (ec, left, TypeManager.int64_type, loc)) != null) ||
2278                             ((e = Convert.ImplicitConversion (ec, left, TypeManager.uint64_type, loc)) != null)){
2279                                 left = e;
2280                                 type = e.Type;
2281
2282                                 if (type == TypeManager.int32_type || type == TypeManager.uint32_type){
2283                                         right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (31), loc);
2284                                         right = right.DoResolve (ec);
2285                                 } else {
2286                                         right = new Binary (Binary.Operator.BitwiseAnd, right, new IntLiteral (63), loc);
2287                                         right = right.DoResolve (ec);
2288                                 }
2289
2290                                 return this;
2291                         }
2292                         Error_OperatorCannotBeApplied ();
2293                         return null;
2294                 }
2295
2296                 Expression ResolveOperator (EmitContext ec)
2297                 {
2298                         Type l = left.Type;
2299                         Type r = right.Type;
2300
2301                         bool overload_failed = false;
2302
2303                         //
2304                         // Special cases: string or type parameter comapred to null
2305                         //
2306                         if (oper == Operator.Equality || oper == Operator.Inequality){
2307                                 if ((l == TypeManager.string_type && (right is NullLiteral)) ||
2308                                     (r == TypeManager.string_type && (left is NullLiteral))){
2309                                         Type = TypeManager.bool_type;
2310                                         
2311                                         return this;
2312                                 }
2313
2314                                 if (l.IsGenericParameter && (right is NullLiteral)) {
2315                                         if (l.BaseType == TypeManager.value_type) {
2316                                                 Error_OperatorCannotBeApplied ();
2317                                                 return null;
2318                                         }
2319
2320                                         left = new BoxedCast (left);
2321                                         Type = TypeManager.bool_type;
2322                                         return this;
2323                                 }
2324
2325                                 if (r.IsGenericParameter && (left is NullLiteral)) {
2326                                         if (r.BaseType == TypeManager.value_type) {
2327                                                 Error_OperatorCannotBeApplied ();
2328                                                 return null;
2329                                         }
2330
2331                                         right = new BoxedCast (right);
2332                                         Type = TypeManager.bool_type;
2333                                         return this;
2334                                 }
2335                                 
2336                                 // IntPtr equality
2337                                 if (l == TypeManager.intptr_type && r == TypeManager.intptr_type) {
2338                                         Type = TypeManager.bool_type;
2339                                         
2340                                         return this;
2341                                 }
2342                         }
2343
2344                         //
2345                         // Do not perform operator overload resolution when both sides are
2346                         // built-in types
2347                         //
2348                         if (!(TypeManager.IsCLRType (l) && TypeManager.IsCLRType (r))){
2349                                 //
2350                                 // Step 1: Perform Operator Overload location
2351                                 //
2352                                 Expression left_expr, right_expr;
2353                                 
2354                                 string op = oper_names [(int) oper];
2355                                 
2356                                 MethodGroupExpr union;
2357                                 left_expr = MemberLookup (ec, l, op, MemberTypes.Method, AllBindingFlags, loc);
2358                                 if (r != l){
2359                                         right_expr = MemberLookup (
2360                                                 ec, r, op, MemberTypes.Method, AllBindingFlags, loc);
2361                                         union = Invocation.MakeUnionSet (left_expr, right_expr, loc);
2362                                 } else
2363                                         union = (MethodGroupExpr) left_expr;
2364                                 
2365                                 if (union != null) {
2366                                         ArrayList args = new ArrayList (2);
2367                                         args.Add (new Argument (left, Argument.AType.Expression));
2368                                         args.Add (new Argument (right, Argument.AType.Expression));
2369                                         
2370                                         MethodBase method = Invocation.OverloadResolve (
2371                                                 ec, union, args, true, Location.Null);
2372
2373                                         if (method != null) {
2374                                                 MethodInfo mi = (MethodInfo) method;
2375                                                 
2376                                                 return new BinaryMethod (mi.ReturnType, method, args);
2377                                         } else {
2378                                                 overload_failed = true;
2379                                         }
2380                                 }
2381                         }
2382                         
2383                         //
2384                         // Step 0: String concatenation (because overloading will get this wrong)
2385                         //
2386                         if (oper == Operator.Addition){
2387                                 //
2388                                 // If any of the arguments is a string, cast to string
2389                                 //
2390                                 
2391                                 // Simple constant folding
2392                                 if (left is StringConstant && right is StringConstant)
2393                                         return new StringConstant (((StringConstant) left).Value + ((StringConstant) right).Value);
2394
2395                                 if (l == TypeManager.string_type || r == TypeManager.string_type) {
2396
2397                                         if (r == TypeManager.void_type || l == TypeManager.void_type) {
2398                                                 Error_OperatorCannotBeApplied ();
2399                                                 return null;
2400                                         }
2401                                         
2402                                         // try to fold it in on the left
2403                                         if (left is StringConcat) {
2404
2405                                                 //
2406                                                 // We have to test here for not-null, since we can be doubly-resolved
2407                                                 // take care of not appending twice
2408                                                 //
2409                                                 if (type == null){
2410                                                         type = TypeManager.string_type;
2411                                                         ((StringConcat) left).Append (ec, right);
2412                                                         return left.Resolve (ec);
2413                                                 } else {
2414                                                         return left;
2415                                                 }
2416                                         }
2417
2418                                         // Otherwise, start a new concat expression
2419                                         return new StringConcat (ec, loc, left, right).Resolve (ec);
2420                                 }
2421
2422                                 //
2423                                 // Transform a + ( - b) into a - b
2424                                 //
2425                                 if (right is Unary){
2426                                         Unary right_unary = (Unary) right;
2427
2428                                         if (right_unary.Oper == Unary.Operator.UnaryNegation){
2429                                                 oper = Operator.Subtraction;
2430                                                 right = right_unary.Expr;
2431                                                 r = right.Type;
2432                                         }
2433                                 }
2434                         }
2435
2436                         if (oper == Operator.Equality || oper == Operator.Inequality){
2437                                 if (l == TypeManager.bool_type || r == TypeManager.bool_type){
2438                                         if (r != TypeManager.bool_type || l != TypeManager.bool_type){
2439                                                 Error_OperatorCannotBeApplied ();
2440                                                 return null;
2441                                         }
2442                                         
2443                                         type = TypeManager.bool_type;
2444                                         return this;
2445                                 }
2446
2447                                 //
2448                                 // operator != (object a, object b)
2449                                 // operator == (object a, object b)
2450                                 //
2451                                 // For this to be used, both arguments have to be reference-types.
2452                                 // Read the rationale on the spec (14.9.6)
2453                                 //
2454                                 // Also, if at compile time we know that the classes do not inherit
2455                                 // one from the other, then we catch the error there.
2456                                 //
2457                                 if (!(l.IsValueType || r.IsValueType)){
2458                                         type = TypeManager.bool_type;
2459
2460                                         if (l == r)
2461                                                 return this;
2462                                         
2463                                         if (l.IsSubclassOf (r) || r.IsSubclassOf (l))
2464                                                 return this;
2465
2466                                         //
2467                                         // Also, a standard conversion must exist from either one
2468                                         //
2469                                         if (!(Convert.ImplicitStandardConversionExists (left, r) ||
2470                                               Convert.ImplicitStandardConversionExists (right, l))){
2471                                                 Error_OperatorCannotBeApplied ();
2472                                                 return null;
2473                                         }
2474                                         //
2475                                         // We are going to have to convert to an object to compare
2476                                         //
2477                                         if (l != TypeManager.object_type)
2478                                                 left = new EmptyCast (left, TypeManager.object_type);
2479                                         if (r != TypeManager.object_type)
2480                                                 right = new EmptyCast (right, TypeManager.object_type);
2481
2482                                         //
2483                                         // FIXME: CSC here catches errors cs254 and cs252
2484                                         //
2485                                         return this;
2486                                 }
2487
2488                                 //
2489                                 // One of them is a valuetype, but the other one is not.
2490                                 //
2491                                 if (!l.IsValueType || !r.IsValueType) {
2492                                         Error_OperatorCannotBeApplied ();
2493                                         return null;
2494                                 }
2495                         }
2496
2497                         // Only perform numeric promotions on:
2498                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
2499                         //
2500                         if (oper == Operator.Addition || oper == Operator.Subtraction) {
2501                                 if (TypeManager.IsDelegateType (l)){
2502                                         if (right.eclass == ExprClass.MethodGroup && RootContext.V2){
2503                                                 Expression tmp = Convert.ImplicitConversionRequired (ec, right, l, loc);
2504                                                 if (tmp == null)
2505                                                         return null;
2506                                                 right = tmp;
2507                                                 r = right.Type;
2508                                         }
2509                                 
2510                                         if (TypeManager.IsDelegateType (r)){
2511                                         MethodInfo method;
2512                                         ArrayList args = new ArrayList (2);
2513                                         
2514                                         args = new ArrayList (2);
2515                                         args.Add (new Argument (left, Argument.AType.Expression));
2516                                         args.Add (new Argument (right, Argument.AType.Expression));
2517                                         
2518                                         if (oper == Operator.Addition)
2519                                                 method = TypeManager.delegate_combine_delegate_delegate;
2520                                         else
2521                                                 method = TypeManager.delegate_remove_delegate_delegate;
2522
2523                                         if (l != r) {
2524                                                 Error_OperatorCannotBeApplied ();
2525                                                 return null;
2526                                         }
2527
2528                                         return new BinaryDelegate (l, method, args);
2529                                 }
2530                                 }
2531
2532                                 //
2533                                 // Pointer arithmetic:
2534                                 //
2535                                 // T* operator + (T* x, int y);
2536                                 // T* operator + (T* x, uint y);
2537                                 // T* operator + (T* x, long y);
2538                                 // T* operator + (T* x, ulong y);
2539                                 //
2540                                 // T* operator + (int y,   T* x);
2541                                 // T* operator + (uint y,  T *x);
2542                                 // T* operator + (long y,  T *x);
2543                                 // T* operator + (ulong y, T *x);
2544                                 //
2545                                 // T* operator - (T* x, int y);
2546                                 // T* operator - (T* x, uint y);
2547                                 // T* operator - (T* x, long y);
2548                                 // T* operator - (T* x, ulong y);
2549                                 //
2550                                 // long operator - (T* x, T *y)
2551                                 //
2552                                 if (l.IsPointer){
2553                                         if (r.IsPointer && oper == Operator.Subtraction){
2554                                                 if (r == l)
2555                                                         return new PointerArithmetic (
2556                                                                 false, left, right, TypeManager.int64_type,
2557                                                                 loc);
2558                                         } else {
2559                                                 Expression t = Make32or64 (ec, right);
2560                                                 if (t != null)
2561                                                         return new PointerArithmetic (oper == Operator.Addition, left, t, l, loc);
2562                                         }
2563                                 } else if (r.IsPointer && oper == Operator.Addition){
2564                                         Expression t = Make32or64 (ec, left);
2565                                         if (t != null)
2566                                                 return new PointerArithmetic (true, right, t, r, loc);
2567                                 }
2568                         }
2569                         
2570                         //
2571                         // Enumeration operators
2572                         //
2573                         bool lie = TypeManager.IsEnumType (l);
2574                         bool rie = TypeManager.IsEnumType (r);
2575                         if (lie || rie){
2576                                 Expression temp;
2577
2578                                 // U operator - (E e, E f)
2579                                 if (lie && rie){
2580                                         if (oper == Operator.Subtraction){
2581                                         if (l == r){
2582                                                 type = TypeManager.EnumToUnderlying (l);
2583                                                 return this;
2584                                         } 
2585                                         Error_OperatorCannotBeApplied ();
2586                                         return null;
2587                                 }
2588                                 }
2589                                         
2590                                 //
2591                                 // operator + (E e, U x)
2592                                 // operator - (E e, U x)
2593                                 //
2594                                 if (oper == Operator.Addition || oper == Operator.Subtraction){
2595                                         Type enum_type = lie ? l : r;
2596                                         Type other_type = lie ? r : l;
2597                                         Type underlying_type = TypeManager.EnumToUnderlying (enum_type);
2598                                         
2599                                         if (underlying_type != other_type){
2600                                                 temp = Convert.ImplicitConversion (ec, lie ? right : left, underlying_type, loc);
2601                                                 if (temp != null){
2602                                                         if (lie)
2603                                                                 right = temp;
2604                                                         else
2605                                                                 left = temp;
2606                                                         type = enum_type;
2607                                                         return this;
2608                                                 }
2609                                                         
2610                                                 Error_OperatorCannotBeApplied ();
2611                                                 return null;
2612                                         }
2613
2614                                         type = enum_type;
2615                                         return this;
2616                                 }
2617                                 
2618                                 if (!rie){
2619                                         temp = Convert.ImplicitConversion (ec, right, l, loc);
2620                                         if (temp != null)
2621                                                 right = temp;
2622                                         else {
2623                                                 Error_OperatorCannotBeApplied ();
2624                                                 return null;
2625                                         }
2626                                 } if (!lie){
2627                                         temp = Convert.ImplicitConversion (ec, left, r, loc);
2628                                         if (temp != null){
2629                                                 left = temp;
2630                                                 l = r;
2631                                         } else {
2632                                                 Error_OperatorCannotBeApplied ();
2633                                                 return null;
2634                                         }
2635                                 }
2636
2637                                 if (oper == Operator.Equality || oper == Operator.Inequality ||
2638                                     oper == Operator.LessThanOrEqual || oper == Operator.LessThan ||
2639                                     oper == Operator.GreaterThanOrEqual || oper == Operator.GreaterThan){
2640                                         if (left.Type != right.Type){
2641                                                 Error_OperatorCannotBeApplied ();
2642                                                 return null;
2643                                         }
2644                                         type = TypeManager.bool_type;
2645                                         return this;
2646                                 }
2647
2648                                 if (oper == Operator.BitwiseAnd ||
2649                                     oper == Operator.BitwiseOr ||
2650                                     oper == Operator.ExclusiveOr){
2651                                         type = l;
2652                                         return this;
2653                                 }
2654                                 Error_OperatorCannotBeApplied ();
2655                                 return null;
2656                         }
2657                         
2658                         if (oper == Operator.LeftShift || oper == Operator.RightShift)
2659                                 return CheckShiftArguments (ec);
2660
2661                         if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
2662                                 if (l == TypeManager.bool_type && r == TypeManager.bool_type) {
2663                                         type = TypeManager.bool_type;
2664                                         return this;
2665                                 }
2666
2667                                 if (l != r) {
2668                                         Error_OperatorCannotBeApplied ();
2669                                         return null;
2670                                 }
2671
2672                                 Expression e = new ConditionalLogicalOperator (
2673                                         oper == Operator.LogicalAnd, left, right, l, loc);
2674                                 return e.Resolve (ec);
2675                         } 
2676
2677                         //
2678                         // operator & (bool x, bool y)
2679                         // operator | (bool x, bool y)
2680                         // operator ^ (bool x, bool y)
2681                         //
2682                         if (l == TypeManager.bool_type && r == TypeManager.bool_type){
2683                                 if (oper == Operator.BitwiseAnd ||
2684                                     oper == Operator.BitwiseOr ||
2685                                     oper == Operator.ExclusiveOr){
2686                                         type = l;
2687                                         return this;
2688                                 }
2689                         }
2690                         
2691                         //
2692                         // Pointer comparison
2693                         //
2694                         if (l.IsPointer && r.IsPointer){
2695                                 if (oper == Operator.Equality || oper == Operator.Inequality ||
2696                                     oper == Operator.LessThan || oper == Operator.LessThanOrEqual ||
2697                                     oper == Operator.GreaterThan || oper == Operator.GreaterThanOrEqual){
2698                                         type = TypeManager.bool_type;
2699                                         return this;
2700                                 }
2701                         }
2702                         
2703                         //
2704                         // We are dealing with numbers
2705                         //
2706                         if (overload_failed){
2707                                 Error_OperatorCannotBeApplied ();
2708                                 return null;
2709                         }
2710
2711                         //
2712                         // This will leave left or right set to null if there is an error
2713                         //
2714                         bool check_user_conv = is_user_defined (l) && is_user_defined (r);
2715                         DoNumericPromotions (ec, l, r, check_user_conv);
2716                         if (left == null || right == null){
2717                                 Error_OperatorCannotBeApplied (loc, OperName (oper), l, r);
2718                                 return null;
2719                         }
2720
2721                         //
2722                         // reload our cached types if required
2723                         //
2724                         l = left.Type;
2725                         r = right.Type;
2726                         
2727                         if (oper == Operator.BitwiseAnd ||
2728                             oper == Operator.BitwiseOr ||
2729                             oper == Operator.ExclusiveOr){
2730                                 if (l == r){
2731                                         if (((l == TypeManager.int32_type) ||
2732                                              (l == TypeManager.uint32_type) ||
2733                                              (l == TypeManager.short_type) ||
2734                                              (l == TypeManager.ushort_type) ||
2735                                              (l == TypeManager.int64_type) ||
2736                                              (l == TypeManager.uint64_type))){
2737                                                 type = l;
2738                                         } else {
2739                                                 Error_OperatorCannotBeApplied ();
2740                                                 return null;
2741                                         }
2742                                 } else {
2743                                         Error_OperatorCannotBeApplied ();
2744                                         return null;
2745                                 }
2746                         }
2747
2748                         if (oper == Operator.Equality ||
2749                             oper == Operator.Inequality ||
2750                             oper == Operator.LessThanOrEqual ||
2751                             oper == Operator.LessThan ||
2752                             oper == Operator.GreaterThanOrEqual ||
2753                             oper == Operator.GreaterThan){
2754                                 type = TypeManager.bool_type;
2755                         }
2756
2757                         return this;
2758                 }
2759
2760                 public override Expression DoResolve (EmitContext ec)
2761                 {
2762                         if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) {
2763                                 left = ((ParenthesizedExpression) left).Expr;
2764                                 left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type);
2765                                 if (left == null)
2766                                         return null;
2767
2768                                 if (left.eclass == ExprClass.Type) {
2769                                         Error (75, "Casting a negative value needs to have the value in parentheses.");
2770                                         return null;
2771                                 }
2772                         } else
2773                                 left = left.Resolve (ec);
2774                         right = right.Resolve (ec);
2775
2776                         if (left == null || right == null)
2777                                 return null;
2778
2779                         eclass = ExprClass.Value;
2780
2781                         Constant rc = right as Constant;
2782                         Constant lc = left as Constant;
2783
2784                         if (rc != null & lc != null){
2785                                 Expression e = ConstantFold.BinaryFold (
2786                                         ec, oper, lc, rc, loc);
2787                                         if (e != null)
2788                                                 return e;
2789                         }
2790
2791                         return ResolveOperator (ec);
2792                 }
2793
2794                 /// <remarks>
2795                 ///   EmitBranchable is called from Statement.EmitBoolExpression in the
2796                 ///   context of a conditional bool expression.  This function will return
2797                 ///   false if it is was possible to use EmitBranchable, or true if it was.
2798                 ///
2799                 ///   The expression's code is generated, and we will generate a branch to `target'
2800                 ///   if the resulting expression value is equal to isTrue
2801                 /// </remarks>
2802                 public override void EmitBranchable (EmitContext ec, Label target, bool onTrue)
2803                 {
2804                         ILGenerator ig = ec.ig;
2805
2806                         //
2807                         // This is more complicated than it looks, but its just to avoid
2808                         // duplicated tests: basically, we allow ==, !=, >, <, >= and <=
2809                         // but on top of that we want for == and != to use a special path
2810                         // if we are comparing against null
2811                         //
2812                         if ((oper == Operator.Equality || oper == Operator.Inequality) && (left is Constant || right is Constant)) {
2813                                 bool my_on_true = oper == Operator.Inequality ? onTrue : !onTrue;
2814
2815                                 //
2816                                 // put the constant on the rhs, for simplicity
2817                                 //
2818                                 if (left is Constant) {
2819                                         Expression swap = right;
2820                                         right = left;
2821                                         left = swap;
2822                                 }
2823                                         
2824                                 if (((Constant) right).IsZeroInteger) {
2825                                         left.Emit (ec);
2826                                         if (my_on_true)
2827                                                 ig.Emit (OpCodes.Brtrue, target);
2828                                         else
2829                                                 ig.Emit (OpCodes.Brfalse, target);
2830                                         
2831                                         return;
2832                                 } else if (right is BoolConstant){
2833                                         left.Emit (ec);
2834                                         if (my_on_true != ((BoolConstant) right).Value)
2835                                                 ig.Emit (OpCodes.Brtrue, target);
2836                                         else
2837                                                 ig.Emit (OpCodes.Brfalse, target);
2838                                         
2839                                         return;
2840                                 }
2841
2842                         } else if (oper == Operator.LogicalAnd) {
2843
2844                                 if (onTrue) {
2845                                                 Label tests_end = ig.DefineLabel ();
2846                                                 
2847                                         left.EmitBranchable (ec, tests_end, false);
2848                                         right.EmitBranchable (ec, target, true);
2849                                                         ig.MarkLabel (tests_end);
2850                                         } else {
2851                                         left.EmitBranchable (ec, target, false);
2852                                         right.EmitBranchable (ec, target, false);
2853                                         }
2854
2855                                 return;
2856                                                                 
2857                         } else if (oper == Operator.LogicalOr){
2858                                 if (onTrue) {
2859                                         left.EmitBranchable (ec, target, true);
2860                                         right.EmitBranchable (ec, target, true);
2861                                                 
2862                                         } else {
2863                                                 Label tests_end = ig.DefineLabel ();
2864                                         left.EmitBranchable (ec, tests_end, true);
2865                                         right.EmitBranchable (ec, target, false);
2866                                         ig.MarkLabel (tests_end);
2867                                 }
2868                                                 
2869                                 return;
2870
2871                         } else if (!(oper == Operator.LessThan        || oper == Operator.GreaterThan ||
2872                                      oper == Operator.LessThanOrEqual || oper == Operator.GreaterThanOrEqual ||
2873                                      oper == Operator.Equality        || oper == Operator.Inequality)) {
2874                                 base.EmitBranchable (ec, target, onTrue);
2875                                 return;
2876                                 }
2877                                 
2878                         left.Emit (ec);
2879                         right.Emit (ec);
2880
2881                         Type t = left.Type;
2882                         bool isUnsigned = is_unsigned (t) || t == TypeManager.double_type || t == TypeManager.float_type;
2883
2884                         switch (oper){
2885                         case Operator.Equality:
2886                                 if (onTrue)
2887                                         ig.Emit (OpCodes.Beq, target);
2888                                 else
2889                                         ig.Emit (OpCodes.Bne_Un, target);
2890                                 break;
2891
2892                         case Operator.Inequality:
2893                                 if (onTrue)
2894                                         ig.Emit (OpCodes.Bne_Un, target);
2895                                 else
2896                                         ig.Emit (OpCodes.Beq, target);
2897                                 break;
2898
2899                         case Operator.LessThan:
2900                                 if (onTrue)
2901                                         if (isUnsigned)
2902                                                 ig.Emit (OpCodes.Blt_Un, target);
2903                                         else
2904                                                 ig.Emit (OpCodes.Blt, target);
2905                                 else
2906                                         if (isUnsigned)
2907                                                 ig.Emit (OpCodes.Bge_Un, target);
2908                                         else
2909                                                 ig.Emit (OpCodes.Bge, target);
2910                                 break;
2911
2912                         case Operator.GreaterThan:
2913                                 if (onTrue)
2914                                         if (isUnsigned)
2915                                                 ig.Emit (OpCodes.Bgt_Un, target);
2916                                         else
2917                                                 ig.Emit (OpCodes.Bgt, target);
2918                                 else
2919                                         if (isUnsigned)
2920                                                 ig.Emit (OpCodes.Ble_Un, target);
2921                                         else
2922                                                 ig.Emit (OpCodes.Ble, target);
2923                                 break;
2924
2925                         case Operator.LessThanOrEqual:
2926                                 if (onTrue)
2927                                         if (isUnsigned)
2928                                                 ig.Emit (OpCodes.Ble_Un, target);
2929                                         else
2930                                                 ig.Emit (OpCodes.Ble, target);
2931                                 else
2932                                         if (isUnsigned)
2933                                                 ig.Emit (OpCodes.Bgt_Un, target);
2934                                         else
2935                                                 ig.Emit (OpCodes.Bgt, target);
2936                                 break;
2937
2938
2939                         case Operator.GreaterThanOrEqual:
2940                                 if (onTrue)
2941                                         if (isUnsigned)
2942                                                 ig.Emit (OpCodes.Bge_Un, target);
2943                                         else
2944                                                 ig.Emit (OpCodes.Bge, target);
2945                                 else
2946                                         if (isUnsigned)
2947                                                 ig.Emit (OpCodes.Blt_Un, target);
2948                                         else
2949                                                 ig.Emit (OpCodes.Blt, target);
2950                                 break;
2951                         default:
2952                                 Console.WriteLine (oper);
2953                                 throw new Exception ("what is THAT");
2954                         }
2955                 }
2956                 
2957                 public override void Emit (EmitContext ec)
2958                 {
2959                         ILGenerator ig = ec.ig;
2960                         Type l = left.Type;
2961                         OpCode opcode;
2962
2963                         //
2964                         // Handle short-circuit operators differently
2965                         // than the rest
2966                         //
2967                         if (oper == Operator.LogicalAnd) {
2968                                 Label load_zero = ig.DefineLabel ();
2969                                 Label end = ig.DefineLabel ();
2970
2971                                 left.EmitBranchable (ec, load_zero, false);
2972                                                 right.Emit (ec);
2973                                                 ig.Emit (OpCodes.Br, end);
2974
2975                                 ig.MarkLabel (load_zero);
2976                                 ig.Emit (OpCodes.Ldc_I4_0);
2977                                 ig.MarkLabel (end);
2978                                 return;
2979                         } else if (oper == Operator.LogicalOr) {
2980                                 Label load_one = ig.DefineLabel ();
2981                                 Label end = ig.DefineLabel ();
2982                                 
2983                                 left.EmitBranchable (ec, load_one, true);
2984                                                 right.Emit (ec);
2985                                                 ig.Emit (OpCodes.Br, end);
2986
2987                                 ig.MarkLabel (load_one);
2988                                 ig.Emit (OpCodes.Ldc_I4_1);
2989                                 ig.MarkLabel (end);
2990                                 return;
2991                         }
2992
2993                         left.Emit (ec);
2994                         right.Emit (ec);
2995
2996                         bool isUnsigned = is_unsigned (left.Type);
2997                         
2998                         switch (oper){
2999                         case Operator.Multiply:
3000                                 if (ec.CheckState){
3001                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
3002                                                 opcode = OpCodes.Mul_Ovf;
3003                                         else if (isUnsigned)
3004                                                 opcode = OpCodes.Mul_Ovf_Un;
3005                                         else
3006                                                 opcode = OpCodes.Mul;
3007                                 } else
3008                                         opcode = OpCodes.Mul;
3009
3010                                 break;
3011
3012                         case Operator.Division:
3013                                 if (isUnsigned)
3014                                         opcode = OpCodes.Div_Un;
3015                                 else
3016                                         opcode = OpCodes.Div;
3017                                 break;
3018
3019                         case Operator.Modulus:
3020                                 if (isUnsigned)
3021                                         opcode = OpCodes.Rem_Un;
3022                                 else
3023                                         opcode = OpCodes.Rem;
3024                                 break;
3025
3026                         case Operator.Addition:
3027                                 if (ec.CheckState){
3028                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
3029                                                 opcode = OpCodes.Add_Ovf;
3030                                         else if (isUnsigned)
3031                                                 opcode = OpCodes.Add_Ovf_Un;
3032                                         else
3033                                                 opcode = OpCodes.Add;
3034                                 } else
3035                                         opcode = OpCodes.Add;
3036                                 break;
3037
3038                         case Operator.Subtraction:
3039                                 if (ec.CheckState){
3040                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
3041                                                 opcode = OpCodes.Sub_Ovf;
3042                                         else if (isUnsigned)
3043                                                 opcode = OpCodes.Sub_Ovf_Un;
3044                                         else
3045                                                 opcode = OpCodes.Sub;
3046                                 } else
3047                                         opcode = OpCodes.Sub;
3048                                 break;
3049
3050                         case Operator.RightShift:
3051                                 if (isUnsigned)
3052                                         opcode = OpCodes.Shr_Un;
3053                                 else
3054                                         opcode = OpCodes.Shr;
3055                                 break;
3056                                 
3057                         case Operator.LeftShift:
3058                                 opcode = OpCodes.Shl;
3059                                 break;
3060
3061                         case Operator.Equality:
3062                                 opcode = OpCodes.Ceq;
3063                                 break;
3064
3065                         case Operator.Inequality:
3066                                 ig.Emit (OpCodes.Ceq);
3067                                 ig.Emit (OpCodes.Ldc_I4_0);
3068                                 
3069                                 opcode = OpCodes.Ceq;
3070                                 break;
3071
3072                         case Operator.LessThan:
3073                                 if (isUnsigned)
3074                                         opcode = OpCodes.Clt_Un;
3075                                 else
3076                                         opcode = OpCodes.Clt;
3077                                 break;
3078
3079                         case Operator.GreaterThan:
3080                                 if (isUnsigned)
3081                                         opcode = OpCodes.Cgt_Un;
3082                                 else
3083                                         opcode = OpCodes.Cgt;
3084                                 break;
3085
3086                         case Operator.LessThanOrEqual:
3087                                 Type lt = left.Type;
3088                                 
3089                                 if (isUnsigned || (lt == TypeManager.double_type || lt == TypeManager.float_type))
3090                                         ig.Emit (OpCodes.Cgt_Un);
3091                                 else
3092                                         ig.Emit (OpCodes.Cgt);
3093                                 ig.Emit (OpCodes.Ldc_I4_0);
3094                                 
3095                                 opcode = OpCodes.Ceq;
3096                                 break;
3097
3098                         case Operator.GreaterThanOrEqual:
3099                                 Type le = left.Type;
3100                                 
3101                                 if (isUnsigned || (le == TypeManager.double_type || le == TypeManager.float_type))
3102                                         ig.Emit (OpCodes.Clt_Un);
3103                                 else
3104                                         ig.Emit (OpCodes.Clt);
3105                                 
3106                                 ig.Emit (OpCodes.Ldc_I4_0);
3107                                 
3108                                 opcode = OpCodes.Ceq;
3109                                 break;
3110
3111                         case Operator.BitwiseOr:
3112                                 opcode = OpCodes.Or;
3113                                 break;
3114
3115                         case Operator.BitwiseAnd:
3116                                 opcode = OpCodes.And;
3117                                 break;
3118
3119                         case Operator.ExclusiveOr:
3120                                 opcode = OpCodes.Xor;
3121                                 break;
3122
3123                         default:
3124                                 throw new Exception ("This should not happen: Operator = "
3125                                                      + oper.ToString ());
3126                         }
3127
3128                         ig.Emit (opcode);
3129                 }
3130         }
3131
3132         //
3133         // Object created by Binary when the binary operator uses an method instead of being
3134         // a binary operation that maps to a CIL binary operation.
3135         //
3136         public class BinaryMethod : Expression {
3137                 public MethodBase method;
3138                 public ArrayList  Arguments;
3139                 
3140                 public BinaryMethod (Type t, MethodBase m, ArrayList args)
3141                 {
3142                         method = m;
3143                         Arguments = args;
3144                         type = t;
3145                         eclass = ExprClass.Value;
3146                 }
3147
3148                 public override Expression DoResolve (EmitContext ec)
3149                 {
3150                         return this;
3151                 }
3152
3153                 public override void Emit (EmitContext ec)
3154                 {
3155                         ILGenerator ig = ec.ig;
3156                         
3157                         if (Arguments != null) 
3158                                 Invocation.EmitArguments (ec, method, Arguments);
3159                         
3160                         if (method is MethodInfo)
3161                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
3162                         else
3163                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
3164                 }
3165         }
3166
3167         //
3168         // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string
3169         // b, c, d... may be strings or objects.
3170         //
3171         public class StringConcat : Expression {
3172                 ArrayList operands;
3173                 bool invalid = false;
3174                 
3175                 
3176                 public StringConcat (EmitContext ec, Location loc, Expression left, Expression right)
3177                 {
3178                         this.loc = loc;
3179                         type = TypeManager.string_type;
3180                         eclass = ExprClass.Value;
3181                 
3182                         operands = new ArrayList (2);
3183                         Append (ec, left);
3184                         Append (ec, right);
3185                 }
3186                 
3187                 public override Expression DoResolve (EmitContext ec)
3188                 {
3189                         if (invalid)
3190                                 return null;
3191                         
3192                         return this;
3193                 }
3194                 
3195                 public void Append (EmitContext ec, Expression operand)
3196                 {
3197                         //
3198                         // Constant folding
3199                         //
3200                         if (operand is StringConstant && operands.Count != 0) {
3201                                 StringConstant last_operand = operands [operands.Count - 1] as StringConstant;
3202                                 if (last_operand != null) {
3203                                         operands [operands.Count - 1] = new StringConstant (last_operand.Value + ((StringConstant) operand).Value);
3204                                         return;
3205                                 }
3206                         }
3207                         
3208                         //
3209                         // Conversion to object
3210                         //
3211                         if (operand.Type != TypeManager.string_type) {
3212                                 Expression no = Convert.ImplicitConversion (ec, operand, TypeManager.object_type, loc);
3213                                 
3214                                 if (no == null) {
3215                                         Binary.Error_OperatorCannotBeApplied (loc, "+", TypeManager.string_type, operand.Type);
3216                                         invalid = true;
3217                                 }
3218                                 operand = no;
3219                         }
3220                         
3221                         operands.Add (operand);
3222                 }
3223
3224                 public override void Emit (EmitContext ec)
3225                 {
3226                         MethodInfo concat_method = null;
3227                         
3228                         //
3229                         // Are we also concating objects?
3230                         //
3231                         bool is_strings_only = true;
3232                         
3233                         //
3234                         // Do conversion to arguments; check for strings only
3235                         //
3236                         for (int i = 0; i < operands.Count; i ++) {
3237                                 Expression e = (Expression) operands [i];
3238                                 is_strings_only &= e.Type == TypeManager.string_type;
3239                         }
3240                         
3241                         for (int i = 0; i < operands.Count; i ++) {
3242                                 Expression e = (Expression) operands [i];
3243                                 
3244                                 if (! is_strings_only && e.Type == TypeManager.string_type) {
3245                                         // need to make sure this is an object, because the EmitParams
3246                                         // method might look at the type of this expression, see it is a
3247                                         // string and emit a string [] when we want an object [];
3248                                         
3249                                         e = Convert.ImplicitConversion (ec, e, TypeManager.object_type, loc);
3250                                 }
3251                                 operands [i] = new Argument (e, Argument.AType.Expression);
3252                         }
3253                         
3254                         //
3255                         // Find the right method
3256                         //
3257                         switch (operands.Count) {
3258                         case 1:
3259                                 //
3260                                 // This should not be possible, because simple constant folding
3261                                 // is taken care of in the Binary code.
3262                                 //
3263                                 throw new Exception ("how did you get here?");
3264                         
3265                         case 2:
3266                                 concat_method = is_strings_only ? 
3267                                         TypeManager.string_concat_string_string :
3268                                         TypeManager.string_concat_object_object ;
3269                                 break;
3270                         case 3:
3271                                 concat_method = is_strings_only ? 
3272                                         TypeManager.string_concat_string_string_string :
3273                                         TypeManager.string_concat_object_object_object ;
3274                                 break;
3275                         case 4:
3276                                 //
3277                                 // There is not a 4 param overlaod for object (the one that there is
3278                                 // is actually a varargs methods, and is only in corlib because it was
3279                                 // introduced there before.).
3280                                 //
3281                                 if (!is_strings_only)
3282                                         goto default;
3283                                 
3284                                 concat_method = TypeManager.string_concat_string_string_string_string;
3285                                 break;
3286                         default:
3287                                 concat_method = is_strings_only ? 
3288                                         TypeManager.string_concat_string_dot_dot_dot :
3289                                         TypeManager.string_concat_object_dot_dot_dot ;
3290                                 break;
3291                         }
3292                         
3293                         Invocation.EmitArguments (ec, concat_method, operands);
3294                         ec.ig.Emit (OpCodes.Call, concat_method);
3295                 }
3296         }
3297
3298         //
3299         // Object created with +/= on delegates
3300         //
3301         public class BinaryDelegate : Expression {
3302                 MethodInfo method;
3303                 ArrayList  args;
3304
3305                 public BinaryDelegate (Type t, MethodInfo mi, ArrayList args)
3306                 {
3307                         method = mi;
3308                         this.args = args;
3309                         type = t;
3310                         eclass = ExprClass.Value;
3311                 }
3312
3313                 public override Expression DoResolve (EmitContext ec)
3314                 {
3315                         return this;
3316                 }
3317
3318                 public override void Emit (EmitContext ec)
3319                 {
3320                         ILGenerator ig = ec.ig;
3321                         
3322                         Invocation.EmitArguments (ec, method, args);
3323                         
3324                         ig.Emit (OpCodes.Call, (MethodInfo) method);
3325                         ig.Emit (OpCodes.Castclass, type);
3326                 }
3327
3328                 public Expression Right {
3329                         get {
3330                                 Argument arg = (Argument) args [1];
3331                                 return arg.Expr;
3332                         }
3333                 }
3334
3335                 public bool IsAddition {
3336                         get {
3337                                 return method == TypeManager.delegate_combine_delegate_delegate;
3338                         }
3339                 }
3340         }
3341         
3342         //
3343         // User-defined conditional logical operator
3344         public class ConditionalLogicalOperator : Expression {
3345                 Expression left, right;
3346                 bool is_and;
3347
3348                 public ConditionalLogicalOperator (bool is_and, Expression left, Expression right, Type t, Location loc)
3349                 {
3350                         type = t;
3351                         eclass = ExprClass.Value;
3352                         this.loc = loc;
3353                         this.left = left;
3354                         this.right = right;
3355                         this.is_and = is_and;
3356                 }
3357
3358                 protected void Error19 ()
3359                 {
3360                         Binary.Error_OperatorCannotBeApplied (loc, is_and ? "&&" : "||", type, type);
3361                 }
3362
3363                 protected void Error218 ()
3364                 {
3365                         Error (218, "The type ('" + TypeManager.CSharpName (type) + "') must contain " +
3366                                "declarations of operator true and operator false");
3367                 }
3368
3369                 Expression op_true, op_false, op;
3370                 LocalTemporary left_temp;
3371
3372                 public override Expression DoResolve (EmitContext ec)
3373                 {
3374                         MethodInfo method;
3375                         Expression operator_group;
3376
3377                         operator_group = MethodLookup (ec, type, is_and ? "op_BitwiseAnd" : "op_BitwiseOr", loc);
3378                         if (operator_group == null) {
3379                                 Error19 ();
3380                                 return null;
3381                         }
3382
3383                         left_temp = new LocalTemporary (ec, type);
3384
3385                         ArrayList arguments = new ArrayList ();
3386                         arguments.Add (new Argument (left_temp, Argument.AType.Expression));
3387                         arguments.Add (new Argument (right, Argument.AType.Expression));
3388                         method = Invocation.OverloadResolve (
3389                                 ec, (MethodGroupExpr) operator_group, arguments, false, loc)
3390                                 as MethodInfo;
3391                         if ((method == null) || (method.ReturnType != type)) {
3392                                 Error19 ();
3393                                 return null;
3394                         }
3395
3396                         op = new StaticCallExpr (method, arguments, loc);
3397
3398                         op_true = GetOperatorTrue (ec, left_temp, loc);
3399                         op_false = GetOperatorFalse (ec, left_temp, loc);
3400                         if ((op_true == null) || (op_false == null)) {
3401                                 Error218 ();
3402                                 return null;
3403                         }
3404
3405                         return this;
3406                 }
3407
3408                 public override void Emit (EmitContext ec)
3409                 {
3410                         ILGenerator ig = ec.ig;
3411                         Label false_target = ig.DefineLabel ();
3412                         Label end_target = ig.DefineLabel ();
3413
3414                         ig.Emit (OpCodes.Nop);
3415
3416                         left.Emit (ec);
3417                         left_temp.Store (ec);
3418
3419                         (is_and ? op_false : op_true).EmitBranchable (ec, false_target, false);
3420                         left_temp.Emit (ec);
3421                         ig.Emit (OpCodes.Br, end_target);
3422                         ig.MarkLabel (false_target);
3423                         op.Emit (ec);
3424                         ig.MarkLabel (end_target);
3425
3426                         ig.Emit (OpCodes.Nop);
3427                 }
3428         }
3429
3430         public class PointerArithmetic : Expression {
3431                 Expression left, right;
3432                 bool is_add;
3433
3434                 //
3435                 // We assume that `l' is always a pointer
3436                 //
3437                 public PointerArithmetic (bool is_addition, Expression l, Expression r, Type t, Location loc)
3438                 {
3439                         type = t;
3440                         eclass = ExprClass.Variable;
3441                         this.loc = loc;
3442                         left = l;
3443                         right = r;
3444                         is_add = is_addition;
3445                 }
3446
3447                 public override Expression DoResolve (EmitContext ec)
3448                 {
3449                         //
3450                         // We are born fully resolved
3451                         //
3452                         return this;
3453                 }
3454
3455                 public override void Emit (EmitContext ec)
3456                 {
3457                         Type op_type = left.Type;
3458                         ILGenerator ig = ec.ig;
3459                         int size = GetTypeSize (TypeManager.GetElementType (op_type));
3460                         Type rtype = right.Type;
3461                         
3462                         if (rtype.IsPointer){
3463                                 //
3464                                 // handle (pointer - pointer)
3465                                 //
3466                                 left.Emit (ec);
3467                                 right.Emit (ec);
3468                                 ig.Emit (OpCodes.Sub);
3469
3470                                 if (size != 1){
3471                                         if (size == 0)
3472                                                 ig.Emit (OpCodes.Sizeof, op_type);
3473                                         else 
3474                                                 IntLiteral.EmitInt (ig, size);
3475                                         ig.Emit (OpCodes.Div);
3476                                 }
3477                                 ig.Emit (OpCodes.Conv_I8);
3478                         } else {
3479                                 //
3480                                 // handle + and - on (pointer op int)
3481                                 //
3482                                 left.Emit (ec);
3483                                 ig.Emit (OpCodes.Conv_I);
3484                                 right.Emit (ec);
3485                                 if (size != 1){
3486                                         if (size == 0)
3487                                                 ig.Emit (OpCodes.Sizeof, op_type);
3488                                         else 
3489                                                 IntLiteral.EmitInt (ig, size);
3490                                         if (rtype == TypeManager.int64_type)
3491                                                 ig.Emit (OpCodes.Conv_I8);
3492                                         else if (rtype == TypeManager.uint64_type)
3493                                                 ig.Emit (OpCodes.Conv_U8);
3494                                         ig.Emit (OpCodes.Mul);
3495                                         ig.Emit (OpCodes.Conv_I);
3496                                 }
3497                                 if (is_add)
3498                                         ig.Emit (OpCodes.Add);
3499                                 else
3500                                         ig.Emit (OpCodes.Sub);
3501                         }
3502                 }
3503         }
3504         
3505         /// <summary>
3506         ///   Implements the ternary conditional operator (?:)
3507         /// </summary>
3508         public class Conditional : Expression {
3509                 Expression expr, trueExpr, falseExpr;
3510                 
3511                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
3512                 {
3513                         this.expr = expr;
3514                         this.trueExpr = trueExpr;
3515                         this.falseExpr = falseExpr;
3516                         this.loc = l;
3517                 }
3518
3519                 public Expression Expr {
3520                         get {
3521                                 return expr;
3522                         }
3523                 }
3524
3525                 public Expression TrueExpr {
3526                         get {
3527                                 return trueExpr;
3528                         }
3529                 }
3530
3531                 public Expression FalseExpr {
3532                         get {
3533                                 return falseExpr;
3534                         }
3535                 }
3536
3537                 public override Expression DoResolve (EmitContext ec)
3538                 {
3539                         expr = expr.Resolve (ec);
3540
3541                         if (expr == null)
3542                                 return null;
3543                         
3544                         if (expr.Type != TypeManager.bool_type){
3545                                 expr = Expression.ResolveBoolean (
3546                                         ec, expr, loc);
3547                                 
3548                                 if (expr == null)
3549                                         return null;
3550                         }
3551                         
3552                         trueExpr = trueExpr.Resolve (ec);
3553                         falseExpr = falseExpr.Resolve (ec);
3554
3555                         if (trueExpr == null || falseExpr == null)
3556                                 return null;
3557
3558                         eclass = ExprClass.Value;
3559                         if (trueExpr.Type == falseExpr.Type)
3560                                 type = trueExpr.Type;
3561                         else {
3562                                 Expression conv;
3563                                 Type true_type = trueExpr.Type;
3564                                 Type false_type = falseExpr.Type;
3565
3566                                 if (trueExpr is NullLiteral){
3567                                         type = false_type;
3568                                         return this;
3569                                 } else if (falseExpr is NullLiteral){
3570                                         type = true_type;
3571                                         return this;
3572                                 }
3573                                 
3574                                 //
3575                                 // First, if an implicit conversion exists from trueExpr
3576                                 // to falseExpr, then the result type is of type falseExpr.Type
3577                                 //
3578                                 conv = Convert.ImplicitConversion (ec, trueExpr, false_type, loc);
3579                                 if (conv != null){
3580                                         //
3581                                         // Check if both can convert implicitl to each other's type
3582                                         //
3583                                         if (Convert.ImplicitConversion (ec, falseExpr, true_type, loc) != null){
3584                                                 Error (172,
3585                                                        "Can not compute type of conditional expression " +
3586                                                        "as `" + TypeManager.CSharpName (trueExpr.Type) +
3587                                                        "' and `" + TypeManager.CSharpName (falseExpr.Type) +
3588                                                        "' convert implicitly to each other");
3589                                                 return null;
3590                                         }
3591                                         type = false_type;
3592                                         trueExpr = conv;
3593                                 } else if ((conv = Convert.ImplicitConversion(ec, falseExpr, true_type,loc))!= null){
3594                                         type = true_type;
3595                                         falseExpr = conv;
3596                                 } else {
3597                                         Error (173, "The type of the conditional expression can " +
3598                                                "not be computed because there is no implicit conversion" +
3599                                                " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
3600                                                " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
3601                                         return null;
3602                                 }
3603                         }
3604
3605                         if (expr is BoolConstant){
3606                                 BoolConstant bc = (BoolConstant) expr;
3607
3608                                 if (bc.Value)
3609                                         return trueExpr;
3610                                 else
3611                                         return falseExpr;
3612                         }
3613
3614                         return this;
3615                 }
3616
3617                 public override void Emit (EmitContext ec)
3618                 {
3619                         ILGenerator ig = ec.ig;
3620                         Label false_target = ig.DefineLabel ();
3621                         Label end_target = ig.DefineLabel ();
3622
3623                         expr.EmitBranchable (ec, false_target, false);
3624                         trueExpr.Emit (ec);
3625                         ig.Emit (OpCodes.Br, end_target);
3626                         ig.MarkLabel (false_target);
3627                         falseExpr.Emit (ec);
3628                         ig.MarkLabel (end_target);
3629                 }
3630
3631         }
3632
3633         /// <summary>
3634         ///   Local variables
3635         /// </summary>
3636         public class LocalVariableReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
3637                 public readonly string Name;
3638                 public readonly Block Block;
3639                 LocalInfo local_info;
3640                 bool is_readonly;
3641                 
3642                 public LocalVariableReference (Block block, string name, Location l)
3643                 {
3644                         Block = block;
3645                         Name = name;
3646                         loc = l;
3647                         eclass = ExprClass.Variable;
3648                 }
3649
3650                 // Setting `is_readonly' to false will allow you to create a writable
3651                 // reference to a read-only variable.  This is used by foreach and using.
3652                 public LocalVariableReference (Block block, string name, Location l,
3653                                                LocalInfo local_info, bool is_readonly)
3654                         : this (block, name, l)
3655                 {
3656                         this.local_info = local_info;
3657                         this.is_readonly = is_readonly;
3658                 }
3659
3660                 public VariableInfo VariableInfo {
3661                         get { return local_info.VariableInfo; }
3662                 }
3663
3664                 public bool IsReadOnly {
3665                         get {
3666                                 return is_readonly;
3667                         }
3668                 }
3669
3670                 protected void DoResolveBase (EmitContext ec)
3671                 {
3672                         if (local_info == null) {
3673                                 local_info = Block.GetLocalInfo (Name);
3674                                 is_readonly = local_info.ReadOnly;
3675                         }
3676
3677                         type = local_info.VariableType;
3678 #if false
3679                         if (ec.InAnonymousMethod)
3680                                 Block.LiftVariable (local_info);
3681 #endif
3682                 }
3683                 
3684                 protected Expression DoResolve (EmitContext ec, bool is_lvalue)
3685                 {
3686                         Expression e = Block.GetConstantExpression (Name);
3687                         if (e != null) {
3688                                 local_info.Used = true;
3689                                 eclass = ExprClass.Value;
3690                                 return e;
3691                         }
3692
3693                         VariableInfo variable_info = local_info.VariableInfo; 
3694                         if ((variable_info != null) && !variable_info.IsAssigned (ec, loc))
3695                                 return null;
3696
3697                         if (!is_lvalue)
3698                                 local_info.Used = true;
3699
3700                         if (local_info.LocalBuilder == null)
3701                                 return ec.RemapLocal (local_info);
3702                         
3703                         return this;
3704                 }
3705
3706                 public override Expression DoResolve (EmitContext ec)
3707                 {
3708                         DoResolveBase (ec);
3709
3710                         return DoResolve (ec, false);
3711                 }
3712
3713                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3714                 {
3715                         DoResolveBase (ec);
3716
3717                         VariableInfo variable_info = local_info.VariableInfo; 
3718                         if (variable_info != null)
3719                                 variable_info.SetAssigned (ec);
3720
3721                         Expression e = DoResolve (ec, true);
3722
3723                         if (e == null)
3724                                 return null;
3725
3726                         if (is_readonly){
3727                                 Error (1604, "cannot assign to `" + Name + "' because it is readonly");
3728                                 return null;
3729                         }
3730
3731                         if (local_info.LocalBuilder == null)
3732                                 return ec.RemapLocalLValue (local_info, right_side);
3733                         
3734                         return this;
3735                 }
3736
3737                 public bool VerifyFixed (bool is_expression)
3738                 {
3739                         return !is_expression || local_info.IsFixed;
3740                 }
3741
3742                 public override void Emit (EmitContext ec)
3743                 {
3744                         ILGenerator ig = ec.ig;
3745
3746                         ig.Emit (OpCodes.Ldloc, local_info.LocalBuilder);
3747                 }
3748                 
3749                 public void EmitAssign (EmitContext ec, Expression source)
3750                 {
3751                         ILGenerator ig = ec.ig;
3752
3753                         source.Emit (ec);
3754                         ig.Emit (OpCodes.Stloc, local_info.LocalBuilder);
3755                 }
3756                 
3757                 public void AddressOf (EmitContext ec, AddressOp mode)
3758                 {
3759                         ILGenerator ig = ec.ig;
3760                         
3761                         ig.Emit (OpCodes.Ldloca, local_info.LocalBuilder);
3762                 }
3763
3764                 public override string ToString ()
3765                 {
3766                         return String.Format ("{0} ({1}:{2})", GetType (), Name, loc);
3767                 }
3768         }
3769
3770         /// <summary>
3771         ///   This represents a reference to a parameter in the intermediate
3772         ///   representation.
3773         /// </summary>
3774         public class ParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable {
3775                 Parameters pars;
3776                 String name;
3777                 int idx;
3778                 Block block;
3779                 VariableInfo vi;
3780                 public Parameter.Modifier mod;
3781                 public bool is_ref, is_out;
3782                 
3783                 public ParameterReference (Parameters pars, Block block, int idx, string name, Location loc)
3784                 {
3785                         this.pars = pars;
3786                         this.block = block;
3787                         this.idx  = idx;
3788                         this.name = name;
3789                         this.loc = loc;
3790                         eclass = ExprClass.Variable;
3791                 }
3792
3793                 public VariableInfo VariableInfo {
3794                         get { return vi; }
3795                 }
3796
3797                 public bool VerifyFixed (bool is_expression)
3798                 {
3799                         return !is_expression || TypeManager.IsValueType (type);
3800                 }
3801
3802                 public bool IsAssigned (EmitContext ec, Location loc)
3803                 {
3804                         if (!ec.DoFlowAnalysis || !is_out ||
3805                             ec.CurrentBranching.IsAssigned (vi))
3806                                 return true;
3807
3808                         Report.Error (165, loc,
3809                                       "Use of unassigned parameter `" + name + "'");
3810                         return false;
3811                 }
3812
3813                 public bool IsFieldAssigned (EmitContext ec, string field_name, Location loc)
3814                 {
3815                         if (!ec.DoFlowAnalysis || !is_out ||
3816                             ec.CurrentBranching.IsFieldAssigned (vi, field_name))
3817                                 return true;
3818
3819                         Report.Error (170, loc,
3820                                       "Use of possibly unassigned field `" + field_name + "'");
3821                         return false;
3822                 }
3823
3824                 public void SetAssigned (EmitContext ec)
3825                 {
3826                         if (is_out && ec.DoFlowAnalysis)
3827                                 ec.CurrentBranching.SetAssigned (vi);
3828                 }
3829
3830                 public void SetFieldAssigned (EmitContext ec, string field_name)
3831                 {
3832                         if (is_out && ec.DoFlowAnalysis)
3833                                 ec.CurrentBranching.SetFieldAssigned (vi, field_name);
3834                 }
3835
3836                 protected void DoResolveBase (EmitContext ec)
3837                 {
3838                         type = pars.GetParameterInfo (ec.DeclSpace, idx, out mod);
3839                         is_ref = (mod & Parameter.Modifier.ISBYREF) != 0;
3840                         is_out = (mod & Parameter.Modifier.OUT) != 0;
3841                         eclass = ExprClass.Variable;
3842
3843                         if (is_out)
3844                                 vi = block.ParameterMap [idx];
3845                 }
3846
3847                 //
3848                 // Notice that for ref/out parameters, the type exposed is not the
3849                 // same type exposed externally.
3850                 //
3851                 // for "ref int a":
3852                 //   externally we expose "int&"
3853                 //   here we expose       "int".
3854                 //
3855                 // We record this in "is_ref".  This means that the type system can treat
3856                 // the type as it is expected, but when we generate the code, we generate
3857                 // the alternate kind of code.
3858                 //
3859                 public override Expression DoResolve (EmitContext ec)
3860                 {
3861                         DoResolveBase (ec);
3862
3863                         if (is_out && ec.DoFlowAnalysis && !IsAssigned (ec, loc))
3864                                 return null;
3865
3866                         if (ec.RemapToProxy)
3867                                 return ec.RemapParameter (idx);
3868                         
3869                         return this;
3870                 }
3871
3872                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
3873                 {
3874                         DoResolveBase (ec);
3875
3876                         SetAssigned (ec);
3877
3878                         if (ec.RemapToProxy)
3879                                 return ec.RemapParameterLValue (idx, right_side);
3880                         
3881                         return this;
3882                 }
3883
3884                 static public void EmitLdArg (ILGenerator ig, int x)
3885                 {
3886                         if (x <= 255){
3887                                 switch (x){
3888                                 case 0: ig.Emit (OpCodes.Ldarg_0); break;
3889                                 case 1: ig.Emit (OpCodes.Ldarg_1); break;
3890                                 case 2: ig.Emit (OpCodes.Ldarg_2); break;
3891                                 case 3: ig.Emit (OpCodes.Ldarg_3); break;
3892                                 default: ig.Emit (OpCodes.Ldarg_S, (byte) x); break;
3893                                 }
3894                         } else
3895                                 ig.Emit (OpCodes.Ldarg, x);
3896                 }
3897                 
3898                 //
3899                 // This method is used by parameters that are references, that are
3900                 // being passed as references:  we only want to pass the pointer (that
3901                 // is already stored in the parameter, not the address of the pointer,
3902                 // and not the value of the variable).
3903                 //
3904                 public void EmitLoad (EmitContext ec)
3905                 {
3906                         ILGenerator ig = ec.ig;
3907                         int arg_idx = idx;
3908
3909                         if (!ec.IsStatic)
3910                                 arg_idx++;
3911
3912                         EmitLdArg (ig, arg_idx);
3913                 }
3914                 
3915                 public override void Emit (EmitContext ec)
3916                 {
3917                         ILGenerator ig = ec.ig;
3918                         
3919                         int arg_idx = idx;
3920
3921                         if (!ec.IsStatic)
3922                                 arg_idx++;
3923
3924                         EmitLdArg (ig, arg_idx);
3925
3926                         if (!is_ref)
3927                                 return;
3928
3929                         //
3930                         // If we are a reference, we loaded on the stack a pointer
3931                         // Now lets load the real value
3932                         //
3933                         LoadFromPtr (ig, type);
3934                 }
3935
3936                 public void EmitAssign (EmitContext ec, Expression source)
3937                 {
3938                         ILGenerator ig = ec.ig;
3939                         
3940                         int arg_idx = idx;
3941
3942                         if (!ec.IsStatic)
3943                                 arg_idx++;
3944
3945                         if (is_ref)
3946                                 EmitLdArg (ig, arg_idx);
3947                         
3948                         source.Emit (ec);
3949
3950                         if (is_ref)
3951                                 StoreFromPtr (ig, type);
3952                         else {
3953                                 if (arg_idx <= 255)
3954                                         ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
3955                                 else
3956                                         ig.Emit (OpCodes.Starg, arg_idx);
3957                         }
3958                 }
3959
3960                 public void AddressOf (EmitContext ec, AddressOp mode)
3961                 {
3962                         int arg_idx = idx;
3963
3964                         if (!ec.IsStatic)
3965                                 arg_idx++;
3966
3967                         if (is_ref){
3968                                 if (arg_idx <= 255)
3969                                         ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
3970                                 else
3971                                         ec.ig.Emit (OpCodes.Ldarg, arg_idx);
3972                         } else {
3973                                 if (arg_idx <= 255)
3974                                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
3975                                 else
3976                                         ec.ig.Emit (OpCodes.Ldarga, arg_idx);
3977                         }
3978                 }
3979
3980         }
3981         
3982         /// <summary>
3983         ///   Used for arguments to New(), Invocation()
3984         /// </summary>
3985         public class Argument {
3986                 public enum AType : byte {
3987                         Expression,
3988                         Ref,
3989                         Out
3990                 };
3991
3992                 public readonly AType ArgType;
3993                 public Expression Expr;
3994                 
3995                 public Argument (Expression expr, AType type)
3996                 {
3997                         this.Expr = expr;
3998                         this.ArgType = type;
3999                 }
4000
4001                 public Type Type {
4002                         get {
4003                                 if (ArgType == AType.Ref || ArgType == AType.Out)
4004                                         return TypeManager.GetReferenceType (Expr.Type);
4005                                 else
4006                                         return Expr.Type;
4007                         }
4008                 }
4009
4010                 public Parameter.Modifier GetParameterModifier ()
4011                 {
4012                         switch (ArgType) {
4013                         case AType.Out:
4014                                 return Parameter.Modifier.OUT | Parameter.Modifier.ISBYREF;
4015
4016                         case AType.Ref:
4017                                 return Parameter.Modifier.REF | Parameter.Modifier.ISBYREF;
4018
4019                         default:
4020                                 return Parameter.Modifier.NONE;
4021                         }
4022                 }
4023
4024                 public static string FullDesc (Argument a)
4025                 {
4026                         return (a.ArgType == AType.Ref ? "ref " :
4027                                 (a.ArgType == AType.Out ? "out " : "")) +
4028                                 TypeManager.CSharpName (a.Expr.Type);
4029                 }
4030
4031                 public bool ResolveMethodGroup (EmitContext ec, Location loc)
4032                 {
4033                         ConstructedType ctype = Expr as ConstructedType;
4034                         if (ctype != null)
4035                                 Expr = ctype.GetMemberAccess (ec);
4036
4037                         // FIXME: csc doesn't report any error if you try to use `ref' or
4038                         //        `out' in a delegate creation expression.
4039                         Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
4040                         if (Expr == null)
4041                                 return false;
4042
4043                         return true;
4044                 }
4045                 
4046                 public bool Resolve (EmitContext ec, Location loc)
4047                 {
4048                         if (ArgType == AType.Ref) {
4049                                 Expr = Expr.Resolve (ec);
4050                                 if (Expr == null)
4051                                         return false;
4052
4053                                 Expr = Expr.ResolveLValue (ec, Expr);
4054                         } else if (ArgType == AType.Out)
4055                                 Expr = Expr.ResolveLValue (ec, new EmptyExpression ());
4056                         else
4057                                 Expr = Expr.Resolve (ec);
4058
4059                         if (Expr == null)
4060                                 return false;
4061
4062                         if (ArgType == AType.Expression)
4063                                 return true;
4064                         else {
4065                                 //
4066                                 // Catch errors where fields of a MarshalByRefObject are passed as ref or out
4067                                 // This is only allowed for `this'
4068                                 //
4069                                 FieldExpr fe = Expr as FieldExpr;
4070                                 if (fe != null && !fe.IsStatic){
4071                                         Expression instance = fe.InstanceExpression;
4072
4073                                         if (instance.GetType () != typeof (This)){
4074                                                 if (fe.InstanceExpression.Type.IsSubclassOf (TypeManager.mbr_type)){
4075                                                         Report.Error (197, loc,
4076                                                                       "Can not pass a type that derives from MarshalByRefObject with out or ref");
4077                                                         return false;
4078                                                 }
4079                                         }
4080                                 }
4081                         }
4082
4083                         if (Expr.eclass != ExprClass.Variable){
4084                                 //
4085                                 // We just probe to match the CSC output
4086                                 //
4087                                 if (Expr.eclass == ExprClass.PropertyAccess ||
4088                                     Expr.eclass == ExprClass.IndexerAccess){
4089                                         Report.Error (
4090                                                 206, loc,
4091                                                 "A property or indexer can not be passed as an out or ref " +
4092                                                 "parameter");
4093                                 } else {
4094                                         Report.Error (
4095                                                 1510, loc,
4096                                                 "An lvalue is required as an argument to out or ref");
4097                                 }
4098                                 return false;
4099                         }
4100                                 
4101                         return true;
4102                 }
4103
4104                 public void Emit (EmitContext ec)
4105                 {
4106                         //
4107                         // Ref and Out parameters need to have their addresses taken.
4108                         //
4109                         // ParameterReferences might already be references, so we want
4110                         // to pass just the value
4111                         //
4112                         if (ArgType == AType.Ref || ArgType == AType.Out){
4113                                 AddressOp mode = AddressOp.Store;
4114
4115                                 if (ArgType == AType.Ref)
4116                                         mode |= AddressOp.Load;
4117                                 
4118                                 if (Expr is ParameterReference){
4119                                         ParameterReference pr = (ParameterReference) Expr;
4120
4121                                         if (pr.is_ref)
4122                                                 pr.EmitLoad (ec);
4123                                         else {
4124                                                 
4125                                                 pr.AddressOf (ec, mode);
4126                                         }
4127                                 } else {
4128                                         ((IMemoryLocation)Expr).AddressOf (ec, mode);
4129                                 }
4130                         } else
4131                                 Expr.Emit (ec);
4132                 }
4133         }
4134
4135         /// <summary>
4136         ///   Invocation of methods or delegates.
4137         /// </summary>
4138         public class Invocation : ExpressionStatement {
4139                 public readonly ArrayList Arguments;
4140
4141                 Expression expr;
4142                 MethodBase method = null;
4143                 bool is_base;
4144                 
4145                 static Hashtable method_parameter_cache;
4146
4147                 static Invocation ()
4148                 {
4149                         method_parameter_cache = new PtrHashtable ();
4150                 }
4151                         
4152                 //
4153                 // arguments is an ArrayList, but we do not want to typecast,
4154                 // as it might be null.
4155                 //
4156                 // FIXME: only allow expr to be a method invocation or a
4157                 // delegate invocation (7.5.5)
4158                 //
4159                 public Invocation (Expression expr, ArrayList arguments, Location l)
4160                 {
4161                         this.expr = expr;
4162                         Arguments = arguments;
4163                         loc = l;
4164                 }
4165
4166                 public Expression Expr {
4167                         get {
4168                                 return expr;
4169                         }
4170                 }
4171
4172                 /// <summary>
4173                 ///   Returns the Parameters (a ParameterData interface) for the
4174                 ///   Method `mb'
4175                 /// </summary>
4176                 public static ParameterData GetParameterData (MethodBase mb)
4177                 {
4178                         object pd = method_parameter_cache [mb];
4179                         object ip;
4180                         
4181                         if (pd != null)
4182                                 return (ParameterData) pd;
4183
4184                         ip = TypeManager.LookupParametersByBuilder (mb);
4185                         if (ip != null){
4186                                 method_parameter_cache [mb] = ip;
4187
4188                                 return (ParameterData) ip;
4189                         } else {
4190                                 ReflectionParameters rp = new ReflectionParameters (mb);
4191                                 method_parameter_cache [mb] = rp;
4192
4193                                 return (ParameterData) rp;
4194                         }
4195                 }
4196
4197                 /// <summary>
4198                 ///   Determines "better conversion" as specified in 7.4.2.3
4199                 ///
4200                 ///    Returns : 1 if a->p is better
4201                 ///              0 if a->q or neither is better 
4202                 /// </summary>
4203                 static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, Location loc)
4204                 {
4205                         Type argument_type = a.Type;
4206                         Expression argument_expr = a.Expr;
4207
4208                         if (argument_type == null)
4209                                 throw new Exception ("Expression of type " + a.Expr +
4210                                                      " does not resolve its type");
4211
4212                         //
4213                         // This is a special case since csc behaves this way.
4214                         //
4215                         if (argument_expr is NullLiteral &&
4216                             p == TypeManager.string_type &&
4217                             q == TypeManager.object_type)
4218                                 return 1;
4219                         else if (argument_expr is NullLiteral &&
4220                                  p == TypeManager.object_type &&
4221                                  q == TypeManager.string_type)
4222                                 return 0;
4223                         
4224                         //
4225                         // csc behaves this way so we emulate it. Basically, if the argument
4226                         // is null and one of the types to compare is 'object' and the other
4227                         // is a reference type, we prefer the other.
4228                         //
4229                         // I can't find this anywhere in the spec but we can interpret this
4230                         // to mean that null can be of any type you wish in such a context
4231                         //
4232                         if (p != null && q != null) {
4233                                 if (argument_expr is NullLiteral &&
4234                                     !p.IsValueType &&
4235                                     q == TypeManager.object_type)
4236                                         return 1;
4237                                 else if (argument_expr is NullLiteral &&
4238                                          !q.IsValueType &&
4239                                          p == TypeManager.object_type)
4240                                         return 0;
4241                         }
4242                                 
4243                         if (p == q)
4244                                 return 0;
4245                         
4246                         if (argument_type == p)
4247                                 return 1;
4248
4249                         if (argument_type == q)
4250                                 return 0;
4251
4252                         //
4253                         // Now probe whether an implicit constant expression conversion
4254                         // can be used.
4255                         //
4256                         // An implicit constant expression conversion permits the following
4257                         // conversions:
4258                         //
4259                         //    * A constant-expression of type `int' can be converted to type
4260                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
4261                         //      of the expression is withing the range of the destination type.
4262                         //
4263                         //    * A constant-expression of type long can be converted to type
4264                         //      ulong, provided the value of the constant expression is not negative
4265                         //
4266                         // FIXME: Note that this assumes that constant folding has
4267                         // taken place.  We dont do constant folding yet.
4268                         //
4269
4270                         if (argument_expr is IntConstant){
4271                                 IntConstant ei = (IntConstant) argument_expr;
4272                                 int value = ei.Value;
4273
4274                                 if (p == TypeManager.sbyte_type){
4275                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
4276                                                 return 1;
4277                                 } else if (p == TypeManager.byte_type){
4278                                         if (q == TypeManager.sbyte_type &&
4279                                             value >= SByte.MinValue && value <= SByte.MaxValue)
4280                                                 return 0;
4281                                         else if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
4282                                                 return 1;
4283                                 } else if (p == TypeManager.short_type){
4284                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
4285                                                 return 1;
4286                                 } else if (p == TypeManager.ushort_type){
4287                                         if (q == TypeManager.short_type &&
4288                                             value >= Int16.MinValue && value <= Int16.MaxValue)
4289                                                 return 0;
4290                                         else if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
4291                                                 return 1;
4292                                 } else if (p == TypeManager.int32_type){
4293                                         if (value >= Int32.MinValue && value <= Int32.MaxValue)
4294                                                 return 1;
4295                                 } else if (p == TypeManager.uint32_type){
4296                                         //
4297                                         // we can optimize this case: a positive int32
4298                                         // always fits on a uint32
4299                                         //
4300                                         if (value >= 0)
4301                                                 return 1;
4302                                 } else if (p == TypeManager.uint64_type){
4303                                         //
4304                                         // we can optimize this case: a positive int32
4305                                         // always fits on a uint64
4306                                         //
4307
4308                                         //
4309                                         // This special case is needed because csc behaves like this.
4310                                         // int -> uint is better than int -> ulong!
4311                                         //
4312                                         if (q == TypeManager.uint32_type)
4313                                                 return 0;
4314                                         
4315                                         if (q == TypeManager.int64_type)
4316                                                 return 0;
4317                                         else if (value >= 0)
4318                                                 return 1;
4319                                 } else if (p == TypeManager.int64_type){
4320                                         return 1;
4321                                 }
4322                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongConstant){
4323                                 LongConstant lc = (LongConstant) argument_expr;
4324                                 
4325                                 if (p == TypeManager.uint64_type){
4326                                         if (lc.Value > 0)
4327                                                 return 1;
4328                                 }
4329                         }
4330
4331                         if (q == null) {
4332                                 Expression tmp = Convert.ImplicitConversion (ec, argument_expr, p, loc);
4333                                 
4334                                 if (tmp != null)
4335                                         return 1;
4336                                 else
4337                                         return 0;
4338                         }
4339
4340                         Expression p_tmp = new EmptyExpression (p);
4341                         Expression q_tmp = new EmptyExpression (q);
4342                         
4343                         if (Convert.ImplicitConversionExists (ec, p_tmp, q) == true &&
4344                             Convert.ImplicitConversionExists (ec, q_tmp, p) == false)
4345                                 return 1;
4346
4347                         if (p == TypeManager.sbyte_type)
4348                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
4349                                     q == TypeManager.uint32_type || q == TypeManager.uint64_type)
4350                                         return 1;
4351
4352                         if (p == TypeManager.short_type)
4353                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
4354                                     q == TypeManager.uint64_type)
4355                                         return 1;
4356
4357                         if (p == TypeManager.int32_type)
4358                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
4359                                         return 1;
4360
4361                         if (p == TypeManager.int64_type)
4362                                 if (q == TypeManager.uint64_type)
4363                                         return 1;
4364
4365                         return 0;
4366                 }
4367                 
4368                 /// <summary>
4369                 ///   Determines "Better function" between candidate
4370                 ///   and the current best match
4371                 /// </summary>
4372                 /// <remarks>
4373                 ///    Returns an integer indicating :
4374                 ///     0 if candidate ain't better
4375                 ///     1 if candidate is better than the current best match
4376                 /// </remarks>
4377                 static int BetterFunction (EmitContext ec, ArrayList args,
4378                                            MethodBase candidate, bool candidate_params,
4379                                            MethodBase best, bool best_params,
4380                                            Location loc)
4381                 {
4382                         ParameterData candidate_pd = GetParameterData (candidate);
4383                         ParameterData best_pd;
4384                         int argument_count;
4385                 
4386                         if (args == null)
4387                                 argument_count = 0;
4388                         else
4389                                 argument_count = args.Count;
4390
4391                         int cand_count = candidate_pd.Count;
4392
4393                         //
4394                         // If there is no best method, than this one
4395                         // is better, however, if we already found a
4396                         // best method, we cant tell. This happens
4397                         // if we have:
4398                         // 
4399                         //      interface IFoo {
4400                         //              void DoIt ();
4401                         //      }
4402                         //      
4403                         //      interface IBar {
4404                         //              void DoIt ();
4405                         //      }
4406                         //      
4407                         //      interface IFooBar : IFoo, IBar {}
4408                         //
4409                         // We cant tell if IFoo.DoIt is better than IBar.DoIt
4410                         //
4411                         // However, we have to consider that
4412                         // Trim (); is better than Trim (params char[] chars);
4413                         //
4414                         if (cand_count == 0 && argument_count == 0)
4415                                 return best == null || best_params ? 1 : 0;
4416
4417                         if (candidate_pd.ParameterModifier (cand_count - 1) != Parameter.Modifier.PARAMS)
4418                                 if (cand_count != argument_count)
4419                                         return 0;
4420
4421                         if (best == null) {
4422                                 int x = 0;
4423
4424                                 if (argument_count == 0 && cand_count == 1 &&
4425                                     candidate_pd.ParameterModifier (cand_count - 1) == Parameter.Modifier.PARAMS)
4426                                         return 1;
4427                                 
4428                                 for (int j = 0; j < argument_count; ++j) {
4429
4430                                         Argument a = (Argument) args [j];
4431                                         Type t = candidate_pd.ParameterType (j);
4432
4433                                         if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
4434                                                 if (candidate_params)
4435                                                         t = TypeManager.GetElementType (t);
4436
4437                                         x = BetterConversion (ec, a, t, null, loc);
4438                                         
4439                                         if (x <= 0)
4440                                                 break;
4441                                 }
4442
4443                                 if (x > 0)
4444                                         return 1;
4445                                 else
4446                                         return 0;
4447                         }
4448
4449                         best_pd = GetParameterData (best);
4450
4451                         int rating1 = 0, rating2 = 0;
4452                         
4453                         for (int j = 0; j < argument_count; ++j) {
4454                                 int x, y;
4455                                 
4456                                 Argument a = (Argument) args [j];
4457
4458                                 Type ct = candidate_pd.ParameterType (j);
4459                                 Type bt = best_pd.ParameterType (j);
4460
4461                                 if (candidate_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
4462                                         if (candidate_params)
4463                                                 ct = TypeManager.GetElementType (ct);
4464
4465                                 if (best_pd.ParameterModifier (j) == Parameter.Modifier.PARAMS)
4466                                         if (best_params)
4467                                                 bt = TypeManager.GetElementType (bt);
4468
4469                                 x = BetterConversion (ec, a, ct, bt, loc);
4470                                 y = BetterConversion (ec, a, bt, ct, loc);
4471
4472                                 if (x < y)
4473                                         return 0;
4474                                 
4475                                 rating1 += x;
4476                                 rating2 += y;
4477                         }
4478
4479                         //
4480                         // If a method (in the normal form) with the
4481                         // same signature as the expanded form of the
4482                         // current best params method already exists,
4483                         // the expanded form is not applicable so we
4484                         // force it to select the candidate
4485                         //
4486                         if (!candidate_params && best_params && cand_count == argument_count)
4487                                 return 1;
4488
4489                         if (rating1 > rating2)
4490                                 return 1;
4491                         else
4492                                 return 0;
4493                 }
4494
4495                 public static string FullMethodDesc (MethodBase mb)
4496                 {
4497                         string ret_type = "";
4498
4499                         if (mb == null)
4500                                 return "";
4501
4502                         if (mb is MethodInfo)
4503                                 ret_type = TypeManager.CSharpName (((MethodInfo) mb).ReturnType);
4504                         
4505                         StringBuilder sb = new StringBuilder (ret_type);
4506                         sb.Append (" ");
4507                         sb.Append (mb.ReflectedType.ToString ());
4508                         sb.Append (".");
4509                         sb.Append (mb.Name);
4510                         
4511                         ParameterData pd = GetParameterData (mb);
4512
4513                         int count = pd.Count;
4514                         sb.Append (" (");
4515                         
4516                         for (int i = count; i > 0; ) {
4517                                 i--;
4518
4519                                 sb.Append (pd.ParameterDesc (count - i - 1));
4520                                 if (i != 0)
4521                                         sb.Append (", ");
4522                         }
4523                         
4524                         sb.Append (")");
4525                         return sb.ToString ();
4526                 }
4527
4528                 public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2, Location loc)
4529                 {
4530                         MemberInfo [] miset;
4531                         MethodGroupExpr union;
4532
4533                         if (mg1 == null) {
4534                                 if (mg2 == null)
4535                                         return null;
4536                                 return (MethodGroupExpr) mg2;
4537                         } else {
4538                                 if (mg2 == null)
4539                                         return (MethodGroupExpr) mg1;
4540                         }
4541                         
4542                         MethodGroupExpr left_set = null, right_set = null;
4543                         int length1 = 0, length2 = 0;
4544                         
4545                         left_set = (MethodGroupExpr) mg1;
4546                         length1 = left_set.Methods.Length;
4547                         
4548                         right_set = (MethodGroupExpr) mg2;
4549                         length2 = right_set.Methods.Length;
4550                         
4551                         ArrayList common = new ArrayList ();
4552
4553                         foreach (MethodBase r in right_set.Methods){
4554                                 if (TypeManager.ArrayContainsMethod (left_set.Methods, r))
4555                                         common.Add (r);
4556                         }
4557
4558                         miset = new MemberInfo [length1 + length2 - common.Count];
4559                         left_set.Methods.CopyTo (miset, 0);
4560                         
4561                         int k = length1;
4562
4563                         foreach (MethodBase r in right_set.Methods) {
4564                                 if (!common.Contains (r))
4565                                         miset [k++] = r;
4566                         }
4567
4568                         union = new MethodGroupExpr (miset, loc);
4569                         
4570                         return union;
4571                 }
4572
4573                 static bool IsParamsMethodApplicable (EmitContext ec, MethodGroupExpr me,
4574                                                       ArrayList arguments, ref MethodBase candidate)
4575                 {
4576                         if (!me.HasTypeArguments &&
4577                             !InferParamsTypeArguments (ec, arguments, ref candidate))
4578                                 return false;
4579
4580                         return IsParamsMethodApplicable (ec, arguments, candidate);
4581                 }
4582
4583                 /// <summary>
4584                 ///   Determines if the candidate method, if a params method, is applicable
4585                 ///   in its expanded form to the given set of arguments
4586                 /// </summary>
4587                 static bool IsParamsMethodApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
4588                 {
4589                         int arg_count;
4590                         
4591                         if (arguments == null)
4592                                 arg_count = 0;
4593                         else
4594                                 arg_count = arguments.Count;
4595                         
4596                         ParameterData pd = GetParameterData (candidate);
4597                         
4598                         int pd_count = pd.Count;
4599
4600                         if (pd_count == 0)
4601                                 return false;
4602                         
4603                         if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
4604                                 return false;
4605                         
4606                         if (pd_count - 1 > arg_count)
4607                                 return false;
4608                         
4609                         if (pd_count == 1 && arg_count == 0)
4610                                 return true;
4611
4612                         //
4613                         // If we have come this far, the case which
4614                         // remains is when the number of parameters is
4615                         // less than or equal to the argument count.
4616                         //
4617                         for (int i = 0; i < pd_count - 1; ++i) {
4618
4619                                 Argument a = (Argument) arguments [i];
4620
4621                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
4622                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4623                                 Parameter.Modifier p_mod = pd.ParameterModifier (i) &
4624                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4625
4626                                 if (a_mod == p_mod) {
4627
4628                                         if (a_mod == Parameter.Modifier.NONE)
4629                                                 if (!Convert.ImplicitConversionExists (ec,
4630                                                                                        a.Expr,
4631                                                                                        pd.ParameterType (i)))
4632                                                         return false;
4633                                                                                 
4634                                         if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
4635                                                 Type pt = pd.ParameterType (i);
4636
4637                                                 if (!pt.IsByRef)
4638                                                         pt = TypeManager.GetReferenceType (pt);
4639                                                 
4640                                                 if (pt != a.Type)
4641                                                         return false;
4642                                         }
4643                                 } else
4644                                         return false;
4645                                 
4646                         }
4647
4648                         Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
4649
4650                         for (int i = pd_count - 1; i < arg_count; i++) {
4651                                 Argument a = (Argument) arguments [i];
4652                                 
4653                                 if (!Convert.ImplicitConversionExists (ec, a.Expr, element_type))
4654                                         return false;
4655                         }
4656                         
4657                         return true;
4658                 }
4659
4660                 static bool IsApplicable (EmitContext ec, MethodGroupExpr me,
4661                                           ArrayList arguments, ref MethodBase candidate)
4662                 {
4663                         if (!me.HasTypeArguments &&
4664                             !InferTypeArguments (ec, arguments, ref candidate))
4665                                 return false;
4666
4667                         return IsApplicable (ec, arguments, candidate);
4668                 }
4669
4670                 /// <summary>
4671                 ///   Determines if the candidate method is applicable (section 14.4.2.1)
4672                 ///   to the given set of arguments
4673                 /// </summary>
4674                 static bool IsApplicable (EmitContext ec, ArrayList arguments, MethodBase candidate)
4675                 {
4676                         int arg_count;
4677
4678                         if (arguments == null)
4679                                 arg_count = 0;
4680                         else
4681                                 arg_count = arguments.Count;
4682
4683
4684                         ParameterData pd = GetParameterData (candidate);
4685
4686                         if (arg_count != pd.Count)
4687                                 return false;
4688
4689                         for (int i = arg_count; i > 0; ) {
4690                                 i--;
4691
4692                                 Argument a = (Argument) arguments [i];
4693
4694                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
4695                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4696                                 Parameter.Modifier p_mod = pd.ParameterModifier (i) &
4697                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
4698
4699
4700                                 if (a_mod == p_mod ||
4701                                     (a_mod == Parameter.Modifier.NONE && p_mod == Parameter.Modifier.PARAMS)) {
4702                                         if (a_mod == Parameter.Modifier.NONE) {
4703                                                 if (!Convert.ImplicitConversionExists (ec,
4704                                                                                        a.Expr,
4705                                                                                        pd.ParameterType (i)))
4706                                                         return false;
4707                                         }
4708                                         
4709                                         if ((a_mod & Parameter.Modifier.ISBYREF) != 0) {
4710                                                 Type pt = pd.ParameterType (i);
4711
4712                                                 if (!pt.IsByRef)
4713                                                         pt = TypeManager.GetReferenceType (pt);
4714                                                 
4715                                                 if (pt != a.Type)
4716                                                         return false;
4717                                         }
4718                                 } else
4719                                         return false;
4720                         }
4721
4722                         return true;
4723                 }
4724                 
4725                 /// <summary>
4726                 ///   Find the Applicable Function Members (7.4.2.1)
4727                 ///
4728                 ///   me: Method Group expression with the members to select.
4729                 ///       it might contain constructors or methods (or anything
4730                 ///       that maps to a method).
4731                 ///
4732                 ///   Arguments: ArrayList containing resolved Argument objects.
4733                 ///
4734                 ///   loc: The location if we want an error to be reported, or a Null
4735                 ///        location for "probing" purposes.
4736                 ///
4737                 ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
4738                 ///            that is the best match of me on Arguments.
4739                 ///
4740                 /// </summary>
4741                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
4742                                                           ArrayList Arguments, bool may_fail,
4743                                                           Location loc)
4744                 {
4745                         MethodBase method = null;
4746                         Type applicable_type = null;
4747                         int argument_count;
4748                         ArrayList candidates = new ArrayList ();
4749
4750                         //
4751                         // Used to keep a map between the candidate
4752                         // and whether it is being considered in its
4753                         // normal or expanded form
4754                         //
4755                         // false is normal form, true is expanded form
4756                         //
4757                         Hashtable candidate_to_form = new PtrHashtable ();
4758
4759
4760                         //
4761                         // First we construct the set of applicable methods
4762                         //
4763                         // We start at the top of the type hierarchy and
4764                         // go down to find applicable methods
4765                         //
4766                         applicable_type = me.DeclaringType;
4767                         
4768                         if (me.Name == "Invoke" && TypeManager.IsDelegateType (applicable_type)) {
4769                                 Error_InvokeOnDelegate (loc);
4770                                 return null;
4771                         }
4772
4773                         bool found_applicable = false;
4774
4775                         MethodBase[] methods = me.Methods;
4776
4777                         for (int i = 0; i < methods.Length; i++) {
4778                                 Type decl_type = methods [i].DeclaringType;
4779
4780                                 //
4781                                 // If we have already found an applicable method
4782                                 // we eliminate all base types (Section 14.5.5.1)
4783                                 //
4784                                 if (decl_type != applicable_type &&
4785                                     (applicable_type.IsSubclassOf (decl_type) ||
4786                                      TypeManager.ImplementsInterface (applicable_type, decl_type)) &&
4787                                     found_applicable)
4788                                         continue;
4789
4790                                 // Check if candidate is applicable (section 14.4.2.1)
4791                                 if (IsApplicable (ec, me, Arguments, ref methods [i])) {
4792                                         // Candidate is applicable in normal form
4793                                         MethodBase candidate = methods [i];
4794                                         candidates.Add (candidate);
4795                                         applicable_type = candidate.DeclaringType;
4796                                         found_applicable = true;
4797                                         candidate_to_form [candidate] = false;
4798                                 } else if (IsParamsMethodApplicable (ec, me, Arguments, ref methods [i])) {
4799                                         // Candidate is applicable in expanded form
4800                                         MethodBase candidate = methods [i];
4801                                         candidates.Add (candidate);
4802                                         applicable_type = candidate.DeclaringType;
4803                                         found_applicable = true; 
4804                                         candidate_to_form [candidate] = true;
4805                                 }
4806                         }
4807
4808                         if (Arguments == null)
4809                                 argument_count = 0;
4810                         else
4811                                 argument_count = Arguments.Count;
4812
4813                         //
4814                         // Now we actually find the best method
4815                         //
4816                         int candidate_top = candidates.Count;
4817                         for (int ix = 0; ix < candidate_top; ix++){
4818                                 MethodBase candidate = (MethodBase) candidates [ix];
4819                                 
4820                                 bool cand_params = (bool) candidate_to_form [candidate];
4821                                 bool method_params = false;
4822                                 
4823                                 if (method != null)
4824                                         method_params = (bool) candidate_to_form [method];
4825                                 
4826                                 int x = BetterFunction (ec, Arguments,
4827                                                         candidate, cand_params,
4828                                                         method, method_params,
4829                                                         loc);
4830                                 if (x == 0)
4831                                         continue;
4832                                 
4833                                 method = candidate;
4834                         }
4835
4836                         if (method == null) {
4837                                 int errors = Report.Errors;
4838
4839                                 //
4840                                 // Okay so we have failed to find anything so we
4841                                 // return by providing info about the closest match
4842                                 //
4843                                 for (int i = 0; i < methods.Length; ++i) {
4844
4845                                         MethodBase c = methods [i];
4846                                         if (c == null)
4847                                                 continue;
4848
4849                                         ParameterData pd = GetParameterData (c);
4850                                         if (pd.Count != argument_count)
4851                                                 continue;
4852
4853                                         if (!InferTypeArguments (ec, Arguments, ref c))
4854                                                 continue;
4855
4856                                         VerifyArgumentsCompat (ec, Arguments, argument_count,
4857                                                                c, false, null, loc);
4858                                         break;
4859                                 }
4860
4861                                 if (Report.Errors > errors)
4862                                         return null;
4863
4864                                 string report_name = me.Name;
4865                                 if (report_name == ".ctor")
4866                                         report_name = me.DeclaringType.ToString ();
4867                                         
4868                                 for (int i = 0; i < methods.Length; ++i) {
4869
4870                                         MethodBase c = methods [i];
4871                                         if (c == null)
4872                                                 continue;
4873
4874                                         ParameterData pd = GetParameterData (c);
4875                                         if (pd.Count != argument_count)
4876                                                 continue;
4877
4878                                         if (InferTypeArguments (ec, Arguments, ref c))
4879                                                 continue;
4880
4881                                         Report.Error (411, loc, "The type arguments for " +
4882                                                       "method `{0}' cannot be infered from " +
4883                                                       "the usage. Try specifying the type " +
4884                                                       "arguments explicitly.", report_name);
4885                                         break;
4886                                 }
4887
4888                                 if (!may_fail && (errors == Report.Errors))
4889                                         Error_WrongNumArguments (loc, report_name,
4890                                                                  argument_count);
4891                                 
4892                                 return null;
4893                         }
4894
4895                         //
4896                         // Now check that there are no ambiguities i.e the selected method
4897                         // should be better than all the others
4898                         //
4899                         bool best_params = (bool) candidate_to_form [method];
4900
4901                         for (int ix = 0; ix < candidate_top; ix++){
4902                                 MethodBase candidate = (MethodBase) candidates [ix];
4903
4904                                 if (candidate == method)
4905                                         continue;
4906                                                
4907                                 //
4908                                 // If a normal method is applicable in
4909                                 // the sense that it has the same
4910                                 // number of arguments, then the
4911                                 // expanded params method is never
4912                                 // applicable so we debar the params
4913                                 // method.
4914                                 //
4915                                 // if ((IsParamsMethodApplicable (ec, Arguments, candidate) &&
4916 //                                      IsApplicable (ec, Arguments, method)))
4917 //                                         continue;
4918                                 
4919                                 bool cand_params = (bool) candidate_to_form [candidate];
4920                                 int x = BetterFunction (ec, Arguments,
4921                                                         method, best_params,
4922                                                         candidate, cand_params,
4923                                                         loc);
4924
4925                                 if (x != 1) {
4926                                         Report.Error (
4927                                                 121, loc,
4928                                                 "Ambiguous call when selecting function due to implicit casts");
4929                                         return null;
4930                                 }
4931                         }
4932
4933                         //
4934                         // And now check if the arguments are all
4935                         // compatible, perform conversions if
4936                         // necessary etc. and return if everything is
4937                         // all right
4938                         //
4939                         if (!VerifyArgumentsCompat (ec, Arguments, argument_count, method,
4940                                                     best_params, null, loc))
4941                                 return null;
4942
4943                         return method;
4944                 }
4945
4946                 static void Error_WrongNumArguments (Location loc, String name, int arg_count)
4947                 {
4948                         Report.Error (1501, loc,
4949                                       "No overload for method `" + name + "' takes `" +
4950                                       arg_count + "' arguments");
4951                 }
4952
4953                 static void Error_InvokeOnDelegate (Location loc)
4954                 {
4955                         Report.Error (1533, loc,
4956                                       "Invoke cannot be called directly on a delegate");
4957                 }
4958                         
4959                 static void Error_InvalidArguments (Location loc, int idx, MethodBase method,
4960                                                     Type delegate_type, string arg_sig, string par_desc)
4961                 {
4962                         if (delegate_type == null) 
4963                                 Report.Error (1502, loc,
4964                                               "The best overloaded match for method '" +
4965                                               FullMethodDesc (method) +
4966                                               "' has some invalid arguments");
4967                         else
4968                                 Report.Error (1594, loc,
4969                                               "Delegate '" + delegate_type.ToString () +
4970                                               "' has some invalid arguments.");
4971                         Report.Error (1503, loc,
4972                                       String.Format ("Argument {0}: Cannot convert from '{1}' to '{2}'",
4973                                                      idx, arg_sig, par_desc));
4974                 }
4975                 
4976                 public static bool VerifyArgumentsCompat (EmitContext ec, ArrayList Arguments,
4977                                                           int argument_count,
4978                                                           MethodBase method, 
4979                                                           bool chose_params_expanded,
4980                                                           Type delegate_type,
4981                                                           Location loc)
4982                 {
4983                         ParameterData pd = GetParameterData (method);
4984                         int pd_count = pd.Count;
4985                         
4986                         for (int j = 0; j < argument_count; j++) {
4987                                 Argument a = (Argument) Arguments [j];
4988                                 Expression a_expr = a.Expr;
4989                                 Type parameter_type = pd.ParameterType (j);
4990                                 Parameter.Modifier pm = pd.ParameterModifier (j);
4991                                 
4992                                 if (pm == Parameter.Modifier.PARAMS){
4993                                         if ((pm & ~Parameter.Modifier.PARAMS) != a.GetParameterModifier ()) {
4994                                                 if (!Location.IsNull (loc))
4995                                                         Error_InvalidArguments (
4996                                                                 loc, j, method, delegate_type,
4997                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
4998                                                 return false;
4999                                         }
5000
5001                                         if (chose_params_expanded)
5002                                                 parameter_type = TypeManager.GetElementType (parameter_type);
5003                                 } else {
5004                                         //
5005                                         // Check modifiers
5006                                         //
5007                                         if (pd.ParameterModifier (j) != a.GetParameterModifier ()){
5008                                                 if (!Location.IsNull (loc))
5009                                                         Error_InvalidArguments (
5010                                                                 loc, j, method, delegate_type,
5011                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
5012                                                 return false;
5013                                         }
5014                                 }
5015
5016                                 //
5017                                 // Check Type
5018                                 //
5019                                 if (a.Type != parameter_type){
5020                                         Expression conv;
5021                                         
5022                                         conv = Convert.ImplicitConversion (ec, a_expr, parameter_type, loc);
5023
5024                                         if (conv == null) {
5025                                                 if (!Location.IsNull (loc)) 
5026                                                         Error_InvalidArguments (
5027                                                                 loc, j, method, delegate_type,
5028                                                                 Argument.FullDesc (a), pd.ParameterDesc (j));
5029                                                 return false;
5030                                         }
5031                                         
5032                                         //
5033                                         // Update the argument with the implicit conversion
5034                                         //
5035                                         if (a_expr != conv)
5036                                                 a.Expr = conv;
5037                                 }
5038
5039                                 Parameter.Modifier a_mod = a.GetParameterModifier () &
5040                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
5041                                 Parameter.Modifier p_mod = pd.ParameterModifier (j) &
5042                                         ~(Parameter.Modifier.OUT | Parameter.Modifier.REF);
5043                                 
5044                                 if (a_mod != p_mod &&
5045                                     pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS) {
5046                                         if (!Location.IsNull (loc)) {
5047                                                 Report.Error (1502, loc,
5048                                                        "The best overloaded match for method '" + FullMethodDesc (method)+
5049                                                        "' has some invalid arguments");
5050                                                 Report.Error (1503, loc,
5051                                                        "Argument " + (j+1) +
5052                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
5053                                                        + "' to '" + pd.ParameterDesc (j) + "'");
5054                                         }
5055                                         
5056                                         return false;
5057                                 }
5058                         }
5059
5060                         return true;
5061                 }
5062
5063                 static bool InferType (Type pt, Type at, ref Type[] infered)
5064                 {
5065                         if (pt.IsGenericParameter) {
5066                                 int pos = pt.GenericParameterPosition;
5067
5068                                 if (infered [pos] == null) {
5069                                         Type check = at;
5070                                         while (check.IsArray)
5071                                                 check = check.GetElementType ();
5072
5073                                         if (pt.Equals (check))
5074                                                 return false;
5075
5076                                         infered [pos] = at;
5077                                         return true;
5078                                 }
5079
5080                                 if (infered [pos] != at)
5081                                         return false;
5082
5083                                 return true;
5084                         }
5085
5086                         if (!pt.ContainsGenericParameters)
5087                                 return true;
5088
5089                         if (at.IsArray) {
5090                                 if (!pt.IsArray ||
5091                                     (at.GetArrayRank () != pt.GetArrayRank ()))
5092                                         return false;
5093
5094                                 return InferType (pt.GetElementType (), at.GetElementType (),
5095                                                   ref infered);
5096                         }
5097
5098                         if (pt.IsArray) {
5099                                 if (!at.IsArray ||
5100                                     (pt.GetArrayRank () != at.GetArrayRank ()))
5101                                         return false;
5102
5103                                 return InferType (pt.GetElementType (), at.GetElementType (),
5104                                                   ref infered);
5105                         }
5106
5107                         if (!at.IsGenericInstance)
5108                                 return false;
5109
5110                         Type[] at_args = at.GetGenericArguments ();
5111                         Type[] pt_args = pt.GetGenericArguments ();
5112
5113                         if (at_args.Length != pt_args.Length)
5114                                 return false;
5115
5116                         Type[] infered_types = new Type [at_args.Length];
5117
5118                         for (int i = 0; i < at_args.Length; i++)
5119                                 if (!InferType (pt_args [i], at_args [i], ref infered_types))
5120                                         return false;
5121
5122                         for (int i = 0; i < infered_types.Length; i++)
5123                                 if (infered_types [i] == null)
5124                                         return false;
5125
5126                         for (int i = 0; i < infered_types.Length; i++) {
5127                                 if (infered [i] == null) {
5128                                         infered [i] = infered_types [i];
5129                                         continue;
5130                                 }
5131
5132                                 if (infered [i] != infered_types [i])
5133                                         return false;
5134                         }
5135
5136                         return true;
5137                 }
5138
5139                 static bool InferParamsTypeArguments (EmitContext ec, ArrayList arguments,
5140                                                       ref MethodBase method)
5141                 {
5142                         if ((arguments == null) || !TypeManager.IsGenericMethod (method))
5143                                 return true;
5144
5145                         int arg_count;
5146                         
5147                         if (arguments == null)
5148                                 arg_count = 0;
5149                         else
5150                                 arg_count = arguments.Count;
5151                         
5152                         ParameterData pd = GetParameterData (method);
5153
5154                         int pd_count = pd.Count;
5155
5156                         if (pd_count == 0)
5157                                 return false;
5158                         
5159                         if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
5160                                 return false;
5161                         
5162                         if (pd_count - 1 > arg_count)
5163                                 return false;
5164                         
5165                         if (pd_count == 1 && arg_count == 0)
5166                                 return true;
5167
5168                         Type[] method_args = method.GetGenericArguments ();
5169                         Type[] infered_types = new Type [method_args.Length];
5170
5171                         //
5172                         // If we have come this far, the case which
5173                         // remains is when the number of parameters is
5174                         // less than or equal to the argument count.
5175                         //
5176                         for (int i = 0; i < pd_count - 1; ++i) {
5177                                 Argument a = (Argument) arguments [i];
5178
5179                                 if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
5180                                         continue;
5181
5182                                 Type pt = pd.ParameterType (i);
5183                                 Type at = a.Type;
5184
5185                                 if (!InferType (pt, at, ref infered_types))
5186                                         return false;
5187                         }
5188
5189                         Type element_type = TypeManager.GetElementType (pd.ParameterType (pd_count - 1));
5190
5191                         for (int i = pd_count - 1; i < arg_count; i++) {
5192                                 Argument a = (Argument) arguments [i];
5193
5194                                 if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
5195                                         continue;
5196
5197                                 if (!InferType (element_type, a.Type, ref infered_types))
5198                                         return false;
5199                         }
5200
5201                         for (int i = 0; i < infered_types.Length; i++)
5202                                 if (infered_types [i] == null)
5203                                         return false;
5204
5205                         method = method.BindGenericParameters (infered_types);
5206                         return true;
5207                 }
5208
5209                 public static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
5210                                                        ref Type[] infered_types)
5211                 {
5212                         for (int i = 0; i < arg_types.Length; i++) {
5213                                 if (arg_types [i] == null)
5214                                         continue;
5215
5216                                 if (!InferType (param_types [i], arg_types [i],
5217                                                 ref infered_types))
5218                                         return false;
5219                         }
5220
5221                         for (int i = 0; i < infered_types.Length; i++)
5222                                 if (infered_types [i] == null)
5223                                         return false;
5224
5225                         return true;
5226                 }
5227
5228                 static bool InferTypeArguments (EmitContext ec, ArrayList arguments,
5229                                                 ref MethodBase method)
5230                 {
5231                         if (!TypeManager.IsGenericMethod (method))
5232                                 return true;
5233
5234                         int arg_count;
5235                         if (arguments != null)
5236                                 arg_count = arguments.Count;
5237                         else
5238                                 arg_count = 0;
5239
5240                         ParameterData pd = GetParameterData (method);
5241                         if (arg_count != pd.Count)
5242                                 return false;
5243
5244                         Type[] method_args = method.GetGenericArguments ();
5245                         Type[] infered_types = new Type [method_args.Length];
5246
5247                         Type[] param_types = new Type [pd.Count];
5248                         Type[] arg_types = new Type [pd.Count];
5249
5250                         for (int i = 0; i < arg_count; i++) {
5251                                 param_types [i] = pd.ParameterType (i);
5252
5253                                 Argument a = (Argument) arguments [i];
5254                                 if ((a.Expr is NullLiteral) || (a.Expr is MethodGroupExpr))
5255                                         continue;
5256
5257                                 arg_types [i] = a.Type;
5258                         }
5259
5260                         if (!InferTypeArguments (param_types, arg_types, ref infered_types))
5261                                 return false;
5262
5263                         method = method.BindGenericParameters (infered_types);
5264                         return true;
5265                 }
5266
5267                 public static bool InferTypeArguments (EmitContext ec, ParameterData apd,
5268                                                        ref MethodBase method)
5269                 {
5270                         if (!TypeManager.IsGenericMethod (method))
5271                                 return true;
5272
5273                         ParameterData pd = GetParameterData (method);
5274                         if (apd.Count != pd.Count)
5275                                 return false;
5276
5277                         Type[] method_args = method.GetGenericArguments ();
5278                         Type[] infered_types = new Type [method_args.Length];
5279
5280                         Type[] param_types = new Type [pd.Count];
5281                         Type[] arg_types = new Type [pd.Count];
5282
5283                         for (int i = 0; i < apd.Count; i++) {
5284                                 param_types [i] = pd.ParameterType (i);
5285                                 arg_types [i] = apd.ParameterType (i);
5286                         }
5287
5288                         if (!InferTypeArguments (param_types, arg_types, ref infered_types))
5289                                 return false;
5290
5291                         method = method.BindGenericParameters (infered_types);
5292                         return true;
5293                 }
5294
5295                 public override Expression DoResolve (EmitContext ec)
5296                 {
5297                         //
5298                         // First, resolve the expression that is used to
5299                         // trigger the invocation
5300                         //
5301                         if (expr is BaseAccess)
5302                                 is_base = true;
5303
5304                         if (expr is ConstructedType)
5305                                 expr = ((ConstructedType) expr).GetMemberAccess (ec);
5306
5307                         expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup);
5308                         if (expr == null)
5309                                 return null;
5310
5311                         if (!(expr is MethodGroupExpr)) {
5312                                 Type expr_type = expr.Type;
5313
5314                                 if (expr_type != null){
5315                                         bool IsDelegate = TypeManager.IsDelegateType (expr_type);
5316                                         if (IsDelegate)
5317                                                 return (new DelegateInvocation (
5318                                                         this.expr, Arguments, loc)).Resolve (ec);
5319                                 }
5320                         }
5321
5322                         if (!(expr is MethodGroupExpr)){
5323                                 expr.Error_UnexpectedKind (ResolveFlags.MethodGroup);
5324                                 return null;
5325                         }
5326
5327                         //
5328                         // Next, evaluate all the expressions in the argument list
5329                         //
5330                         if (Arguments != null){
5331                                 foreach (Argument a in Arguments){
5332                                         if (!a.Resolve (ec, loc))
5333                                                 return null;
5334                                 }
5335                         }
5336
5337                         MethodGroupExpr mg = (MethodGroupExpr) expr;
5338                         method = OverloadResolve (ec, mg, Arguments, false, loc);
5339
5340                         if (method == null)
5341                                 return null;
5342
5343                         MethodInfo mi = method as MethodInfo;
5344                         if (mi != null) {
5345                                 type = TypeManager.TypeToCoreType (mi.ReturnType);
5346                                 if (!mi.IsStatic && !mg.IsExplicitImpl && (mg.InstanceExpression == null))
5347                                         SimpleName.Error_ObjectRefRequired (ec, loc, mi.Name);
5348                         }
5349
5350                         if (type.IsPointer){
5351                                 if (!ec.InUnsafe){
5352                                         UnsafeError (loc);
5353                                         return null;
5354                                 }
5355                         }
5356                         
5357                         //
5358                         // Only base will allow this invocation to happen.
5359                         //
5360                         if (is_base && method.IsAbstract){
5361                                 Report.Error (205, loc, "Cannot call an abstract base member: " +
5362                                               FullMethodDesc (method));
5363                                 return null;
5364                         }
5365
5366                         if ((method.Attributes & MethodAttributes.SpecialName) != 0){
5367                                 if (TypeManager.IsSpecialMethod (method))
5368                                         Report.Error (571, loc, method.Name + ": can not call operator or accessor");
5369                         }
5370                         
5371                         eclass = ExprClass.Value;
5372                         return this;
5373                 }
5374
5375                 // <summary>
5376                 //   Emits the list of arguments as an array
5377                 // </summary>
5378                 static void EmitParams (EmitContext ec, int idx, ArrayList arguments)
5379                 {
5380                         ILGenerator ig = ec.ig;
5381                         int count = arguments.Count - idx;
5382                         Argument a = (Argument) arguments [idx];
5383                         Type t = a.Expr.Type;
5384
5385                         IntConstant.EmitInt (ig, count);
5386                         ig.Emit (OpCodes.Newarr, TypeManager.TypeToCoreType (t));
5387
5388                         int top = arguments.Count;
5389                         for (int j = idx; j < top; j++){
5390                                 a = (Argument) arguments [j];
5391                                 
5392                                 ig.Emit (OpCodes.Dup);
5393                                 IntConstant.EmitInt (ig, j - idx);
5394
5395                                 bool is_stobj, has_type_arg;
5396                                 OpCode op = ArrayAccess.GetStoreOpcode (t, out is_stobj, out has_type_arg);
5397                                 if (is_stobj)
5398                                         ig.Emit (OpCodes.Ldelema, t);
5399
5400                                 a.Emit (ec);
5401
5402                                 if (has_type_arg)
5403                                         ig.Emit (op, t);
5404                                 else
5405                                         ig.Emit (op);
5406                         }
5407                 }
5408                 
5409                 /// <summary>
5410                 ///   Emits a list of resolved Arguments that are in the arguments
5411                 ///   ArrayList.
5412                 /// 
5413                 ///   The MethodBase argument might be null if the
5414                 ///   emission of the arguments is known not to contain
5415                 ///   a `params' field (for example in constructors or other routines
5416                 ///   that keep their arguments in this structure)
5417                 /// </summary>
5418                 public static void EmitArguments (EmitContext ec, MethodBase mb, ArrayList arguments)
5419                 {
5420                         ParameterData pd;
5421                         if (mb != null)
5422                                 pd = GetParameterData (mb);
5423                         else
5424                                 pd = null;
5425
5426                         //
5427                         // If we are calling a params method with no arguments, special case it
5428                         //
5429                         if (arguments == null){
5430                                 if (pd != null && pd.Count > 0 &&
5431                                     pd.ParameterModifier (0) == Parameter.Modifier.PARAMS){
5432                                         ILGenerator ig = ec.ig;
5433
5434                                         IntConstant.EmitInt (ig, 0);
5435                                         ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (0)));
5436                                 }
5437
5438                                 return;
5439                         }
5440
5441                         int top = arguments.Count;
5442
5443                         for (int i = 0; i < top; i++){
5444                                 Argument a = (Argument) arguments [i];
5445
5446                                 if (pd != null){
5447                                         if (pd.ParameterModifier (i) == Parameter.Modifier.PARAMS){
5448                                                 //
5449                                                 // Special case if we are passing the same data as the
5450                                                 // params argument, do not put it in an array.
5451                                                 //
5452                                                 if (pd.ParameterType (i) == a.Type)
5453                                                         a.Emit (ec);
5454                                                 else
5455                                                         EmitParams (ec, i, arguments);
5456                                                 return;
5457                                         }
5458                                 }
5459                                             
5460                                 a.Emit (ec);
5461                         }
5462
5463                         if (pd != null && pd.Count > top &&
5464                             pd.ParameterModifier (top) == Parameter.Modifier.PARAMS){
5465                                 ILGenerator ig = ec.ig;
5466
5467                                 IntConstant.EmitInt (ig, 0);
5468                                 ig.Emit (OpCodes.Newarr, TypeManager.GetElementType (pd.ParameterType (top)));
5469                         }
5470                 }
5471
5472                 /// <remarks>
5473                 ///   is_base tells whether we want to force the use of the `call'
5474                 ///   opcode instead of using callvirt.  Call is required to call
5475                 ///   a specific method, while callvirt will always use the most
5476                 ///   recent method in the vtable.
5477                 ///
5478                 ///   is_static tells whether this is an invocation on a static method
5479                 ///
5480                 ///   instance_expr is an expression that represents the instance
5481                 ///   it must be non-null if is_static is false.
5482                 ///
5483                 ///   method is the method to invoke.
5484                 ///
5485                 ///   Arguments is the list of arguments to pass to the method or constructor.
5486                 /// </remarks>
5487                 public static void EmitCall (EmitContext ec, bool is_base,
5488                                              bool is_static, Expression instance_expr,
5489                                              MethodBase method, ArrayList Arguments, Location loc)
5490                 {
5491                         ILGenerator ig = ec.ig;
5492                         bool struct_call = false;
5493                         bool this_call = false;
5494
5495                         Type decl_type = method.DeclaringType;
5496
5497                         if (!RootContext.StdLib) {
5498                                 // Replace any calls to the system's System.Array type with calls to
5499                                 // the newly created one.
5500                                 if (method == TypeManager.system_int_array_get_length)
5501                                         method = TypeManager.int_array_get_length;
5502                                 else if (method == TypeManager.system_int_array_get_rank)
5503                                         method = TypeManager.int_array_get_rank;
5504                                 else if (method == TypeManager.system_object_array_clone)
5505                                         method = TypeManager.object_array_clone;
5506                                 else if (method == TypeManager.system_int_array_get_length_int)
5507                                         method = TypeManager.int_array_get_length_int;
5508                                 else if (method == TypeManager.system_int_array_get_lower_bound_int)
5509                                         method = TypeManager.int_array_get_lower_bound_int;
5510                                 else if (method == TypeManager.system_int_array_get_upper_bound_int)
5511                                         method = TypeManager.int_array_get_upper_bound_int;
5512                                 else if (method == TypeManager.system_void_array_copyto_array_int)
5513                                         method = TypeManager.void_array_copyto_array_int;
5514                         }
5515
5516                         //
5517                         // This checks the `ConditionalAttribute' on the method, and the
5518                         // ObsoleteAttribute
5519                         //
5520                         TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (method, loc);
5521                         if ((flags & TypeManager.MethodFlags.IsObsoleteError) != 0)
5522                                 return;
5523                         if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
5524                                 return;
5525                         
5526                         if (!is_static){
5527                                 if (TypeManager.IsValueType (decl_type))
5528                                         struct_call = true;
5529                                 //
5530                                 // If this is ourselves, push "this"
5531                                 //
5532                                 if (instance_expr == null){
5533                                         this_call = true;
5534                                         ig.Emit (OpCodes.Ldarg_0);
5535                                 } else {
5536                                         Type itype = instance_expr.Type;
5537
5538                                         //
5539                                         // Push the instance expression
5540                                         //
5541                                         if (TypeManager.IsValueType (itype)){
5542                                                 //
5543                                                 // Special case: calls to a function declared in a 
5544                                                 // reference-type with a value-type argument need
5545                                                 // to have their value boxed.  
5546                                                 if (decl_type.IsValueType || itype.IsGenericParameter){
5547                                                         //
5548                                                         // If the expression implements IMemoryLocation, then
5549                                                         // we can optimize and use AddressOf on the
5550                                                         // return.
5551                                                         //
5552                                                         // If not we have to use some temporary storage for
5553                                                         // it.
5554                                                         if (instance_expr is IMemoryLocation){
5555                                                                 ((IMemoryLocation)instance_expr).
5556                                                                         AddressOf (ec, AddressOp.LoadStore);
5557                                                         }
5558                                                         else {
5559                                                                 instance_expr.Emit (ec);
5560                                                                 LocalBuilder temp = ig.DeclareLocal (itype);
5561                                                                 ig.Emit (OpCodes.Stloc, temp);
5562                                                                 ig.Emit (OpCodes.Ldloca, temp);
5563                                                         }
5564                                                         if (itype.IsGenericParameter)
5565                                                                 ig.Emit (OpCodes.Constrained, itype);
5566                                                         else
5567                                                                 struct_call = true;
5568                                                 } else {
5569                                                         instance_expr.Emit (ec);
5570                                                         ig.Emit (OpCodes.Box, itype);
5571                                                 } 
5572                                         } else
5573                                                 instance_expr.Emit (ec);
5574                                 }
5575                         }
5576
5577                         EmitArguments (ec, method, Arguments);
5578                         //
5579                         // If you have:
5580                         // this.DoFoo ();
5581                         // and DoFoo is not virtual, you can omit the callvirt,
5582                         // because you don't need the null checking behavior.
5583                         //
5584                         if (is_static || struct_call || is_base || (this_call && !method.IsVirtual)){
5585                                 if (method is MethodInfo) {
5586                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
5587                                 } else
5588                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5589                         } else {
5590                                 if (method is MethodInfo)
5591                                         ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
5592                                 else
5593                                         ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
5594                         }
5595                 }
5596                 
5597                 public override void Emit (EmitContext ec)
5598                 {
5599                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
5600
5601                         EmitCall (ec, is_base, method.IsStatic, mg.InstanceExpression, method, Arguments, loc);
5602                 }
5603                 
5604                 public override void EmitStatement (EmitContext ec)
5605                 {
5606                         Emit (ec);
5607
5608                         // 
5609                         // Pop the return value if there is one
5610                         //
5611                         if (method is MethodInfo){
5612                                 Type ret = ((MethodInfo)method).ReturnType;
5613                                 if (TypeManager.TypeToCoreType (ret) != TypeManager.void_type)
5614                                         ec.ig.Emit (OpCodes.Pop);
5615                         }
5616                 }
5617         }
5618
5619         public class InvocationOrCast : ExpressionStatement
5620         {
5621                 Expression expr;
5622                 Expression argument;
5623
5624                 public InvocationOrCast (Expression expr, Expression argument, Location loc)
5625                 {
5626                         this.expr = expr;
5627                         this.argument = argument;
5628                         this.loc = loc;
5629                 }
5630
5631                 public override Expression DoResolve (EmitContext ec)
5632                 {
5633                         //
5634                         // First try to resolve it as a cast.
5635                         //
5636                         type = ec.DeclSpace.ResolveType (expr, true, loc);
5637                         if (type != null) {
5638                                 Cast cast = new Cast (new TypeExpression (type, loc), argument, loc);
5639                                 return cast.Resolve (ec);
5640                         }
5641
5642                         //
5643                         // This can either be a type or a delegate invocation.
5644                         // Let's just resolve it and see what we'll get.
5645                         //
5646                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
5647                         if (expr == null)
5648                                 return null;
5649
5650                         //
5651                         // Ok, so it's a Cast.
5652                         //
5653                         if (expr.eclass == ExprClass.Type) {
5654                                 Cast cast = new Cast (new TypeExpression (expr.Type, loc), argument, loc);
5655                                 return cast.Resolve (ec);
5656                         }
5657
5658                         //
5659                         // It's a delegate invocation.
5660                         //
5661                         if (!TypeManager.IsDelegateType (expr.Type)) {
5662                                 Error (149, "Method name expected");
5663                                 return null;
5664                         }
5665
5666                         ArrayList args = new ArrayList ();
5667                         args.Add (new Argument (argument, Argument.AType.Expression));
5668                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
5669                         return invocation.Resolve (ec);
5670                 }
5671
5672                 void error201 ()
5673                 {
5674                         Error (201, "Only assignment, call, increment, decrement and new object " +
5675                                "expressions can be used as a statement");
5676                 }
5677
5678                 public override ExpressionStatement ResolveStatement (EmitContext ec)
5679                 {
5680                         //
5681                         // First try to resolve it as a cast.
5682                         //
5683                         type = ec.DeclSpace.ResolveType (expr, true, loc);
5684                         if (type != null) {
5685                                 error201 ();
5686                                 return null;
5687                         }
5688
5689                         //
5690                         // This can either be a type or a delegate invocation.
5691                         // Let's just resolve it and see what we'll get.
5692                         //
5693                         expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
5694                         if ((expr == null) || (expr.eclass == ExprClass.Type)) {
5695                                 error201 ();
5696                                 return null;
5697                         }
5698
5699                         //
5700                         // It's a delegate invocation.
5701                         //
5702                         if (!TypeManager.IsDelegateType (expr.Type)) {
5703                                 Error (149, "Method name expected");
5704                                 return null;
5705                         }
5706
5707                         ArrayList args = new ArrayList ();
5708                         args.Add (new Argument (argument, Argument.AType.Expression));
5709                         DelegateInvocation invocation = new DelegateInvocation (expr, args, loc);
5710                         return invocation.ResolveStatement (ec);
5711                 }
5712
5713                 public override void Emit (EmitContext ec)
5714                 {
5715                         throw new Exception ("Cannot happen");
5716                 }
5717
5718                 public override void EmitStatement (EmitContext ec)
5719                 {
5720                         throw new Exception ("Cannot happen");
5721                 }
5722         }
5723
5724         //
5725         // This class is used to "disable" the code generation for the
5726         // temporary variable when initializing value types.
5727         //
5728         class EmptyAddressOf : EmptyExpression, IMemoryLocation {
5729                 public void AddressOf (EmitContext ec, AddressOp Mode)
5730                 {
5731                         // nothing
5732                 }
5733         }
5734         
5735         /// <summary>
5736         ///    Implements the new expression 
5737         /// </summary>
5738         public class New : ExpressionStatement, IMemoryLocation {
5739                 public readonly ArrayList Arguments;
5740
5741                 //
5742                 // During bootstrap, it contains the RequestedType,
5743                 // but if `type' is not null, it *might* contain a NewDelegate
5744                 // (because of field multi-initialization)
5745                 //
5746                 public Expression RequestedType;
5747
5748                 MethodBase method = null;
5749
5750                 //
5751                 // If set, the new expression is for a value_target, and
5752                 // we will not leave anything on the stack.
5753                 //
5754                 Expression value_target;
5755                 bool value_target_set = false;
5756                 bool is_type_parameter = false;
5757                 
5758                 public New (Expression requested_type, ArrayList arguments, Location l)
5759                 {
5760                         RequestedType = requested_type;
5761                         Arguments = arguments;
5762                         loc = l;
5763                 }
5764
5765                 public bool SetValueTypeVariable (Expression value)
5766                 {
5767                         value_target = value;
5768                         value_target_set = true;
5769                         if (!(value_target is IMemoryLocation)){
5770                                 Error_UnexpectedKind ("variable");
5771                                 return false;
5772                         }
5773                         return true;
5774                 }
5775
5776                 //
5777                 // This function is used to disable the following code sequence for
5778                 // value type initialization:
5779                 //
5780                 // AddressOf (temporary)
5781                 // Construct/Init
5782                 // LoadTemporary
5783                 //
5784                 // Instead the provide will have provided us with the address on the
5785                 // stack to store the results.
5786                 //
5787                 static Expression MyEmptyExpression;
5788                 
5789                 public void DisableTemporaryValueType ()
5790                 {
5791                         if (MyEmptyExpression == null)
5792                                 MyEmptyExpression = new EmptyAddressOf ();
5793
5794                         //
5795                         // To enable this, look into:
5796                         // test-34 and test-89 and self bootstrapping.
5797                         //
5798                         // For instance, we can avoid a copy by using `newobj'
5799                         // instead of Call + Push-temp on value types.
5800 //                      value_target = MyEmptyExpression;
5801                 }
5802
5803                 public override Expression DoResolve (EmitContext ec)
5804                 {
5805                         //
5806                         // The New DoResolve might be called twice when initializing field
5807                         // expressions (see EmitFieldInitializers, the call to
5808                         // GetInitializerExpression will perform a resolve on the expression,
5809                         // and later the assign will trigger another resolution
5810                         //
5811                         // This leads to bugs (#37014)
5812                         //
5813                         if (type != null){
5814                                 if (RequestedType is NewDelegate)
5815                                         return RequestedType;
5816                                 return this;
5817                         }
5818                         
5819                         type = ec.DeclSpace.ResolveType (RequestedType, false, loc);
5820                         
5821                         if (type == null)
5822                                 return null;
5823                         
5824                         bool IsDelegate = TypeManager.IsDelegateType (type);
5825                         
5826                         if (IsDelegate){
5827                                 RequestedType = (new NewDelegate (type, Arguments, loc)).Resolve (ec);
5828                                 if (RequestedType != null)
5829                                         if (!(RequestedType is NewDelegate))
5830                                                 throw new Exception ("NewDelegate.Resolve returned a non NewDelegate: " + RequestedType.GetType ());
5831                                 return RequestedType;
5832                         }
5833
5834                         if (type.IsGenericParameter) {
5835                                 if (!TypeManager.HasConstructorConstraint (type)) {
5836                                         Error (304, String.Format (
5837                                                        "Cannot create an instance of the " +
5838                                                        "variable type '{0}' because it " +
5839                                                        "doesn't have the new() constraint",
5840                                                        type));
5841                                         return null;
5842                                 }
5843
5844                                 if ((Arguments != null) && (Arguments.Count != 0)) {
5845                                         Error (417, String.Format (
5846                                                        "`{0}': cannot provide arguments " +
5847                                                        "when creating an instance of a " +
5848                                                        "variable type.", type));
5849                                         return null;
5850                                 }
5851
5852                                 is_type_parameter = true;
5853                                 eclass = ExprClass.Value;
5854                                 return this;
5855                         } else if (type.IsInterface || type.IsAbstract){
5856                                 Error (144, "It is not possible to create instances of interfaces or abstract classes");
5857                                 return null;
5858                         }
5859                         
5860                         bool is_struct = type.IsValueType;
5861                         eclass = ExprClass.Value;
5862
5863                         //
5864                         // SRE returns a match for .ctor () on structs (the object constructor), 
5865                         // so we have to manually ignore it.
5866                         //
5867                         if (is_struct && Arguments == null)
5868                                 return this;
5869                         
5870                         Expression ml;
5871                         ml = MemberLookupFinal (ec, null, type, ".ctor",
5872                                                 MemberTypes.Constructor,
5873                                                 AllBindingFlags | BindingFlags.DeclaredOnly, loc);
5874
5875                         if (ml == null)
5876                                 return null;
5877                         
5878                         if (! (ml is MethodGroupExpr)){
5879                                 if (!is_struct){
5880                                         ml.Error_UnexpectedKind ("method group");
5881                                         return null;
5882                                 }
5883                         }
5884
5885                         if (ml != null) {
5886                                 if (Arguments != null){
5887                                         foreach (Argument a in Arguments){
5888                                                 if (!a.Resolve (ec, loc))
5889                                                         return null;
5890                                         }
5891                                 }
5892
5893                                 method = Invocation.OverloadResolve (
5894                                         ec, (MethodGroupExpr) ml, Arguments, false, loc);
5895                                 
5896                         }
5897
5898                         if (method == null) { 
5899                                 if (!is_struct || Arguments.Count > 0) {
5900                                         Error (1501, String.Format (
5901                                             "New invocation: Can not find a constructor in `{0}' for this argument list",
5902                                             TypeManager.CSharpName (type)));
5903                                         return null;
5904                                 }
5905                         }
5906
5907                         return this;
5908                 }
5909
5910                 bool DoEmitTypeParameter (EmitContext ec)
5911                 {
5912                         ILGenerator ig = ec.ig;
5913
5914                         ig.Emit (OpCodes.Ldtoken, type);
5915                         ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
5916                         ig.Emit (OpCodes.Call, TypeManager.activator_create_instance);
5917                         ig.Emit (OpCodes.Unbox_Any, type);
5918
5919                         return true;
5920                 }
5921
5922                 //
5923                 // This DoEmit can be invoked in two contexts:
5924                 //    * As a mechanism that will leave a value on the stack (new object)
5925                 //    * As one that wont (init struct)
5926                 //
5927                 // You can control whether a value is required on the stack by passing
5928                 // need_value_on_stack.  The code *might* leave a value on the stack
5929                 // so it must be popped manually
5930                 //
5931                 // If we are dealing with a ValueType, we have a few
5932                 // situations to deal with:
5933                 //
5934                 //    * The target is a ValueType, and we have been provided
5935                 //      the instance (this is easy, we are being assigned).
5936                 //
5937                 //    * The target of New is being passed as an argument,
5938                 //      to a boxing operation or a function that takes a
5939                 //      ValueType.
5940                 //
5941                 //      In this case, we need to create a temporary variable
5942                 //      that is the argument of New.
5943                 //
5944                 // Returns whether a value is left on the stack
5945                 //
5946                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
5947                 {
5948                         bool is_value_type = type.IsValueType;
5949                         ILGenerator ig = ec.ig;
5950
5951                         if (is_value_type){
5952                                 IMemoryLocation ml;
5953
5954                                 // Allow DoEmit() to be called multiple times.
5955                                 // We need to create a new LocalTemporary each time since
5956                                 // you can't share LocalBuilders among ILGeneators.
5957                                 if (!value_target_set)
5958                                         value_target = new LocalTemporary (ec, type);
5959
5960                                 ml = (IMemoryLocation) value_target;
5961                                 ml.AddressOf (ec, AddressOp.Store);
5962                         }
5963
5964                         if (method != null)
5965                                 Invocation.EmitArguments (ec, method, Arguments);
5966
5967                         if (is_value_type){
5968                                 if (method == null)
5969                                         ig.Emit (OpCodes.Initobj, type);
5970                                 else 
5971                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
5972                                 if (need_value_on_stack){
5973                                         value_target.Emit (ec);
5974                                         return true;
5975                                 }
5976                                 return false;
5977                         } else {
5978                                 ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
5979                                 return true;
5980                         }
5981                 }
5982
5983                 public override void Emit (EmitContext ec)
5984                 {
5985                         if (is_type_parameter)
5986                                 DoEmitTypeParameter (ec);
5987                         else
5988                                 DoEmit (ec, true);
5989                 }
5990                 
5991                 public override void EmitStatement (EmitContext ec)
5992                 {
5993                         if (is_type_parameter)
5994                                 throw new InvalidOperationException ();
5995
5996                         if (DoEmit (ec, false))
5997                                 ec.ig.Emit (OpCodes.Pop);
5998                 }
5999
6000                 public void AddressOf (EmitContext ec, AddressOp Mode)
6001                 {
6002                         if (is_type_parameter)
6003                                 throw new InvalidOperationException ();
6004
6005                         if (!type.IsValueType){
6006                                 //
6007                                 // We throw an exception.  So far, I believe we only need to support
6008                                 // value types:
6009                                 // foreach (int j in new StructType ())
6010                                 // see bug 42390
6011                                 //
6012                                 throw new Exception ("AddressOf should not be used for classes");
6013                         }
6014
6015                         if (!value_target_set)
6016                                 value_target = new LocalTemporary (ec, type);
6017                                         
6018                         IMemoryLocation ml = (IMemoryLocation) value_target;
6019                         ml.AddressOf (ec, AddressOp.Store);
6020                         if (method != null)
6021                                 Invocation.EmitArguments (ec, method, Arguments);
6022
6023                         if (method == null)
6024                                 ec.ig.Emit (OpCodes.Initobj, type);
6025                         else 
6026                                 ec.ig.Emit (OpCodes.Call, (ConstructorInfo) method);
6027                         
6028                         ((IMemoryLocation) value_target).AddressOf (ec, Mode);
6029                 }
6030         }
6031
6032         /// <summary>
6033         ///   14.5.10.2: Represents an array creation expression.
6034         /// </summary>
6035         ///
6036         /// <remarks>
6037         ///   There are two possible scenarios here: one is an array creation
6038         ///   expression that specifies the dimensions and optionally the
6039         ///   initialization data and the other which does not need dimensions
6040         ///   specified but where initialization data is mandatory.
6041         /// </remarks>
6042         public class ArrayCreation : ExpressionStatement {
6043                 Expression requested_base_type;
6044                 ArrayList initializers;
6045
6046                 //
6047                 // The list of Argument types.
6048                 // This is used to construct the `newarray' or constructor signature
6049                 //
6050                 ArrayList arguments;
6051
6052                 //
6053                 // Method used to create the array object.
6054                 //
6055                 MethodBase new_method = null;
6056                 
6057                 Type array_element_type;
6058                 Type underlying_type;
6059                 bool is_one_dimensional = false;
6060                 bool is_builtin_type = false;
6061                 bool expect_initializers = false;
6062                 int num_arguments = 0;
6063                 int dimensions = 0;
6064                 string rank;
6065
6066                 ArrayList array_data;
6067
6068                 Hashtable bounds;
6069
6070                 //
6071                 // The number of array initializers that we can handle
6072                 // via the InitializeArray method - through EmitStaticInitializers
6073                 //
6074                 int num_automatic_initializers;
6075
6076                 const int max_automatic_initializers = 6;
6077                 
6078                 public ArrayCreation (Expression requested_base_type, ArrayList exprs, string rank, ArrayList initializers, Location l)
6079                 {
6080                         this.requested_base_type = requested_base_type;
6081                         this.initializers = initializers;
6082                         this.rank = rank;
6083                         loc = l;
6084
6085                         arguments = new ArrayList ();
6086
6087                         foreach (Expression e in exprs) {
6088                                 arguments.Add (new Argument (e, Argument.AType.Expression));
6089                                 num_arguments++;
6090                         }
6091                 }
6092
6093                 public ArrayCreation (Expression requested_base_type, string rank, ArrayList initializers, Location l)
6094                 {
6095                         this.requested_base_type = requested_base_type;
6096                         this.initializers = initializers;
6097                         this.rank = rank;
6098                         loc = l;
6099
6100                         //this.rank = rank.Substring (0, rank.LastIndexOf ('['));
6101                         //
6102                         //string tmp = rank.Substring (rank.LastIndexOf ('['));
6103                         //
6104                         //dimensions = tmp.Length - 1;
6105                         expect_initializers = true;
6106                 }
6107
6108                 public Expression FormArrayType (Expression base_type, int idx_count, string rank)
6109                 {
6110                         StringBuilder sb = new StringBuilder (rank);
6111                         
6112                         sb.Append ("[");
6113                         for (int i = 1; i < idx_count; i++)
6114                                 sb.Append (",");
6115                         
6116                         sb.Append ("]");
6117
6118                         return new ComposedCast (base_type, sb.ToString (), loc);
6119                 }
6120
6121                 void Error_IncorrectArrayInitializer ()
6122                 {
6123                         Error (178, "Incorrectly structured array initializer");
6124                 }
6125                 
6126                 public bool CheckIndices (EmitContext ec, ArrayList probe, int idx, bool specified_dims)
6127                 {
6128                         if (specified_dims) { 
6129                                 Argument a = (Argument) arguments [idx];
6130                                 
6131                                 if (!a.Resolve (ec, loc))
6132                                         return false;
6133                                 
6134                                 if (!(a.Expr is Constant)) {
6135                                         Error (150, "A constant value is expected");
6136                                         return false;
6137                                 }
6138                                 
6139                                 int value = (int) ((Constant) a.Expr).GetValue ();
6140                                 
6141                                 if (value != probe.Count) {
6142                                         Error_IncorrectArrayInitializer ();
6143                                         return false;
6144                                 }
6145                                 
6146                                 bounds [idx] = value;
6147                         }
6148
6149                         int child_bounds = -1;
6150                         foreach (object o in probe) {
6151                                 if (o is ArrayList) {
6152                                         int current_bounds = ((ArrayList) o).Count;
6153                                         
6154                                         if (child_bounds == -1) 
6155                                                 child_bounds = current_bounds;
6156
6157                                         else if (child_bounds != current_bounds){
6158                                                 Error_IncorrectArrayInitializer ();
6159                                                 return false;
6160                                         }
6161                                         if (specified_dims && (idx + 1 >= arguments.Count)){
6162                                                 Error (623, "Array initializers can only be used in a variable or field initializer, try using the new expression");
6163                                                 return false;
6164                                         }
6165                                         
6166                                         bool ret = CheckIndices (ec, (ArrayList) o, idx + 1, specified_dims);
6167                                         if (!ret)
6168                                                 return false;
6169                                 } else {
6170                                         if (child_bounds != -1){
6171                                                 Error_IncorrectArrayInitializer ();
6172                                                 return false;
6173                                         }
6174                                         
6175                                         Expression tmp = (Expression) o;
6176                                         tmp = tmp.Resolve (ec);
6177                                         if (tmp == null)
6178                                                 continue;
6179
6180                                         // Console.WriteLine ("I got: " + tmp);
6181                                         // Handle initialization from vars, fields etc.
6182
6183                                         Expression conv = Convert.ImplicitConversionRequired (
6184                                                 ec, tmp, underlying_type, loc);
6185                                         
6186                                         if (conv == null) 
6187                                                 return false;
6188
6189                                         if (conv is StringConstant || conv is DecimalConstant || conv is NullCast) {
6190                                                 // These are subclasses of Constant that can appear as elements of an
6191                                                 // array that cannot be statically initialized (with num_automatic_initializers
6192                                                 // > max_automatic_initializers), so num_automatic_initializers should be left as zero.
6193                                                 array_data.Add (conv);
6194                                         } else if (conv is Constant) {
6195                                                 // These are the types of Constant that can appear in arrays that can be
6196                                                 // statically allocated.
6197                                                 array_data.Add (conv);
6198                                                 num_automatic_initializers++;
6199                                         } else
6200                                                 array_data.Add (conv);
6201                                 }
6202                         }
6203
6204                         return true;
6205                 }
6206                 
6207                 public void UpdateIndices (EmitContext ec)
6208                 {
6209                         int i = 0;
6210                         for (ArrayList probe = initializers; probe != null;) {
6211                                 if (probe.Count > 0 && probe [0] is ArrayList) {
6212                                         Expression e = new IntConstant (probe.Count);
6213                                         arguments.Add (new Argument (e, Argument.AType.Expression));
6214
6215                                         bounds [i++] =  probe.Count;
6216                                         
6217                                         probe = (ArrayList) probe [0];
6218                                         
6219                                 } else {
6220                                         Expression e = new IntConstant (probe.Count);
6221                                         arguments.Add (new Argument (e, Argument.AType.Expression));
6222
6223                                         bounds [i++] = probe.Count;
6224                                         probe = null;
6225                                 }
6226                         }
6227
6228                 }
6229                 
6230                 public bool ValidateInitializers (EmitContext ec, Type array_type)
6231                 {
6232                         if (initializers == null) {
6233                                 if (expect_initializers)
6234                                         return false;
6235                                 else
6236                                         return true;
6237                         }
6238                         
6239                         if (underlying_type == null)
6240                                 return false;
6241                         
6242                         //
6243                         // We use this to store all the date values in the order in which we
6244                         // will need to store them in the byte blob later
6245                         //
6246                         array_data = new ArrayList ();
6247                         bounds = new Hashtable ();
6248                         
6249                         bool ret;
6250
6251                         if (arguments != null) {
6252                                 ret = CheckIndices (ec, initializers, 0, true);
6253                                 return ret;
6254                         } else {
6255                                 arguments = new ArrayList ();
6256
6257                                 ret = CheckIndices (ec, initializers, 0, false);
6258                                 
6259                                 if (!ret)
6260                                         return false;
6261                                 
6262                                 UpdateIndices (ec);
6263                                 
6264                                 if (arguments.Count != dimensions) {
6265                                         Error_IncorrectArrayInitializer ();
6266                                         return false;
6267                                 }
6268
6269                                 return ret;
6270                         }
6271                 }
6272
6273                 void Error_NegativeArrayIndex ()
6274                 {
6275                         Error (284, "Can not create array with a negative size");
6276                 }
6277                 
6278                 //
6279                 // Converts `source' to an int, uint, long or ulong.
6280                 //
6281                 Expression ExpressionToArrayArgument (EmitContext ec, Expression source)
6282                 {
6283                         Expression target;
6284                         
6285                         bool old_checked = ec.CheckState;
6286                         ec.CheckState = true;
6287                         
6288                         target = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, loc);
6289                         if (target == null){
6290                                 target = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, loc);
6291                                 if (target == null){
6292                                         target = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, loc);
6293                                         if (target == null){
6294                                                 target = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, loc);
6295                                                 if (target == null)
6296                                                         Convert.Error_CannotImplicitConversion (loc, source.Type, TypeManager.int32_type);
6297                                         }
6298                                 }
6299                         } 
6300                         ec.CheckState = old_checked;
6301
6302                         //
6303                         // Only positive constants are allowed at compile time
6304                         //
6305                         if (target is Constant){
6306                                 if (target is IntConstant){
6307                                         if (((IntConstant) target).Value < 0){
6308                                                 Error_NegativeArrayIndex ();
6309                                                 return null;
6310                                         }
6311                                 }
6312
6313                                 if (target is LongConstant){
6314                                         if (((LongConstant) target).Value < 0){
6315                                                 Error_NegativeArrayIndex ();
6316                                                 return null;
6317                                         }
6318                                 }
6319                                 
6320                         }
6321
6322                         return target;
6323                 }
6324
6325                 //
6326                 // Creates the type of the array
6327                 //
6328                 bool LookupType (EmitContext ec)
6329                 {
6330                         StringBuilder array_qualifier = new StringBuilder (rank);
6331
6332                         //
6333                         // `In the first form allocates an array instace of the type that results
6334                         // from deleting each of the individual expression from the expression list'
6335                         //
6336                         if (num_arguments > 0) {
6337                                 array_qualifier.Append ("[");
6338                                 for (int i = num_arguments-1; i > 0; i--)
6339                                         array_qualifier.Append (",");
6340                                 array_qualifier.Append ("]");                           
6341                         }
6342
6343                         //
6344                         // Lookup the type
6345                         //
6346                         Expression array_type_expr;
6347                         array_type_expr = new ComposedCast (requested_base_type, array_qualifier.ToString (), loc);
6348                         type = ec.DeclSpace.ResolveType (array_type_expr, false, loc);
6349
6350                         if (type == null)
6351                                 return false;
6352
6353                         underlying_type = type;
6354                         if (underlying_type.IsArray)
6355                                 underlying_type = TypeManager.GetElementType (underlying_type);
6356                         dimensions = type.GetArrayRank ();
6357
6358                         return true;
6359                 }
6360                 
6361                 public override Expression DoResolve (EmitContext ec)
6362                 {
6363                         int arg_count;
6364
6365                         if (!LookupType (ec))
6366                                 return null;
6367                         
6368                         //
6369                         // First step is to validate the initializers and fill
6370                         // in any missing bits
6371                         //
6372                         if (!ValidateInitializers (ec, type))
6373                                 return null;
6374
6375                         if (arguments == null)
6376                                 arg_count = 0;
6377                         else {
6378                                 arg_count = arguments.Count;
6379                                 foreach (Argument a in arguments){
6380                                         if (!a.Resolve (ec, loc))
6381                                                 return null;
6382
6383                                         Expression real_arg = ExpressionToArrayArgument (ec, a.Expr, loc);
6384                                         if (real_arg == null)
6385                                                 return null;
6386
6387                                         a.Expr = real_arg;
6388                                 }
6389                         }
6390                         
6391                         array_element_type = TypeManager.GetElementType (type);
6392
6393                         if (arg_count == 1) {
6394                                 is_one_dimensional = true;
6395                                 eclass = ExprClass.Value;
6396                                 return this;
6397                         }
6398
6399                         is_builtin_type = TypeManager.IsBuiltinType (type);
6400
6401                         if (is_builtin_type) {
6402                                 Expression ml;
6403                                 
6404                                 ml = MemberLookup (ec, type, ".ctor", MemberTypes.Constructor,
6405                                                    AllBindingFlags, loc);
6406                                 
6407                                 if (!(ml is MethodGroupExpr)) {
6408                                         ml.Error_UnexpectedKind ("method group");
6409                                         return null;
6410                                 }
6411                                 
6412                                 if (ml == null) {
6413                                         Error (-6, "New invocation: Can not find a constructor for " +
6414                                                       "this argument list");
6415                                         return null;
6416                                 }
6417                                 
6418                                 new_method = Invocation.OverloadResolve (
6419                                         ec, (MethodGroupExpr) ml, arguments, false, loc);
6420
6421                                 if (new_method == null) {
6422                                         Error (-6, "New invocation: Can not find a constructor for " +
6423                                                       "this argument list");
6424                                         return null;
6425                                 }
6426                                 
6427                                 eclass = ExprClass.Value;
6428                                 return this;
6429                         } else {
6430                                 ModuleBuilder mb = CodeGen.Module.Builder;
6431                                 ArrayList args = new ArrayList ();
6432                                 
6433                                 if (arguments != null) {
6434                                         for (int i = 0; i < arg_count; i++)
6435                                                 args.Add (TypeManager.int32_type);
6436                                 }
6437                                 
6438                                 Type [] arg_types = null;
6439
6440                                 if (args.Count > 0)
6441                                         arg_types = new Type [args.Count];
6442                                 
6443                                 args.CopyTo (arg_types, 0);
6444                                 
6445                                 new_method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
6446                                                             arg_types);
6447
6448                                 if (new_method == null) {
6449                                         Error (-6, "New invocation: Can not find a constructor for " +
6450                                                       "this argument list");
6451                                         return null;
6452                                 }
6453                                 
6454                                 eclass = ExprClass.Value;
6455                                 return this;
6456                         }
6457                 }
6458
6459                 public static byte [] MakeByteBlob (ArrayList array_data, Type underlying_type, Location loc)
6460                 {
6461                         int factor;
6462                         byte [] data;
6463                         byte [] element;
6464                         int count = array_data.Count;
6465
6466                         if (underlying_type.IsEnum)
6467                                 underlying_type = TypeManager.EnumToUnderlying (underlying_type);
6468                         
6469                         factor = GetTypeSize (underlying_type);
6470                         if (factor == 0)
6471                                 throw new Exception ("unrecognized type in MakeByteBlob: " + underlying_type);
6472
6473                         data = new byte [(count * factor + 4) & ~3];
6474                         int idx = 0;
6475                         
6476                         for (int i = 0; i < count; ++i) {
6477                                 object v = array_data [i];
6478
6479                                 if (v is EnumConstant)
6480                                         v = ((EnumConstant) v).Child;
6481                                 
6482                                 if (v is Constant && !(v is StringConstant))
6483                                         v = ((Constant) v).GetValue ();
6484                                 else {
6485                                         idx += factor;
6486                                         continue;
6487                                 }
6488                                 
6489                                 if (underlying_type == TypeManager.int64_type){
6490                                         if (!(v is Expression)){
6491                                                 long val = (long) v;
6492                                                 
6493                                                 for (int j = 0; j < factor; ++j) {
6494                                                         data [idx + j] = (byte) (val & 0xFF);
6495                                                         val = (val >> 8);
6496                                                 }
6497                                         }
6498                                 } else if (underlying_type == TypeManager.uint64_type){
6499                                         if (!(v is Expression)){
6500                                                 ulong val = (ulong) v;
6501
6502                                                 for (int j = 0; j < factor; ++j) {
6503                                                         data [idx + j] = (byte) (val & 0xFF);
6504                                                         val = (val >> 8);
6505                                                 }
6506                                         }
6507                                 } else if (underlying_type == TypeManager.float_type) {
6508                                         if (!(v is Expression)){
6509                                                 element = BitConverter.GetBytes ((float) v);
6510                                                         
6511                                                 for (int j = 0; j < factor; ++j)
6512                                                         data [idx + j] = element [j];
6513                                         }
6514                                 } else if (underlying_type == TypeManager.double_type) {
6515                                         if (!(v is Expression)){
6516                                                 element = BitConverter.GetBytes ((double) v);
6517
6518                                                 for (int j = 0; j < factor; ++j)
6519                                                         data [idx + j] = element [j];
6520                                         }
6521                                 } else if (underlying_type == TypeManager.char_type){
6522                                         if (!(v is Expression)){
6523                                                 int val = (int) ((char) v);
6524                                                 
6525                                                 data [idx] = (byte) (val & 0xff);
6526                                                 data [idx+1] = (byte) (val >> 8);
6527                                         }
6528                                 } else if (underlying_type == TypeManager.short_type){
6529                                         if (!(v is Expression)){
6530                                                 int val = (int) ((short) v);
6531                                         
6532                                                 data [idx] = (byte) (val & 0xff);
6533                                                 data [idx+1] = (byte) (val >> 8);
6534                                         }
6535                                 } else if (underlying_type == TypeManager.ushort_type){
6536                                         if (!(v is Expression)){
6537                                                 int val = (int) ((ushort) v);
6538                                         
6539                                                 data [idx] = (byte) (val & 0xff);
6540                                                 data [idx+1] = (byte) (val >> 8);
6541                                         }
6542                                 } else if (underlying_type == TypeManager.int32_type) {
6543                                         if (!(v is Expression)){
6544                                                 int val = (int) v;
6545                                         
6546                                                 data [idx]   = (byte) (val & 0xff);
6547                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
6548                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
6549                                                 data [idx+3] = (byte) (val >> 24);
6550                                         }
6551                                 } else if (underlying_type == TypeManager.uint32_type) {
6552                                         if (!(v is Expression)){
6553                                                 uint val = (uint) v;
6554                                         
6555                                                 data [idx]   = (byte) (val & 0xff);
6556                                                 data [idx+1] = (byte) ((val >> 8) & 0xff);
6557                                                 data [idx+2] = (byte) ((val >> 16) & 0xff);
6558                                                 data [idx+3] = (byte) (val >> 24);
6559                                         }
6560                                 } else if (underlying_type == TypeManager.sbyte_type) {
6561                                         if (!(v is Expression)){
6562                                                 sbyte val = (sbyte) v;
6563                                                 data [idx] = (byte) val;
6564                                         }
6565                                 } else if (underlying_type == TypeManager.byte_type) {
6566                                         if (!(v is Expression)){
6567                                                 byte val = (byte) v;
6568                                                 data [idx] = (byte) val;
6569                                         }
6570                                 } else if (underlying_type == TypeManager.bool_type) {
6571                                         if (!(v is Expression)){
6572                                                 bool val = (bool) v;
6573                                                 data [idx] = (byte) (val ? 1 : 0);
6574                                         }
6575                                 } else if (underlying_type == TypeManager.decimal_type){
6576                                         if (!(v is Expression)){
6577                                                 int [] bits = Decimal.GetBits ((decimal) v);
6578                                                 int p = idx;
6579
6580                                                 // FIXME: For some reason, this doesn't work on the MS runtime.
6581                                                 int [] nbits = new int [4];
6582                                                 nbits [0] = bits [3];
6583                                                 nbits [1] = bits [2];
6584                                                 nbits [2] = bits [0];
6585                                                 nbits [3] = bits [1];
6586                                                 
6587                                                 for (int j = 0; j < 4; j++){
6588                                                         data [p++] = (byte) (nbits [j] & 0xff);
6589                                                         data [p++] = (byte) ((nbits [j] >> 8) & 0xff);
6590                                                         data [p++] = (byte) ((nbits [j] >> 16) & 0xff);
6591                                                         data [p++] = (byte) (nbits [j] >> 24);
6592                                                 }
6593                                         }
6594                                 } else
6595                                         throw new Exception ("Unrecognized type in MakeByteBlob: " + underlying_type);
6596
6597                                 idx += factor;
6598                         }
6599
6600                         return data;
6601                 }
6602
6603                 //
6604                 // Emits the initializers for the array
6605                 //
6606                 void EmitStaticInitializers (EmitContext ec, bool is_expression)
6607                 {
6608                         //
6609                         // First, the static data
6610                         //
6611                         FieldBuilder fb;
6612                         ILGenerator ig = ec.ig;
6613                         
6614                         byte [] data = MakeByteBlob (array_data, underlying_type, loc);
6615
6616                         fb = RootContext.MakeStaticData (data);
6617
6618                         if (is_expression)
6619                                 ig.Emit (OpCodes.Dup);
6620                         ig.Emit (OpCodes.Ldtoken, fb);
6621                         ig.Emit (OpCodes.Call,
6622                                  TypeManager.void_initializearray_array_fieldhandle);
6623                 }
6624
6625                 //
6626                 // Emits pieces of the array that can not be computed at compile
6627                 // time (variables and string locations).
6628                 //
6629                 // This always expect the top value on the stack to be the array
6630                 //
6631                 void EmitDynamicInitializers (EmitContext ec, bool is_expression)
6632                 {
6633                         ILGenerator ig = ec.ig;
6634                         int dims = bounds.Count;
6635                         int [] current_pos = new int [dims];
6636                         int top = array_data.Count;
6637
6638                         MethodInfo set = null;
6639
6640                         if (dims != 1){
6641                                 Type [] args;
6642                                 ModuleBuilder mb = null;
6643                                 mb = CodeGen.Module.Builder;
6644                                 args = new Type [dims + 1];
6645
6646                                 int j;
6647                                 for (j = 0; j < dims; j++)
6648                                         args [j] = TypeManager.int32_type;
6649
6650                                 args [j] = array_element_type;
6651                                 
6652                                 set = mb.GetArrayMethod (
6653                                         type, "Set",
6654                                         CallingConventions.HasThis | CallingConventions.Standard,
6655                                         TypeManager.void_type, args);
6656                         }
6657                         
6658                         for (int i = 0; i < top; i++){
6659
6660                                 Expression e = null;
6661
6662                                 if (array_data [i] is Expression)
6663                                         e = (Expression) array_data [i];
6664
6665                                 if (e != null) {
6666                                         //
6667                                         // Basically we do this for string literals and
6668                                         // other non-literal expressions
6669                                         //
6670                                         if (e is EnumConstant){
6671                                                 e = ((EnumConstant) e).Child;
6672                                         }
6673                                         
6674                                         if (e is StringConstant || e is DecimalConstant || !(e is Constant) ||
6675                                             num_automatic_initializers <= max_automatic_initializers) {
6676                                                 Type etype = e.Type;
6677                                                 
6678                                                 if (is_expression || i != top - 1)
6679                                                         ig.Emit (OpCodes.Dup);
6680
6681                                                 for (int idx = 0; idx < dims; idx++) 
6682                                                         IntConstant.EmitInt (ig, current_pos [idx]);
6683
6684                                                 //
6685                                                 // If we are dealing with a struct, get the
6686                                                 // address of it, so we can store it.
6687                                                 //
6688                                                 if ((dims == 1) && 
6689                                                     etype.IsSubclassOf (TypeManager.value_type) &&
6690                                                     (!TypeManager.IsBuiltinOrEnum (etype) ||
6691                                                      etype == TypeManager.decimal_type)) {
6692                                                         if (e is New){
6693                                                                 New n = (New) e;
6694
6695                                                                 //
6696                                                                 // Let new know that we are providing
6697                                                                 // the address where to store the results
6698                                                                 //
6699                                                                 n.DisableTemporaryValueType ();
6700                                                         }
6701
6702                                                         ig.Emit (OpCodes.Ldelema, etype);
6703                                                 }
6704
6705                                                 e.Emit (ec);
6706
6707                                                 if (dims == 1)
6708                                                         ArrayAccess.EmitStoreOpcode (ig, array_element_type);
6709                                                 else 
6710                                                         ig.Emit (OpCodes.Call, set);
6711                                                 
6712                                         }
6713                                 }
6714                                 
6715                                 //
6716                                 // Advance counter
6717                                 //
6718                                 for (int j = dims - 1; j >= 0; j--){
6719                                         current_pos [j]++;
6720                                         if (current_pos [j] < (int) bounds [j])
6721                                                 break;
6722                                         current_pos [j] = 0;
6723                                 }
6724                         }
6725                 }
6726
6727                 void EmitArrayArguments (EmitContext ec)
6728                 {
6729                         ILGenerator ig = ec.ig;
6730                         
6731                         foreach (Argument a in arguments) {
6732                                 Type atype = a.Type;
6733                                 a.Emit (ec);
6734
6735                                 if (atype == TypeManager.uint64_type)
6736                                         ig.Emit (OpCodes.Conv_Ovf_U4);
6737                                 else if (atype == TypeManager.int64_type)
6738                                         ig.Emit (OpCodes.Conv_Ovf_I4);
6739                         }
6740                 }
6741                 
6742                 void DoEmit (EmitContext ec, bool is_statement)
6743                 {
6744                         ILGenerator ig = ec.ig;
6745                         
6746                         EmitArrayArguments (ec);
6747                         if (is_one_dimensional)
6748                                 ig.Emit (OpCodes.Newarr, array_element_type);
6749                         else {
6750                                 if (is_builtin_type) 
6751                                         ig.Emit (OpCodes.Newobj, (ConstructorInfo) new_method);
6752                                 else 
6753                                         ig.Emit (OpCodes.Newobj, (MethodInfo) new_method);
6754                         }
6755                         
6756                         if (initializers != null){
6757                                 //
6758                                 // FIXME: Set this variable correctly.
6759                                 // 
6760                                 bool dynamic_initializers = true;
6761
6762                                 // This will never be true for array types that cannot be statically
6763                                 // initialized. num_automatic_initializers will always be zero.  See
6764                                 // CheckIndices.
6765                                         if (num_automatic_initializers > max_automatic_initializers)
6766                                                 EmitStaticInitializers (ec, dynamic_initializers || !is_statement);
6767                                 
6768                                 if (dynamic_initializers)
6769                                         EmitDynamicInitializers (ec, !is_statement);
6770                         }
6771                 }
6772                 
6773                 public override void Emit (EmitContext ec)
6774                 {
6775                         DoEmit (ec, false);
6776                 }
6777
6778                 public override void EmitStatement (EmitContext ec)
6779                 {
6780                         DoEmit (ec, true);
6781                 }
6782
6783                 public object EncodeAsAttribute ()
6784                 {
6785                         if (!is_one_dimensional){
6786                                 Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays");
6787                                 return null;
6788                         }
6789
6790                         if (array_data == null){
6791                                 Report.Error (-212, Location, "array should be initialized when passing it to an attribute");
6792                                 return null;
6793                         }
6794                         
6795                         object [] ret = new object [array_data.Count];
6796                         int i = 0;
6797                         foreach (Expression e in array_data){
6798                                 object v;
6799                                 
6800                                 if (e is NullLiteral)
6801                                         v = null;
6802                                 else {
6803                                         if (!Attribute.GetAttributeArgumentExpression (e, Location, out v))
6804                                                 return null;
6805                                 }
6806                                 ret [i++] = v;
6807                         }
6808                         return ret;
6809                 }
6810
6811                 public Expression TurnIntoConstant ()
6812                 {
6813                         //
6814                         // Should use something like the above attribute thing.
6815                         // It should return a subclass of Constant that just returns
6816                         // the computed value of the array
6817                         //
6818                         throw new Exception ("Does not support yet Turning array into a Constant");
6819                 }
6820         }
6821         
6822         /// <summary>
6823         ///   Represents the `this' construct
6824         /// </summary>
6825         public class This : Expression, IAssignMethod, IMemoryLocation, IVariable {
6826
6827                 Block block;
6828                 VariableInfo variable_info;
6829                 
6830                 public This (Block block, Location loc)
6831                 {
6832                         this.loc = loc;
6833                         this.block = block;
6834                 }
6835
6836                 public This (Location loc)
6837                 {
6838                         this.loc = loc;
6839                 }
6840
6841                 public VariableInfo VariableInfo {
6842                         get { return variable_info; }
6843                 }
6844
6845                 public bool VerifyFixed (bool is_expression)
6846                 {
6847                         if ((variable_info == null) || (variable_info.LocalInfo == null))
6848                                 return false;
6849                         else
6850                                 return variable_info.LocalInfo.IsFixed;
6851                 }
6852
6853                 public bool ResolveBase (EmitContext ec)
6854                 {
6855                         eclass = ExprClass.Variable;
6856
6857                         if (ec.TypeContainer.CurrentType != null)
6858                                 type = ec.TypeContainer.CurrentType.ResolveType (ec);
6859                         else
6860                                 type = ec.ContainerType;
6861
6862                         if (ec.IsStatic) {
6863                                 Error (26, "Keyword this not valid in static code");
6864                                 return false;
6865                         }
6866
6867                         if ((block != null) && (block.ThisVariable != null))
6868                                 variable_info = block.ThisVariable.VariableInfo;
6869
6870                         return true;
6871                 }
6872
6873                 public override Expression DoResolve (EmitContext ec)
6874                 {
6875                         if (!ResolveBase (ec))
6876                                 return null;
6877
6878                         if ((variable_info != null) && !variable_info.IsAssigned (ec)) {
6879                                 Error (188, "The this object cannot be used before all " +
6880                                        "of its fields are assigned to");
6881                                 variable_info.SetAssigned (ec);
6882                                 return this;
6883                         }
6884
6885                         if (ec.IsFieldInitializer) {
6886                                 Error (27, "Keyword `this' can't be used outside a constructor, " +
6887                                        "a method or a property.");
6888                                 return null;
6889                         }
6890
6891                         return this;
6892                 }
6893
6894                 override public Expression DoResolveLValue (EmitContext ec, Expression right_side)
6895                 {
6896                         if (!ResolveBase (ec))
6897                                 return null;
6898
6899                         if (variable_info != null)
6900                                 variable_info.SetAssigned (ec);
6901                         
6902                         if (ec.TypeContainer is Class){
6903                                 Error (1604, "Cannot assign to `this'");
6904                                 return null;
6905                         }
6906
6907                         return this;
6908                 }
6909
6910                 public override void Emit (EmitContext ec)
6911                 {
6912                         ILGenerator ig = ec.ig;
6913
6914                         ec.EmitThis ();
6915                         if (ec.TypeContainer is Struct)
6916                                 ig.Emit (OpCodes.Ldobj, type);
6917                 }
6918
6919                 public void EmitAssign (EmitContext ec, Expression source)
6920                 {
6921                         ILGenerator ig = ec.ig;
6922                         
6923                         if (ec.TypeContainer is Struct){
6924                                 ec.EmitThis ();
6925                                 source.Emit (ec);
6926                                 ig.Emit (OpCodes.Stobj, type);
6927                         } else {
6928                                 source.Emit (ec);
6929                                 ig.Emit (OpCodes.Starg, 0);
6930                         }
6931                 }
6932
6933                 public void AddressOf (EmitContext ec, AddressOp mode)
6934                 {
6935                         ec.EmitThis ();
6936
6937                         // FIMXE
6938                         // FIGURE OUT WHY LDARG_S does not work
6939                         //
6940                         // consider: struct X { int val; int P { set { val = value; }}}
6941                         //
6942                         // Yes, this looks very bad. Look at `NOTAS' for
6943                         // an explanation.
6944                         // ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
6945                 }
6946         }
6947
6948         //
6949         // This produces the value that renders an instance, used by the iterators code
6950         //
6951         public class ProxyInstance : Expression, IMemoryLocation  {
6952                 public override Expression DoResolve (EmitContext ec)
6953                 {
6954                         eclass = ExprClass.Variable;
6955                         type = ec.ContainerType;
6956                         return this;
6957                 }
6958                 
6959                 public override void Emit (EmitContext ec)
6960                 {
6961                         ec.ig.Emit (OpCodes.Ldarg_0);
6962
6963                 }
6964                 
6965                 public void AddressOf (EmitContext ec, AddressOp mode)
6966                 {
6967                         ec.ig.Emit (OpCodes.Ldarg_0);
6968                 }
6969         }
6970
6971         /// <summary>
6972         ///   Implements the typeof operator
6973         /// </summary>
6974         public class TypeOf : Expression {
6975                 public readonly Expression QueriedType;
6976                 protected Type typearg;
6977                 
6978                 public TypeOf (Expression queried_type, Location l)
6979                 {
6980                         QueriedType = queried_type;
6981                         loc = l;
6982                 }
6983
6984                 public override Expression DoResolve (EmitContext ec)
6985                 {
6986                         typearg = ec.DeclSpace.ResolveType (QueriedType, false, loc);
6987
6988                         if (typearg == null)
6989                                 return null;
6990
6991                         if (typearg == TypeManager.void_type) {
6992                                 Error (673, "System.Void cannot be used from C# - " +
6993                                        "use typeof (void) to get the void type object");
6994                                 return null;
6995                         }
6996
6997                         type = TypeManager.type_type;
6998                         eclass = ExprClass.Type;
6999                         return this;
7000                 }
7001
7002                 public override void Emit (EmitContext ec)
7003                 {
7004                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
7005                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
7006                 }
7007
7008                 public Type TypeArg { 
7009                         get { return typearg; }
7010                 }
7011         }
7012
7013         /// <summary>
7014         ///   Implements the `typeof (void)' operator
7015         /// </summary>
7016         public class TypeOfVoid : TypeOf {
7017                 public TypeOfVoid (Location l) : base (null, l)
7018                 {
7019                         loc = l;
7020                 }
7021
7022                 public override Expression DoResolve (EmitContext ec)
7023                 {
7024                         type = TypeManager.type_type;
7025                         typearg = TypeManager.void_type;
7026                         eclass = ExprClass.Type;
7027                         return this;
7028                 }
7029         }
7030
7031         /// <summary>
7032         ///   Implements the sizeof expression
7033         /// </summary>
7034         public class SizeOf : Expression {
7035                 public Expression QueriedType;
7036                 Type type_queried;
7037                 
7038                 public SizeOf (Expression queried_type, Location l)
7039                 {
7040                         this.QueriedType = queried_type;
7041                         loc = l;
7042                 }
7043
7044                 public override Expression DoResolve (EmitContext ec)
7045                 {
7046                         if (!ec.InUnsafe) {
7047                                 Report.Error (
7048                                         233, loc, "Sizeof may only be used in an unsafe context " +
7049                                         "(consider using System.Runtime.InteropServices.Marshal.Sizeof");
7050                                 return null;
7051                         }
7052                                 
7053                         QueriedType = ec.DeclSpace.ResolveTypeExpr (QueriedType, false, loc);
7054                         if (QueriedType == null || QueriedType.Type == null)
7055                                 return null;
7056
7057                         if (QueriedType is TypeParameterExpr){
7058                                 ((TypeParameterExpr)QueriedType).Error_CannotUseAsUnmanagedType (loc);
7059                                 return null;
7060                         }
7061
7062                         type_queried = QueriedType.Type;
7063                         if (!TypeManager.IsUnmanagedType (type_queried)){
7064                                 Report.Error (208, loc, "Cannot take the size of an unmanaged type (" + TypeManager.CSharpName (type_queried) + ")");
7065                                 return null;
7066                         }
7067                         
7068                         type = TypeManager.int32_type;
7069                         eclass = ExprClass.Value;
7070                         return this;
7071                 }
7072
7073                 public override void Emit (EmitContext ec)
7074                 {
7075                         int size = GetTypeSize (type_queried);
7076
7077                         if (size == 0)
7078                                 ec.ig.Emit (OpCodes.Sizeof, type_queried);
7079                         else
7080                                 IntConstant.EmitInt (ec.ig, size);
7081                 }
7082         }
7083
7084         /// <summary>
7085         ///   Implements the member access expression
7086         /// </summary>
7087         public class MemberAccess : Expression {
7088                 public string Identifier;
7089                 protected Expression expr;
7090                 protected TypeArguments args;
7091                 
7092                 public MemberAccess (Expression expr, string id, Location l)
7093                 {
7094                         this.expr = expr;
7095                         Identifier = id;
7096                         loc = l;
7097                 }
7098
7099                 public MemberAccess (Expression expr, string id, TypeArguments args,
7100                                      Location l)
7101                         : this (expr, id, l)
7102                 {
7103                         this.args = args;
7104                 }
7105
7106                 public Expression Expr {
7107                         get {
7108                                 return expr;
7109                         }
7110                 }
7111
7112                 static void error176 (Location loc, string name)
7113                 {
7114                         Report.Error (176, loc, "Static member `" +
7115                                       name + "' cannot be accessed " +
7116                                       "with an instance reference, qualify with a " +
7117                                       "type name instead");
7118                 }
7119
7120                 static bool IdenticalNameAndTypeName (EmitContext ec, Expression left_original, Location loc)
7121                 {
7122                         if (left_original == null)
7123                                 return false;
7124
7125                         if (!(left_original is SimpleName))
7126                                 return false;
7127
7128                         SimpleName sn = (SimpleName) left_original;
7129
7130                         TypeExpr t = RootContext.LookupType (ec.DeclSpace, sn.Name, true, loc);
7131                         if (t != null)
7132                                 return true;
7133
7134                         return false;
7135                 }
7136                 
7137                 public static Expression ResolveMemberAccess (EmitContext ec, Expression member_lookup,
7138                                                               Expression left, Location loc,
7139                                                               Expression left_original)
7140                 {
7141                         bool left_is_type, left_is_explicit;
7142
7143                         // If `left' is null, then we're called from SimpleNameResolve and this is
7144                         // a member in the currently defining class.
7145                         if (left == null) {
7146                                 left_is_type = ec.IsStatic || ec.IsFieldInitializer;
7147                                 left_is_explicit = false;
7148
7149                                 // Implicitly default to `this' unless we're static.
7150                                 if (!ec.IsStatic && !ec.IsFieldInitializer && !ec.InEnumContext)
7151                                         left = ec.GetThis (loc);
7152                         } else {
7153                                 left_is_type = left is TypeExpr;
7154                                 left_is_explicit = true;
7155                         }
7156
7157                         if (member_lookup is FieldExpr){
7158                                 FieldExpr fe = (FieldExpr) member_lookup;
7159                                 FieldInfo fi = fe.FieldInfo;
7160                                 Type decl_type = fi.DeclaringType;
7161
7162                                 if (fi is FieldBuilder) {
7163                                         Const c = TypeManager.LookupConstant ((FieldBuilder) fi);
7164                                         
7165                                         if (c != null) {
7166                                                 object o;
7167                                                 if (!c.LookupConstantValue (out o))
7168                                                         return null;
7169
7170                                                 object real_value = ((Constant) c.Expr).GetValue ();
7171
7172                                                 return Constantify (real_value, fi.FieldType);
7173                                         }
7174                                 }
7175
7176                                 if (fi.IsLiteral) {
7177                                         Type t = fi.FieldType;
7178                                         
7179                                         object o;
7180
7181                                         if (fi is FieldBuilder)
7182                                                 o = TypeManager.GetValue ((FieldBuilder) fi);
7183                                         else
7184                                                 o = fi.GetValue (fi);
7185                                         
7186                                         if (decl_type.IsSubclassOf (TypeManager.enum_type)) {
7187                                                 if (left_is_explicit && !left_is_type &&
7188                                                     !IdenticalNameAndTypeName (ec, left_original, loc)) {
7189                                                         error176 (loc, fe.FieldInfo.Name);
7190                                                         return null;
7191                                                 }                                       
7192                                                 
7193                                                 Expression enum_member = MemberLookup (
7194                                                         ec, decl_type, "value__", MemberTypes.Field,
7195                                                         AllBindingFlags, loc); 
7196
7197                                                 Enum en = TypeManager.LookupEnum (decl_type);
7198
7199                                                 Constant c;
7200                                                 if (en != null)
7201                                                         c = Constantify (o, en.UnderlyingType);
7202                                                 else 
7203                                                         c = Constantify (o, enum_member.Type);
7204                                                 
7205                                                 return new EnumConstant (c, decl_type);
7206                                         }
7207                                         
7208                                         Expression exp = Constantify (o, t);
7209
7210                                         if (left_is_explicit && !left_is_type) {
7211                                                 error176 (loc, fe.FieldInfo.Name);
7212                                                 return null;
7213                                         }
7214                                         
7215                                         return exp;
7216                                 }
7217
7218                                 if (fi.FieldType.IsPointer && !ec.InUnsafe){
7219                                         UnsafeError (loc);
7220                                         return null;
7221                                 }
7222                         }
7223
7224                         if (member_lookup is EventExpr) {
7225                                 EventExpr ee = (EventExpr) member_lookup;
7226                                 
7227                                 //
7228                                 // If the event is local to this class, we transform ourselves into
7229                                 // a FieldExpr
7230                                 //
7231
7232                                 if (ee.EventInfo.DeclaringType == ec.ContainerType ||
7233                                     TypeManager.IsNestedChildOf(ec.ContainerType, ee.EventInfo.DeclaringType)) {
7234                                         MemberInfo mi = GetFieldFromEvent (ee);
7235
7236                                         if (mi == null) {
7237                                                 //
7238                                                 // If this happens, then we have an event with its own
7239                                                 // accessors and private field etc so there's no need
7240                                                 // to transform ourselves.
7241                                                 //
7242                                                 return ee;
7243                                         }
7244
7245                                         Expression ml = ExprClassFromMemberInfo (ec, mi, loc);
7246                                         
7247                                         if (ml == null) {
7248                                                 Report.Error (-200, loc, "Internal error!!");
7249                                                 return null;
7250                                         }
7251
7252                                         if (!left_is_explicit)
7253                                                 left = null;
7254                                         
7255                                         return ResolveMemberAccess (ec, ml, left, loc, left_original);
7256                                 }
7257                         }
7258
7259                         if (member_lookup is IMemberExpr) {
7260                                 IMemberExpr me = (IMemberExpr) member_lookup;
7261
7262                                 if (left_is_type){
7263                                         MethodGroupExpr mg = me as MethodGroupExpr;
7264                                         if ((mg != null) && left_is_explicit && left.Type.IsInterface)
7265                                                 mg.IsExplicitImpl = left_is_explicit;
7266
7267                                         if (!me.IsStatic){
7268                                                 if ((ec.IsFieldInitializer || ec.IsStatic) &&
7269                                                     IdenticalNameAndTypeName (ec, left_original, loc))
7270                                                         return member_lookup;
7271
7272                                                 SimpleName.Error_ObjectRefRequired (ec, loc, me.Name);
7273                                                 return null;
7274                                         }
7275
7276                                 } else {
7277                                         if (!me.IsInstance){
7278                                                 if (IdenticalNameAndTypeName (ec, left_original, loc))
7279                                                         return member_lookup;
7280
7281                                                 if (left_is_explicit) {
7282                                                         error176 (loc, me.Name);
7283                                                         return null;
7284                                                 }
7285                                         }
7286
7287                                         //
7288                                         // Since we can not check for instance objects in SimpleName,
7289                                         // becaue of the rule that allows types and variables to share
7290                                         // the name (as long as they can be de-ambiguated later, see 
7291                                         // IdenticalNameAndTypeName), we have to check whether left 
7292                                         // is an instance variable in a static context
7293                                         //
7294                                         // However, if the left-hand value is explicitly given, then
7295                                         // it is already our instance expression, so we aren't in
7296                                         // static context.
7297                                         //
7298
7299                                         if (ec.IsStatic && !left_is_explicit && left is IMemberExpr){
7300                                                 IMemberExpr mexp = (IMemberExpr) left;
7301
7302                                                 if (!mexp.IsStatic){
7303                                                         SimpleName.Error_ObjectRefRequired (ec, loc, mexp.Name);
7304                                                         return null;
7305                                                 }
7306                                         }
7307
7308                                         me.InstanceExpression = left;
7309                                 }
7310
7311                                 return member_lookup;
7312                         }
7313
7314                         Console.WriteLine ("Left is: " + left);
7315                         Report.Error (-100, loc, "Support for [" + member_lookup + "] is not present yet");
7316                         Environment.Exit (1);
7317                         return null;
7318                 }
7319                 
7320                 public virtual Expression DoResolve (EmitContext ec, Expression right_side,
7321                                                      ResolveFlags flags)
7322                 {
7323                         if (type != null)
7324                                 throw new Exception ();
7325
7326                         //
7327                         // Resolve the expression with flow analysis turned off, we'll do the definite
7328                         // assignment checks later.  This is because we don't know yet what the expression
7329                         // will resolve to - it may resolve to a FieldExpr and in this case we must do the
7330                         // definite assignment check on the actual field and not on the whole struct.
7331                         //
7332
7333                         Expression original = expr;
7334                         expr = expr.Resolve (ec, flags | ResolveFlags.DisableFlowAnalysis);
7335                         if (expr == null)
7336                                 return null;
7337
7338                         if (expr is SimpleName){
7339                                 SimpleName child_expr = (SimpleName) expr;
7340
7341                                 Expression new_expr = new SimpleName (child_expr.Name, Identifier, loc);
7342
7343                                 return new_expr.Resolve (ec, flags);
7344                         }
7345                                         
7346                         //
7347                         // TODO: I mailed Ravi about this, and apparently we can get rid
7348                         // of this and put it in the right place.
7349                         // 
7350                         // Handle enums here when they are in transit.
7351                         // Note that we cannot afford to hit MemberLookup in this case because
7352                         // it will fail to find any members at all
7353                         //
7354
7355                         Type expr_type;
7356                         if (expr is TypeExpr){
7357                                 expr_type = ((TypeExpr) expr).ResolveType (ec);
7358
7359                                 if (!ec.DeclSpace.CheckAccessLevel (expr_type)){
7360                                         Error (122, "`" + expr_type + "' " +
7361                                                "is inaccessible because of its protection level");
7362                                         return null;
7363                                 }
7364
7365                                 if (expr_type == TypeManager.enum_type || expr_type.IsSubclassOf (TypeManager.enum_type)){
7366                                         Enum en = TypeManager.LookupEnum (expr_type);
7367
7368                                         if (en != null) {
7369                                                 object value = en.LookupEnumValue (ec, Identifier, loc);
7370                                                 
7371                                                 if (value != null){
7372                                                         Constant c = Constantify (value, en.UnderlyingType);
7373                                                         return new EnumConstant (c, expr_type);
7374                                                 }
7375                                         }
7376                                 }
7377                         } else
7378                                 expr_type = expr.Type;
7379                         
7380                         if (expr_type.IsPointer){
7381                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7382                                        TypeManager.CSharpName (expr_type) + ")");
7383                                 return null;
7384                         }
7385
7386                         int errors = Report.Errors;
7387
7388                         Expression member_lookup;
7389                         member_lookup = MemberLookup (
7390                                 ec, expr_type, expr_type, Identifier, loc);
7391                         if ((member_lookup == null) && (args != null)) {
7392                                 string lookup_id = Identifier + "!" + args.Count;
7393                                 member_lookup = MemberLookup (
7394                                         ec, expr_type, expr_type, lookup_id, loc);
7395                         }
7396                         if (member_lookup == null) {
7397                                 MemberLookupFailed (
7398                                         ec, expr_type, expr_type, Identifier, null, loc);
7399                                 return null;
7400                         }
7401
7402                         if (member_lookup is TypeExpr) {
7403                                 if (!(expr is TypeExpr) && !(expr is SimpleName)) {
7404                                         Error (572, "Can't reference type `" + Identifier + "' through an expression; try `" +
7405                                                member_lookup.Type + "' instead");
7406                                         return null;
7407                                 }
7408
7409                                 return member_lookup;
7410                         }
7411
7412                         if (args != null) {
7413                                 string full_name = expr_type + "." + Identifier;
7414
7415                                 if (member_lookup is FieldExpr) {
7416                                         Report.Error (307, loc, "The field `{0}' cannot " +
7417                                                       "be used with type arguments", full_name);
7418                                         return null;
7419                                 } else if (member_lookup is EventExpr) {
7420                                         Report.Error (307, loc, "The event `{0}' cannot " +
7421                                                       "be used with type arguments", full_name);
7422                                         return null;
7423                                 } else if (member_lookup is PropertyExpr) {
7424                                         Report.Error (307, loc, "The property `{0}' cannot " +
7425                                                       "be used with type arguments", full_name);
7426                                         return null;
7427                                 }
7428                         }
7429                         
7430                         member_lookup = ResolveMemberAccess (ec, member_lookup, expr, loc, original);
7431                         if (member_lookup == null)
7432                                 return null;
7433
7434                         if (args != null) {
7435                                 MethodGroupExpr mg = member_lookup as MethodGroupExpr;
7436                                 if (mg == null)
7437                                         throw new InternalErrorException ();
7438
7439                                 if (args.Resolve (ec) == false)
7440                                         return null;
7441
7442                                 Type[] atypes = args.Arguments;
7443
7444                                 int first_count = 0;
7445                                 MethodInfo first = null;
7446
7447                                 ArrayList list = new ArrayList ();
7448                                 foreach (MethodBase mb in mg.Methods) {
7449                                         MethodInfo mi = mb as MethodInfo;
7450                                         if ((mi == null) || !mi.HasGenericParameters)
7451                                                 continue;
7452
7453                                         Type[] gen_params = mi.GetGenericArguments ();
7454
7455                                         if (first == null) {
7456                                                 first = mi;
7457                                                 first_count = gen_params.Length;
7458                                         }
7459
7460                                         if (gen_params.Length != atypes.Length)
7461                                                 continue;
7462
7463                                         list.Add (mi.BindGenericParameters (atypes));
7464                                 }
7465
7466                                 if (list.Count > 0) {
7467                                         MethodGroupExpr new_mg = new MethodGroupExpr (
7468                                                 list, mg.Location);
7469                                         new_mg.InstanceExpression = mg.InstanceExpression;
7470                                         new_mg.HasTypeArguments = true;
7471                                         return new_mg;
7472                                 }
7473
7474                                 string name = expr_type + "." + Identifier;
7475
7476                                 if (first != null)
7477                                         Report.Error (
7478                                                 305, loc, "Using the generic method `{0}' " +
7479                                                 "requires {1} type arguments", name,
7480                                                 first_count);
7481                                 else
7482                                         Report.Error (
7483                                                 308, loc, "The non-generic method `{0}' " +
7484                                                 "cannot be used with type arguments", name);
7485
7486                                 return null;
7487                         }
7488
7489                         // The following DoResolve/DoResolveLValue will do the definite assignment
7490                         // check.
7491
7492                         if (right_side != null)
7493                                 member_lookup = member_lookup.DoResolveLValue (ec, right_side);
7494                         else
7495                                 member_lookup = member_lookup.DoResolve (ec);
7496
7497                         return member_lookup;
7498                 }
7499
7500                 public override Expression DoResolve (EmitContext ec)
7501                 {
7502                         return DoResolve (ec, null, ResolveFlags.VariableOrValue |
7503                                           ResolveFlags.SimpleName | ResolveFlags.Type);
7504                 }
7505
7506                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7507                 {
7508                         return DoResolve (ec, right_side, ResolveFlags.VariableOrValue |
7509                                           ResolveFlags.SimpleName | ResolveFlags.Type);
7510                 }
7511
7512                 public override Expression ResolveAsTypeStep (EmitContext ec)
7513                 {
7514                         string fname = null;
7515                         MemberAccess full_expr = this;
7516                         while (full_expr != null) {
7517                                 if (fname != null)
7518                                         fname = String.Concat (full_expr.Identifier, ".", fname);
7519                                 else
7520                                         fname = full_expr.Identifier;
7521
7522                                 if (full_expr.Expr is SimpleName) {
7523                                         string full_name = String.Concat (((SimpleName) full_expr.Expr).Name, ".", fname);
7524                                         Type fully_qualified = ec.DeclSpace.FindType (loc, full_name);
7525                                         if (fully_qualified != null)
7526                                                 return new TypeExpression (fully_qualified, loc);
7527                                 }
7528
7529                                 full_expr = full_expr.Expr as MemberAccess;
7530                         }
7531
7532                         Expression new_expr = expr.ResolveAsTypeStep (ec);
7533
7534                         if (new_expr == null)
7535                                 return null;
7536
7537                         if (new_expr is SimpleName){
7538                                 SimpleName child_expr = (SimpleName) new_expr;
7539                                 
7540                                 new_expr = new SimpleName (child_expr.Name, Identifier, loc);
7541
7542                                 return new_expr.ResolveAsTypeStep (ec);
7543                         }
7544
7545                         Type expr_type = ((TypeExpr) new_expr).ResolveType (ec);
7546
7547                         if (expr_type.IsPointer){
7548                                 Error (23, "The `.' operator can not be applied to pointer operands (" +
7549                                        TypeManager.CSharpName (expr_type) + ")");
7550                                 return null;
7551                         }
7552
7553                         Expression member_lookup;
7554                         string lookup_id;
7555                         if (args != null)
7556                                 lookup_id = Identifier + "!" + args.Count;
7557                         else
7558                                 lookup_id = Identifier;
7559                         member_lookup = MemberLookupFinal (
7560                                 ec, expr_type, expr_type, lookup_id, loc);
7561                         if (member_lookup == null)
7562                                 return null;
7563
7564                         TypeExpr texpr = member_lookup as TypeExpr;
7565                         if (texpr == null)
7566                                 return null;
7567
7568                         Type t = texpr.ResolveType (ec);
7569                         if (t == null)
7570                                 return null;
7571
7572                         if (TypeManager.HasGenericArguments (expr_type)) {
7573                                 Type[] decl_args = TypeManager.GetTypeArguments (expr_type);
7574
7575                                 TypeArguments new_args = new TypeArguments (loc);
7576                                 foreach (Type decl in decl_args)
7577                                         new_args.Add (new TypeExpression (decl, loc));
7578
7579                                 if (args != null)
7580                                         new_args.Add (args);
7581
7582                                 args = new_args;
7583                         }
7584
7585                         if (args != null) {
7586                                 ConstructedType ctype = new ConstructedType (t, args, loc);
7587                                 return ctype.ResolveAsTypeStep (ec);
7588                         }
7589
7590                         return texpr;
7591                 }
7592
7593                 public override void Emit (EmitContext ec)
7594                 {
7595                         throw new Exception ("Should not happen");
7596                 }
7597
7598                 public override string ToString ()
7599                 {
7600                         if (args != null)
7601                                 return expr + "." + Identifier + "!" + args.Count;
7602                         else
7603                                 return expr + "." + Identifier;
7604                 }
7605         }
7606
7607         /// <summary>
7608         ///   Implements checked expressions
7609         /// </summary>
7610         public class CheckedExpr : Expression {
7611
7612                 public Expression Expr;
7613
7614                 public CheckedExpr (Expression e, Location l)
7615                 {
7616                         Expr = e;
7617                         loc = l;
7618                 }
7619
7620                 public override Expression DoResolve (EmitContext ec)
7621                 {
7622                         bool last_check = ec.CheckState;
7623                         bool last_const_check = ec.ConstantCheckState;
7624
7625                         ec.CheckState = true;
7626                         ec.ConstantCheckState = true;
7627                         Expr = Expr.Resolve (ec);
7628                         ec.CheckState = last_check;
7629                         ec.ConstantCheckState = last_const_check;
7630                         
7631                         if (Expr == null)
7632                                 return null;
7633
7634                         if (Expr is Constant)
7635                                 return Expr;
7636                         
7637                         eclass = Expr.eclass;
7638                         type = Expr.Type;
7639                         return this;
7640                 }
7641
7642                 public override void Emit (EmitContext ec)
7643                 {
7644                         bool last_check = ec.CheckState;
7645                         bool last_const_check = ec.ConstantCheckState;
7646                         
7647                         ec.CheckState = true;
7648                         ec.ConstantCheckState = true;
7649                         Expr.Emit (ec);
7650                         ec.CheckState = last_check;
7651                         ec.ConstantCheckState = last_const_check;
7652                 }
7653                 
7654         }
7655
7656         /// <summary>
7657         ///   Implements the unchecked expression
7658         /// </summary>
7659         public class UnCheckedExpr : Expression {
7660
7661                 public Expression Expr;
7662
7663                 public UnCheckedExpr (Expression e, Location l)
7664                 {
7665                         Expr = e;
7666                         loc = l;
7667                 }
7668
7669                 public override Expression DoResolve (EmitContext ec)
7670                 {
7671                         bool last_check = ec.CheckState;
7672                         bool last_const_check = ec.ConstantCheckState;
7673
7674                         ec.CheckState = false;
7675                         ec.ConstantCheckState = false;
7676                         Expr = Expr.Resolve (ec);
7677                         ec.CheckState = last_check;
7678                         ec.ConstantCheckState = last_const_check;
7679
7680                         if (Expr == null)
7681                                 return null;
7682
7683                         if (Expr is Constant)
7684                                 return Expr;
7685                         
7686                         eclass = Expr.eclass;
7687                         type = Expr.Type;
7688                         return this;
7689                 }
7690
7691                 public override void Emit (EmitContext ec)
7692                 {
7693                         bool last_check = ec.CheckState;
7694                         bool last_const_check = ec.ConstantCheckState;
7695                         
7696                         ec.CheckState = false;
7697                         ec.ConstantCheckState = false;
7698                         Expr.Emit (ec);
7699                         ec.CheckState = last_check;
7700                         ec.ConstantCheckState = last_const_check;
7701                 }
7702                 
7703         }
7704
7705         /// <summary>
7706         ///   An Element Access expression.
7707         ///
7708         ///   During semantic analysis these are transformed into 
7709         ///   IndexerAccess, ArrayAccess or a PointerArithmetic.
7710         /// </summary>
7711         public class ElementAccess : Expression {
7712                 public ArrayList  Arguments;
7713                 public Expression Expr;
7714                 
7715                 public ElementAccess (Expression e, ArrayList e_list, Location l)
7716                 {
7717                         Expr = e;
7718
7719                         loc  = l;
7720                         
7721                         if (e_list == null)
7722                                 return;
7723                         
7724                         Arguments = new ArrayList ();
7725                         foreach (Expression tmp in e_list)
7726                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
7727                         
7728                 }
7729
7730                 bool CommonResolve (EmitContext ec)
7731                 {
7732                         Expr = Expr.Resolve (ec);
7733
7734                         if (Expr == null) 
7735                                 return false;
7736
7737                         if (Arguments == null)
7738                                 return false;
7739
7740                         foreach (Argument a in Arguments){
7741                                 if (!a.Resolve (ec, loc))
7742                                         return false;
7743                         }
7744
7745                         return true;
7746                 }
7747
7748                 Expression MakePointerAccess ()
7749                 {
7750                         Type t = Expr.Type;
7751
7752                         if (t == TypeManager.void_ptr_type){
7753                                 Error (242, "The array index operation is not valid for void pointers");
7754                                 return null;
7755                         }
7756                         if (Arguments.Count != 1){
7757                                 Error (196, "A pointer must be indexed by a single value");
7758                                 return null;
7759                         }
7760                         Expression p;
7761
7762                         p = new PointerArithmetic (true, Expr, ((Argument)Arguments [0]).Expr, t, loc);
7763                         return new Indirection (p, loc);
7764                 }
7765                 
7766                 public override Expression DoResolve (EmitContext ec)
7767                 {
7768                         if (!CommonResolve (ec))
7769                                 return null;
7770
7771                         //
7772                         // We perform some simple tests, and then to "split" the emit and store
7773                         // code we create an instance of a different class, and return that.
7774                         //
7775                         // I am experimenting with this pattern.
7776                         //
7777                         Type t = Expr.Type;
7778
7779                         if (t == TypeManager.array_type){
7780                                 Report.Error (21, loc, "Cannot use indexer on System.Array");
7781                                 return null;
7782                         }
7783                         
7784                         if (t.IsArray)
7785                                 return (new ArrayAccess (this, loc)).Resolve (ec);
7786                         else if (t.IsPointer)
7787                                 return MakePointerAccess ();
7788                         else
7789                                 return (new IndexerAccess (this, loc)).Resolve (ec);
7790                 }
7791
7792                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
7793                 {
7794                         if (!CommonResolve (ec))
7795                                 return null;
7796
7797                         Type t = Expr.Type;
7798                         if (t.IsArray)
7799                                 return (new ArrayAccess (this, loc)).ResolveLValue (ec, right_side);
7800                         else if (t.IsPointer)
7801                                 return MakePointerAccess ();
7802                         else
7803                                 return (new IndexerAccess (this, loc)).ResolveLValue (ec, right_side);
7804                 }
7805                 
7806                 public override void Emit (EmitContext ec)
7807                 {
7808                         throw new Exception ("Should never be reached");
7809                 }
7810         }
7811
7812         /// <summary>
7813         ///   Implements array access 
7814         /// </summary>
7815         public class ArrayAccess : Expression, IAssignMethod, IMemoryLocation {
7816                 //
7817                 // Points to our "data" repository
7818                 //
7819                 ElementAccess ea;
7820
7821                 LocalTemporary [] cached_locations;
7822                 
7823                 public ArrayAccess (ElementAccess ea_data, Location l)
7824                 {
7825                         ea = ea_data;
7826                         eclass = ExprClass.Variable;
7827                         loc = l;
7828                 }
7829
7830                 public override Expression DoResolve (EmitContext ec)
7831                 {
7832 #if false
7833                         ExprClass eclass = ea.Expr.eclass;
7834
7835                         // As long as the type is valid
7836                         if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
7837                               eclass == ExprClass.Value)) {
7838                                 ea.Expr.Error_UnexpectedKind ("variable or value");
7839                                 return null;
7840                         }
7841 #endif
7842
7843                         Type t = ea.Expr.Type;
7844                         if (t.GetArrayRank () != ea.Arguments.Count){
7845                                 ea.Error (22,
7846                                           "Incorrect number of indexes for array " +
7847                                           " expected: " + t.GetArrayRank () + " got: " +
7848                                           ea.Arguments.Count);
7849                                 return null;
7850                         }
7851
7852                         type = TypeManager.GetElementType (t);
7853                         if (type.IsPointer && !ec.InUnsafe){
7854                                 UnsafeError (ea.Location);
7855                                 return null;
7856                         }
7857
7858                         foreach (Argument a in ea.Arguments){
7859                                 Type argtype = a.Type;
7860
7861                                 if (argtype == TypeManager.int32_type ||
7862                                     argtype == TypeManager.uint32_type ||
7863                                     argtype == TypeManager.int64_type ||
7864                                     argtype == TypeManager.uint64_type)
7865                                         continue;
7866
7867                                 //
7868                                 // Mhm.  This is strage, because the Argument.Type is not the same as
7869                                 // Argument.Expr.Type: the value changes depending on the ref/out setting.
7870                                 //
7871                                 // Wonder if I will run into trouble for this.
7872                                 //
7873                                 a.Expr = ExpressionToArrayArgument (ec, a.Expr, ea.Location);
7874                                 if (a.Expr == null)
7875                                         return null;
7876                         }
7877                         
7878                         eclass = ExprClass.Variable;
7879
7880                         return this;
7881                 }
7882
7883                 /// <summary>
7884                 ///    Emits the right opcode to load an object of Type `t'
7885                 ///    from an array of T
7886                 /// </summary>
7887                 static public void EmitLoadOpcode (ILGenerator ig, Type type)
7888                 {
7889                         if (type == TypeManager.byte_type || type == TypeManager.bool_type)
7890                                 ig.Emit (OpCodes.Ldelem_U1);
7891                         else if (type == TypeManager.sbyte_type)
7892                                 ig.Emit (OpCodes.Ldelem_I1);
7893                         else if (type == TypeManager.short_type)
7894                                 ig.Emit (OpCodes.Ldelem_I2);
7895                         else if (type == TypeManager.ushort_type || type == TypeManager.char_type)
7896                                 ig.Emit (OpCodes.Ldelem_U2);
7897                         else if (type == TypeManager.int32_type)
7898                                 ig.Emit (OpCodes.Ldelem_I4);
7899                         else if (type == TypeManager.uint32_type)
7900                                 ig.Emit (OpCodes.Ldelem_U4);
7901                         else if (type == TypeManager.uint64_type)
7902                                 ig.Emit (OpCodes.Ldelem_I8);
7903                         else if (type == TypeManager.int64_type)
7904                                 ig.Emit (OpCodes.Ldelem_I8);
7905                         else if (type == TypeManager.float_type)
7906                                 ig.Emit (OpCodes.Ldelem_R4);
7907                         else if (type == TypeManager.double_type)
7908                                 ig.Emit (OpCodes.Ldelem_R8);
7909                         else if (type == TypeManager.intptr_type)
7910                                 ig.Emit (OpCodes.Ldelem_I);
7911                         else if (TypeManager.IsEnumType (type)){
7912                                 EmitLoadOpcode (ig, TypeManager.EnumToUnderlying (type));
7913                         } else if (type.IsValueType){
7914                                 ig.Emit (OpCodes.Ldelema, type);
7915                                 ig.Emit (OpCodes.Ldobj, type);
7916                         } else if (type.IsGenericParameter)
7917                                 ig.Emit (OpCodes.Ldelem_Any, type);
7918                         else
7919                                 ig.Emit (OpCodes.Ldelem_Ref);
7920                 }
7921
7922                 /// <summary>
7923                 ///    Emits the right opcode to store an object of Type `t'
7924                 ///    from an array of T.  
7925                 /// </summary>
7926                 static public void EmitStoreOpcode (ILGenerator ig, Type t)
7927                 {
7928                         bool is_stobj, has_type_arg;
7929                         OpCode op = GetStoreOpcode (t, out is_stobj, out has_type_arg);
7930                         if (has_type_arg)
7931                                 ig.Emit (op, t);
7932                         else
7933                                 ig.Emit (op);
7934                 }
7935
7936                 /// <summary>
7937                 ///    Returns the right opcode to store an object of Type `t'
7938                 ///    from an array of T.  
7939                 /// </summary>
7940                 static public OpCode GetStoreOpcode (Type t, out bool is_stobj, out bool has_type_arg)
7941                 {
7942                         //Console.WriteLine (new System.Diagnostics.StackTrace ());
7943                         has_type_arg = false; is_stobj = false;
7944                         t = TypeManager.TypeToCoreType (t);
7945                         if (TypeManager.IsEnumType (t) && t != TypeManager.enum_type)
7946                                 t = TypeManager.EnumToUnderlying (t);
7947                         if (t == TypeManager.byte_type || t == TypeManager.sbyte_type ||
7948                             t == TypeManager.bool_type)
7949                                 return OpCodes.Stelem_I1;
7950                         else if (t == TypeManager.short_type || t == TypeManager.ushort_type ||
7951                                  t == TypeManager.char_type)
7952                                 return OpCodes.Stelem_I2;
7953                         else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
7954                                 return OpCodes.Stelem_I4;
7955                         else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
7956                                 return OpCodes.Stelem_I8;
7957                         else if (t == TypeManager.float_type)
7958                                 return OpCodes.Stelem_R4;
7959                         else if (t == TypeManager.double_type)
7960                                 return OpCodes.Stelem_R8;
7961                         else if (t == TypeManager.intptr_type) {
7962                                 has_type_arg = true;
7963                                 is_stobj = true;
7964                                 return OpCodes.Stobj;
7965                         } else if (t.IsValueType) {
7966                                 has_type_arg = true;
7967                                 is_stobj = true;
7968                                 return OpCodes.Stobj;
7969                         } else if (t.IsGenericParameter) {
7970                                 has_type_arg = true;
7971                                 return OpCodes.Stelem_Any;
7972                         } else
7973                                 return OpCodes.Stelem_Ref;
7974                 }
7975
7976                 MethodInfo FetchGetMethod ()
7977                 {
7978                         ModuleBuilder mb = CodeGen.Module.Builder;
7979                         int arg_count = ea.Arguments.Count;
7980                         Type [] args = new Type [arg_count];
7981                         MethodInfo get;
7982                         
7983                         for (int i = 0; i < arg_count; i++){
7984                                 //args [i++] = a.Type;
7985                                 args [i] = TypeManager.int32_type;
7986                         }
7987                         
7988                         get = mb.GetArrayMethod (
7989                                 ea.Expr.Type, "Get",
7990                                 CallingConventions.HasThis |
7991                                 CallingConventions.Standard,
7992                                 type, args);
7993                         return get;
7994                 }
7995                                 
7996
7997                 MethodInfo FetchAddressMethod ()
7998                 {
7999                         ModuleBuilder mb = CodeGen.Module.Builder;
8000                         int arg_count = ea.Arguments.Count;
8001                         Type [] args = new Type [arg_count];
8002                         MethodInfo address;
8003                         Type ret_type;
8004                         
8005                         ret_type = TypeManager.GetReferenceType (type);
8006                         
8007                         for (int i = 0; i < arg_count; i++){
8008                                 //args [i++] = a.Type;
8009                                 args [i] = TypeManager.int32_type;
8010                         }
8011                         
8012                         address = mb.GetArrayMethod (
8013                                 ea.Expr.Type, "Address",
8014                                 CallingConventions.HasThis |
8015                                 CallingConventions.Standard,
8016                                 ret_type, args);
8017
8018                         return address;
8019                 }
8020
8021                 //
8022                 // Load the array arguments into the stack.
8023                 //
8024                 // If we have been requested to cache the values (cached_locations array
8025                 // initialized), then load the arguments the first time and store them
8026                 // in locals.  otherwise load from local variables.
8027                 //
8028                 void LoadArrayAndArguments (EmitContext ec)
8029                 {
8030                         ILGenerator ig = ec.ig;
8031                         
8032                         if (cached_locations == null){
8033                                 ea.Expr.Emit (ec);
8034                                 foreach (Argument a in ea.Arguments){
8035                                         Type argtype = a.Expr.Type;
8036                                         
8037                                         a.Expr.Emit (ec);
8038                                         
8039                                         if (argtype == TypeManager.int64_type)
8040                                                 ig.Emit (OpCodes.Conv_Ovf_I);
8041                                         else if (argtype == TypeManager.uint64_type)
8042                                                 ig.Emit (OpCodes.Conv_Ovf_I_Un);
8043                                 }
8044                                 return;
8045                         }
8046
8047                         if (cached_locations [0] == null){
8048                                 cached_locations [0] = new LocalTemporary (ec, ea.Expr.Type);
8049                                 ea.Expr.Emit (ec);
8050                                 ig.Emit (OpCodes.Dup);
8051                                 cached_locations [0].Store (ec);
8052                                 
8053                                 int j = 1;
8054                                 
8055                                 foreach (Argument a in ea.Arguments){
8056                                         Type argtype = a.Expr.Type;
8057                                         
8058                                         cached_locations [j] = new LocalTemporary (ec, TypeManager.intptr_type /* a.Expr.Type */);
8059                                         a.Expr.Emit (ec);
8060                                         if (argtype == TypeManager.int64_type)
8061                                                 ig.Emit (OpCodes.Conv_Ovf_I);
8062                                         else if (argtype == TypeManager.uint64_type)
8063                                                 ig.Emit (OpCodes.Conv_Ovf_I_Un);
8064
8065                                         ig.Emit (OpCodes.Dup);
8066                                         cached_locations [j].Store (ec);
8067                                         j++;
8068                                 }
8069                                 return;
8070                         }
8071
8072                         foreach (LocalTemporary lt in cached_locations)
8073                                 lt.Emit (ec);
8074                 }
8075
8076                 public new void CacheTemporaries (EmitContext ec)
8077                 {
8078                         cached_locations = new LocalTemporary [ea.Arguments.Count + 1];
8079                 }
8080                 
8081                 public override void Emit (EmitContext ec)
8082                 {
8083                         int rank = ea.Expr.Type.GetArrayRank ();
8084                         ILGenerator ig = ec.ig;
8085
8086                         LoadArrayAndArguments (ec);
8087                         
8088                         if (rank == 1)
8089                                 EmitLoadOpcode (ig, type);
8090                         else {
8091                                 MethodInfo method;
8092                                 
8093                                 method = FetchGetMethod ();
8094                                 ig.Emit (OpCodes.Call, method);
8095                         }
8096                 }
8097
8098                 public void EmitAssign (EmitContext ec, Expression source)
8099                 {
8100                         int rank = ea.Expr.Type.GetArrayRank ();
8101                         ILGenerator ig = ec.ig;
8102                         Type t = source.Type;
8103
8104                         LoadArrayAndArguments (ec);
8105
8106                         //
8107                         // The stobj opcode used by value types will need
8108                         // an address on the stack, not really an array/array
8109                         // pair
8110                         //
8111                         if (rank == 1){
8112                                 if (t == TypeManager.enum_type || t == TypeManager.decimal_type ||
8113                                     (t.IsSubclassOf (TypeManager.value_type) && !TypeManager.IsEnumType (t) && !TypeManager.IsBuiltinType (t)))
8114                                         ig.Emit (OpCodes.Ldelema, t);
8115                         }
8116                         
8117                         source.Emit (ec);
8118
8119                         if (rank == 1)
8120                                 EmitStoreOpcode (ig, t);
8121                         else {
8122                                 ModuleBuilder mb = CodeGen.Module.Builder;
8123                                 int arg_count = ea.Arguments.Count;
8124                                 Type [] args = new Type [arg_count + 1];
8125                                 MethodInfo set;
8126                                 
8127                                 for (int i = 0; i < arg_count; i++){
8128                                         //args [i++] = a.Type;
8129                                         args [i] = TypeManager.int32_type;
8130                                 }
8131
8132                                 args [arg_count] = type;
8133                                 
8134                                 set = mb.GetArrayMethod (
8135                                         ea.Expr.Type, "Set",
8136                                         CallingConventions.HasThis |
8137                                         CallingConventions.Standard,
8138                                         TypeManager.void_type, args);
8139                                 
8140                                 ig.Emit (OpCodes.Call, set);
8141                         }
8142                 }
8143
8144                 public void AddressOf (EmitContext ec, AddressOp mode)
8145                 {
8146                         int rank = ea.Expr.Type.GetArrayRank ();
8147                         ILGenerator ig = ec.ig;
8148
8149                         LoadArrayAndArguments (ec);
8150
8151                         if (rank == 1){
8152                                 ig.Emit (OpCodes.Ldelema, type);
8153                         } else {
8154                                 MethodInfo address = FetchAddressMethod ();
8155                                 ig.Emit (OpCodes.Call, address);
8156                         }
8157                 }
8158         }
8159
8160         
8161         class Indexers {
8162                 public ArrayList Properties;
8163                 static Hashtable map;
8164
8165                 public struct Indexer {
8166                         public readonly Type Type;
8167                         public readonly MethodInfo Getter, Setter;
8168
8169                         public Indexer (Type type, MethodInfo get, MethodInfo set)
8170                         {
8171                                 this.Type = type;
8172                                 this.Getter = get;
8173                                 this.Setter = set;
8174                         }
8175                 }
8176
8177                 static Indexers ()
8178                 {
8179                         map = new Hashtable ();
8180                 }
8181
8182                 Indexers ()
8183                 {
8184                         Properties = new ArrayList ();
8185                 }
8186                                 
8187                 void Append (MemberInfo [] mi)
8188                 {
8189                         foreach (PropertyInfo property in mi){
8190                                 MethodInfo get, set;
8191                                 
8192                                 get = property.GetGetMethod (true);
8193                                 set = property.GetSetMethod (true);
8194                                 Properties.Add (new Indexer (property.PropertyType, get, set));
8195                         }
8196                 }
8197
8198                 static private MemberInfo [] GetIndexersForTypeOrInterface (Type caller_type, Type lookup_type)
8199                 {
8200                         string p_name = TypeManager.IndexerPropertyName (lookup_type);
8201
8202                         MemberInfo [] mi = TypeManager.MemberLookup (
8203                                 caller_type, caller_type, lookup_type, MemberTypes.Property,
8204                                 BindingFlags.Public | BindingFlags.Instance |
8205                                 BindingFlags.DeclaredOnly, p_name);
8206
8207                         if (mi == null || mi.Length == 0)
8208                                 return null;
8209
8210                         return mi;
8211                 }
8212                 
8213                 static public Indexers GetIndexersForType (Type caller_type, Type lookup_type, Location loc) 
8214                 {
8215                         Indexers ix = (Indexers) map [lookup_type];
8216
8217                         if (ix != null)
8218                                 return ix;
8219
8220                         Type copy = lookup_type;
8221                         while (copy != TypeManager.object_type && copy != null){
8222                                 MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, copy);
8223
8224                                 if (mi != null){
8225                                         if (ix == null)
8226                                                 ix = new Indexers ();
8227
8228                                         ix.Append (mi);
8229                                 }
8230                                         
8231                                 copy = copy.BaseType;
8232                         }
8233
8234                         if (!lookup_type.IsInterface)
8235                                 return ix;
8236
8237                         TypeExpr [] ifaces = TypeManager.GetInterfaces (lookup_type);
8238                         if (ifaces != null) {
8239                                 foreach (TypeExpr iface in ifaces) {
8240                                         Type itype = iface.Type;
8241                                         MemberInfo [] mi = GetIndexersForTypeOrInterface (caller_type, itype);
8242                                         if (mi != null){
8243                                                 if (ix == null)
8244                                                         ix = new Indexers ();
8245                                         
8246                                                 ix.Append (mi);
8247                                         }
8248                                 }
8249                         }
8250
8251                         return ix;
8252                 }
8253         }
8254
8255         /// <summary>
8256         ///   Expressions that represent an indexer call.
8257         /// </summary>
8258         public class IndexerAccess : Expression, IAssignMethod {
8259                 //
8260                 // Points to our "data" repository
8261                 //
8262                 MethodInfo get, set;
8263                 ArrayList set_arguments;
8264                 bool is_base_indexer;
8265
8266                 protected Type indexer_type;
8267                 protected Type current_type;
8268                 protected Expression instance_expr;
8269                 protected ArrayList arguments;
8270                 
8271                 public IndexerAccess (ElementAccess ea, Location loc)
8272                         : this (ea.Expr, false, loc)
8273                 {
8274                         this.arguments = ea.Arguments;
8275                 }
8276
8277                 protected IndexerAccess (Expression instance_expr, bool is_base_indexer,
8278                                          Location loc)
8279                 {
8280                         this.instance_expr = instance_expr;
8281                         this.is_base_indexer = is_base_indexer;
8282                         this.eclass = ExprClass.Value;
8283                         this.loc = loc;
8284                 }
8285
8286                 protected virtual bool CommonResolve (EmitContext ec)
8287                 {
8288                         indexer_type = instance_expr.Type;
8289                         current_type = ec.ContainerType;
8290
8291                         return true;
8292                 }
8293
8294                 public override Expression DoResolve (EmitContext ec)
8295                 {
8296                         ArrayList AllGetters = new ArrayList();
8297                         if (!CommonResolve (ec))
8298                                 return null;
8299
8300                         //
8301                         // Step 1: Query for all `Item' *properties*.  Notice
8302                         // that the actual methods are pointed from here.
8303                         //
8304                         // This is a group of properties, piles of them.  
8305
8306                         bool found_any = false, found_any_getters = false;
8307                         Type lookup_type = indexer_type;
8308
8309                         Indexers ilist;
8310                         ilist = Indexers.GetIndexersForType (current_type, lookup_type, loc);
8311                         if (ilist != null) {
8312                                 found_any = true;
8313                                 if (ilist.Properties != null) {
8314                                         foreach (Indexers.Indexer ix in ilist.Properties) {
8315                                                 if (ix.Getter != null)
8316                                                         AllGetters.Add(ix.Getter);
8317                                         }
8318                                 }
8319                         }
8320
8321                         if (AllGetters.Count > 0) {
8322                                 found_any_getters = true;
8323                                 get = (MethodInfo) Invocation.OverloadResolve (
8324                                         ec, new MethodGroupExpr (AllGetters, loc),
8325                                         arguments, false, loc);
8326                         }
8327
8328                         if (!found_any) {
8329                                 Report.Error (21, loc,
8330                                               "Type `" + TypeManager.CSharpName (indexer_type) +
8331                                               "' does not have any indexers defined");
8332                                 return null;
8333                         }
8334
8335                         if (!found_any_getters) {
8336                                 Error (154, "indexer can not be used in this context, because " +
8337                                        "it lacks a `get' accessor");
8338                                 return null;
8339                         }
8340
8341                         if (get == null) {
8342                                 Error (1501, "No Overload for method `this' takes `" +
8343                                        arguments.Count + "' arguments");
8344                                 return null;
8345                         }
8346
8347                         //
8348                         // Only base will allow this invocation to happen.
8349                         //
8350                         if (get.IsAbstract && this is BaseIndexerAccess){
8351                                 Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (get));
8352                                 return null;
8353                         }
8354
8355                         type = get.ReturnType;
8356                         if (type.IsPointer && !ec.InUnsafe){
8357                                 UnsafeError (loc);
8358                                 return null;
8359                         }
8360                         
8361                         eclass = ExprClass.IndexerAccess;
8362                         return this;
8363                 }
8364
8365                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
8366                 {
8367                         ArrayList AllSetters = new ArrayList();
8368                         if (!CommonResolve (ec))
8369                                 return null;
8370
8371                         bool found_any = false, found_any_setters = false;
8372
8373                         Indexers ilist = Indexers.GetIndexersForType (current_type, indexer_type, loc);
8374                         if (ilist != null) {
8375                                 found_any = true;
8376                                 if (ilist.Properties != null) {
8377                                         foreach (Indexers.Indexer ix in ilist.Properties) {
8378                                                 if (ix.Setter != null)
8379                                                         AllSetters.Add(ix.Setter);
8380                                         }
8381                                 }
8382                         }
8383                         if (AllSetters.Count > 0) {
8384                                 found_any_setters = true;
8385                                 set_arguments = (ArrayList) arguments.Clone ();
8386                                 set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
8387                                 set = (MethodInfo) Invocation.OverloadResolve (
8388                                         ec, new MethodGroupExpr (AllSetters, loc),
8389                                         set_arguments, false, loc);
8390                         }
8391
8392                         if (!found_any) {
8393                                 Report.Error (21, loc,
8394                                               "Type `" + TypeManager.CSharpName (indexer_type) +
8395                                               "' does not have any indexers defined");
8396                                 return null;
8397                         }
8398
8399                         if (!found_any_setters) {
8400                                 Error (154, "indexer can not be used in this context, because " +
8401                                        "it lacks a `set' accessor");
8402                                 return null;
8403                         }
8404
8405                         if (set == null) {
8406                                 Error (1501, "No Overload for method `this' takes `" +
8407                                        arguments.Count + "' arguments");
8408                                 return null;
8409                         }
8410
8411                         //
8412                         // Only base will allow this invocation to happen.
8413                         //
8414                         if (set.IsAbstract && this is BaseIndexerAccess){
8415                                 Report.Error (205, loc, "Cannot call an abstract base indexer: " + Invocation.FullMethodDesc (set));
8416                                 return null;
8417                         }
8418
8419                         //
8420                         // Now look for the actual match in the list of indexers to set our "return" type
8421                         //
8422                         type = TypeManager.void_type;   // default value
8423                         foreach (Indexers.Indexer ix in ilist.Properties){
8424                                 if (ix.Setter == set){
8425                                         type = ix.Type;
8426                                         break;
8427                                 }
8428                         }
8429                         
8430                         eclass = ExprClass.IndexerAccess;
8431                         return this;
8432                 }
8433                 
8434                 public override void Emit (EmitContext ec)
8435                 {
8436                         Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, get, arguments, loc);
8437                 }
8438
8439                 //
8440                 // source is ignored, because we already have a copy of it from the
8441                 // LValue resolution and we have already constructed a pre-cached
8442                 // version of the arguments (ea.set_arguments);
8443                 //
8444                 public void EmitAssign (EmitContext ec, Expression source)
8445                 {
8446                         Invocation.EmitCall (ec, is_base_indexer, false, instance_expr, set, set_arguments, loc);
8447                 }
8448         }
8449
8450         /// <summary>
8451         ///   The base operator for method names
8452         /// </summary>
8453         public class BaseAccess : Expression {
8454                 string member;
8455                 
8456                 public BaseAccess (string member, Location l)
8457                 {
8458                         this.member = member;
8459                         loc = l;
8460                 }
8461
8462                 public override Expression DoResolve (EmitContext ec)
8463                 {
8464                         Expression c = CommonResolve (ec);
8465
8466                         if (c == null)
8467                                 return null;
8468
8469                         //
8470                         // MethodGroups use this opportunity to flag an error on lacking ()
8471                         //
8472                         if (!(c is MethodGroupExpr))
8473                                 return c.Resolve (ec);
8474                         return c;
8475                 }
8476
8477                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
8478                 {
8479                         Expression c = CommonResolve (ec);
8480
8481                         if (c == null)
8482                                 return null;
8483
8484                         //
8485                         // MethodGroups use this opportunity to flag an error on lacking ()
8486                         //
8487                         if (! (c is MethodGroupExpr))
8488                                 return c.DoResolveLValue (ec, right_side);
8489
8490                         return c;
8491                 }
8492
8493                 Expression CommonResolve (EmitContext ec)
8494                 {
8495                         Expression member_lookup;
8496                         Type current_type = ec.ContainerType;
8497                         Type base_type = current_type.BaseType;
8498                         Expression e;
8499
8500                         if (ec.IsStatic){
8501                                 Error (1511, "Keyword base is not allowed in static method");
8502                                 return null;
8503                         }
8504
8505                         if (ec.IsFieldInitializer){
8506                                 Error (1512, "Keyword base is not available in the current context");
8507                                 return null;
8508                         }
8509                         
8510                         member_lookup = MemberLookup (ec, ec.ContainerType, null, base_type,
8511                                                       member, AllMemberTypes, AllBindingFlags,
8512                                                       loc);
8513                         if (member_lookup == null) {
8514                                 MemberLookupFailed (
8515                                         ec, base_type, base_type, member, null, loc);
8516                                 return null;
8517                         }
8518
8519                         Expression left;
8520                         
8521                         if (ec.IsStatic)
8522                                 left = new TypeExpression (base_type, loc);
8523                         else
8524                                 left = ec.GetThis (loc);
8525                         
8526                         e = MemberAccess.ResolveMemberAccess (ec, member_lookup, left, loc, null);
8527
8528                         if (e is PropertyExpr){
8529                                 PropertyExpr pe = (PropertyExpr) e;
8530
8531                                 pe.IsBase = true;
8532                         }
8533
8534                         return e;
8535                 }
8536
8537                 public override void Emit (EmitContext ec)
8538                 {
8539                         throw new Exception ("Should never be called"); 
8540                 }
8541         }
8542
8543         /// <summary>
8544         ///   The base indexer operator
8545         /// </summary>
8546         public class BaseIndexerAccess : IndexerAccess {
8547                 public BaseIndexerAccess (ArrayList args, Location loc)
8548                         : base (null, true, loc)
8549                 {
8550                         arguments = new ArrayList ();
8551                         foreach (Expression tmp in args)
8552                                 arguments.Add (new Argument (tmp, Argument.AType.Expression));
8553                 }
8554
8555                 protected override bool CommonResolve (EmitContext ec)
8556                 {
8557                         instance_expr = ec.GetThis (loc);
8558
8559                         current_type = ec.ContainerType.BaseType;
8560                         indexer_type = current_type;
8561
8562                         foreach (Argument a in arguments){
8563                                 if (!a.Resolve (ec, loc))
8564                                         return false;
8565                         }
8566
8567                         return true;
8568                 }
8569         }
8570         
8571         /// <summary>
8572         ///   This class exists solely to pass the Type around and to be a dummy
8573         ///   that can be passed to the conversion functions (this is used by
8574         ///   foreach implementation to typecast the object return value from
8575         ///   get_Current into the proper type.  All code has been generated and
8576         ///   we only care about the side effect conversions to be performed
8577         ///
8578         ///   This is also now used as a placeholder where a no-action expression
8579         ///   is needed (the `New' class).
8580         /// </summary>
8581         public class EmptyExpression : Expression {
8582                 public EmptyExpression ()
8583                 {
8584                         type = TypeManager.object_type;
8585                         eclass = ExprClass.Value;
8586                         loc = Location.Null;
8587                 }
8588
8589                 public EmptyExpression (Type t)
8590                 {
8591                         type = t;
8592                         eclass = ExprClass.Value;
8593                         loc = Location.Null;
8594                 }
8595                 
8596                 public override Expression DoResolve (EmitContext ec)
8597                 {
8598                         return this;
8599                 }
8600
8601                 public override void Emit (EmitContext ec)
8602                 {
8603                         // nothing, as we only exist to not do anything.
8604                 }
8605
8606                 //
8607                 // This is just because we might want to reuse this bad boy
8608                 // instead of creating gazillions of EmptyExpressions.
8609                 // (CanImplicitConversion uses it)
8610                 //
8611                 public void SetType (Type t)
8612                 {
8613                         type = t;
8614                 }
8615         }
8616
8617         public class UserCast : Expression {
8618                 MethodBase method;
8619                 Expression source;
8620                 
8621                 public UserCast (MethodInfo method, Expression source, Location l)
8622                 {
8623                         this.method = method;
8624                         this.source = source;
8625                         type = method.ReturnType;
8626                         eclass = ExprClass.Value;
8627                         loc = l;
8628                 }
8629
8630                 public override Expression DoResolve (EmitContext ec)
8631                 {
8632                         //
8633                         // We are born fully resolved
8634                         //
8635                         return this;
8636                 }
8637
8638                 public override void Emit (EmitContext ec)
8639                 {
8640                         ILGenerator ig = ec.ig;
8641
8642                         source.Emit (ec);
8643                         
8644                         if (method is MethodInfo)
8645                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
8646                         else
8647                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
8648
8649                 }
8650         }
8651
8652         // <summary>
8653         //   This class is used to "construct" the type during a typecast
8654         //   operation.  Since the Type.GetType class in .NET can parse
8655         //   the type specification, we just use this to construct the type
8656         //   one bit at a time.
8657         // </summary>
8658         public class ComposedCast : TypeExpr {
8659                 Expression left;
8660                 string dim;
8661                 
8662                 public ComposedCast (Expression left, string dim, Location l)
8663                 {
8664                         this.left = left;
8665                         this.dim = dim;
8666                         loc = l;
8667                 }
8668
8669                 public override TypeExpr DoResolveAsTypeStep (EmitContext ec)
8670                 {
8671                         Type ltype = ec.DeclSpace.ResolveType (left, false, loc);
8672                         if (ltype == null)
8673                                 return null;
8674
8675                         if ((ltype == TypeManager.void_type) && (dim != "*")) {
8676                                 Report.Error (1547, Location,
8677                                               "Keyword 'void' cannot be used in this context");
8678                                 return null;
8679                         }
8680
8681                         int pos = 0;
8682                         while ((pos < dim.Length) && (dim [pos] == '[')) {
8683                                 pos++;
8684
8685                                 if (dim [pos] == ']') {
8686                                         ltype = ltype.MakeArrayType ();
8687                                         pos++;
8688
8689                                         if (pos < dim.Length)
8690                                                 continue;
8691
8692                                         type = ltype;
8693                                         eclass = ExprClass.Type;
8694                                         return this;
8695                                 }
8696
8697                                 int rank = 0;
8698                                 while (dim [pos] == ',') {
8699                                         pos++; rank++;
8700                                 }
8701
8702                                 if ((dim [pos] != ']') || (pos != dim.Length-1))
8703                                         return null;
8704                                                 
8705                                 type = ltype.MakeArrayType (rank + 1);
8706                                 eclass = ExprClass.Type;
8707                                 return this;
8708                         }
8709
8710                         //
8711                         // ltype.Fullname is already fully qualified, so we can skip
8712                         // a lot of probes, and go directly to TypeManager.LookupType
8713                         //
8714                         string fname = ltype.FullName != null ? ltype.FullName : ltype.Name;
8715                         string cname = fname + dim;
8716                         type = TypeManager.LookupTypeDirect (cname);
8717                         if (type == null){
8718                                 //
8719                                 // For arrays of enumerations we are having a problem
8720                                 // with the direct lookup.  Need to investigate.
8721                                 //
8722                                 // For now, fall back to the full lookup in that case.
8723                                 //
8724                                 TypeExpr texpr = RootContext.LookupType (
8725                                         ec.DeclSpace, cname, false, loc);
8726
8727                                 if (texpr == null)
8728                                         return null;
8729
8730                                 type = texpr.ResolveType (ec);
8731                                 if (type == null)
8732                                         return null;
8733                         }
8734
8735                         if (!ec.ResolvingTypeTree){
8736                                 //
8737                                 // If the above flag is set, this is being invoked from the ResolveType function.
8738                                 // Upper layers take care of the type validity in this context.
8739                                 //
8740                         if (!ec.InUnsafe && type.IsPointer){
8741                                 UnsafeError (loc);
8742                                 return null;
8743                         }
8744                         }
8745                         
8746                         eclass = ExprClass.Type;
8747                         return this;
8748                 }
8749
8750                 public override string Name {
8751                         get {
8752                                 return left + dim;
8753                         }
8754                 }
8755         }
8756
8757         //
8758         // This class is used to represent the address of an array, used
8759         // only by the Fixed statement, this is like the C "&a [0]" construct.
8760         //
8761         public class ArrayPtr : Expression {
8762                 Expression array;
8763                 
8764                 public ArrayPtr (Expression array, Location l)
8765                 {
8766                         Type array_type = TypeManager.GetElementType (array.Type);
8767
8768                         this.array = array;
8769
8770                         type = TypeManager.GetPointerType (array_type);
8771                         eclass = ExprClass.Value;
8772                         loc = l;
8773                 }
8774
8775                 public override void Emit (EmitContext ec)
8776                 {
8777                         ILGenerator ig = ec.ig;
8778                         
8779                         array.Emit (ec);
8780                         IntLiteral.EmitInt (ig, 0);
8781                         ig.Emit (OpCodes.Ldelema, TypeManager.GetElementType (array.Type));
8782                 }
8783
8784                 public override Expression DoResolve (EmitContext ec)
8785                 {
8786                         //
8787                         // We are born fully resolved
8788                         //
8789                         return this;
8790                 }
8791         }
8792
8793         //
8794         // Used by the fixed statement
8795         //
8796         public class StringPtr : Expression {
8797                 LocalBuilder b;
8798                 
8799                 public StringPtr (LocalBuilder b, Location l)
8800                 {
8801                         this.b = b;
8802                         eclass = ExprClass.Value;
8803                         type = TypeManager.char_ptr_type;
8804                         loc = l;
8805                 }
8806
8807                 public override Expression DoResolve (EmitContext ec)
8808                 {
8809                         // This should never be invoked, we are born in fully
8810                         // initialized state.
8811
8812                         return this;
8813                 }
8814
8815                 public override void Emit (EmitContext ec)
8816                 {
8817                         ILGenerator ig = ec.ig;
8818
8819                         ig.Emit (OpCodes.Ldloc, b);
8820                         ig.Emit (OpCodes.Conv_I);
8821                         ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
8822                         ig.Emit (OpCodes.Add);
8823                 }
8824         }
8825         
8826         //
8827         // Implements the `stackalloc' keyword
8828         //
8829         public class StackAlloc : Expression {
8830                 Type otype;
8831                 Expression t;
8832                 Expression count;
8833                 
8834                 public StackAlloc (Expression type, Expression count, Location l)
8835                 {
8836                         t = type;
8837                         this.count = count;
8838                         loc = l;
8839                 }
8840
8841                 public override Expression DoResolve (EmitContext ec)
8842                 {
8843                         count = count.Resolve (ec);
8844                         if (count == null)
8845                                 return null;
8846                         
8847                         if (count.Type != TypeManager.int32_type){
8848                                 count = Convert.ImplicitConversionRequired (ec, count, TypeManager.int32_type, loc);
8849                                 if (count == null)
8850                                         return null;
8851                         }
8852
8853                         if (ec.CurrentBranching.InCatch () ||
8854                             ec.CurrentBranching.InFinally (true)) {
8855                                 Error (255,
8856                                               "stackalloc can not be used in a catch or finally block");
8857                                 return null;
8858                         }
8859
8860                         otype = ec.DeclSpace.ResolveType (t, false, loc);
8861
8862                         if (otype == null)
8863                                 return null;
8864
8865                         if (!TypeManager.VerifyUnManaged (otype, loc))
8866                                 return null;
8867
8868                         type = TypeManager.GetPointerType (otype);
8869                         eclass = ExprClass.Value;
8870
8871                         return this;
8872                 }
8873
8874                 public override void Emit (EmitContext ec)
8875                 {
8876                         int size = GetTypeSize (otype);
8877                         ILGenerator ig = ec.ig;
8878                                 
8879                         if (size == 0)
8880                                 ig.Emit (OpCodes.Sizeof, otype);
8881                         else
8882                                 IntConstant.EmitInt (ig, size);
8883                         count.Emit (ec);
8884                         ig.Emit (OpCodes.Mul);
8885                         ig.Emit (OpCodes.Localloc);
8886                 }
8887         }
8888 }