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