Revert Ravi's patch, it was completely broken
[mono.git] / mcs / mcs / expression.cs
index 12b271ae8fa3093ab7f2ab0deea46b3c8aee30dd..6aad796de48e0dcbe04c3c404fde260aa84eec8b 100755 (executable)
@@ -69,6 +69,27 @@ namespace CIR {
                        }
                }
 
+               // <summary>
+               //   Utility wrapper routine for Error, just to beautify the code
+               // </summary>
+               static protected void Error (TypeContainer tc, int error, string s)
+               {
+                       tc.RootContext.Report.Error (error, s);
+               }
+
+               static protected void Error (TypeContainer tc, int error, Location l, string s)
+               {
+                       tc.RootContext.Report.Error (error, l, s);
+               }
+               
+               // <summary>
+               //   Utility wrapper routine for Warning, just to beautify the code
+               // </summary>
+               static protected void Warning (TypeContainer tc, int warning, string s)
+               {
+                       tc.RootContext.Report.Warning (warning, s);
+               }
+
                // <summary>
                //   Performs semantic analysis on the Expression
                // </summary>
@@ -167,13 +188,14 @@ namespace CIR {
                // This is so we can catch correctly attempts to invoke instance methods
                // from a static body (scan for error 120 in ResolveSimpleName).
                //
-               public static Expression MemberLookup (RootContext rc, Type t, string name,
-                                                         bool same_type, MemberTypes mt, BindingFlags bf)
+               public static Expression MemberLookup (TypeContainer tc, Type t, string name,
+                                                      bool same_type, MemberTypes mt, BindingFlags bf)
                {
                        if (same_type)
                                bf |= BindingFlags.NonPublic;
 
-                       MemberInfo [] mi = rc.TypeManager.FindMembers (t, mt, bf, Type.FilterName, name);
+                       MemberInfo [] mi = tc.RootContext.TypeManager.FindMembers (
+                               t, mt, bf, Type.FilterName, name);
 
                        if (mi == null)
                                return null;
@@ -183,8 +205,10 @@ namespace CIR {
                        
                        for (int i = 0; i < mi.Length; i++)
                                if (!(mi [i] is MethodBase)){
-                                       rc.Report.Error (-5, "Do not know how to reproduce this case: " + 
-                                                        "Methods and non-Method with the same name, report this please");
+                                       Error (tc,
+                                              -5, "Do not know how to reproduce this case: " + 
+                                              "Methods and non-Method with the same name, " +
+                                              "report this please");
 
                                        for (i = 0; i < mi.Length; i++){
                                                Type tt = mi [i].GetType ();
@@ -213,49 +237,46 @@ namespace CIR {
                        BindingFlags.Static |
                        BindingFlags.Instance;
 
-               public static Expression MemberLookup (RootContext rc, Type t, string name,
+               public static Expression MemberLookup (TypeContainer tc, Type t, string name,
                                                       bool same_type)
                {
-                       return MemberLookup (rc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
+                       return MemberLookup (tc, t, name, same_type, AllMemberTypes, AllBindingsFlags);
                }
-               
-               // <summary>
-               //   Resolves the E in `E.I' side for a member_access
-               //
-               //   This is suboptimal and should be merged with ResolveMemberAccess
-               // </summary>
-               static Expression ResolvePrimary (TypeContainer tc, string name)
-               {
-                       int dot_pos = name.LastIndexOf (".");
-
-                       if (tc.RootContext.IsNamespace (name))
-                               return new NamespaceExpr (name);
-
-                       if (dot_pos != -1){
-                       } else {
-                               Type t = tc.LookupType (name, false);
-
-                               if (t != null)
-                                       return new TypeExpr (t);
-                       }
 
-                       return null;
-               }
-                       
+               //
+               // I am in general unhappy with this implementation.
+               //
+               // I need to revise this.
+               //
                static public Expression ResolveMemberAccess (TypeContainer tc, string name)
                {
-                       Expression left_e;
+                       Expression left_e = null;
                        int dot_pos = name.LastIndexOf (".");
                        string left = name.Substring (0, dot_pos);
                        string right = name.Substring (dot_pos + 1);
+                       Type t;
 
-                       left_e = ResolvePrimary (tc, left);
-                       if (left_e == null)
+                       if ((t = tc.LookupType (left, false)) != null)
+                               left_e = new TypeExpr (t);
+                       else {
+                               //
+                               // FIXME: IMplement:
+                               
+                               // Handle here:
+                               //    T.P  Static property access (P) on Type T.
+                               //    e.P  instance property access on instance e for P.
+                               //    p
+                               //
+                       }
+
+                       if (left_e == null){
+                               Error (tc, 246, "Can not find type or namespace `"+left+"'");
                                return null;
+                       }
 
                        switch (left_e.ExprClass){
                        case ExprClass.Type:
-                               return  MemberLookup (tc.RootContext,
+                               return  MemberLookup (tc,
                                                      left_e.Type, right,
                                                      left_e.Type == tc.TypeBuilder);
                                
@@ -268,10 +289,8 @@ namespace CIR {
                        case ExprClass.EventAccess:
                        case ExprClass.MethodGroup:
                        case ExprClass.Invalid:
-                               tc.RootContext.Report.Error (-1000,
-                                                            "Internal compiler error, should have " +
-                                                            "got these handled before");
-                               break;
+                               throw new Exception ("Should have got the " + left_e.ExprClass +
+                                                    " handled before");
                        }
                        
                        return null;
@@ -280,12 +299,12 @@ namespace CIR {
                static public Expression ImplicitReferenceConversion (Expression expr, Type target_type)
                {
                        Type expr_type = expr.Type;
-                       
+
                        if (target_type == TypeManager.object_type) {
                                if (expr_type.IsClass)
                                        return new EmptyCast (expr, target_type);
                                if (expr_type.IsValueType)
-                                       return new BoxedCast (expr, target_type);
+                                       return new BoxedCast (expr);
                        } else if (expr_type.IsSubclassOf (target_type))
                                return new EmptyCast (expr, target_type);
                        else 
@@ -319,31 +338,36 @@ namespace CIR {
 
                        return ne.Resolve (tc);
                }
-                                                   
+
+               static int level = 0;
+
+               static Hashtable conversion_cache;
                // <summary>
                //   Converts implicitly the resolved expression `expr' into the
                //   `target_type'.  It returns a new expression that can be used
                //   in a context that expects a `target_type'. 
                // </summary>
-               static public Expression ConvertImplicit (TypeContainer tc, Expression expr, Type target_type)
+               static public Expression ConvertImplicit (TypeContainer tc, Expression expr,
+                                                         Type target_type)
                {
                        Type expr_type = expr.Type;
 
+                       Console.WriteLine ("ConvertImplicit " + expr_type + " => " + target_type);
+
                        if (expr_type == target_type)
                                return expr;
                        
-                       //
-                       // Step 1: Perform implicit conversions as found on expr.Type
-                       //
+                       if (level != 0) {
+                               if (conversion_cache == null)
+                                       conversion_cache = new Hashtable ();
+                               
+                               Expression conv = (Expression) conversion_cache [expr_type + "=>" + target_type];
 
-                       if (UserImplicitCast.CanConvert (tc, expr, target_type) == true) {
-                               Expression imp = new UserImplicitCast (expr, target_type);
-                               imp.Resolve (tc);
-                               return imp;
+                               return conv;
                        }
                        
                        //
-                       // Step 2: Built-in conversions.
+                       // Step 1: Built-in conversions.
                        //
                        if (expr_type == TypeManager.sbyte_type){
                                //
@@ -473,11 +497,27 @@ namespace CIR {
                                        return new OpcodeCast (expr, target_type, OpCodes.Conv_R8);
                                if (target_type == TypeManager.decimal_type)
                                        return InternalTypeConstructor (tc, expr, target_type);
-                       } else
-                               return ImplicitReferenceConversion (expr, target_type);
+                       } 
 
+                       Expression e;
                        
+                       e = ImplicitReferenceConversion (expr, target_type);
+                       if (e != null){
+                               return e;
+                       }
+
+                       level++;
+                       e = UserImplicitCast.CanConvert (tc, expr, target_type);
+                       level--;
+
+                       if (e != null) {
 
+                               if (conversion_cache == null)
+                                       conversion_cache = new Hashtable ();
+                               
+                               conversion_cache.Add (expr_type.ToString () + "=>" + target_type.ToString (), e);
+                               return e;
+                       }
                        //
                        //  Could not find an implicit cast.
                        //
@@ -560,7 +600,7 @@ namespace CIR {
                                TypeManager.CSharpName (target.Type) + "' to `" +
                                TypeManager.CSharpName (type) + "'";
 
-                       tc.RootContext.Report.Error (29, l, msg);
+                       Error (tc, 29, l, msg);
 
                        return null;
                }
@@ -788,11 +828,6 @@ namespace CIR {
                        return expr;
                }
 
-               void report (TypeContainer tc, int error, string s)
-               {
-                       tc.RootContext.Report.Error (error, s);
-               }
-
                static string ExprClassName (ExprClass c)
                {
                        switch (c){
@@ -825,8 +860,8 @@ namespace CIR {
                // </summary>
                protected void report118 (TypeContainer tc, Expression expr, string expected)
                {
-                       report (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
-                               "' where an " + expected + " was expected");
+                       Error (tc, 118, "Expression denotes a '" + ExprClassName (expr.ExprClass) +
+                              "' where an " + expected + " was expected");
                }
        }
 
@@ -894,8 +929,8 @@ namespace CIR {
        // </summary>
        public class BoxedCast : EmptyCast {
 
-               public BoxedCast (Expression expr, Type target_type)
-                       : base (expr, target_type)
+               public BoxedCast (Expression expr)
+                       : base (expr, TypeManager.object_type)
                {
                }
 
@@ -1088,7 +1123,7 @@ namespace CIR {
                        else
                                op_name = "op_" + oper;
 
-                       mg = MemberLookup (tc.RootContext, expr_type, op_name, false);
+                       mg = MemberLookup (tc, expr_type, op_name, false);
                        
                        if (mg != null) {
                                Arguments = new ArrayList ();
@@ -1262,9 +1297,16 @@ namespace CIR {
                                }
                        }
 
-                       tc.RootContext.Report.Error (187, "No such operator '" + OperName () +
-                                                    "' defined for type '" +
-                                                    TypeManager.CSharpName (expr_type) + "'");
+                       if (oper == Operator.AddressOf){
+                               if (expr.ExprClass != ExprClass.Variable){
+                                       Error (tc, 211, "Cannot take the address of non-variables");
+                                       return null;
+                               }
+                               type = Type.GetType (expr.Type.ToString () + "*");
+                       }
+                       
+                       Error (tc, 187, "No such operator '" + OperName () + "' defined for type '" +
+                              TypeManager.CSharpName (expr_type) + "'");
                        return null;
 
                }
@@ -1313,7 +1355,7 @@ namespace CIR {
                                //
                                if (oper == Operator.PreDecrement || oper == Operator.PreIncrement ||
                                    oper == Operator.PostDecrement || oper == Operator.PostIncrement){
-                                       ((LValue) expr).Store (ig);
+                                       ((LValue) expr).Store (ec);
                                }
                                return;
                        }
@@ -1339,7 +1381,8 @@ namespace CIR {
                                break;
                                
                        case Operator.AddressOf:
-                               throw new Exception ("Not implemented yet");
+                               ((LValue)expr).AddressOf (ec);
+                               break;
                                
                        case Operator.Indirection:
                                throw new Exception ("Not implemented yet");
@@ -1358,7 +1401,7 @@ namespace CIR {
                                        else
                                                ig.Emit (OpCodes.Add);
                                        ig.Emit (OpCodes.Dup);
-                                       ((LValue) expr).Store (ig);
+                                       ((LValue) expr).Store (ec);
                                } else {
                                        throw new Exception ("Handle Indexers and Properties here");
                                }
@@ -1378,7 +1421,7 @@ namespace CIR {
                                                ig.Emit (OpCodes.Sub);
                                        else
                                                ig.Emit (OpCodes.Add);
-                                       ((LValue) expr).Store (ig);
+                                       ((LValue) expr).Store (ec);
                                } else {
                                        throw new Exception ("Handle Indexers and Properties here");
                                }
@@ -1486,6 +1529,10 @@ namespace CIR {
                
                public override Expression Resolve (TypeContainer tc)
                {
+                       expr = expr.Resolve (tc);
+                       if (expr == null)
+                               return null;
+                       
                        type = tc.LookupType (target_type, false);
                        eclass = ExprClass.Value;
                        
@@ -1664,11 +1711,11 @@ namespace CIR {
                                    (other == TypeManager.int64_type)){
                                        string oper = OperName ();
                                        
-                                       tc.RootContext.Report.Error (34, "Operator `" + OperName ()
-                                                                    + "' is ambiguous on operands of type `"
-                                                                    + TypeManager.CSharpName (l) + "' "
-                                                                    + "and `" + TypeManager.CSharpName (r)
-                                                                    + "'");
+                                       Error (tc, 34, "Operator `" + OperName ()
+                                              + "' is ambiguous on operands of type `"
+                                              + TypeManager.CSharpName (l) + "' "
+                                              + "and `" + TypeManager.CSharpName (r)
+                                              + "'");
                                }
                                type = TypeManager.uint64_type;
                        } else if (l == TypeManager.int64_type || r == TypeManager.int64_type){
@@ -1726,11 +1773,10 @@ namespace CIR {
 
                void error19 (TypeContainer tc)
                {
-                       tc.RootContext.Report.Error (
-                               19,
-                               "Operator " + OperName () + " cannot be applied to operands of type `" +
-                               TypeManager.CSharpName (left.Type) + "' and `" +
-                               TypeManager.CSharpName (right.Type) + "'");
+                       Error (tc, 19,
+                              "Operator " + OperName () + " cannot be applied to operands of type `" +
+                              TypeManager.CSharpName (left.Type) + "' and `" +
+                              TypeManager.CSharpName (right.Type) + "'");
                                                     
                }
                
@@ -1771,9 +1817,9 @@ namespace CIR {
                        
                        string op = "op_" + oper;
 
-                       left_expr = MemberLookup (tc.RootContext, l, op, false);
+                       left_expr = MemberLookup (tc, l, op, false);
 
-                       right_expr = MemberLookup (tc.RootContext, r, op, false);
+                       right_expr = MemberLookup (tc, r, op, false);
 
                        MethodGroupExpr union = Invocation.MakeUnionSet (left_expr, right_expr);
 
@@ -1804,12 +1850,45 @@ namespace CIR {
 
                                if (l != TypeManager.bool_type || r != TypeManager.bool_type)
                                        error19 (tc);
-                       } else
+                       } else if (oper == Operator.Addition){
+                               //
+                               // If any of the arguments is a string, cast to string
+                               //
+                               if (l == TypeManager.string_type){
+                                       if (r == TypeManager.string_type){
+                                               // string + string
+                                               method = TypeManager.string_concat_string_string;
+                                       } else {
+                                               // string + object
+                                               method = TypeManager.string_concat_object_object;
+                                               right = ConvertImplicit (tc, right, TypeManager.object_type);
+                                       }
+                                       type = TypeManager.string_type;
+
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+                               } else if (r == TypeManager.string_type){
+                                       // object + string
+                                       method = TypeManager.string_concat_object_object;
+                                       Arguments = new ArrayList ();
+                                       Arguments.Add (new Argument (left, Argument.AType.Expression));
+                                       Arguments.Add (new Argument (right, Argument.AType.Expression));
+
+                                       left = ConvertImplicit (tc, left, TypeManager.object_type);
+                                       type = TypeManager.string_type;
+                               }
+
+                               //
+                               // FIXME: is Delegate operator + (D x, D y) handled?
+                               //
+                       } else                  
                                DoNumericPromotions (tc, l, r);
 
                        if (left == null || right == null)
                                return null;
 
+
                        if (oper == Operator.BitwiseAnd ||
                            oper == Operator.BitwiseOr ||
                            oper == Operator.ExclusiveOr){
@@ -2073,12 +2152,14 @@ namespace CIR {
 
        public class Conditional : Expression {
                Expression expr, trueExpr, falseExpr;
+               Location l;
                
-               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr)
+               public Conditional (Expression expr, Expression trueExpr, Expression falseExpr, Location l)
                {
                        this.expr = expr;
                        this.trueExpr = trueExpr;
                        this.falseExpr = falseExpr;
+                       this.l = l;
                }
 
                public Expression Expr {
@@ -2101,13 +2182,60 @@ namespace CIR {
 
                public override Expression Resolve (TypeContainer tc)
                {
-                       // FIXME: Implement;
-                       throw new Exception ("Unimplemented");
-                       // return this;
+                       expr = expr.Resolve (tc);
+
+                       if (expr.Type != TypeManager.bool_type)
+                               expr = Expression.ConvertImplicitRequired (
+                                       tc, expr, TypeManager.bool_type, l);
+                       
+                       trueExpr = trueExpr.Resolve (tc);
+                       falseExpr = falseExpr.Resolve (tc);
+
+                       if (expr == null || trueExpr == null || falseExpr == null)
+                               return null;
+                       
+                       if (trueExpr.Type == falseExpr.Type)
+                               type = trueExpr.Type;
+                       else {
+                               Expression conv;
+
+                               //
+                               // First, if an implicit conversion exists from trueExpr
+                               // to falseExpr, then the result type is of type falseExpr.Type
+                               //
+                               conv = ConvertImplicit (tc, trueExpr, falseExpr.Type);
+                               if (conv != null){
+                                       type = falseExpr.Type;
+                                       trueExpr = conv;
+                               } else if ((conv = ConvertImplicit (tc, falseExpr, trueExpr.Type)) != null){
+                                       type = trueExpr.Type;
+                                       falseExpr = conv;
+                               } else {
+                                       Error (tc, 173, l, "The type of the conditional expression can " +
+                                              "not be computed because there is no implicit conversion" +
+                                              " from `" + TypeManager.CSharpName (trueExpr.Type) + "'" +
+                                              " and `" + TypeManager.CSharpName (falseExpr.Type) + "'");
+                                       return null;
+                               }
+                       }
+
+                       eclass = ExprClass.Value;
+                       return this;
                }
 
                public override void Emit (EmitContext ec)
                {
+                       ILGenerator ig = ec.ig;
+                       Label false_target = ig.DefineLabel ();
+                       Label end_target = ig.DefineLabel ();
+
+                       expr.Emit (ec);
+                       ig.Emit (OpCodes.Brfalse, false_target);
+                       trueExpr.Emit (ec);
+                       ig.Emit (OpCodes.Br, end_target);
+                       ig.MarkLabel (false_target);
+                       falseExpr.Emit (ec);
+                       ig.MarkLabel (end_target);
                }
        }
 
@@ -2167,7 +2295,7 @@ namespace CIR {
                        Expression e;
                        Report r = tc.RootContext.Report;
 
-                       e = MemberLookup (tc.RootContext, tc.TypeBuilder, Name, true);
+                       e = MemberLookup (tc, tc.TypeBuilder, Name, true);
                        if (e != null){
                                if (e is TypeExpr)
                                        return e;
@@ -2189,8 +2317,8 @@ namespace CIR {
                        //
                        // FIXME: implement me.
 
-                       r.Error (103, Location, "The name `" + Name + "' does not exist in the class `" +
-                                tc.Name + "'");
+                       Error (tc, 103, Location, "The name `" + Name + "' does not exist in the class `" +
+                              tc.Name + "'");
 
                        return null;
                }
@@ -2219,7 +2347,19 @@ namespace CIR {
        //   A simple interface that should be implemeneted by LValues
        // </summary>
        public interface LValue {
-               void Store (ILGenerator ig);
+
+               // <summary>
+               //   The Store method should store the contents of the top
+               //   of the stack into the storage that is implemented by
+               //   the particular implementation of LValue
+               // </summary>
+               void Store     (EmitContext ec);
+
+               // <summary>
+               //   The AddressOf method should generate code that loads
+               //   the address of the LValue and leaves it on the stack
+               // </summary>
+               void AddressOf (EmitContext ec);
        }
        
        public class LocalVariableReference : Expression, LValue {
@@ -2253,6 +2393,8 @@ namespace CIR {
                        ILGenerator ig = ec.ig;
                        int idx = vi.Idx;
 
+                       vi.Used = true;
+                       
                        switch (idx){
                        case 0:
                                ig.Emit (OpCodes.Ldloc_0);
@@ -2271,19 +2413,21 @@ namespace CIR {
                                break;
 
                        default:
-                               if (idx < 255)
-                                       ig.Emit (OpCodes.Ldloc_S, idx);
+                               if (idx <= 255)
+                                       ig.Emit (OpCodes.Ldloc_S, (byte) idx);
                                else
                                        ig.Emit (OpCodes.Ldloc, idx);
                                break;
                        }
                }
 
-               public void Store (ILGenerator ig)
+               public void Store (EmitContext ec)
                {
+                       ILGenerator ig = ec.ig;
                        VariableInfo vi = VariableInfo;
                        int idx = vi.Idx;
-                                       
+
+                       vi.Assigned = true;
                        switch (idx){
                        case 0:
                                ig.Emit (OpCodes.Stloc_0);
@@ -2302,13 +2446,27 @@ namespace CIR {
                                break;
                                
                        default:
-                               if (idx < 255)
-                                       ig.Emit (OpCodes.Stloc_S, idx);
+                               if (idx <= 255)
+                                       ig.Emit (OpCodes.Stloc_S, (byte) idx);
                                else
                                        ig.Emit (OpCodes.Stloc, idx);
                                break;
                        }
                }
+
+               public void AddressOf (EmitContext ec)
+               {
+                       VariableInfo vi = VariableInfo;
+                       int idx = vi.Idx;
+
+                       vi.Used = true;
+                       vi.Assigned = true;
+                       
+                       if (idx <= 255)
+                               ec.ig.Emit (OpCodes.Ldloca_S, (byte) idx);
+                       else
+                               ec.ig.Emit (OpCodes.Ldloca, idx);
+               }
        }
 
        public class ParameterReference : Expression, LValue {
@@ -2335,20 +2493,28 @@ namespace CIR {
 
                public override void Emit (EmitContext ec)
                {
-                       if (Idx < 255)
-                               ec.ig.Emit (OpCodes.Ldarg_S, Idx);
+                       if (Idx <= 255)
+                               ec.ig.Emit (OpCodes.Ldarg_S, (byte) Idx);
                        else
                                ec.ig.Emit (OpCodes.Ldarg, Idx);
                }
 
-               public void Store (ILGenerator ig)
+               public void Store (EmitContext ec)
                {
-                       if (Idx < 255)
-                               ig.Emit (OpCodes.Starg_S, Idx);
+                       if (Idx <= 255)
+                               ec.ig.Emit (OpCodes.Starg_S, (byte) Idx);
                        else
-                               ig.Emit (OpCodes.Starg, Idx);
+                               ec.ig.Emit (OpCodes.Starg, Idx);
                        
                }
+
+               public void AddressOf (EmitContext ec)
+               {
+                       if (Idx <= 255)
+                               ec.ig.Emit (OpCodes.Ldarga_S, (byte) Idx);
+                       else
+                               ec.ig.Emit (OpCodes.Ldarga, Idx);
+               }
        }
        
        // <summary>
@@ -2547,7 +2713,7 @@ namespace CIR {
 
                        Expression mg;
                        
-                       mg = MemberLookup (tc.RootContext, to, "op_Implicit", false);
+                       mg = MemberLookup (tc, to, "op_Implicit", false);
 
                        if (mg != null) {
                                MethodGroupExpr me = (MethodGroupExpr) mg;
@@ -2562,7 +2728,7 @@ namespace CIR {
                                }
                        }
 
-                       mg = MemberLookup (tc.RootContext, from, "op_Implicit", false);
+                       mg = MemberLookup (tc, from, "op_Implicit", false);
 
                        if (mg != null) {
                                MethodGroupExpr me = (MethodGroupExpr) mg;
@@ -2593,11 +2759,10 @@ namespace CIR {
 
                        if (argument_type == null)
                                throw new Exception ("Expression of type " + a.Expr + " does not resolve its type");
-                       
-                       
+
                        if (p == q)
                                return 0;
-
+                       
                        if (argument_type == p)
                                return 1;
 
@@ -2662,16 +2827,30 @@ namespace CIR {
                                }
                        }
 
-                       // User-defined Implicit conversions come here
-                       
-                       if (q != null)
-                               if (ConversionExists (tc, p, q) == true &&
-                                   ConversionExists (tc, q, p) == false)
+                       if (q == null) {
+
+                               Expression tmp;
+
+                               tmp = ConvertImplicit (tc, argument_expr, p);
+
+                               if (tmp != null)
                                        return 1;
-                       
+                               else
+                                       return 0;
+
+                       }
+
+                       Expression p_tmp, q_tmp;
+
+                       p_tmp = ConvertImplicit (tc, argument_expr, p);
+                       q_tmp = ConvertImplicit (tc, argument_expr, q);
+
+                       if (p_tmp != null && q_tmp == null)
+                               return 1;
+
                        if (p == TypeManager.sbyte_type)
                                if (q == TypeManager.byte_type || q == TypeManager.ushort_type ||
-                                   q == TypeManager.uint32_type || q == TypeManager.uint64_type) 
+                                   q == TypeManager.uint32_type || q == TypeManager.uint64_type)
                                        return 1;
 
                        if (p == TypeManager.short_type)
@@ -2839,7 +3018,7 @@ namespace CIR {
                                i--;
                                MethodBase candidate  = me.Methods [i];
                                int x;
-                               
+
                                x = BetterFunction (tc, Arguments, candidate, method);
                                
                                if (x == 0)
@@ -2849,34 +3028,34 @@ namespace CIR {
                                        method = me.Methods [best_match_idx];
                                }
                        }
-                       
-                       if (best_match_idx != -1)
-                               return method;
-
-                       // Now we see if we can at least find a method with the same number of arguments
-                       // and then try doing implicit conversion on the arguments
 
                        if (Arguments == null)
                                argument_count = 0;
                        else
                                argument_count = Arguments.Count;
-
-                       ParameterData pd = null;
                        
-                       for (int i = me.Methods.Length; i > 0;) {
-                               i--;
-                               MethodBase mb = me.Methods [i];
-                               pd = GetParameterData (mb);
+                       ParameterData pd;
+                       
+                       // Now we see if we can at least find a method with the same number of arguments
+                       // and then try doing implicit conversion on the arguments
+                       if (best_match_idx == -1) {
+                               
+                               for (int i = me.Methods.Length; i > 0;) {
+                                       i--;
+                                       MethodBase mb = me.Methods [i];
+                                       pd = GetParameterData (mb);
+                                       
+                                       if (pd.Count == argument_count) {
+                                               best_match_idx = i;
+                                               method = me.Methods [best_match_idx];
+                                               break;
+                                       } else
+                                               continue;
+                               }
 
-                               if (pd.Count == argument_count) {
-                                       best_match_idx = i;
-                                       method = me.Methods [best_match_idx];
-                                       break;
-                               } else
-                                       continue;
                        }
 
-                       if (best_match_idx == -1)
+                       if (method == null)
                                return null;
 
                        // And now convert implicitly, each argument to the required type
@@ -2891,10 +3070,10 @@ namespace CIR {
                                Expression conv = ConvertImplicit (tc, a_expr, pd.ParameterType (j));
 
                                if (conv == null) {
-                                       tc.RootContext.Report.Error (1502, loc,
+                                       Error (tc, 1502, loc,
                                               "The best overloaded match for method '" + FullMethodDesc (method) +
                                               "' has some invalid arguments");
-                                       tc.RootContext.Report.Error (1503, loc,
+                                       Error (tc, 1503, loc,
                                               "Argument " + (j+1) +
                                               " : Cannot convert from '" + TypeManager.CSharpName (a_expr.Type)
                                               + "' to '" + TypeManager.CSharpName (pd.ParameterType (j)) + "'");
@@ -2943,7 +3122,7 @@ namespace CIR {
                        method = OverloadResolve (tc, (MethodGroupExpr) this.expr, Arguments, Location);
 
                        if (method == null){
-                               tc.RootContext.Report.Error (-6, Location,
+                               Error (tc, -6, Location,
                                       "Could not find any applicable function for this argument list");
                                return null;
                        }
@@ -3065,7 +3244,7 @@ namespace CIR {
 
                        Expression ml;
 
-                       ml = MemberLookup (tc.RootContext, type, ".ctor", false,
+                       ml = MemberLookup (tc, type, ".ctor", false,
                                           MemberTypes.Constructor, AllBindingsFlags);
 
                        if (! (ml is MethodGroupExpr)){
@@ -3089,8 +3268,8 @@ namespace CIR {
                        method = Invocation.OverloadResolve (tc, (MethodGroupExpr) ml, Arguments, Location);
 
                        if (method == null) {
-                               tc.RootContext.Report.Error (-6, Location,
-                               "New invocation: Can not find a constructor for this argument list");
+                               Error (tc, -6, Location,
+                                      "New invocation: Can not find a constructor for this argument list");
                                return null;
                        }
                        
@@ -3130,12 +3309,20 @@ namespace CIR {
                        ec.ig.Emit (OpCodes.Ldarg_0);
                }
 
-               public void Store (ILGenerator ig)
+               public void Store (EmitContext ec)
                {
                        //
-                       // Assignment to the "this" variable
+                       // Assignment to the "this" variable.
+                       //
+                       // FIXME: Apparently this is a bug that we
+                       // must catch as `this' seems to be readonly ;-)
                        //
-                       ig.Emit (OpCodes.Starg, 0);
+                       ec.ig.Emit (OpCodes.Starg, 0);
+               }
+
+               public void AddressOf (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldarga_S, (byte) 0);
                }
        }
 
@@ -3210,7 +3397,7 @@ namespace CIR {
                        if (new_expression == null)
                                return null;
 
-                       member_lookup = MemberLookup (tc.RootContext, expr.Type, Identifier, false);
+                       member_lookup = MemberLookup (tc, expr.Type, Identifier, false);
 
                        if (member_lookup is MethodGroupExpr){
                                MethodGroupExpr mg = (MethodGroupExpr) member_lookup;
@@ -3245,7 +3432,7 @@ namespace CIR {
 
                public override void Emit (EmitContext ec)
                {
-                       throw new Exception ("Implement me");
+                       throw new Exception ("Should not happen I think");
                }
 
        }
@@ -3338,31 +3525,6 @@ namespace CIR {
                }
        }
        
-       public class BuiltinTypeAccess : Expression {
-               public readonly string AccessBase;
-               public readonly string Method;
-               
-               public BuiltinTypeAccess (string type, string method)
-               {
-                       System.Console.WriteLine ("DUDE! This type should be fully resolved!");
-                       AccessBase = type;
-                       Method = method;
-               }
-
-               public override Expression Resolve (TypeContainer tc)
-               {
-                       // FIXME: Implement;
-                       throw new Exception ("Unimplemented");
-                       // return this;
-               }
-
-               public override void Emit (EmitContext ec)
-               {
-                       throw new Exception ("Unimplemented");
-               }
-       }
-
-
        //   Fully resolved expression that evaluates to a Field
        // </summary>
        public class FieldExpr : Expression, LValue {
@@ -3406,12 +3568,22 @@ namespace CIR {
                        }
                }
 
-               public void Store (ILGenerator ig)
+               public void Store (EmitContext ec)
                {
                        if (FieldInfo.IsStatic)
-                               ig.Emit (OpCodes.Stsfld, FieldInfo);
+                               ec.ig.Emit (OpCodes.Stsfld, FieldInfo);
                        else
-                               ig.Emit (OpCodes.Stfld, FieldInfo);
+                               ec.ig.Emit (OpCodes.Stfld, FieldInfo);
+               }
+
+               public void AddressOf (EmitContext ec)
+               {
+                       if (FieldInfo.IsStatic)
+                               ec.ig.Emit (OpCodes.Ldsflda, FieldInfo);
+                       else {
+                               Instance.Emit (ec);
+                               ec.ig.Emit (OpCodes.Ldflda, FieldInfo);
+                       }
                }
        }
        
@@ -3451,7 +3623,7 @@ namespace CIR {
        }
 
        // <summary>
-       //   Fully resolved expression that evaluates to a Property
+       //   Fully resolved expression that evaluates to a Expression
        // </summary>
        public class EventExpr : Expression {
                public readonly EventInfo EventInfo;
@@ -3598,105 +3770,48 @@ namespace CIR {
        }
 
        public class UserImplicitCast : Expression {
-
-               Expression source;
-               Type       target; 
                MethodBase method;
                ArrayList  arguments;
                
-               public UserImplicitCast (Expression source, Type target)
+               public UserImplicitCast (MethodInfo method, ArrayList arguments)
                {
-                       this.source = source;
-                       this.target = target;
+                       this.method = method;
+                       this.arguments = arguments;
+                       type = method.ReturnType;
+                       eclass = ExprClass.Value;
                }
 
                public override Expression Resolve (TypeContainer tc)
                {
-                       source = source.Resolve (tc);
-                       
-                       if (source == null)
-                               return null;
-
-                       Expression mg1, mg2;
-                       MethodGroupExpr union;
-                       MethodInfo mi;
-                       
-                       mg1 = MemberLookup (tc.RootContext, source.Type, "op_Implicit", false);
-                       mg2 = MemberLookup (tc.RootContext, target, "op_Implicit", false);
-                       
-                       union = Invocation.MakeUnionSet (mg1, mg2);
-
-                       arguments = new ArrayList ();
-                       arguments.Add (new Argument (source, Argument.AType.Expression));
-                       
-                       if (union != null) {
-                               method = Invocation.OverloadResolve (tc, union, arguments,
-                                                                    new Location ("FIXME", 1, 1));
-                               
-                               if (method != null) {
-                                       mi = (MethodInfo) method;
-
-                                       if (mi.ReturnType == target) {
-                                               type = mi.ReturnType;
-                                               return this;
-                                       }
-                               }
-                       }
-                       
-                       if (target == TypeManager.bool_type) {
-
-                               mg1 = MemberLookup (tc.RootContext, source.Type, "op_True", false);
-                               mg2 = MemberLookup (tc.RootContext, target, "op_True", false);
-                               
-                               union = Invocation.MakeUnionSet (mg1, mg2);
-
-                               if (union == null)
-                                       return null;
-                               
-                               method = Invocation.OverloadResolve (tc, union, arguments,
-                                                                    new Location ("FIXME", 1, 1));
-                               
-                               if (method != null) {
-                                       mi = (MethodInfo) method;
-
-                                       if (mi.ReturnType == target) {
-                                               type = mi.ReturnType;
-                                               return this;
-                                       }
-                               }
-                       }
-
-                       return null;
+                       //
+                       // We are born in a fully resolved state
+                       //
+                       return this;
                }
 
-               public static bool CanConvert (TypeContainer tc, Expression source, Type target)
+               public static Expression CanConvert (TypeContainer tc, Expression source, Type target)
                {
-                       source = source.Resolve (tc);
-                       
-                       if (source == null)
-                               return false;
-
                        Expression mg1, mg2;
                        MethodBase method;
                        ArrayList arguments;
                        
-                       mg1 = MemberLookup (tc.RootContext, source.Type, "op_Implicit", false);
-                       mg2 = MemberLookup (tc.RootContext, target, "op_Implicit", false);
+                       mg1 = MemberLookup (tc, source.Type, "op_Implicit", false);
+                       mg2 = MemberLookup (tc, target, "op_Implicit", false);
                        
                        MethodGroupExpr union = Invocation.MakeUnionSet (mg1, mg2);
 
-                       arguments = new ArrayList ();
-                       arguments.Add (new Argument (source, Argument.AType.Expression));
-                       
                        if (union != null) {
+                               arguments = new ArrayList ();
+                               arguments.Add (new Argument (source, Argument.AType.Expression));
                                
                                method = Invocation.OverloadResolve (tc, union, arguments,
-                                                                               new Location ("FIXME", 1, 1));
+                                                                    new Location ("FIXME", 1, 1));
+
                                if (method != null) {
                                        MethodInfo mi = (MethodInfo) method;
                                        
                                        if (mi.ReturnType == target)
-                                               return true;
+                                               return new UserImplicitCast (mi, arguments);
                                }
                        }
                        
@@ -3705,26 +3820,28 @@ namespace CIR {
                        
                        if (target == TypeManager.bool_type) {
 
-                               mg1 = MemberLookup (tc.RootContext, source.Type, "op_True", false);
-                               mg2 = MemberLookup (tc.RootContext, target, "op_True", false);
+                               mg1 = MemberLookup (tc, source.Type, "op_True", false);
+                               mg2 = MemberLookup (tc, target, "op_True", false);
                                
                                union = Invocation.MakeUnionSet (mg1, mg2);
 
                                if (union == null)
-                                       return false;
+                                       return null;
 
+                               arguments = new ArrayList ();
+                               arguments.Add (new Argument (source, Argument.AType.Expression));
+                       
                                method = Invocation.OverloadResolve (tc, union, arguments,
                                                                     new Location ("FIXME", 1, 1));
                                if (method != null) {
                                        MethodInfo mi = (MethodInfo) method;
 
                                        if (mi.ReturnType == target) 
-                                               return true;
+                                               return new UserImplicitCast (mi, arguments);
                                }
                        }
                        
-                       return false;
-                       
+                       return null;
                }
                
                public override void Emit (EmitContext ec)