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