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