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