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