2001-11-08 Ravi Pratap <ravi@ximian.com>
[mono.git] / mcs / mcs / 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
11 namespace CIR {
12         using System;
13         using System.Collections;
14         using System.Diagnostics;
15         using System.Reflection;
16         using System.Reflection.Emit;
17         using System.Text;
18
19         // <summary>
20         //   Unary expressions.  
21         // </summary>
22         //
23         // <remarks>
24         //   Unary implements unary expressions.   It derives from
25         //   ExpressionStatement becuase the pre/post increment/decrement
26         //   operators can be used in a statement context.
27         // </remarks>
28         public class Unary : ExpressionStatement {
29                 public enum Operator {
30                         UnaryPlus, UnaryNegation, LogicalNot, OnesComplement,
31                         Indirection, AddressOf, PreIncrement,
32                         PreDecrement, PostIncrement, PostDecrement 
33                 }
34
35                 Operator   oper;
36                 Expression expr;
37                 ArrayList  Arguments;
38                 MethodBase method;
39                 Location   loc;
40                 
41                 public Unary (Operator op, Expression expr, Location loc)
42                 {
43                         this.oper = op;
44                         this.expr = expr;
45                         this.loc = loc;
46                 }
47
48                 public Expression Expr {
49                         get {
50                                 return expr;
51                         }
52
53                         set {
54                                 expr = value;
55                         }
56                 }
57
58                 public Operator Oper {
59                         get {
60                                 return oper;
61                         }
62
63                         set {
64                                 oper = value;
65                         }
66                 }
67
68                 // <summary>
69                 //   Returns a stringified representation of the Operator
70                 // </summary>
71                 string OperName ()
72                 {
73                         switch (oper){
74                         case Operator.UnaryPlus:
75                                 return "+";
76                         case Operator.UnaryNegation:
77                                 return "-";
78                         case Operator.LogicalNot:
79                                 return "!";
80                         case Operator.OnesComplement:
81                                 return "~";
82                         case Operator.AddressOf:
83                                 return "&";
84                         case Operator.Indirection:
85                                 return "*";
86                         case Operator.PreIncrement : case Operator.PostIncrement :
87                                 return "++";
88                         case Operator.PreDecrement : case Operator.PostDecrement :
89                                 return "--";
90                         }
91
92                         return oper.ToString ();
93                 }
94
95                 Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
96                 {
97                         if (expr.Type == target_type)
98                                 return expr;
99
100                         return ConvertImplicit (ec, expr, target_type, new Location (-1));
101                 }
102
103                 void error23 (Type t)
104                 {
105                         Report.Error (
106                                 23, loc, "Operator " + OperName () +
107                                 " cannot be applied to operand of type `" +
108                                 TypeManager.CSharpName (t) + "'");
109                 }
110
111                 // <summary>
112                 //   Returns whether an object of type `t' can be incremented
113                 //   or decremented with add/sub (ie, basically whether we can
114                 //   use pre-post incr-decr operations on it, but it is not a
115                 //   System.Decimal, which we test elsewhere)
116                 // </summary>
117                 static bool IsIncrementableNumber (Type t)
118                 {
119                         return (t == TypeManager.sbyte_type) ||
120                                 (t == TypeManager.byte_type) ||
121                                 (t == TypeManager.short_type) ||
122                                 (t == TypeManager.ushort_type) ||
123                                 (t == TypeManager.int32_type) ||
124                                 (t == TypeManager.uint32_type) ||
125                                 (t == TypeManager.int64_type) ||
126                                 (t == TypeManager.uint64_type) ||
127                                 (t == TypeManager.char_type) ||
128                                 (t.IsSubclassOf (TypeManager.enum_type)) ||
129                                 (t == TypeManager.float_type) ||
130                                 (t == TypeManager.double_type);
131                 }
132
133                 static Expression TryReduceNegative (Expression expr)
134                 {
135                         Expression e = null;
136                         
137                         if (expr is IntLiteral)
138                                 e = new IntLiteral (-((IntLiteral) expr).Value);
139                         else if (expr is UIntLiteral)
140                                 e = new LongLiteral (-((UIntLiteral) expr).Value);
141                         else if (expr is LongLiteral)
142                                 e = new LongLiteral (-((LongLiteral) expr).Value);
143                         else if (expr is FloatLiteral)
144                                 e = new FloatLiteral (-((FloatLiteral) expr).Value);
145                         else if (expr is DoubleLiteral)
146                                 e = new DoubleLiteral (-((DoubleLiteral) expr).Value);
147                         else if (expr is DecimalLiteral)
148                                 e = new DecimalLiteral (-((DecimalLiteral) expr).Value);
149
150                         return e;
151                 }
152                 
153                 Expression ResolveOperator (EmitContext ec)
154                 {
155                         Type expr_type = expr.Type;
156
157                         //
158                         // Step 1: Perform Operator Overload location
159                         //
160                         Expression mg;
161                         string op_name;
162                         
163                         if (oper == Operator.PostIncrement || oper == Operator.PreIncrement)
164                                 op_name = "op_Increment";
165                         else if (oper == Operator.PostDecrement || oper == Operator.PreDecrement)
166                                 op_name = "op_Decrement";
167                         else
168                                 op_name = "op_" + oper;
169
170                         mg = MemberLookup (ec, expr_type, op_name, false, loc);
171                         
172                         if (mg == null && expr_type.BaseType != null)
173                                 mg = MemberLookup (ec, expr_type.BaseType, op_name, false, loc);
174                         
175                         if (mg != null) {
176                                 Arguments = new ArrayList ();
177                                 Arguments.Add (new Argument (expr, Argument.AType.Expression));
178                                 
179                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) mg,
180                                                                      Arguments, loc);
181                                 if (method != null) {
182                                         MethodInfo mi = (MethodInfo) method;
183                                         type = mi.ReturnType;
184                                         return this;
185                                 } else {
186                                         error23 (expr_type);
187                                         return null;
188                                 }
189                                         
190                         }
191
192                         //
193                         // Step 2: Default operations on CLI native types.
194                         //
195
196                         // Only perform numeric promotions on:
197                         // +, -, ++, --
198
199                         if (expr_type == null)
200                                 return null;
201                         
202                         if (oper == Operator.LogicalNot){
203                                 if (expr_type != TypeManager.bool_type) {
204                                         error23 (expr.Type);
205                                         return null;
206                                 }
207                                 
208                                 type = TypeManager.bool_type;
209                                 return this;
210                         }
211
212                         if (oper == Operator.OnesComplement) {
213                                 if (!((expr_type == TypeManager.int32_type) ||
214                                       (expr_type == TypeManager.uint32_type) ||
215                                       (expr_type == TypeManager.int64_type) ||
216                                       (expr_type == TypeManager.uint64_type) ||
217                                       (expr_type.IsSubclassOf (TypeManager.enum_type)))){
218                                         error23 (expr.Type);
219                                         return null;
220                                 }
221                                 type = expr_type;
222                                 return this;
223                         }
224
225                         if (oper == Operator.UnaryPlus) {
226                                 //
227                                 // A plus in front of something is just a no-op, so return the child.
228                                 //
229                                 return expr;
230                         }
231
232                         //
233                         // Deals with -literals
234                         // int     operator- (int x)
235                         // long    operator- (long x)
236                         // float   operator- (float f)
237                         // double  operator- (double d)
238                         // decimal operator- (decimal d)
239                         //
240                         if (oper == Operator.UnaryNegation){
241                                 //
242                                 // Fold a "- Constant" into a negative constant
243                                 //
244                         
245                                 Expression e = null;
246
247                                 //
248                                 // Is this a constant? 
249                                 //
250                                 e = TryReduceNegative (expr);
251                                 
252                                 if (e != null){
253                                         e = e.Resolve (ec);
254                                         return e;
255                                 }
256
257                                 //
258                                 // Not a constant we can optimize, perform numeric 
259                                 // promotions to int, long, double.
260                                 //
261                                 //
262                                 // The following is inneficient, because we call
263                                 // ConvertImplicit too many times.
264                                 //
265                                 // It is also not clear if we should convert to Float
266                                 // or Double initially.
267                                 //
268                                 if (expr_type == TypeManager.uint32_type){
269                                         //
270                                         // FIXME: handle exception to this rule that
271                                         // permits the int value -2147483648 (-2^31) to
272                                         // bt written as a decimal interger literal
273                                         //
274                                         type = TypeManager.int64_type;
275                                         expr = ConvertImplicit (ec, expr, type, loc);
276                                         return this;
277                                 }
278
279                                 if (expr_type == TypeManager.uint64_type){
280                                         //
281                                         // FIXME: Handle exception of `long value'
282                                         // -92233720368547758087 (-2^63) to be written as
283                                         // decimal integer literal.
284                                         //
285                                         error23 (expr_type);
286                                         return null;
287                                 }
288
289                                 e = ConvertImplicit (ec, expr, TypeManager.int32_type, loc);
290                                 if (e != null){
291                                         expr = e;
292                                         type = e.Type;
293                                         return this;
294                                 } 
295
296                                 e = ConvertImplicit (ec, expr, TypeManager.int64_type, loc);
297                                 if (e != null){
298                                         expr = e;
299                                         type = e.Type;
300                                         return this;
301                                 }
302
303                                 e = ConvertImplicit (ec, expr, TypeManager.double_type, loc);
304                                 if (e != null){
305                                         expr = e;
306                                         type = e.Type;
307                                         return this;
308                                 }
309
310                                 error23 (expr_type);
311                                 return null;
312                         }
313
314                         //
315                         // The operand of the prefix/postfix increment decrement operators
316                         // should be an expression that is classified as a variable,
317                         // a property access or an indexer access
318                         //
319                         if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
320                             oper == Operator.PostDecrement || oper == Operator.PostIncrement){
321                                 if (expr.ExprClass == ExprClass.Variable){
322                                         if (IsIncrementableNumber (expr_type) ||
323                                             expr_type == TypeManager.decimal_type){
324                                                 type = expr_type;
325                                                 return this;
326                                         }
327                                 } else if (expr.ExprClass == ExprClass.IndexerAccess){
328                                         //
329                                         // FIXME: Verify that we have both get and set methods
330                                         //
331                                         throw new Exception ("Implement me");
332                                 } else if (expr.ExprClass == ExprClass.PropertyAccess){
333                                         PropertyExpr pe = (PropertyExpr) expr;
334                                         
335                                         if (pe.VerifyAssignable ())
336                                                 return this;
337                                         return null;
338                                 } else {
339                                         report118 (loc, expr, "variable, indexer or property access");
340                                 }
341                         }
342
343                         if (oper == Operator.AddressOf){
344                                 if (expr.ExprClass != ExprClass.Variable){
345                                         Error (211, "Cannot take the address of non-variables");
346                                         return null;
347                                 }
348                                 type = Type.GetType (expr.Type.ToString () + "*");
349                         }
350                         
351                         Error (187, "No such operator '" + OperName () + "' defined for type '" +
352                                TypeManager.CSharpName (expr_type) + "'");
353                         return null;
354
355                 }
356
357                 public override Expression DoResolve (EmitContext ec)
358                 {
359                         expr = expr.Resolve (ec);
360                         
361                         if (expr == null)
362                                 return null;
363
364                         eclass = ExprClass.Value;
365                         return ResolveOperator (ec);
366                 }
367
368                 public override void Emit (EmitContext ec)
369                 {
370                         ILGenerator ig = ec.ig;
371                         Type expr_type = expr.Type;
372                         
373                         if (method != null) {
374
375                                 // Note that operators are static anyway
376                                 
377                                 if (Arguments != null) 
378                                         Invocation.EmitArguments (ec, Arguments);
379
380                                 //
381                                 // Post increment/decrement operations need a copy at this
382                                 // point.
383                                 //
384                                 if (oper == Operator.PostDecrement || oper == Operator.PostIncrement)
385                                         ig.Emit (OpCodes.Dup);
386                                 
387
388                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
389
390                                 //
391                                 // Pre Increment and Decrement operators
392                                 //
393                                 if (oper == Operator.PreIncrement || oper == Operator.PreDecrement){
394                                         ig.Emit (OpCodes.Dup);
395                                 }
396                                 
397                                 //
398                                 // Increment and Decrement should store the result
399                                 //
400                                 if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
401                                     oper == Operator.PostDecrement || oper == Operator.PostIncrement){
402                                         ((IStackStore) expr).Store (ec);
403                                 }
404                                 return;
405                         }
406                         
407                         switch (oper) {
408                         case Operator.UnaryPlus:
409                                 throw new Exception ("This should be caught by Resolve");
410                                 
411                         case Operator.UnaryNegation:
412                                 expr.Emit (ec);
413                                 ig.Emit (OpCodes.Neg);
414                                 break;
415                                 
416                         case Operator.LogicalNot:
417                                 expr.Emit (ec);
418                                 ig.Emit (OpCodes.Ldc_I4_0);
419                                 ig.Emit (OpCodes.Ceq);
420                                 break;
421                                 
422                         case Operator.OnesComplement:
423                                 expr.Emit (ec);
424                                 ig.Emit (OpCodes.Not);
425                                 break;
426                                 
427                         case Operator.AddressOf:
428                                 ((IMemoryLocation)expr).AddressOf (ec);
429                                 break;
430                                 
431                         case Operator.Indirection:
432                                 throw new Exception ("Not implemented yet");
433                                 
434                         case Operator.PreIncrement:
435                         case Operator.PreDecrement:
436                                 if (expr.ExprClass == ExprClass.Variable){
437                                         //
438                                         // Resolve already verified that it is an "incrementable"
439                                         // 
440                                         expr.Emit (ec);
441                                         ig.Emit (OpCodes.Ldc_I4_1);
442                                         
443                                         if (oper == Operator.PreDecrement)
444                                                 ig.Emit (OpCodes.Sub);
445                                         else
446                                                 ig.Emit (OpCodes.Add);
447                                         ig.Emit (OpCodes.Dup);
448                                         ((IStackStore) expr).Store (ec);
449                                 } else {
450                                         throw new Exception ("Handle Indexers and Properties here");
451                                 }
452                                 break;
453                                 
454                         case Operator.PostIncrement:
455                         case Operator.PostDecrement:
456                                 if (expr is IStackStore){
457                                         //
458                                         // Resolve already verified that it is an "incrementable"
459                                         // 
460                                         expr.Emit (ec);
461                                         ig.Emit (OpCodes.Dup);
462                                         ig.Emit (OpCodes.Ldc_I4_1);
463                                         
464                                         if (oper == Operator.PostDecrement)
465                                                 ig.Emit (OpCodes.Sub);
466                                         else
467                                                 ig.Emit (OpCodes.Add);
468                                         ((IStackStore) expr).Store (ec);
469                                 } else {
470                                         Console.WriteLine ("Unknown exprclass: " + expr);
471                                 }
472                                 break;
473                                 
474                         default:
475                                 throw new Exception ("This should not happen: Operator = "
476                                                      + oper.ToString ());
477                         }
478                 }
479
480                 // <summary>
481                 //   This will emit the child expression for `ec' avoiding the logical
482                 //   not.  The parent will take care of changing brfalse/brtrue
483                 // </summary>
484                 public void EmitLogicalNot (EmitContext ec)
485                 {
486                         if (oper != Operator.LogicalNot)
487                                 throw new Exception ("EmitLogicalNot can only be called with !expr");
488
489                         expr.Emit (ec);
490                 }
491                 
492                 public override void EmitStatement (EmitContext ec)
493                 {
494                         //
495                         // FIXME: we should rewrite this code to generate
496                         // better code for ++ and -- as we know we wont need
497                         // the values on the stack
498                         //
499                         Emit (ec);
500                         ec.ig.Emit (OpCodes.Pop);
501                 }
502
503                 public override Expression Reduce (EmitContext ec)
504                 {
505                         Expression e;
506                         
507                         //
508                         // We can not reduce expressions that invoke operator overloaded functions.
509                         //
510                         if (method != null)
511                                 return this;
512
513                         //
514                         // First, reduce our child.  Note that although we handle 
515                         //
516                         expr = expr.Reduce (ec);
517                         if (!(expr is Literal))
518                                 return expr;
519                         
520                         switch (oper){
521                         case Operator.UnaryPlus:
522                                 return expr;
523                                 
524                         case Operator.UnaryNegation:
525                                 e = TryReduceNegative (expr);
526                                 if (e == null)
527                                         break;
528                                 return e;
529                                 
530                         case Operator.LogicalNot:
531                                 BoolLiteral b = (BoolLiteral) expr;
532
533                                 return new BoolLiteral (!(b.Value));
534                                 
535                         case Operator.OnesComplement:
536                                 Type et = expr.Type;
537                                 
538                                 if (et == TypeManager.int32_type)
539                                         return new IntLiteral (~ ((IntLiteral) expr).Value);
540                                 if (et == TypeManager.uint32_type)
541                                         return new UIntLiteral (~ ((UIntLiteral) expr).Value);
542                                 if (et == TypeManager.int64_type)
543                                         return new LongLiteral (~ ((LongLiteral) expr).Value);
544                                 if (et == TypeManager.uint64_type)
545                                         return new ULongLiteral (~ ((ULongLiteral) expr).Value);
546                                 break;
547                         }
548                         return this;
549                 }
550         }
551         
552         public class Probe : Expression {
553                 public readonly string ProbeType;
554                 public readonly Operator Oper;
555                 Expression expr;
556                 Type probe_type;
557                 
558                 public enum Operator {
559                         Is, As
560                 }
561                 
562                 public Probe (Operator oper, Expression expr, string probe_type)
563                 {
564                         Oper = oper;
565                         ProbeType = probe_type;
566                         this.expr = expr;
567                 }
568
569                 public Expression Expr {
570                         get {
571                                 return expr;
572                         }
573                 }
574                 
575                 public override Expression DoResolve (EmitContext ec)
576                 {
577                         probe_type = ec.TypeContainer.LookupType (ProbeType, false);
578
579                         if (probe_type == null)
580                                 return null;
581
582                         expr = expr.Resolve (ec);
583                         
584                         type = TypeManager.bool_type;
585                         eclass = ExprClass.Value;
586
587                         return this;
588                 }
589
590                 public override void Emit (EmitContext ec)
591                 {
592                         ILGenerator ig = ec.ig;
593                         
594                         expr.Emit (ec);
595                         
596                         if (Oper == Operator.Is){
597                                 ig.Emit (OpCodes.Isinst, probe_type);
598                                 ig.Emit (OpCodes.Ldnull);
599                                 ig.Emit (OpCodes.Cgt_Un);
600                         } else {
601                                 ig.Emit (OpCodes.Isinst, probe_type);
602                         }
603                 }
604         }
605
606         // <summary>
607         //   This represents a typecast in the source language.
608         //
609         //   FIXME: Cast expressions have an unusual set of parsing
610         //   rules, we need to figure those out.
611         // </summary>
612         public class Cast : Expression {
613                 string target_type;
614                 Expression expr;
615                 Location   loc;
616                         
617                 public Cast (string cast_type, Expression expr, Location loc)
618                 {
619                         this.target_type = cast_type;
620                         this.expr = expr;
621                         this.loc = loc;
622                 }
623
624                 public string TargetType {
625                         get {
626                                 return target_type;
627                         }
628                 }
629
630                 public Expression Expr {
631                         get {
632                                 return expr;
633                         }
634                         set {
635                                 expr = value;
636                         }
637                 }
638                 
639                 public override Expression DoResolve (EmitContext ec)
640                 {
641                         expr = expr.Resolve (ec);
642                         if (expr == null)
643                                 return null;
644                         
645                         type = ec.TypeContainer.LookupType (target_type, false);
646                         eclass = ExprClass.Value;
647                         
648                         if (type == null)
649                                 return null;
650
651                         expr = ConvertExplicit (ec, expr, type, loc);
652
653                         return expr;
654                 }
655
656                 public override void Emit (EmitContext ec)
657                 {
658                         //
659                         // This one will never happen
660                         //
661                         throw new Exception ("Should not happen");
662                 }
663         }
664
665         public class Binary : Expression {
666                 public enum Operator {
667                         Multiply, Division, Modulus,
668                         Addition, Subtraction,
669                         LeftShift, RightShift,
670                         LessThan, GreaterThan, LessThanOrEqual, GreaterThanOrEqual, 
671                         Equality, Inequality,
672                         BitwiseAnd,
673                         ExclusiveOr,
674                         BitwiseOr,
675                         LogicalAnd,
676                         LogicalOr
677                 }
678
679                 Operator oper;
680                 Expression left, right;
681                 MethodBase method;
682                 ArrayList  Arguments;
683                 Location   loc;
684                 
685
686                 public Binary (Operator oper, Expression left, Expression right, Location loc)
687                 {
688                         this.oper = oper;
689                         this.left = left;
690                         this.right = right;
691                         this.loc = loc;
692                 }
693
694                 public Operator Oper {
695                         get {
696                                 return oper;
697                         }
698                         set {
699                                 oper = value;
700                         }
701                 }
702                 
703                 public Expression Left {
704                         get {
705                                 return left;
706                         }
707                         set {
708                                 left = value;
709                         }
710                 }
711
712                 public Expression Right {
713                         get {
714                                 return right;
715                         }
716                         set {
717                                 right = value;
718                         }
719                 }
720
721
722                 // <summary>
723                 //   Returns a stringified representation of the Operator
724                 // </summary>
725                 string OperName ()
726                 {
727                         switch (oper){
728                         case Operator.Multiply:
729                                 return "*";
730                         case Operator.Division:
731                                 return "/";
732                         case Operator.Modulus:
733                                 return "%";
734                         case Operator.Addition:
735                                 return "+";
736                         case Operator.Subtraction:
737                                 return "-";
738                         case Operator.LeftShift:
739                                 return "<<";
740                         case Operator.RightShift:
741                                 return ">>";
742                         case Operator.LessThan:
743                                 return "<";
744                         case Operator.GreaterThan:
745                                 return ">";
746                         case Operator.LessThanOrEqual:
747                                 return "<=";
748                         case Operator.GreaterThanOrEqual:
749                                 return ">=";
750                         case Operator.Equality:
751                                 return "==";
752                         case Operator.Inequality:
753                                 return "!=";
754                         case Operator.BitwiseAnd:
755                                 return "&";
756                         case Operator.BitwiseOr:
757                                 return "|";
758                         case Operator.ExclusiveOr:
759                                 return "^";
760                         case Operator.LogicalOr:
761                                 return "||";
762                         case Operator.LogicalAnd:
763                                 return "&&";
764                         }
765
766                         return oper.ToString ();
767                 }
768
769                 Expression ForceConversion (EmitContext ec, Expression expr, Type target_type)
770                 {
771                         if (expr.Type == target_type)
772                                 return expr;
773
774                         return ConvertImplicit (ec, expr, target_type, new Location (-1));
775                 }
776                 
777                 //
778                 // Note that handling the case l == Decimal || r == Decimal
779                 // is taken care of by the Step 1 Operator Overload resolution.
780                 //
781                 bool DoNumericPromotions (EmitContext ec, Type l, Type r)
782                 {
783                         if (l == TypeManager.double_type || r == TypeManager.double_type){
784                                 //
785                                 // If either operand is of type double, the other operand is
786                                 // conveted to type double.
787                                 //
788                                 if (r != TypeManager.double_type)
789                                         right = ConvertImplicit (ec, right, TypeManager.double_type, loc);
790                                 if (l != TypeManager.double_type)
791                                         left = ConvertImplicit (ec, left, TypeManager.double_type, loc);
792                                 
793                                 type = TypeManager.double_type;
794                         } else if (l == TypeManager.float_type || r == TypeManager.float_type){
795                                 //
796                                 // if either operand is of type float, th eother operand is
797                                 // converd to type float.
798                                 //
799                                 if (r != TypeManager.double_type)
800                                         right = ConvertImplicit (ec, right, TypeManager.float_type, loc);
801                                 if (l != TypeManager.double_type)
802                                         left = ConvertImplicit (ec, left, TypeManager.float_type, loc);
803                                 type = TypeManager.float_type;
804                         } else if (l == TypeManager.uint64_type || r == TypeManager.uint64_type){
805                                 Expression e;
806                                 Type other;
807                                 //
808                                 // If either operand is of type ulong, the other operand is
809                                 // converted to type ulong.  or an error ocurrs if the other
810                                 // operand is of type sbyte, short, int or long
811                                 //
812                                 
813                                 if (l == TypeManager.uint64_type){
814                                         if (r != TypeManager.uint64_type && right is IntLiteral){
815                                                 e = TryImplicitIntConversion (l, (IntLiteral) right);
816                                                 if (e != null)
817                                                         right = e;
818                                         }
819                                         other = right.Type;
820                                 } else {
821                                         if (left is IntLiteral){
822                                                 e = TryImplicitIntConversion (r, (IntLiteral) left);
823                                                 if (e != null)
824                                                         left = e;
825                                         }
826                                         other = left.Type;
827                                 }
828
829                                 if ((other == TypeManager.sbyte_type) ||
830                                     (other == TypeManager.short_type) ||
831                                     (other == TypeManager.int32_type) ||
832                                     (other == TypeManager.int64_type)){
833                                         string oper = OperName ();
834                                         
835                                         Error (34, loc, "Operator `" + OperName ()
836                                                + "' is ambiguous on operands of type `"
837                                                + TypeManager.CSharpName (l) + "' "
838                                                + "and `" + TypeManager.CSharpName (r)
839                                                + "'");
840                                 }
841                                 type = TypeManager.uint64_type;
842                         } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
843                                 //
844                                 // If either operand is of type long, the other operand is converted
845                                 // to type long.
846                                 //
847                                 if (l != TypeManager.int64_type)
848                                         left = ConvertImplicit (ec, left, TypeManager.int64_type, loc);
849                                 if (r != TypeManager.int64_type)
850                                         right = ConvertImplicit (ec, right, TypeManager.int64_type, loc);
851
852                                 type = TypeManager.int64_type;
853                         } else if (l == TypeManager.uint32_type || r == TypeManager.uint32_type){
854                                 //
855                                 // If either operand is of type uint, and the other
856                                 // operand is of type sbyte, short or int, othe operands are
857                                 // converted to type long.
858                                 //
859                                 Type other = null;
860                                 
861                                 if (l == TypeManager.uint32_type)
862                                         other = r;
863                                 else if (r == TypeManager.uint32_type)
864                                         other = l;
865
866                                 if ((other == TypeManager.sbyte_type) ||
867                                     (other == TypeManager.short_type) ||
868                                     (other == TypeManager.int32_type)){
869                                         left = ForceConversion (ec, left, TypeManager.int64_type);
870                                         right = ForceConversion (ec, right, TypeManager.int64_type);
871                                         type = TypeManager.int64_type;
872                                 } else {
873                                         //
874                                         // if either operand is of type uint, the other
875                                         // operand is converd to type uint
876                                         //
877                                         left = ForceConversion (ec, left, TypeManager.uint32_type);
878                                         right = ForceConversion (ec, right, TypeManager.uint32_type);
879                                         type = TypeManager.uint32_type;
880                                 } 
881                         } else if (l == TypeManager.decimal_type || r == TypeManager.decimal_type){
882                                 if (l != TypeManager.decimal_type)
883                                         left = ConvertImplicit (ec, left, TypeManager.decimal_type, loc);
884                                 if (r != TypeManager.decimal_type)
885                                         right = ConvertImplicit (ec, right, TypeManager.decimal_type, loc);
886
887                                 type = TypeManager.decimal_type;
888                         } else {
889                                 Expression l_tmp, r_tmp;
890
891                                 l_tmp = ForceConversion (ec, left, TypeManager.int32_type);
892                                 if (l_tmp == null)
893                                         return false;
894                                 
895                                 r_tmp = ForceConversion (ec, right, TypeManager.int32_type);
896                                 if (r_tmp == null)
897                                         return false;
898
899                                 left = l_tmp;
900                                 right = r_tmp;
901                                 
902                                 type = TypeManager.int32_type;
903                         }
904
905                         return true;
906                 }
907
908                 void error19 ()
909                 {
910                         Error (19, loc,
911                                "Operator " + OperName () + " cannot be applied to operands of type `" +
912                                TypeManager.CSharpName (left.Type) + "' and `" +
913                                TypeManager.CSharpName (right.Type) + "'");
914                                                      
915                 }
916                 
917                 Expression CheckShiftArguments (EmitContext ec)
918                 {
919                         Expression e;
920                         Type l = left.Type;
921                         Type r = right.Type;
922
923                         e = ForceConversion (ec, right, TypeManager.int32_type);
924                         if (e == null){
925                                 error19 ();
926                                 return null;
927                         }
928                         right = e;
929
930                         if (((e = ConvertImplicit (ec, left, TypeManager.int32_type, loc)) != null) ||
931                             ((e = ConvertImplicit (ec, left, TypeManager.uint32_type, loc)) != null) ||
932                             ((e = ConvertImplicit (ec, left, TypeManager.int64_type, loc)) != null) ||
933                             ((e = ConvertImplicit (ec, left, TypeManager.uint64_type, loc)) != null)){
934                                 left = e;
935                                 type = e.Type;
936
937                                 return this;
938                         }
939                         error19 ();
940                         return null;
941                 }
942                 
943                 Expression ResolveOperator (EmitContext ec)
944                 {
945                         Type l = left.Type;
946                         Type r = right.Type;
947
948                         //
949                         // Step 1: Perform Operator Overload location
950                         //
951                         Expression left_expr, right_expr;
952                         
953                         string op = "op_" + oper;
954
955                         left_expr = MemberLookup (ec, l, op, false, loc);
956                         if (left_expr == null && l.BaseType != null)
957                                 left_expr = MemberLookup (ec, l.BaseType, op, false, loc);
958                         
959                         right_expr = MemberLookup (ec, r, op, false, loc);
960                         if (right_expr == null && r.BaseType != null)
961                                 right_expr = MemberLookup (ec, r.BaseType, op, false, loc);
962                         
963                         MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
964                         
965                         if (union != null) {
966                                 Arguments = new ArrayList ();
967                                 Arguments.Add (new Argument (left, Argument.AType.Expression));
968                                 Arguments.Add (new Argument (right, Argument.AType.Expression));
969                                 
970                                 method = Invocation.OverloadResolve (ec, union, Arguments, loc);
971                                 if (method != null) {
972                                         MethodInfo mi = (MethodInfo) method;
973                                         type = mi.ReturnType;
974                                         return this;
975                                 } else {
976                                         error19 ();
977                                         return null;
978                                 }
979                         }       
980
981                         //
982                         // Step 2: Default operations on CLI native types.
983                         //
984                         
985                         // Only perform numeric promotions on:
986                         // +, -, *, /, %, &, |, ^, ==, !=, <, >, <=, >=
987                         //
988                         if (oper == Operator.Addition){
989                                 //
990                                 // If any of the arguments is a string, cast to string
991                                 //
992                                 if (l == TypeManager.string_type){
993                                         if (r == TypeManager.string_type){
994                                                 if (left is Literal && right is Literal){
995                                                         StringLiteral ls = (StringLiteral) left;
996                                                         StringLiteral rs = (StringLiteral) right;
997                                                         
998                                                         return new StringLiteral (ls.Value + rs.Value);
999                                                 }
1000                                                 
1001                                                 // string + string
1002                                                 method = TypeManager.string_concat_string_string;
1003                                         } else {
1004                                                 // string + object
1005                                                 method = TypeManager.string_concat_object_object;
1006                                                 right = ConvertImplicit (ec, right,
1007                                                                          TypeManager.object_type, loc);
1008                                         }
1009                                         type = TypeManager.string_type;
1010
1011                                         Arguments = new ArrayList ();
1012                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
1013                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
1014
1015                                         return this;
1016                                         
1017                                 } else if (r == TypeManager.string_type){
1018                                         // object + string
1019                                         method = TypeManager.string_concat_object_object;
1020                                         Arguments = new ArrayList ();
1021                                         Arguments.Add (new Argument (left, Argument.AType.Expression));
1022                                         Arguments.Add (new Argument (right, Argument.AType.Expression));
1023
1024                                         left = ConvertImplicit (ec, left, TypeManager.object_type, loc);
1025                                         type = TypeManager.string_type;
1026
1027                                         return this;
1028                                 }
1029
1030                                 //
1031                                 // FIXME: is Delegate operator + (D x, D y) handled?
1032                                 //
1033                         }
1034                         
1035                         if (oper == Operator.LeftShift || oper == Operator.RightShift)
1036                                 return CheckShiftArguments (ec);
1037
1038                         if (oper == Operator.LogicalOr || oper == Operator.LogicalAnd){
1039                                 if (l != TypeManager.bool_type || r != TypeManager.bool_type){
1040                                         error19 ();
1041                                         return null;
1042                                 }
1043
1044                                 type = TypeManager.bool_type;
1045                                 return this;
1046                         } 
1047
1048                         if (oper == Operator.Equality || oper == Operator.Inequality){
1049                                 if (l == TypeManager.bool_type || r == TypeManager.bool_type){
1050                                         if (r != TypeManager.bool_type || l != TypeManager.bool_type){
1051                                                 error19 ();
1052                                                 return null;
1053                                         }
1054                                         
1055                                         type = TypeManager.bool_type;
1056                                         return this;
1057                                 }
1058
1059                         }
1060
1061                         //
1062                         // We are dealing with numbers
1063                         //
1064
1065                         if (!DoNumericPromotions (ec, l, r)){
1066                                 // Attempt:
1067                                 //
1068                                 // operator != (object a, object b)
1069                                 // operator == (object a, object b)
1070                                 //
1071
1072                                 if (oper == Operator.Equality || oper == Operator.Inequality){
1073                                         Expression li, ri;
1074                                         li = ConvertImplicit (ec, left, TypeManager.object_type, loc);
1075                                         if (li != null){
1076                                                 ri = ConvertImplicit (ec, right, TypeManager.object_type,
1077                                                                       loc);
1078                                                 if (ri != null){
1079                                                         left = li;
1080                                                         right = ri;
1081                                                         
1082                                                         type = TypeManager.bool_type;
1083                                                         return this;
1084                                                 }
1085                                         }
1086                                 }
1087
1088                                 error19 ();
1089                                 return null;
1090                         }
1091
1092                         if (left == null || right == null)
1093                                 return null;
1094
1095                         
1096                         if (oper == Operator.BitwiseAnd ||
1097                             oper == Operator.BitwiseOr ||
1098                             oper == Operator.ExclusiveOr){
1099                                 if (!((l == TypeManager.int32_type) ||
1100                                       (l == TypeManager.uint32_type) ||
1101                                       (l == TypeManager.int64_type) ||
1102                                       (l == TypeManager.uint64_type))){
1103                                         error19 ();
1104                                         return null;
1105                                 }
1106                                 type = l;
1107                         }
1108
1109                         if (oper == Operator.Equality ||
1110                             oper == Operator.Inequality ||
1111                             oper == Operator.LessThanOrEqual ||
1112                             oper == Operator.LessThan ||
1113                             oper == Operator.GreaterThanOrEqual ||
1114                             oper == Operator.GreaterThan){
1115                                 type = TypeManager.bool_type;
1116                         }
1117
1118                         return this;
1119                 }
1120                 
1121                 public override Expression DoResolve (EmitContext ec)
1122                 {
1123                         left = left.Resolve (ec);
1124                         right = right.Resolve (ec);
1125
1126                         if (left == null || right == null)
1127                                 return null;
1128
1129                         if (left.Type == null)
1130                                 throw new Exception (
1131                                         "Resolve returned non null, but did not set the type! (" +
1132                                         left + ") at Line: " + loc.Row);
1133                         if (right.Type == null)
1134                                 throw new Exception (
1135                                         "Resolve returned non null, but did not set the type! (" +
1136                                         right + ") at Line: "+ loc.Row);
1137
1138                         eclass = ExprClass.Value;
1139
1140                         return ResolveOperator (ec);
1141                 }
1142
1143                 public bool IsBranchable ()
1144                 {
1145                         if (oper == Operator.Equality ||
1146                             oper == Operator.Inequality ||
1147                             oper == Operator.LessThan ||
1148                             oper == Operator.GreaterThan ||
1149                             oper == Operator.LessThanOrEqual ||
1150                             oper == Operator.GreaterThanOrEqual){
1151                                 return true;
1152                         } else
1153                                 return false;
1154                 }
1155
1156                 // <summary>
1157                 //   This entry point is used by routines that might want
1158                 //   to emit a brfalse/brtrue after an expression, and instead
1159                 //   they could use a more compact notation.
1160                 //
1161                 //   Typically the code would generate l.emit/r.emit, followed
1162                 //   by the comparission and then a brtrue/brfalse.  The comparissions
1163                 //   are sometimes inneficient (there are not as complete as the branches
1164                 //   look for the hacks in Emit using double ceqs).
1165                 //
1166                 //   So for those cases we provide EmitBranchable that can emit the
1167                 //   branch with the test
1168                 // </summary>
1169                 public void EmitBranchable (EmitContext ec, int target)
1170                 {
1171                         OpCode opcode;
1172                         bool close_target = false;
1173                         
1174                         left.Emit (ec);
1175                         right.Emit (ec);
1176                         
1177                         switch (oper){
1178                         case Operator.Equality:
1179                                 if (close_target)
1180                                         opcode = OpCodes.Beq_S;
1181                                 else
1182                                         opcode = OpCodes.Beq;
1183                                 break;
1184
1185                         case Operator.Inequality:
1186                                 if (close_target)
1187                                         opcode = OpCodes.Bne_Un_S;
1188                                 else
1189                                         opcode = OpCodes.Bne_Un;
1190                                 break;
1191
1192                         case Operator.LessThan:
1193                                 if (close_target)
1194                                         opcode = OpCodes.Blt_S;
1195                                 else
1196                                         opcode = OpCodes.Blt;
1197                                 break;
1198
1199                         case Operator.GreaterThan:
1200                                 if (close_target)
1201                                         opcode = OpCodes.Bgt_S;
1202                                 else
1203                                         opcode = OpCodes.Bgt;
1204                                 break;
1205
1206                         case Operator.LessThanOrEqual:
1207                                 if (close_target)
1208                                         opcode = OpCodes.Ble_S;
1209                                 else
1210                                         opcode = OpCodes.Ble;
1211                                 break;
1212
1213                         case Operator.GreaterThanOrEqual:
1214                                 if (close_target)
1215                                         opcode = OpCodes.Bge_S;
1216                                 else
1217                                         opcode = OpCodes.Ble;
1218                                 break;
1219
1220                         default:
1221                                 throw new Exception ("EmitBranchable called on non-EmitBranchable operator: "
1222                                                      + oper.ToString ());
1223                         }
1224
1225                         ec.ig.Emit (opcode, target);
1226                 }
1227                 
1228                 public override void Emit (EmitContext ec)
1229                 {
1230                         ILGenerator ig = ec.ig;
1231                         Type l = left.Type;
1232                         Type r = right.Type;
1233                         OpCode opcode;
1234
1235                         if (method != null) {
1236
1237                                 // Note that operators are static anyway
1238                                 
1239                                 if (Arguments != null) 
1240                                         Invocation.EmitArguments (ec, Arguments);
1241                                 
1242                                 if (method is MethodInfo)
1243                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
1244                                 else
1245                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
1246
1247                                 return;
1248                         }
1249                         
1250                         left.Emit (ec);
1251                         right.Emit (ec);
1252
1253                         switch (oper){
1254                         case Operator.Multiply:
1255                                 if (ec.CheckState){
1256                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1257                                                 opcode = OpCodes.Mul_Ovf;
1258                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1259                                                 opcode = OpCodes.Mul_Ovf_Un;
1260                                         else
1261                                                 opcode = OpCodes.Mul;
1262                                 } else
1263                                         opcode = OpCodes.Mul;
1264
1265                                 break;
1266
1267                         case Operator.Division:
1268                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1269                                         opcode = OpCodes.Div_Un;
1270                                 else
1271                                         opcode = OpCodes.Div;
1272                                 break;
1273
1274                         case Operator.Modulus:
1275                                 if (l == TypeManager.uint32_type || l == TypeManager.uint64_type)
1276                                         opcode = OpCodes.Rem_Un;
1277                                 else
1278                                         opcode = OpCodes.Rem;
1279                                 break;
1280
1281                         case Operator.Addition:
1282                                 if (ec.CheckState){
1283                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1284                                                 opcode = OpCodes.Add_Ovf;
1285                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1286                                                 opcode = OpCodes.Add_Ovf_Un;
1287                                         else
1288                                                 opcode = OpCodes.Mul;
1289                                 } else
1290                                         opcode = OpCodes.Add;
1291                                 break;
1292
1293                         case Operator.Subtraction:
1294                                 if (ec.CheckState){
1295                                         if (l == TypeManager.int32_type || l == TypeManager.int64_type)
1296                                                 opcode = OpCodes.Sub_Ovf;
1297                                         else if (l==TypeManager.uint32_type || l==TypeManager.uint64_type)
1298                                                 opcode = OpCodes.Sub_Ovf_Un;
1299                                         else
1300                                                 opcode = OpCodes.Sub;
1301                                 } else
1302                                         opcode = OpCodes.Sub;
1303                                 break;
1304
1305                         case Operator.RightShift:
1306                                 opcode = OpCodes.Shr;
1307                                 break;
1308                                 
1309                         case Operator.LeftShift:
1310                                 opcode = OpCodes.Shl;
1311                                 break;
1312
1313                         case Operator.Equality:
1314                                 opcode = OpCodes.Ceq;
1315                                 break;
1316
1317                         case Operator.Inequality:
1318                                 ec.ig.Emit (OpCodes.Ceq);
1319                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1320                                 
1321                                 opcode = OpCodes.Ceq;
1322                                 break;
1323
1324                         case Operator.LessThan:
1325                                 opcode = OpCodes.Clt;
1326                                 break;
1327
1328                         case Operator.GreaterThan:
1329                                 opcode = OpCodes.Cgt;
1330                                 break;
1331
1332                         case Operator.LessThanOrEqual:
1333                                 ec.ig.Emit (OpCodes.Cgt);
1334                                 ec.ig.Emit (OpCodes.Ldc_I4_0);
1335                                 
1336                                 opcode = OpCodes.Ceq;
1337                                 break;
1338
1339                         case Operator.GreaterThanOrEqual:
1340                                 ec.ig.Emit (OpCodes.Clt);
1341                                 ec.ig.Emit (OpCodes.Ldc_I4_1);
1342                                 
1343                                 opcode = OpCodes.Sub;
1344                                 break;
1345
1346                         case Operator.LogicalOr:
1347                         case Operator.BitwiseOr:
1348                                 opcode = OpCodes.Or;
1349                                 break;
1350
1351                         case Operator.LogicalAnd:
1352                         case Operator.BitwiseAnd:
1353                                 opcode = OpCodes.And;
1354                                 break;
1355
1356                         case Operator.ExclusiveOr:
1357                                 opcode = OpCodes.Xor;
1358                                 break;
1359
1360                         default:
1361                                 throw new Exception ("This should not happen: Operator = "
1362                                                      + oper.ToString ());
1363                         }
1364
1365                         ig.Emit (opcode);
1366                 }
1367
1368                 // <summary>
1369                 //   Constant expression reducer for binary operations
1370                 // </summary>
1371                 public override Expression Reduce (EmitContext ec)
1372                 {
1373                         Console.WriteLine ("Reduce called");
1374                         
1375                         left = left.Reduce (ec);
1376                         right = right.Reduce (ec);
1377
1378                         if (!(left is Literal && right is Literal))
1379                                 return this;
1380
1381                         if (method == TypeManager.string_concat_string_string){
1382                                 StringLiteral ls = (StringLiteral) left;
1383                                 StringLiteral rs = (StringLiteral) right;
1384                                 
1385                                 return new StringLiteral (ls.Value + rs.Value);
1386                         }
1387
1388                         // FINISH ME.
1389                         
1390                         return this;
1391                 }
1392         }
1393
1394         public class Conditional : Expression {
1395                 Expression expr, trueExpr, falseExpr;
1396                 Location loc;
1397                 
1398                 public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
1399                 {
1400                         this.expr = expr;
1401                         this.trueExpr = trueExpr;
1402                         this.falseExpr = falseExpr;
1403                         this.loc = l;
1404                 }
1405
1406                 public Expression Expr {
1407                         get {
1408                                 return expr;
1409                         }
1410                 }
1411
1412                 public Expression TrueExpr {
1413                         get {
1414                                 return trueExpr;
1415                         }
1416                 }
1417
1418                 public Expression FalseExpr {
1419                         get {
1420                                 return falseExpr;
1421                         }
1422                 }
1423
1424                 public override Expression DoResolve (EmitContext ec)
1425                 {
1426                         expr = expr.Resolve (ec);
1427
1428                         if (expr.Type != TypeManager.bool_type)
1429                                 expr = Expression.ConvertImplicitRequired (
1430                                         ec, expr, TypeManager.bool_type, loc);
1431                         
1432                         trueExpr = trueExpr.Resolve (ec);
1433                         falseExpr = falseExpr.Resolve (ec);
1434
1435                         if (expr == null || trueExpr == null || falseExpr == null)
1436                                 return null;
1437
1438                         if (trueExpr.Type == falseExpr.Type)
1439                                 type = trueExpr.Type;
1440                         else {
1441                                 Expression conv;
1442
1443                                 //
1444                                 // First, if an implicit conversion exists from trueExpr
1445                                 // to falseExpr, then the result type is of type falseExpr.Type
1446                                 //
1447                                 conv = ConvertImplicit (ec, trueExpr, falseExpr.Type, loc);
1448                                 if (conv != null){
1449                                         type = falseExpr.Type;
1450                                         trueExpr = conv;
1451                                 } else if ((conv = ConvertImplicit(ec, falseExpr,trueExpr.Type,loc))!= null){
1452                                         type = trueExpr.Type;
1453                                         falseExpr = conv;
1454                                 } else {
1455                                         Error (173, loc, "The type of the conditional expression can " +
1456                                                "not be computed because there is no implicit conversion" +
1457                                                " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
1458                                                " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
1459                                         return null;
1460                                 }
1461                         }
1462
1463                         if (expr is BoolLiteral){
1464                                 BoolLiteral bl = (BoolLiteral) expr;
1465
1466                                 if (bl.Value)
1467                                         return trueExpr;
1468                                 else
1469                                         return falseExpr;
1470                         }
1471                         
1472                         eclass = ExprClass.Value;
1473                         return this;
1474                 }
1475
1476                 public override void Emit (EmitContext ec)
1477                 {
1478                         ILGenerator ig = ec.ig;
1479                         Label false_target = ig.DefineLabel ();
1480                         Label end_target = ig.DefineLabel ();
1481
1482                         expr.Emit (ec);
1483                         ig.Emit (OpCodes.Brfalse, false_target);
1484                         trueExpr.Emit (ec);
1485                         ig.Emit (OpCodes.Br, end_target);
1486                         ig.MarkLabel (false_target);
1487                         falseExpr.Emit (ec);
1488                         ig.MarkLabel (end_target);
1489                 }
1490
1491                 public override Expression Reduce (EmitContext ec)
1492                 {
1493                         expr = expr.Reduce (ec);
1494                         trueExpr = trueExpr.Reduce (ec);
1495                         falseExpr = falseExpr.Reduce (ec);
1496
1497                         if (!(expr is Literal && trueExpr is Literal && falseExpr is Literal))
1498                                 return this;
1499
1500                         BoolLiteral bl = (BoolLiteral) expr;
1501
1502                         if (bl.Value)
1503                                 return trueExpr;
1504                         else
1505                                 return falseExpr;
1506                 }
1507         }
1508
1509         public class LocalVariableReference : Expression, IStackStore, IMemoryLocation {
1510                 public readonly string Name;
1511                 public readonly Block Block;
1512
1513                 VariableInfo variable_info;
1514                 
1515                 public LocalVariableReference (Block block, string name)
1516                 {
1517                         Block = block;
1518                         Name = name;
1519                         eclass = ExprClass.Variable;
1520                 }
1521
1522                 public VariableInfo VariableInfo {
1523                         get {
1524                                 if (variable_info == null)
1525                                         variable_info = Block.GetVariableInfo (Name);
1526                                 return variable_info;
1527                         }
1528                 }
1529                 
1530                 public override Expression DoResolve (EmitContext ec)
1531                 {
1532                         VariableInfo vi = VariableInfo;
1533
1534                         type = vi.VariableType;
1535                         return this;
1536                 }
1537
1538                 public override void Emit (EmitContext ec)
1539                 {
1540                         VariableInfo vi = VariableInfo;
1541                         ILGenerator ig = ec.ig;
1542                         int idx = vi.Idx;
1543
1544                         vi.Used = true;
1545
1546                         switch (idx){
1547                         case 0:
1548                                 ig.Emit (OpCodes.Ldloc_0);
1549                                 break;
1550                                 
1551                         case 1:
1552                                 ig.Emit (OpCodes.Ldloc_1);
1553                                 break;
1554                                 
1555                         case 2:
1556                                 ig.Emit (OpCodes.Ldloc_2);
1557                                 break;
1558                                 
1559                         case 3:
1560                                 ig.Emit (OpCodes.Ldloc_3);
1561                                 break;
1562                                 
1563                         default:
1564                                 if (idx <= 255)
1565                                         ig.Emit (OpCodes.Ldloc_S, (byte) idx);
1566                                 else
1567                                         ig.Emit (OpCodes.Ldloc, idx);
1568                                 break;
1569                         }
1570                 }
1571                 
1572                 public static void Store (ILGenerator ig, int idx)
1573                 {
1574                         switch (idx){
1575                         case 0:
1576                                 ig.Emit (OpCodes.Stloc_0);
1577                                 break;
1578                                 
1579                         case 1:
1580                                 ig.Emit (OpCodes.Stloc_1);
1581                                 break;
1582                                 
1583                         case 2:
1584                                 ig.Emit (OpCodes.Stloc_2);
1585                                 break;
1586                                 
1587                         case 3:
1588                                 ig.Emit (OpCodes.Stloc_3);
1589                                 break;
1590                                 
1591                         default:
1592                                 if (idx <= 255)
1593                                         ig.Emit (OpCodes.Stloc_S, (byte) idx);
1594                                 else
1595                                         ig.Emit (OpCodes.Stloc, idx);
1596                                 break;
1597                         }
1598                 }
1599                 
1600                 public void Store (EmitContext ec)
1601                 {
1602                         ILGenerator ig = ec.ig;
1603                         VariableInfo vi = VariableInfo;
1604
1605                         vi.Assigned = true;
1606
1607                         // Funny seems the above generates optimal code for us, but
1608                         // seems to take too long to generate what we need.
1609                         // ig.Emit (OpCodes.Stloc, vi.LocalBuilder);
1610
1611                         Store (ig, vi.Idx);
1612                 }
1613
1614                 public void AddressOf (EmitContext ec)
1615                 {
1616                         VariableInfo vi = VariableInfo;
1617                         int idx = vi.Idx;
1618
1619                         vi.Used = true;
1620                         vi.Assigned = true;
1621                         
1622                         if (idx <= 255)
1623                                 ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
1624                         else
1625                                 ec.ig.Emit (OpCodes.Ldloca, idx);
1626                 }
1627         }
1628
1629         public class ParameterReference : Expression, IStackStore, IMemoryLocation {
1630                 public readonly Parameters Pars;
1631                 public readonly String Name;
1632                 public readonly int Idx;
1633                 int arg_idx;
1634                 
1635                 public ParameterReference (Parameters pars, int idx, string name)
1636                 {
1637                         Pars = pars;
1638                         Idx  = idx;
1639                         Name = name;
1640                         eclass = ExprClass.Variable;
1641                 }
1642
1643                 public override Expression DoResolve (EmitContext ec)
1644                 {
1645                         Type [] types = Pars.GetParameterInfo (ec.TypeContainer);
1646
1647                         type = types [Idx];
1648
1649                         arg_idx = Idx;
1650                         if (!ec.IsStatic)
1651                                 arg_idx++;
1652                         
1653                         return this;
1654                 }
1655
1656                 public override void Emit (EmitContext ec)
1657                 {
1658                         if (arg_idx <= 255)
1659                                 ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
1660                         else
1661                                 ec.ig.Emit (OpCodes.Ldarg, arg_idx);
1662                 }
1663
1664                 public void Store (EmitContext ec)
1665                 {
1666                         if (arg_idx <= 255)
1667                                 ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
1668                         else
1669                                 ec.ig.Emit (OpCodes.Starg, arg_idx);
1670                         
1671                 }
1672
1673                 public void AddressOf (EmitContext ec)
1674                 {
1675                         if (arg_idx <= 255)
1676                                 ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
1677                         else
1678                                 ec.ig.Emit (OpCodes.Ldarga, arg_idx);
1679                 }
1680         }
1681         
1682         // <summary>
1683         //   Used for arguments to New(), Invocation()
1684         // </summary>
1685         public class Argument {
1686                 public enum AType {
1687                         Expression,
1688                         Ref,
1689                         Out
1690                 };
1691
1692                 public readonly AType ArgType;
1693                 public Expression expr;
1694
1695                 public Argument (Expression expr, AType type)
1696                 {
1697                         this.expr = expr;
1698                         this.ArgType = type;
1699                 }
1700
1701                 public Expression Expr {
1702                         get {
1703                                 return expr;
1704                         }
1705
1706                         set {
1707                                 expr = value;
1708                         }
1709                 }
1710
1711                 public Type Type {
1712                         get {
1713                                 return expr.Type;
1714                         }
1715                 }
1716
1717                 public Parameter.Modifier GetParameterModifier ()
1718                 {
1719                         if (ArgType == AType.Ref)
1720                                 return Parameter.Modifier.REF;
1721
1722                         if (ArgType == AType.Out)
1723                                 return Parameter.Modifier.OUT;
1724
1725                         return Parameter.Modifier.NONE;
1726                 }
1727
1728                 public static string FullDesc (Argument a)
1729                 {
1730                         StringBuilder sb = new StringBuilder ();
1731
1732                         if (a.ArgType == AType.Ref)
1733                                 sb.Append ("ref ");
1734
1735                         if (a.ArgType == AType.Out)
1736                                 sb.Append ("out ");
1737
1738                         sb.Append (TypeManager.CSharpName (a.Expr.Type));
1739
1740                         return sb.ToString ();
1741                 }
1742                 
1743                 public bool Resolve (EmitContext ec)
1744                 {
1745                         expr = expr.Resolve (ec);
1746
1747                         return expr != null;
1748                 }
1749
1750                 public void Emit (EmitContext ec)
1751                 {
1752                         expr.Emit (ec);
1753                 }
1754         }
1755
1756         // <summary>
1757         //   Invocation of methods or delegates.
1758         // </summary>
1759         public class Invocation : ExpressionStatement {
1760                 public readonly ArrayList Arguments;
1761                 public readonly Location Location;
1762
1763                 Expression expr;
1764                 MethodBase method = null;
1765                         
1766                 static Hashtable method_parameter_cache;
1767
1768                 static Invocation ()
1769                 {
1770                         method_parameter_cache = new Hashtable ();
1771                 }
1772                         
1773                 //
1774                 // arguments is an ArrayList, but we do not want to typecast,
1775                 // as it might be null.
1776                 //
1777                 // FIXME: only allow expr to be a method invocation or a
1778                 // delegate invocation (7.5.5)
1779                 //
1780                 public Invocation (Expression expr, ArrayList arguments, Location l)
1781                 {
1782                         this.expr = expr;
1783                         Arguments = arguments;
1784                         Location = l;
1785                 }
1786
1787                 public Expression Expr {
1788                         get {
1789                                 return expr;
1790                         }
1791                 }
1792
1793                 // <summary>
1794                 //   Returns the Parameters (a ParameterData interface) for the
1795                 //   Method `mb'
1796                 // </summary>
1797                 public static ParameterData GetParameterData (MethodBase mb)
1798                 {
1799                         object pd = method_parameter_cache [mb];
1800                         object ip;
1801                         
1802                         if (pd != null)
1803                                 return (ParameterData) pd;
1804
1805                         
1806                         ip = TypeContainer.LookupParametersByBuilder (mb);
1807                         if (ip != null){
1808                                 method_parameter_cache [mb] = ip;
1809
1810                                 return (ParameterData) ip;
1811                         } else {
1812                                 ParameterInfo [] pi = mb.GetParameters ();
1813                                 ReflectionParameters rp = new ReflectionParameters (pi);
1814                                 method_parameter_cache [mb] = rp;
1815
1816                                 return (ParameterData) rp;
1817                         }
1818                 }
1819
1820                 // <summary>
1821                 //   Tells whether a user defined conversion from Type `from' to
1822                 //   Type `to' exists.
1823                 //
1824                 //   FIXME: we could implement a cache here. 
1825                 // </summary>
1826                 static bool ConversionExists (EmitContext ec, Type from, Type to, Location loc)
1827                 {
1828                         // Locate user-defined implicit operators
1829
1830                         Expression mg;
1831                         
1832                         mg = MemberLookup (ec, to, "op_Implicit", false, loc);
1833
1834                         if (mg != null) {
1835                                 MethodGroupExpr me = (MethodGroupExpr) mg;
1836                                 
1837                                 for (int i = me.Methods.Length; i > 0;) {
1838                                         i--;
1839                                         MethodBase mb = me.Methods [i];
1840                                         ParameterData pd = GetParameterData (mb);
1841                                         
1842                                         if (from == pd.ParameterType (0))
1843                                                 return true;
1844                                 }
1845                         }
1846
1847                         mg = MemberLookup (ec, from, "op_Implicit", false, loc);
1848
1849                         if (mg != null) {
1850                                 MethodGroupExpr me = (MethodGroupExpr) mg;
1851
1852                                 for (int i = me.Methods.Length; i > 0;) {
1853                                         i--;
1854                                         MethodBase mb = me.Methods [i];
1855                                         MethodInfo mi = (MethodInfo) mb;
1856                                         
1857                                         if (mi.ReturnType == to)
1858                                                 return true;
1859                                 }
1860                         }
1861                         
1862                         return false;
1863                 }
1864                 
1865                 // <summary>
1866                 //  Determines "better conversion" as specified in 7.4.2.3
1867                 //  Returns : 1 if a->p is better
1868                 //            0 if a->q or neither is better 
1869                 // </summary>
1870                 static int BetterConversion (EmitContext ec, Argument a, Type p, Type q, bool use_standard,
1871                                              Location loc)
1872                 {
1873                         Type argument_type = a.Type;
1874                         Expression argument_expr = a.Expr;
1875
1876                         if (argument_type == null)
1877                                 throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
1878
1879                         if (p == q)
1880                                 return 0;
1881                         
1882                         if (argument_type == p)
1883                                 return 1;
1884
1885                         if (argument_type == q)
1886                                 return 0;
1887
1888                         //
1889                         // Now probe whether an implicit constant expression conversion
1890                         // can be used.
1891                         //
1892                         // An implicit constant expression conversion permits the following
1893                         // conversions:
1894                         //
1895                         //    * A constant-expression of type `int' can be converted to type
1896                         //      sbyte, byute, short, ushort, uint, ulong provided the value of
1897                         //      of the expression is withing the range of the destination type.
1898                         //
1899                         //    * A constant-expression of type long can be converted to type
1900                         //      ulong, provided the value of the constant expression is not negative
1901                         //
1902                         // FIXME: Note that this assumes that constant folding has
1903                         // taken place.  We dont do constant folding yet.
1904                         //
1905
1906                         if (argument_expr is IntLiteral){
1907                                 IntLiteral ei = (IntLiteral) argument_expr;
1908                                 int value = ei.Value;
1909                                 
1910                                 if (p == TypeManager.sbyte_type){
1911                                         if (value >= SByte.MinValue && value <= SByte.MaxValue)
1912                                                 return 1;
1913                                 } else if (p == TypeManager.byte_type){
1914                                         if (Byte.MinValue >= 0 && value <= Byte.MaxValue)
1915                                                 return 1;
1916                                 } else if (p == TypeManager.short_type){
1917                                         if (value >= Int16.MinValue && value <= Int16.MaxValue)
1918                                                 return 1;
1919                                 } else if (p == TypeManager.ushort_type){
1920                                         if (value >= UInt16.MinValue && value <= UInt16.MaxValue)
1921                                                 return 1;
1922                                 } else if (p == TypeManager.uint32_type){
1923                                         //
1924                                         // we can optimize this case: a positive int32
1925                                         // always fits on a uint32
1926                                         //
1927                                         if (value >= 0)
1928                                                 return 1;
1929                                 } else if (p == TypeManager.uint64_type){
1930                                         //
1931                                         // we can optimize this case: a positive int32
1932                                         // always fits on a uint64
1933                                         //
1934                                         if (value >= 0)
1935                                                 return 1;
1936                                 }
1937                         } else if (argument_type == TypeManager.int64_type && argument_expr is LongLiteral){
1938                                 LongLiteral ll = (LongLiteral) argument_expr;
1939                                 
1940                                 if (p == TypeManager.uint64_type){
1941                                         if (ll.Value > 0)
1942                                                 return 1;
1943                                 }
1944                         }
1945
1946                         if (q == null) {
1947
1948                                 Expression tmp;
1949
1950                                 if (use_standard)
1951                                         tmp = ConvertImplicitStandard (ec, argument_expr, p, loc);
1952                                 else
1953                                         tmp = ConvertImplicit (ec, argument_expr, p, loc);
1954
1955                                 if (tmp != null)
1956                                         return 1;
1957                                 else
1958                                         return 0;
1959
1960                         }
1961
1962                         if (ConversionExists (ec, p, q, loc) == true &&
1963                             ConversionExists (ec, q, p, loc) == false)
1964                                 return 1;
1965
1966                         if (p == TypeManager.sbyte_type)
1967                                 if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
1968                                     q == TypeManager.uint32_type || q == TypeManager.uint64_type)
1969                                         return 1;
1970
1971                         if (p == TypeManager.short_type)
1972                                 if (q == TypeManager.ushort_type || q == TypeManager.uint32_type ||
1973                                     q == TypeManager.uint64_type)
1974                                         return 1;
1975
1976                         if (p == TypeManager.int32_type)
1977                                 if (q == TypeManager.uint32_type || q == TypeManager.uint64_type)
1978                                         return 1;
1979
1980                         if (p == TypeManager.int64_type)
1981                                 if (q == TypeManager.uint64_type)
1982                                         return 1;
1983
1984                         return 0;
1985                 }
1986                 
1987                 // <summary>
1988                 //  Determines "Better function" and returns an integer indicating :
1989                 //  0 if candidate ain't better
1990                 //  1 if candidate is better than the current best match
1991                 // </summary>
1992                 static int BetterFunction (EmitContext ec, ArrayList args,
1993                                            MethodBase candidate, MethodBase best,
1994                                            bool use_standard, Location loc)
1995                 {
1996                         ParameterData candidate_pd = GetParameterData (candidate);
1997                         ParameterData best_pd;
1998                         int argument_count;
1999
2000                         if (args == null)
2001                                 argument_count = 0;
2002                         else
2003                                 argument_count = args.Count;
2004
2005                         if (candidate_pd.Count == 0 && argument_count == 0)
2006                                 return 1;
2007
2008                         if (best == null) {
2009                                 if (candidate_pd.Count == argument_count) {
2010                                         int x = 0;
2011                                         for (int j = argument_count; j > 0;) {
2012                                                 j--;
2013                                                 
2014                                                 Argument a = (Argument) args [j];
2015                                                 
2016                                                 x = BetterConversion (
2017                                                         ec, a, candidate_pd.ParameterType (j), null,
2018                                                         use_standard, loc);
2019                                                 
2020                                                 if (x <= 0)
2021                                                         break;
2022                                         }
2023                                         
2024                                         if (x > 0)
2025                                                 return 1;
2026                                         else
2027                                                 return 0;
2028                                         
2029                                 } else
2030                                         return 0;
2031                         }
2032
2033                         best_pd = GetParameterData (best);
2034
2035                         if (candidate_pd.Count == argument_count && best_pd.Count == argument_count) {
2036                                 int rating1 = 0, rating2 = 0;
2037                                 
2038                                 for (int j = argument_count; j > 0;) {
2039                                         j--;
2040                                         int x, y;
2041                                         
2042                                         Argument a = (Argument) args [j];
2043
2044                                         x = BetterConversion (ec, a, candidate_pd.ParameterType (j),
2045                                                               best_pd.ParameterType (j), use_standard, loc);
2046                                         y = BetterConversion (ec, a, best_pd.ParameterType (j),
2047                                                               candidate_pd.ParameterType (j), use_standard,
2048                                                               loc);
2049                                         
2050                                         rating1 += x;
2051                                         rating2 += y;
2052                                 }
2053
2054                                 if (rating1 > rating2)
2055                                         return 1;
2056                                 else
2057                                         return 0;
2058                         } else
2059                                 return 0;
2060                         
2061                 }
2062
2063                 public static string FullMethodDesc (MethodBase mb)
2064                 {
2065                         StringBuilder sb = new StringBuilder (mb.Name);
2066                         ParameterData pd = GetParameterData (mb);
2067
2068                         int count = pd.Count;
2069                         sb.Append (" (");
2070                         
2071                         for (int i = count; i > 0; ) {
2072                                 i--;
2073                                 
2074                                 sb.Append (pd.ParameterDesc (count - i - 1));
2075                                 if (i != 0)
2076                                         sb.Append (", ");
2077                         }
2078                         
2079                         sb.Append (")");
2080                         return sb.ToString ();
2081                 }
2082
2083                 public static MethodGroupExpr MakeUnionSet (Expression mg1, Expression mg2)
2084                 {
2085                         MemberInfo [] miset;
2086                         MethodGroupExpr union;
2087                         
2088                         if (mg1 != null && mg2 != null) {
2089                                 
2090                                 MethodGroupExpr left_set = null, right_set = null;
2091                                 int length1 = 0, length2 = 0;
2092                                 
2093                                 left_set = (MethodGroupExpr) mg1;
2094                                 length1 = left_set.Methods.Length;
2095                                 
2096                                 right_set = (MethodGroupExpr) mg2;
2097                                 length2 = right_set.Methods.Length;
2098
2099                                 ArrayList common = new ArrayList ();
2100                                 
2101                                 for (int i = 0; i < left_set.Methods.Length; i++) {
2102                                         for (int j = 0; j < right_set.Methods.Length; j++) {
2103                                                 if (left_set.Methods [i] == right_set.Methods [j]) 
2104                                                         common.Add (left_set.Methods [i]);
2105                                         }
2106                                 }
2107                                 
2108                                 miset = new MemberInfo [length1 + length2 - common.Count];
2109
2110                                 left_set.Methods.CopyTo (miset, 0);
2111
2112                                 int k = 0;
2113                                 
2114                                 for (int j = 0; j < right_set.Methods.Length; j++)
2115                                         if (!common.Contains (right_set.Methods [j]))
2116                                                 miset [length1 + k++] = right_set.Methods [j];
2117                                 
2118                                 union = new MethodGroupExpr (miset);
2119
2120                                 return union;
2121
2122                         } else if (mg1 == null && mg2 != null) {
2123                                 
2124                                 MethodGroupExpr me = (MethodGroupExpr) mg2; 
2125                                 
2126                                 miset = new MemberInfo [me.Methods.Length];
2127                                 me.Methods.CopyTo (miset, 0);
2128
2129                                 union = new MethodGroupExpr (miset);
2130                                 
2131                                 return union;
2132
2133                         } else if (mg2 == null && mg1 != null) {
2134                                 
2135                                 MethodGroupExpr me = (MethodGroupExpr) mg1; 
2136                                 
2137                                 miset = new MemberInfo [me.Methods.Length];
2138                                 me.Methods.CopyTo (miset, 0);
2139
2140                                 union = new MethodGroupExpr (miset);
2141                                 
2142                                 return union;
2143                         }
2144                         
2145                         return null;
2146                 }
2147
2148                 // <summary>
2149                 //  Determines is the candidate method, if a params method, is applicable
2150                 //  in its expanded form to the given set of arguments
2151                 // </summary>
2152                 static bool IsParamsMethodApplicable (ArrayList arguments, MethodBase candidate)
2153                 {
2154                         int arg_count;
2155                         
2156                         if (arguments == null)
2157                                 arg_count = 0;
2158                         else
2159                                 arg_count = arguments.Count;
2160                         
2161                         ParameterData pd = GetParameterData (candidate);
2162                         
2163                         int pd_count = pd.Count;
2164
2165                         if (pd.ParameterModifier (pd_count - 1) != Parameter.Modifier.PARAMS)
2166                                 return false;
2167
2168                         if (pd_count - 1 > arg_count)
2169                                 return false;
2170
2171                         // If we have come this far, the case which remains is when the number of parameters
2172                         // is less than or equal to the argument count. So, we now check if the element type
2173                         // of the params array is compatible with each argument type
2174                         //
2175
2176                         Type element_type = pd.ParameterType (pd_count - 1).GetElementType ();
2177
2178                         for (int i = pd_count - 1; i < arg_count - 1; i++) {
2179                                 Argument a = (Argument) arguments [i];
2180                                 if (!StandardConversionExists (a.Type, element_type))
2181                                         return false;
2182                         }
2183                         
2184                         return true;
2185                 }
2186
2187                 // <summary>
2188                 //  Determines if the candidate method is applicable (section 14.4.2.1)
2189                 //  to the given set of arguments
2190                 // </summary>
2191                 static bool IsApplicable (ArrayList arguments, MethodBase candidate)
2192                 {
2193                         int arg_count;
2194
2195                         if (arguments == null)
2196                                 arg_count = 0;
2197                         else
2198                                 arg_count = arguments.Count;
2199
2200                         ParameterData pd = GetParameterData (candidate);
2201
2202                         int pd_count = pd.Count;
2203
2204                         if (arg_count != pd.Count)
2205                                 return false;
2206
2207                         for (int i = arg_count; i > 0; ) {
2208                                 i--;
2209
2210                                 Argument a = (Argument) arguments [i];
2211
2212                                 Parameter.Modifier a_mod = a.GetParameterModifier ();
2213                                 Parameter.Modifier p_mod = pd.ParameterModifier (i);
2214
2215                                 if (a_mod == p_mod) {
2216                                         
2217                                         if (a_mod == Parameter.Modifier.NONE)
2218                                                 if (!StandardConversionExists (a.Type, pd.ParameterType (i)))
2219                                                         return false;
2220                                         
2221                                         if (a_mod == Parameter.Modifier.REF ||
2222                                             a_mod == Parameter.Modifier.OUT)
2223                                                 if (pd.ParameterType (i) != a.Type)
2224                                                         return false;
2225                                 } else
2226                                         return false;
2227                         }
2228
2229                         return true;
2230                 }
2231                 
2232                 
2233
2234                 // <summary>
2235                 //   Find the Applicable Function Members (7.4.2.1)
2236                 //
2237                 //   me: Method Group expression with the members to select.
2238                 //       it might contain constructors or methods (or anything
2239                 //       that maps to a method).
2240                 //
2241                 //   Arguments: ArrayList containing resolved Argument objects.
2242                 //
2243                 //   loc: The location if we want an error to be reported, or a Null
2244                 //        location for "probing" purposes.
2245                 //
2246                 //   use_standard: controls whether OverloadResolve should use the 
2247                 //   ConvertImplicit or ConvertImplicitStandard during overload resolution.
2248                 //
2249                 //   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
2250                 //            that is the best match of me on Arguments.
2251                 //
2252                 // </summary>
2253                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
2254                                                           ArrayList Arguments, Location loc,
2255                                                           bool use_standard)
2256                 {
2257                         ArrayList afm = new ArrayList ();
2258                         int best_match_idx = -1;
2259                         MethodBase method = null;
2260                         int argument_count;
2261                         
2262                         for (int i = me.Methods.Length; i > 0; ){
2263                                 i--;
2264                                 MethodBase candidate  = me.Methods [i];
2265                                 int x;
2266
2267                                 // Check if candidate is applicable (section 14.4.2.1)
2268                                 if (!IsApplicable (Arguments, candidate))
2269                                         continue;
2270
2271                                 x = BetterFunction (ec, Arguments, candidate, method, use_standard, loc);
2272                                 
2273                                 if (x == 0)
2274                                         continue;
2275                                 else {
2276                                         best_match_idx = i;
2277                                         method = me.Methods [best_match_idx];
2278                                 }
2279                         }
2280
2281                         if (Arguments == null)
2282                                 argument_count = 0;
2283                         else
2284                                 argument_count = Arguments.Count;
2285
2286                         //
2287                         // Now we see if we can find params functions, applicable in their expanded form
2288                         // since if they were applicable in their normal form, they would have been selected
2289                         // above anyways
2290                         //
2291                         if (best_match_idx == -1) {
2292
2293                                 for (int i = me.Methods.Length; i > 0; ) {
2294                                         i--;
2295                                         MethodBase candidate = me.Methods [i];
2296
2297                                         if (IsParamsMethodApplicable (Arguments, candidate)) {
2298                                                 best_match_idx = i;
2299                                                 method = me.Methods [best_match_idx];
2300                                                 break;
2301                                         }
2302                                 }
2303                         }
2304
2305                         //
2306                         // Now we see if we can at least find a method with the same number of arguments
2307                         //
2308                         ParameterData pd;
2309                         
2310                         if (best_match_idx == -1) {
2311                                 
2312                                 for (int i = me.Methods.Length; i > 0;) {
2313                                         i--;
2314                                         MethodBase mb = me.Methods [i];
2315                                         pd = GetParameterData (mb);
2316                                         
2317                                         if (pd.Count == argument_count) {
2318                                                 best_match_idx = i;
2319                                                 method = me.Methods [best_match_idx];
2320                                                 break;
2321                                         } else
2322                                                 continue;
2323                                 }
2324                         }
2325
2326                         if (method == null)
2327                                 return null;
2328                         
2329                         // And now convert implicitly, each argument to the required type
2330                         
2331                         pd = GetParameterData (method);
2332                         int pd_count = pd.Count;
2333
2334                         for (int j = 0; j < argument_count; j++) {
2335
2336                                 Argument a = (Argument) Arguments [j];
2337                                 Expression a_expr = a.Expr;
2338                                 Type parameter_type = pd.ParameterType (j);
2339
2340                                 //
2341                                 // Note that we need to compare against the element type
2342                                 // when we have a params method
2343                                 //
2344                                 if (pd.ParameterModifier (pd_count - 1) == Parameter.Modifier.PARAMS) {
2345                                         if (j >= pd_count - 1) 
2346                                                 parameter_type = pd.ParameterType (pd_count - 1).GetElementType ();
2347                                 }
2348
2349                                 if (a.Type != parameter_type){
2350                                         Expression conv;
2351                                         
2352                                         if (use_standard)
2353                                                 conv = ConvertImplicitStandard (ec, a_expr, parameter_type,
2354                                                                                 Location.Null);
2355                                         else
2356                                                 conv = ConvertImplicit (ec, a_expr, parameter_type,
2357                                                                         Location.Null);
2358
2359                                         if (conv == null) {
2360                                                 if (!Location.IsNull (loc)) {
2361                                                         Error (1502, loc,
2362                                                         "The best overloaded match for method '" + FullMethodDesc (method)+
2363                                                                "' has some invalid arguments");
2364                                                         Error (1503, loc,
2365                                                          "Argument " + (j+1) +
2366                                                          ": Cannot convert from '" + Argument.FullDesc (a) 
2367                                                          + "' to '" + pd.ParameterDesc (j) + "'");
2368                                                 }
2369                                                 return null;
2370                                         }
2371                                         
2372                         
2373                                         
2374                                         //
2375                                         // Update the argument with the implicit conversion
2376                                         //
2377                                         if (a_expr != conv)
2378                                                 a.Expr = conv;
2379
2380                                         // FIXME : For the case of params methods, we need to actually instantiate
2381                                         // an array and initialize it with the argument values etc etc.
2382
2383                                 }
2384                                 
2385                                 if (a.GetParameterModifier () != pd.ParameterModifier (j) &&
2386                                     pd.ParameterModifier (j) != Parameter.Modifier.PARAMS) {
2387                                         if (!Location.IsNull (loc)) {
2388                                                 Error (1502, loc,
2389                                                        "The best overloaded match for method '" + FullMethodDesc (method)+
2390                                                        "' has some invalid arguments");
2391                                                 Error (1503, loc,
2392                                                        "Argument " + (j+1) +
2393                                                        ": Cannot convert from '" + Argument.FullDesc (a) 
2394                                                        + "' to '" + pd.ParameterDesc (j) + "'");
2395                                         }
2396                                         return null;
2397                                 }
2398                                 
2399                                 
2400                         }
2401                         
2402                         return method;
2403                 }
2404                 
2405                 public static MethodBase OverloadResolve (EmitContext ec, MethodGroupExpr me,
2406                                                           ArrayList Arguments, Location loc)
2407                 {
2408                         return OverloadResolve (ec, me, Arguments, loc, false);
2409                 }
2410                         
2411                 public override Expression DoResolve (EmitContext ec)
2412                 {
2413                         //
2414                         // First, resolve the expression that is used to
2415                         // trigger the invocation
2416                         //
2417                         expr = expr.Resolve (ec);
2418                         if (expr == null)
2419                                 return null;
2420
2421                         if (!(expr is MethodGroupExpr)) {
2422                                 Type expr_type = expr.Type;
2423
2424                                 if (expr_type != null){
2425                                         bool IsDelegate = TypeManager.IsDelegateType (expr_type);
2426                                         if (IsDelegate)
2427                                                 return (new DelegateInvocation (
2428                                                         this.expr, Arguments, Location)).Resolve (ec);
2429                                 }
2430                         }
2431
2432                         if (!(expr is MethodGroupExpr)){
2433                                 report118 (Location, this.expr, "method group");
2434                                 return null;
2435                         }
2436
2437                         //
2438                         // Next, evaluate all the expressions in the argument list
2439                         //
2440                         if (Arguments != null){
2441                                 for (int i = Arguments.Count; i > 0;){
2442                                         --i;
2443                                         Argument a = (Argument) Arguments [i];
2444
2445                                         if (!a.Resolve (ec))
2446                                                 return null;
2447                                 }
2448                         }
2449
2450                         method = OverloadResolve (ec, (MethodGroupExpr) this.expr, Arguments,
2451                                                   Location);
2452
2453                         if (method == null){
2454                                 Error (-6, Location,
2455                                        "Could not find any applicable function for this argument list");
2456                                 return null;
2457                         }
2458
2459                         if (method is MethodInfo)
2460                                 type = ((MethodInfo)method).ReturnType;
2461
2462                         eclass = ExprClass.Value;
2463                         return this;
2464                 }
2465
2466                 public static void EmitArguments (EmitContext ec, ArrayList Arguments)
2467                 {
2468                         int top;
2469
2470                         if (Arguments != null)
2471                                 top = Arguments.Count;
2472                         else
2473                                 top = 0;
2474
2475                         for (int i = 0; i < top; i++){
2476                                 Argument a = (Argument) Arguments [i];
2477
2478                                 a.Emit (ec);
2479                         }
2480                 }
2481
2482                 public static void EmitCall (EmitContext ec,
2483                                              bool is_static, Expression instance_expr,
2484                                              MethodBase method, ArrayList Arguments)
2485                 {
2486                         ILGenerator ig = ec.ig;
2487                         bool struct_call = false;
2488                                 
2489                         if (!is_static){
2490                                 //
2491                                 // If this is ourselves, push "this"
2492                                 //
2493                                 if (instance_expr == null){
2494                                         ig.Emit (OpCodes.Ldarg_0);
2495                                 } else {
2496                                         //
2497                                         // Push the instance expression
2498                                         //
2499                                         if (instance_expr.Type.IsSubclassOf (TypeManager.value_type)){
2500
2501                                                 struct_call = true;
2502
2503                                                 //
2504                                                 // If the expression implements IMemoryLocation, then
2505                                                 // we can optimize and use AddressOf on the
2506                                                 // return.
2507                                                 //
2508                                                 // If not we have to use some temporary storage for
2509                                                 // it.
2510                                                 if (instance_expr is IMemoryLocation)
2511                                                         ((IMemoryLocation) instance_expr).AddressOf (ec);
2512                                                 else {
2513                                                         Type t = instance_expr.Type;
2514                                                         
2515                                                         instance_expr.Emit (ec);
2516                                                         LocalBuilder temp = ec.GetTemporaryStorage (t);
2517                                                         ig.Emit (OpCodes.Stloc, temp);
2518                                                         ig.Emit (OpCodes.Ldloca, temp);
2519                                                 }
2520                                         } else 
2521                                                 instance_expr.Emit (ec);
2522                                 }
2523                         }
2524
2525                         if (Arguments != null)
2526                                 EmitArguments (ec, Arguments);
2527
2528                         if (is_static || struct_call){
2529                                 if (method is MethodInfo)
2530                                         ig.Emit (OpCodes.Call, (MethodInfo) method);
2531                                 else
2532                                         ig.Emit (OpCodes.Call, (ConstructorInfo) method);
2533                         } else {
2534                                 if (method is MethodInfo)
2535                                         ig.Emit (OpCodes.Callvirt, (MethodInfo) method);
2536                                 else
2537                                         ig.Emit (OpCodes.Callvirt, (ConstructorInfo) method);
2538                         }
2539                 }
2540                 
2541                 public override void Emit (EmitContext ec)
2542                 {
2543                         MethodGroupExpr mg = (MethodGroupExpr) this.expr;
2544                         EmitCall (ec, method.IsStatic, mg.InstanceExpression, method, Arguments);
2545                 }
2546                 
2547                 public override void EmitStatement (EmitContext ec)
2548                 {
2549                         Emit (ec);
2550
2551                         // 
2552                         // Pop the return value if there is one
2553                         //
2554                         if (method is MethodInfo){
2555                                 if (((MethodInfo)method).ReturnType != TypeManager.void_type)
2556                                         ec.ig.Emit (OpCodes.Pop);
2557                         }
2558                 }
2559         }
2560
2561         public class New : ExpressionStatement {
2562                 public readonly ArrayList Arguments;
2563                 public readonly string    RequestedType;
2564
2565                 Location Location;
2566                 MethodBase method = null;
2567
2568                 //
2569                 // If set, the new expression is for a value_target, and
2570                 // we will not leave anything on the stack.
2571                 //
2572                 Expression value_target;
2573                 
2574                 public New (string requested_type, ArrayList arguments, Location loc)
2575                 {
2576                         RequestedType = requested_type;
2577                         Arguments = arguments;
2578                         Location = loc;
2579                 }
2580
2581                 public Expression ValueTypeVariable {
2582                         get {
2583                                 return value_target;
2584                         }
2585
2586                         set {
2587                                 value_target = value;
2588                         }
2589                 }
2590
2591                 public override Expression DoResolve (EmitContext ec)
2592                 {
2593                         type = ec.TypeContainer.LookupType (RequestedType, false);
2594                         
2595                         if (type == null)
2596                                 return null;
2597                         
2598                         bool IsDelegate = TypeManager.IsDelegateType (type);
2599                         
2600                         if (IsDelegate)
2601                                 return (new NewDelegate (type, Arguments, Location)).Resolve (ec);
2602                         
2603                         Expression ml;
2604                         
2605                         ml = MemberLookup (ec, type, ".ctor", false,
2606                                            MemberTypes.Constructor, AllBindingsFlags, Location);
2607                         
2608                         bool is_struct = false;
2609                         is_struct = type.IsSubclassOf (TypeManager.value_type);
2610                         
2611                         if (! (ml is MethodGroupExpr)){
2612                                 if (!is_struct){
2613                                         report118 (Location, ml, "method group");
2614                                         return null;
2615                                 }
2616                         }
2617                         
2618                         if (ml != null) {
2619                                 if (Arguments != null){
2620                                         for (int i = Arguments.Count; i > 0;){
2621                                                 --i;
2622                                                 Argument a = (Argument) Arguments [i];
2623                                                 
2624                                                 if (!a.Resolve (ec))
2625                                                         return null;
2626                                         }
2627                                 }
2628
2629                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml,
2630                                                                      Arguments, Location);
2631                         }
2632                         
2633                         if (method == null && !is_struct) {
2634                                 Error (-6, Location,
2635                                        "New invocation: Can not find a constructor for " +
2636                                        "this argument list");
2637                                 return null;
2638                         }
2639                         
2640                         eclass = ExprClass.Value;
2641                         return this;
2642                 }
2643
2644                 //
2645                 // This DoEmit can be invoked in two contexts:
2646                 //    * As a mechanism that will leave a value on the stack (new object)
2647                 //    * As one that wont (init struct)
2648                 //
2649                 // You can control whether a value is required on the stack by passing
2650                 // need_value_on_stack.  The code *might* leave a value on the stack
2651                 // so it must be popped manually
2652                 //
2653                 // Returns whether a value is left on the stack
2654                 //
2655                 bool DoEmit (EmitContext ec, bool need_value_on_stack)
2656                 {
2657                         if (method == null){
2658                                 IMemoryLocation ml = (IMemoryLocation) value_target;
2659
2660                                 ml.AddressOf (ec);
2661                         } else {
2662                                 Invocation.EmitArguments (ec, Arguments);
2663                                 ec.ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
2664                                 return true;
2665                         }
2666
2667                         //
2668                         // It must be a value type, sanity check
2669                         //
2670                         if (value_target != null){
2671                                 ec.ig.Emit (OpCodes.Initobj, type);
2672
2673                                 if (need_value_on_stack){
2674                                         value_target.Emit (ec);
2675                                         return true;
2676                                 }
2677                                 return false;
2678                         }
2679
2680                         throw new Exception ("No method and no value type");
2681                 }
2682
2683                 public override void Emit (EmitContext ec)
2684                 {
2685                         DoEmit (ec, true);
2686                 }
2687                 
2688                 public override void EmitStatement (EmitContext ec)
2689                 {
2690                         if (DoEmit (ec, false))
2691                                 ec.ig.Emit (OpCodes.Pop);
2692                 }
2693         }
2694
2695         // <summary>
2696         //   Represents an array creation expression.
2697         // </summary>
2698         //
2699         // <remarks>
2700         //   There are two possible scenarios here: one is an array creation
2701         //   expression that specifies the dimensions and optionally the
2702         //   initialization data
2703         // </remarks>
2704         public class ArrayCreation : ExpressionStatement {
2705
2706                 string RequestedType;
2707                 string Rank;
2708                 ArrayList Initializers;
2709                 Location  Location;
2710                 ArrayList Arguments;
2711
2712                 MethodBase method = null;
2713                 Type array_element_type;
2714                 bool IsOneDimensional = false;
2715                 
2716                 bool IsBuiltinType = false;
2717
2718                 public ArrayCreation (string requested_type, ArrayList exprs,
2719                                       string rank, ArrayList initializers, Location l)
2720                 {
2721                         RequestedType = requested_type;
2722                         Rank          = rank;
2723                         Initializers  = initializers;
2724                         Location      = l;
2725
2726                         Arguments = new ArrayList ();
2727
2728                         foreach (Expression e in exprs)
2729                                 Arguments.Add (new Argument (e, Argument.AType.Expression));
2730                         
2731                 }
2732
2733                 public ArrayCreation (string requested_type, string rank, ArrayList initializers, Location l)
2734                 {
2735                         RequestedType = requested_type;
2736                         Rank = rank;
2737                         Initializers = initializers;
2738                         Location = l;
2739                 }
2740
2741                 public static string FormArrayType (string base_type, int idx_count, string rank)
2742                 {
2743                         StringBuilder sb = new StringBuilder (base_type);
2744
2745                         sb.Append (rank);
2746                         
2747                         sb.Append ("[");
2748                         for (int i = 1; i < idx_count; i++)
2749                                 sb.Append (",");
2750                         sb.Append ("]");
2751                         
2752                         return sb.ToString ();
2753                 }
2754
2755                 public static string FormElementType (string base_type, int idx_count, string rank)
2756                 {
2757                         StringBuilder sb = new StringBuilder (base_type);
2758                         
2759                         sb.Append ("[");
2760                         for (int i = 1; i < idx_count; i++)
2761                                 sb.Append (",");
2762                         sb.Append ("]");
2763
2764                         sb.Append (rank);
2765
2766                         string val = sb.ToString ();
2767
2768                         return val.Substring (0, val.LastIndexOf ("["));
2769                 }
2770                 
2771
2772                 public override Expression DoResolve (EmitContext ec)
2773                 {
2774                         int arg_count;
2775                         
2776                         if (Arguments == null)
2777                                 arg_count = 0;
2778                         else
2779                                 arg_count = Arguments.Count;
2780                         
2781                         string array_type = FormArrayType (RequestedType, arg_count, Rank);
2782
2783                         string element_type = FormElementType (RequestedType, arg_count, Rank);
2784
2785                         type = ec.TypeContainer.LookupType (array_type, false);
2786                         
2787                         array_element_type = ec.TypeContainer.LookupType (element_type, false);
2788                         
2789                         if (type == null)
2790                                 return null;
2791                         
2792                         if (arg_count == 1) {
2793                                 IsOneDimensional = true;
2794                                 eclass = ExprClass.Value;
2795                                 return this;
2796                         }
2797
2798                         IsBuiltinType = TypeManager.IsBuiltinType (type);
2799                         
2800                         if (IsBuiltinType) {
2801                                 
2802                                 Expression ml;
2803                                 
2804                                 ml = MemberLookup (ec, type, ".ctor", false, MemberTypes.Constructor,
2805                                                    AllBindingsFlags, Location);
2806                                 
2807                                 if (!(ml is MethodGroupExpr)){
2808                                         report118 (Location, ml, "method group");
2809                                         return null;
2810                                 }
2811                                 
2812                                 if (ml == null) {
2813                                         Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
2814                                                       "this argument list");
2815                                         return null;
2816                                 }
2817                                 
2818                                 if (Arguments != null) {
2819                                         for (int i = arg_count; i > 0;){
2820                                                 --i;
2821                                                 Argument a = (Argument) Arguments [i];
2822                                                 
2823                                                 if (!a.Resolve (ec))
2824                                                         return null;
2825                                         }
2826                                 }
2827                                 
2828                                 method = Invocation.OverloadResolve (ec, (MethodGroupExpr) ml, Arguments, Location);
2829                                 
2830                                 if (method == null) {
2831                                         Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
2832                                                       "this argument list");
2833                                         return null;
2834                                 }
2835                                 
2836                                 eclass = ExprClass.Value;
2837                                 return this;
2838                                 
2839                         } else {
2840
2841                                 ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
2842
2843                                 ArrayList args = new ArrayList ();
2844                                 if (Arguments != null){
2845                                         for (int i = arg_count; i > 0;){
2846                                                 --i;
2847                                                 Argument a = (Argument) Arguments [i];
2848                                                 
2849                                                 if (!a.Resolve (ec))
2850                                                         return null;
2851                                                 
2852                                                 args.Add (a.Type);
2853                                         }
2854                                 }
2855                                 
2856                                 Type [] arg_types = null;
2857                                 
2858                                 if (args.Count > 0)
2859                                         arg_types = new Type [args.Count];
2860                                 
2861                                 args.CopyTo (arg_types, 0);
2862                                 
2863                                 method = mb.GetArrayMethod (type, ".ctor", CallingConventions.HasThis, null,
2864                                                             arg_types);
2865                                 
2866                                 if (method == null) {
2867                                         Report.Error (-6, Location, "New invocation: Can not find a constructor for " +
2868                                                       "this argument list");
2869                                         return null;
2870                                 }
2871                                 
2872                                 eclass = ExprClass.Value;
2873                                 return this;
2874                                 
2875                         }
2876                 }
2877
2878                 public override void Emit (EmitContext ec)
2879                 {
2880                         ILGenerator ig = ec.ig;
2881                         
2882                         if (IsOneDimensional) {
2883                                 Invocation.EmitArguments (ec, Arguments);
2884                                 ig.Emit (OpCodes.Newarr, array_element_type);
2885                                 
2886                         } else {
2887                                 Invocation.EmitArguments (ec, Arguments);
2888
2889                                 if (IsBuiltinType)
2890                                         ig.Emit (OpCodes.Newobj, (ConstructorInfo) method);
2891                                 else
2892                                         ig.Emit (OpCodes.Newobj, (MethodInfo) method);
2893                         }
2894
2895                         if (Initializers != null){
2896                                 FieldBuilder fb;
2897
2898                                 // FIXME: This is just sample data, need to fill with
2899                                 // real values.
2900                                 byte [] a = new byte [4] { 1, 2, 3, 4 };
2901                                 
2902                                 fb = ec.TypeContainer.RootContext.MakeStaticData (a);
2903
2904                                 ig.Emit (OpCodes.Dup);
2905                                 ig.Emit (OpCodes.Ldtoken, fb);
2906                                 ig.Emit (OpCodes.Call, TypeManager.void_initializearray_array_fieldhandle);
2907                         }
2908                 }
2909                 
2910                 public override void EmitStatement (EmitContext ec)
2911                 {
2912                         Emit (ec);
2913                         ec.ig.Emit (OpCodes.Pop);
2914                 }
2915                 
2916         }
2917         
2918         //
2919         // Represents the `this' construct
2920         //
2921         public class This : Expression, IStackStore, IMemoryLocation {
2922                 Location loc;
2923                 
2924                 public This (Location loc)
2925                 {
2926                         this.loc = loc;
2927                 }
2928
2929                 public override Expression DoResolve (EmitContext ec)
2930                 {
2931                         eclass = ExprClass.Variable;
2932                         type = ec.TypeContainer.TypeBuilder;
2933
2934                         if (ec.IsStatic){
2935                                 Report.Error (26, loc,
2936                                               "Keyword this not valid in static code");
2937                                 return null;
2938                         }
2939                         
2940                         return this;
2941                 }
2942
2943                 public Expression DoResolveLValue (EmitContext ec)
2944                 {
2945                         DoResolve (ec);
2946                         
2947                         if (ec.TypeContainer is Class){
2948                                 Report.Error (1604, loc, "Cannot assign to `this'");
2949                                 return null;
2950                         }
2951
2952                         return this;
2953                 }
2954
2955                 public override void Emit (EmitContext ec)
2956                 {
2957                         ec.ig.Emit (OpCodes.Ldarg_0);
2958                 }
2959
2960                 public void Store (EmitContext ec)
2961                 {
2962                         ec.ig.Emit (OpCodes.Starg, 0);
2963                 }
2964
2965                 public void AddressOf (EmitContext ec)
2966                 {
2967                         ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
2968                 }
2969         }
2970
2971         // <summary>
2972         //   Implements the typeof operator
2973         // </summary>
2974         public class TypeOf : Expression {
2975                 public readonly string QueriedType;
2976                 Type typearg;
2977                 
2978                 public TypeOf (string queried_type)
2979                 {
2980                         QueriedType = queried_type;
2981                 }
2982
2983                 public override Expression DoResolve (EmitContext ec)
2984                 {
2985                         typearg = ec.TypeContainer.LookupType (QueriedType, false);
2986
2987                         if (typearg == null)
2988                                 return null;
2989
2990                         type = TypeManager.type_type;
2991                         eclass = ExprClass.Type;
2992                         return this;
2993                 }
2994
2995                 public override void Emit (EmitContext ec)
2996                 {
2997                         ec.ig.Emit (OpCodes.Ldtoken, typearg);
2998                         ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
2999                 }
3000         }
3001
3002         public class SizeOf : Expression {
3003                 public readonly string QueriedType;
3004                 
3005                 public SizeOf (string queried_type)
3006                 {
3007                         this.QueriedType = queried_type;
3008                 }
3009
3010                 public override Expression DoResolve (EmitContext ec)
3011                 {
3012                         // FIXME: Implement;
3013                         throw new Exception ("Unimplemented");
3014                         // return this;
3015                 }
3016
3017                 public override void Emit (EmitContext ec)
3018                 {
3019                         throw new Exception ("Implement me");
3020                 }
3021         }
3022
3023         public class MemberAccess : Expression {
3024                 public readonly string Identifier;
3025                 Expression expr;
3026                 Expression member_lookup;
3027                 Location loc;
3028                 
3029                 public MemberAccess (Expression expr, string id, Location l)
3030                 {
3031                         this.expr = expr;
3032                         Identifier = id;
3033                         loc = l;
3034                 }
3035
3036                 public Expression Expr {
3037                         get {
3038                                 return expr;
3039                         }
3040                 }
3041
3042                 void error176 (Location loc, string name)
3043                 {
3044                         Report.Error (176, loc, "Static member `" +
3045                                       name + "' cannot be accessed " +
3046                                       "with an instance reference, qualify with a " +
3047                                       "type name instead");
3048                 }
3049                 
3050                 public override Expression DoResolve (EmitContext ec)
3051                 {
3052                         //
3053                         // We are the sole users of ResolveWithSimpleName (ie, the only
3054                         // ones that can cope with it
3055                         //
3056                         expr = expr.ResolveWithSimpleName (ec);
3057
3058                         if (expr == null)
3059                                 return null;
3060
3061                         if (expr is SimpleName){
3062                                 SimpleName child_expr = (SimpleName) expr;
3063                                 
3064                                 expr = new SimpleName (child_expr.Name + "." + Identifier, loc);
3065
3066                                 return expr.Resolve (ec);
3067                         }
3068                                         
3069                         member_lookup = MemberLookup (ec, expr.Type, Identifier, false, loc);
3070
3071                         if (member_lookup == null)
3072                                 return null;
3073                         
3074                         //
3075                         // Method Groups
3076                         //
3077                         if (member_lookup is MethodGroupExpr){
3078                                 MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
3079                                 
3080                                 //
3081                                 // Type.MethodGroup
3082                                 //
3083                                 if (expr is TypeExpr){
3084                                         if (!mg.RemoveInstanceMethods ()){
3085                                                 SimpleName.Error120 (loc, mg.Methods [0].Name); 
3086                                                 return null;
3087                                         }
3088
3089                                         return member_lookup;
3090                                 }
3091
3092                                 //
3093                                 // Instance.MethodGroup
3094                                 //
3095                                 if (!mg.RemoveStaticMethods ()){
3096                                         error176 (loc, mg.Methods [0].Name);
3097                                         return null;
3098                                 }
3099                                 
3100                                 mg.InstanceExpression = expr;
3101                                         
3102                                 return member_lookup;
3103                         }
3104
3105                         if (member_lookup is FieldExpr){
3106                                 FieldExpr fe = (FieldExpr) member_lookup;
3107                                 FieldInfo fi = fe.FieldInfo;
3108
3109                                 if (fi.IsLiteral) {
3110                                         Type t = fi.FieldType;
3111                                         object o = fi.GetValue (null);
3112                                         
3113                                         if (t.IsSubclassOf (TypeManager.enum_type)) {
3114                                                 Expression enum_member = MemberLookup (ec, t, "value__", false, loc); 
3115                                                 Type underlying_type = enum_member.Type;
3116                                                 
3117                                                 Expression e = Literalize (o, underlying_type);
3118                                                 e.Resolve (ec);
3119                                         
3120                                                 return new EnumLiteral (e, t);
3121                                         }
3122
3123                                         Expression exp = Literalize (o, t);
3124                                         exp.Resolve (ec);
3125                                         
3126                                         return exp;
3127                                 }
3128                                 
3129                                 if (expr is TypeExpr){
3130                                         if (!fe.FieldInfo.IsStatic){
3131                                                 error176 (loc, fe.FieldInfo.Name);
3132                                                 return null;
3133                                         }
3134                                         return member_lookup;
3135                                 } else {
3136                                         if (fe.FieldInfo.IsStatic){
3137                                                 error176 (loc, fe.FieldInfo.Name);
3138                                                 return null;
3139                                         }
3140                                         fe.InstanceExpression = expr;
3141
3142                                         return fe;
3143                                 }
3144                         }
3145
3146                         if (member_lookup is PropertyExpr){
3147                                 PropertyExpr pe = (PropertyExpr) member_lookup;
3148
3149                                 if (expr is TypeExpr){
3150                                         if (!pe.IsStatic){
3151                                                 SimpleName.Error120 (loc, pe.PropertyInfo.Name);
3152                                                 return null;
3153                                         }
3154                                         return pe;
3155                                 } else {
3156                                         if (pe.IsStatic){
3157                                                 error176 (loc, pe.PropertyInfo.Name);
3158                                                 return null;
3159                                         }
3160                                         pe.InstanceExpression = expr;
3161
3162                                         return pe;
3163                                 }
3164                         }
3165                         
3166                         Console.WriteLine ("Support for [" + member_lookup + "] is not present yet");
3167                         Environment.Exit (0);
3168                         return null;
3169                 }
3170
3171                 public override void Emit (EmitContext ec)
3172                 {
3173                         throw new Exception ("Should not happen I think");
3174                 }
3175
3176         }
3177
3178         public class CheckedExpr : Expression {
3179
3180                 public Expression Expr;
3181
3182                 public CheckedExpr (Expression e)
3183                 {
3184                         Expr = e;
3185                 }
3186
3187                 public override Expression DoResolve (EmitContext ec)
3188                 {
3189                         Expr = Expr.Resolve (ec);
3190
3191                         if (Expr == null)
3192                                 return null;
3193
3194                         eclass = Expr.ExprClass;
3195                         type = Expr.Type;
3196                         return this;
3197                 }
3198
3199                 public override void Emit (EmitContext ec)
3200                 {
3201                         bool last_check = ec.CheckState;
3202                         
3203                         ec.CheckState = true;
3204                         Expr.Emit (ec);
3205                         ec.CheckState = last_check;
3206                 }
3207                 
3208         }
3209
3210         public class UnCheckedExpr : Expression {
3211
3212                 public Expression Expr;
3213
3214                 public UnCheckedExpr (Expression e)
3215                 {
3216                         Expr = e;
3217                 }
3218
3219                 public override Expression DoResolve (EmitContext ec)
3220                 {
3221                         Expr = Expr.Resolve (ec);
3222
3223                         if (Expr == null)
3224                                 return null;
3225
3226                         eclass = Expr.ExprClass;
3227                         type = Expr.Type;
3228                         return this;
3229                 }
3230
3231                 public override void Emit (EmitContext ec)
3232                 {
3233                         bool last_check = ec.CheckState;
3234                         
3235                         ec.CheckState = false;
3236                         Expr.Emit (ec);
3237                         ec.CheckState = last_check;
3238                 }
3239                 
3240         }
3241
3242         public class ElementAccess : Expression {
3243                 public ArrayList  Arguments;
3244                 public Expression Expr;
3245                 public Location   loc;
3246                 
3247                 public ElementAccess (Expression e, ArrayList e_list, Location l)
3248                 {
3249                         Expr = e;
3250
3251                         Arguments = new ArrayList ();
3252                         foreach (Expression tmp in e_list)
3253                                 Arguments.Add (new Argument (tmp, Argument.AType.Expression));
3254                         
3255                         loc  = l;
3256                 }
3257
3258                 bool CommonResolve (EmitContext ec)
3259                 {
3260                         Expr = Expr.Resolve (ec);
3261
3262                         if (Expr == null) 
3263                                 return false;
3264
3265                         if (Arguments == null)
3266                                 return false;
3267
3268                         for (int i = Arguments.Count; i > 0;){
3269                                 --i;
3270                                 Argument a = (Argument) Arguments [i];
3271                                 
3272                                 if (!a.Resolve (ec))
3273                                         return false;
3274                         }
3275
3276                         return true;
3277                 }
3278                                 
3279                 public override Expression DoResolve (EmitContext ec)
3280                 {
3281                         if (!CommonResolve (ec))
3282                                 return null;
3283
3284                         //
3285                         // We perform some simple tests, and then to "split" the emit and store
3286                         // code we create an instance of a different class, and return that.
3287                         //
3288                         // I am experimenting with this pattern.
3289                         //
3290                         if (Expr.Type.IsSubclassOf (TypeManager.array_type))
3291                                 return (new ArrayAccess (this)).Resolve (ec);
3292                         else
3293                                 return (new IndexerAccess (this)).Resolve (ec);
3294                 }
3295
3296                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3297                 {
3298                         if (!CommonResolve (ec))
3299                                 return null;
3300
3301                         if (Expr.Type.IsSubclassOf (TypeManager.array_type))
3302                                 return (new ArrayAccess (this)).ResolveLValue (ec, right_side);
3303                         else
3304                                 return (new IndexerAccess (this)).ResolveLValue (ec, right_side);
3305                 }
3306                 
3307                 public override void Emit (EmitContext ec)
3308                 {
3309                         throw new Exception ("Should never be reached");
3310                 }
3311         }
3312
3313         //
3314         // Implements array access 
3315         //
3316         public class ArrayAccess : Expression, IAssignMethod {
3317                 //
3318                 // Points to our "data" repository
3319                 //
3320                 ElementAccess ea;
3321                 
3322                 public ArrayAccess (ElementAccess ea_data)
3323                 {
3324                         ea = ea_data;
3325                         eclass = ExprClass.Variable;
3326                 }
3327
3328                 public override Expression DoResolve (EmitContext ec)
3329                 {
3330                         if (ea.Expr.ExprClass != ExprClass.Variable) {
3331                                 report118 (ea.loc, ea.Expr, "variable");
3332                                 return null;
3333                         }
3334
3335                         Type t = ea.Expr.Type;
3336
3337                         if (t.GetArrayRank () != ea.Arguments.Count){
3338                                 Report.Error (22, ea.loc,
3339                                               "Incorrect number of indexes for array " +
3340                                               " expected: " + t.GetArrayRank () + " got: " +
3341                                               ea.Arguments.Count);
3342                                 return null;
3343                         }
3344                         type = t.GetElementType ();
3345                         eclass = ExprClass.Variable;
3346
3347                         return this;
3348                 }
3349
3350                 public override void Emit (EmitContext ec)
3351                 {
3352                         int rank = ea.Expr.Type.GetArrayRank ();
3353                         ILGenerator ig = ec.ig;
3354
3355                         ea.Expr.Emit (ec);
3356
3357                         foreach (Argument a in ea.Arguments)
3358                                 a.Expr.Emit (ec);
3359
3360                         if (rank == 1){
3361                                 if (type == TypeManager.byte_type)
3362                                         ig.Emit (OpCodes.Ldelem_I1);
3363                                 else if (type == TypeManager.sbyte_type)
3364                                         ig.Emit (OpCodes.Ldelem_U1);
3365                                 else if (type == TypeManager.short_type)
3366                                         ig.Emit (OpCodes.Ldelem_I2);
3367                                 else if (type == TypeManager.ushort_type)
3368                                         ig.Emit (OpCodes.Ldelem_U2);
3369                                 else if (type == TypeManager.int32_type)
3370                                         ig.Emit (OpCodes.Ldelem_I4);
3371                                 else if (type == TypeManager.uint32_type)
3372                                         ig.Emit (OpCodes.Ldelem_U4);
3373                                 else if (type == TypeManager.uint64_type)
3374                                         ig.Emit (OpCodes.Ldelem_I8);
3375                                 else if (type == TypeManager.int64_type)
3376                                         ig.Emit (OpCodes.Ldelem_I8);
3377                                 else if (type == TypeManager.float_type)
3378                                         ig.Emit (OpCodes.Ldelem_R4);
3379                                 else if (type == TypeManager.double_type)
3380                                         ig.Emit (OpCodes.Ldelem_R8);
3381                                 else if (type == TypeManager.intptr_type)
3382                                         ig.Emit (OpCodes.Ldelem_I);
3383                                 else
3384                                         ig.Emit (OpCodes.Ldelem_Ref);
3385                         } else {
3386                                 ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
3387                                 Type [] args = new Type [ea.Arguments.Count];
3388                                 MethodInfo get;
3389                                 
3390                                 int i = 0;
3391                                 
3392                                 foreach (Argument a in ea.Arguments)
3393                                         args [i++] = a.Type;
3394                                 
3395                                 get = mb.GetArrayMethod (
3396                                         ea.Expr.Type, "Get",
3397                                         CallingConventions.HasThis |
3398                                         CallingConventions.Standard,
3399                                         type, args);
3400                                 
3401                                 ig.Emit (OpCodes.Call, get);
3402                         }
3403                 }
3404
3405                 public void EmitAssign (EmitContext ec, Expression source)
3406                 {
3407                         int rank = ea.Expr.Type.GetArrayRank ();
3408                         ILGenerator ig = ec.ig;
3409
3410                         ea.Expr.Emit (ec);
3411
3412                         foreach (Argument a in ea.Arguments)
3413                                 a.Expr.Emit (ec);
3414
3415                         source.Emit (ec);
3416
3417                         Type t = source.Type;
3418                         if (rank == 1){
3419                                 if (t == TypeManager.byte_type || t == TypeManager.sbyte_type)
3420                                         ig.Emit (OpCodes.Stelem_I1);
3421                                 else if (t == TypeManager.short_type || t == TypeManager.ushort_type)
3422                                         ig.Emit (OpCodes.Stelem_I2);
3423                                 else if (t == TypeManager.int32_type || t == TypeManager.uint32_type)
3424                                         ig.Emit (OpCodes.Stelem_I4);
3425                                 else if (t == TypeManager.int64_type || t == TypeManager.uint64_type)
3426                                         ig.Emit (OpCodes.Stelem_I8);
3427                                 else if (t == TypeManager.float_type)
3428                                         ig.Emit (OpCodes.Stelem_R4);
3429                                 else if (t == TypeManager.double_type)
3430                                         ig.Emit (OpCodes.Stelem_R8);
3431                                 else if (t == TypeManager.intptr_type)
3432                                         ig.Emit (OpCodes.Stelem_I);
3433                                 else
3434                                         ig.Emit (OpCodes.Stelem_Ref);
3435                         } else {
3436                                 ModuleBuilder mb = ec.TypeContainer.RootContext.ModuleBuilder;
3437                                 Type [] args = new Type [ea.Arguments.Count + 1];
3438                                 MethodInfo set;
3439                                 
3440                                 int i = 0;
3441                                 
3442                                 foreach (Argument a in ea.Arguments)
3443                                         args [i++] = a.Type;
3444
3445                                 args [i] = type;
3446                                 
3447                                 set = mb.GetArrayMethod (
3448                                         ea.Expr.Type, "Set",
3449                                         CallingConventions.HasThis |
3450                                         CallingConventions.Standard,
3451                                         TypeManager.void_type, args);
3452                                 
3453                                 ig.Emit (OpCodes.Call, set);
3454                         }
3455                 }
3456         }
3457         class Indexers {
3458                 public ArrayList getters, setters;
3459                 static Hashtable map;
3460
3461                 static Indexers ()
3462                 {
3463                         map = new Hashtable ();
3464                 }
3465
3466                 Indexers (MemberInfo [] mi)
3467                 {
3468                         foreach (PropertyInfo property in mi){
3469                                 MethodInfo get, set;
3470                                 
3471                                 get = property.GetGetMethod (true);
3472                                 if (get != null){
3473                                         if (getters == null)
3474                                                 getters = new ArrayList ();
3475
3476                                         getters.Add (get);
3477                                 }
3478                                 
3479                                 set = property.GetSetMethod (true);
3480                                 if (set != null){
3481                                         if (setters == null)
3482                                                 setters = new ArrayList ();
3483                                         setters.Add (set);
3484                                 }
3485                         }
3486                 }
3487                 
3488                 static public Indexers GetIndexersForType (Type t, TypeManager tm, Location loc) 
3489                 {
3490                         Indexers ix = (Indexers) map [t];
3491                         string p_name = TypeManager.IndexerPropertyName (t);
3492                         
3493                         if (ix != null)
3494                                 return ix;
3495
3496                         MemberInfo [] mi = tm.FindMembers (
3497                                 t, MemberTypes.Property,
3498                                 BindingFlags.Public | BindingFlags.Instance,
3499                                 Type.FilterName, p_name);
3500
3501                         if (mi == null || mi.Length == 0){
3502                                 Report.Error (21, loc,
3503                                               "Type `" + TypeManager.CSharpName (t) + "' does not have " +
3504                                               "any indexers defined");
3505                                 return null;
3506                         }
3507                         
3508                         ix = new Indexers (mi);
3509                         map [t] = ix;
3510
3511                         return ix;
3512                 }
3513         }
3514         
3515         public class IndexerAccess : Expression, IAssignMethod {
3516                 //
3517                 // Points to our "data" repository
3518                 //
3519                 ElementAccess ea;
3520                 MethodInfo get, set;
3521                 Indexers ilist;
3522                 ArrayList set_arguments;
3523                 
3524                 public IndexerAccess (ElementAccess ea_data)
3525                 {
3526                         ea = ea_data;
3527                         eclass = ExprClass.Value;
3528                 }
3529
3530                 public bool VerifyAssignable (Expression source)
3531                 {
3532                         throw new Exception ("Implement me!");
3533                 }
3534
3535                 public override Expression DoResolve (EmitContext ec)
3536                 {
3537                         Type indexer_type = ea.Expr.Type;
3538                         
3539                         //
3540                         // Step 1: Query for all `Item' *properties*.  Notice
3541                         // that the actual methods are pointed from here.
3542                         //
3543                         // This is a group of properties, piles of them.  
3544
3545                         if (ilist == null)
3546                                 ilist = Indexers.GetIndexersForType (
3547                                         indexer_type, ec.TypeContainer.RootContext.TypeManager, ea.loc);
3548                         
3549                         if (ilist != null && ilist.getters != null && ilist.getters.Count > 0)
3550                                 get = (MethodInfo) Invocation.OverloadResolve (
3551                                         ec, new MethodGroupExpr (ilist.getters), ea.Arguments, ea.loc);
3552
3553                         if (get == null){
3554                                 Report.Error (154, ea.loc,
3555                                               "indexer can not be used in this context, because " +
3556                                               "it lacks a `get' accessor");
3557                                         return null;
3558                         }
3559
3560                         type = get.ReturnType;
3561                         eclass = ExprClass.Value;
3562                         return this;
3563                 }
3564
3565                 public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
3566                 {
3567                         Type indexer_type = ea.Expr.Type;
3568                         Type right_type = right_side.Type;
3569
3570                         if (ilist == null)
3571                                 ilist = Indexers.GetIndexersForType (
3572                                         indexer_type, ec.TypeContainer.RootContext.TypeManager, ea.loc);
3573
3574                         if (ilist != null && ilist.setters != null && ilist.setters.Count > 0){
3575                                 set_arguments = (ArrayList) ea.Arguments.Clone ();
3576                                 set_arguments.Add (new Argument (right_side, Argument.AType.Expression));
3577
3578                                 set = (MethodInfo) Invocation.OverloadResolve (
3579                                         ec, new MethodGroupExpr (ilist.setters), set_arguments, ea.loc);
3580                         }
3581                         
3582                         if (set == null){
3583                                 Report.Error (200, ea.loc,
3584                                               "indexer X.this [" + TypeManager.CSharpName (right_type) +
3585                                               "] lacks a `set' accessor");
3586                                         return null;
3587                         }
3588
3589                         type = TypeManager.void_type;
3590                         eclass = ExprClass.IndexerAccess;
3591                         return this;
3592                 }
3593                 
3594                 public override void Emit (EmitContext ec)
3595                 {
3596                         Invocation.EmitCall (ec, false, ea.Expr, get, ea.Arguments);
3597                 }
3598
3599                 //
3600                 // source is ignored, because we already have a copy of it from the
3601                 // LValue resolution and we have already constructed a pre-cached
3602                 // version of the arguments (ea.set_arguments);
3603                 //
3604                 public void EmitAssign (EmitContext ec, Expression source)
3605                 {
3606                         Invocation.EmitCall (ec, false, ea.Expr, set, set_arguments);
3607                 }
3608         }
3609         
3610         public class BaseAccess : Expression {
3611
3612                 public enum BaseAccessType {
3613                         Member,
3614                         Indexer
3615                 };
3616                 
3617                 public readonly BaseAccessType BAType;
3618                 public readonly string         Member;
3619                 public readonly ArrayList      Arguments;
3620
3621                 public BaseAccess (BaseAccessType t, string member, ArrayList args)
3622                 {
3623                         BAType = t;
3624                         Member = member;
3625                         Arguments = args;
3626                         
3627                 }
3628
3629                 public override Expression DoResolve (EmitContext ec)
3630                 {
3631                         // FIXME: Implement;
3632                         throw new Exception ("Unimplemented");
3633                         // return this;
3634                 }
3635
3636                 public override void Emit (EmitContext ec)
3637                 {
3638                         throw new Exception ("Unimplemented");
3639                 }
3640         }
3641
3642         // <summary>
3643         //   This class exists solely to pass the Type around and to be a dummy
3644         //   that can be passed to the conversion functions (this is used by
3645         //   foreach implementation to typecast the object return value from
3646         //   get_Current into the proper type.  All code has been generated and
3647         //   we only care about the side effect conversions to be performed
3648         // </summary>
3649         
3650         public class EmptyExpression : Expression {
3651                 public EmptyExpression ()
3652                 {
3653                         type = TypeManager.object_type;
3654                         eclass = ExprClass.Value;
3655                 }
3656
3657                 public override Expression DoResolve (EmitContext ec)
3658                 {
3659                         return this;
3660                 }
3661
3662                 public override void Emit (EmitContext ec)
3663                 {
3664                         // nothing, as we only exist to not do anything.
3665                 }
3666         }
3667
3668         public class UserCast : Expression {
3669                 MethodBase method;
3670                 Expression source;
3671                 
3672                 public UserCast (MethodInfo method, Expression source)
3673                 {
3674                         this.method = method;
3675                         this.source = source;
3676                         type = method.ReturnType;
3677                         eclass = ExprClass.Value;
3678                 }
3679
3680                 public override Expression DoResolve (EmitContext ec)
3681                 {
3682                         //
3683                         // We are born fully resolved
3684                         //
3685                         return this;
3686                 }
3687
3688                 public override void Emit (EmitContext ec)
3689                 {
3690                         ILGenerator ig = ec.ig;
3691
3692                         source.Emit (ec);
3693                         
3694                         if (method is MethodInfo)
3695                                 ig.Emit (OpCodes.Call, (MethodInfo) method);
3696                         else
3697                                 ig.Emit (OpCodes.Call, (ConstructorInfo) method);
3698
3699                 }
3700
3701         }
3702 }