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