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