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