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