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