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