* convert.cs (ObjectTypeToPrimitiveTypes): Added. Converts an
[mono.git] / mcs / bmcs / ecore.cs
index 41987d0d1d60b525932f8b71314ac441b68de02f..51ca97ab8f19dc831396befd7e65866feed728a4 100644 (file)
@@ -815,7 +815,7 @@ namespace Mono.CSharp {
                ///   Returns an expression that can be used to invoke operator true
                ///   on the expression if it exists.
                /// </summary>
-               static public StaticCallExpr GetOperatorTrue (EmitContext ec, Expression e, Location loc)
+               static public Expression GetOperatorTrue (EmitContext ec, Expression e, Location loc)
                {
                        return GetOperatorTrueOrFalse (ec, e, true, loc);
                }
@@ -824,16 +824,19 @@ namespace Mono.CSharp {
                ///   Returns an expression that can be used to invoke operator false
                ///   on the expression if it exists.
                /// </summary>
-               static public StaticCallExpr GetOperatorFalse (EmitContext ec, Expression e, Location loc)
+               static public Expression GetOperatorFalse (EmitContext ec, Expression e, Location loc)
                {
                        return GetOperatorTrueOrFalse (ec, e, false, loc);
                }
 
-               static StaticCallExpr GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
+               static Expression GetOperatorTrueOrFalse (EmitContext ec, Expression e, bool is_true, Location loc)
                {
                        MethodBase method;
                        Expression operator_group;
 
+                       if (TypeManager.IsNullableType (e.Type))
+                               return new Nullable.OperatorTrueOrFalse (e, is_true, loc).Resolve (ec);
+
                        operator_group = MethodLookup (ec, e.Type, is_true ? "op_True" : "op_False", loc);
                        if (operator_group == null)
                                return null;
@@ -941,7 +944,7 @@ namespace Mono.CSharp {
                                sb.Append (valid [i]);
                        }
 
-                       Error (119, "Expression denotes a `" + ExprClassName () + "' where " +
+                       Report.Error (119, loc, "Expression denotes a `" + ExprClassName () + "' where " +
                               "a `" + sb.ToString () + "' was expected");
                }
                
@@ -1335,6 +1338,42 @@ namespace Mono.CSharp {
                {
                        Report.Error (248, loc, "Cannot create an array with a negative size");
                }
+
+
+               /// <summary>
+               /// Converts a String to an equivalent SimpleName or a
+               /// MemberAccess expression
+               /// </summary>
+
+               public static Expression StringToExpression (string name, Location loc)
+               {
+                       int pos;
+                       string left;
+                       string right;
+                       
+                       Expression expr = null;
+
+                       pos = name.IndexOf('.');
+                       while (pos != -1)
+                       {
+                               left = name.Substring (0, pos);
+                               right = name.Substring (pos + 1);
+
+                               if (expr == null)
+                                       expr = new SimpleName (left, loc);
+                               else
+                                       expr = new MemberAccess (expr, left, loc);
+
+                               name = right;
+                               pos = name.IndexOf('.');
+                       }
+
+                       if (expr == null)
+                               return new SimpleName (name, loc);
+                       else
+                               return new MemberAccess (expr, name, loc);
+
+               }
                
                //
                // Converts `source' to an int, uint, long or ulong.
@@ -1459,6 +1498,78 @@ namespace Mono.CSharp {
                }
        }
 
+       
+       /// <summary> 
+       /// HelperMethodInvocation of methods or delegates. Used by the
+       /// VB.NET compiler specifically to emit calls to the
+       /// Microsoft.VisualBasic.CompilerServices helper routines
+       /// </summary>
+
+       public class HelperMethodInvocation : Expression
+       {
+               ArrayList args;
+               MethodInfo method;
+               
+               public HelperMethodInvocation (EmitContext ec,  Location l, Type return_type, MethodInfo method, params Expression [] exprs)
+               {
+                       args = new ArrayList ();
+                       foreach (Expression expr in exprs)
+                               args.Add (new Argument (expr, Argument.AType.Expression));
+
+
+                       this.loc = l;
+                       this.method = method;
+                       type = return_type;
+                       eclass = ExprClass.Value;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       Invocation.EmitArguments (ec, method, args, false, null);
+                       ec.ig.Emit (OpCodes.Call, method);
+               }
+       }
+
+       /// <summary> 
+       /// Implicit Creation of types. Used by the VB.NET compiler
+       /// (in the context of Type Conversions) to emit calls to the
+       /// appropriate constructors available in the core libraries.
+       /// </summary>
+
+       public class ImplicitNew : Expression
+       {
+               Expression child;
+               
+               public ImplicitNew (EmitContext ec, string ns, string name, Location l, params Expression [] exprs)
+               {
+                       name = ns + "." + name;
+                       ArrayList args = new ArrayList ();
+               
+                       foreach (Expression expr in exprs)
+                               args.Add (new Argument (expr, Argument.AType.Expression));
+
+                       child = new New (StringToExpression (name, l), args, l).Resolve (ec);
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       child.Emit (ec);
+               }
+       }
+
         //
        // We need to special case this since an empty cast of
        // a NullLiteral is still a Constant
@@ -1493,7 +1604,19 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       child.Emit (ec);
+                               if (!type.IsValueType)
+                                       child.Emit (ec);
+                               else {
+                                       // VB.NET allows Nothing to be converted to any value type
+
+                                       ILGenerator ig = ec.ig;
+
+                                       ig.Emit (OpCodes.Ldtoken, type);
+                                       ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle);
+                                       ig.Emit (OpCodes.Call, TypeManager.activator_create_instance);
+                                       ig.Emit (OpCodes.Unbox, type);
+                                       ig.Emit (OpCodes.Ldobj, type);
+                               }
                }
 
                public override bool IsNegative {
@@ -1998,6 +2121,102 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Castclass, type);
                }
        }
+
+       //
+       // VB.NET specific
+       //
+       public class BooleanToNumericCast : EmptyCast {
+               OpCode op, op2;
+               
+               public BooleanToNumericCast (Expression child, Type return_type, OpCode op)
+                       : base (child, return_type)
+                       
+               {
+                       this.op = op;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+                       ec.ig.Emit (OpCodes.Ldc_I4_0);
+                       ec.ig.Emit (OpCodes.Cgt_Un);
+                       ec.ig.Emit (OpCodes.Neg);
+                       ec.ig.Emit (op);
+               }                       
+       }
+
+       //
+       // VB.NET specific
+       //
+       public class NumericToBooleanCast : EmptyCast {
+
+               Type expr_type; 
+
+               public NumericToBooleanCast (Expression child, Type src_type)
+                       : base (child, TypeManager.bool_type)
+                       
+               {
+                       expr_type = src_type;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       // This should never be invoked, we are born in fully
+                       // initialized state.
+
+                       return this;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       base.Emit (ec);
+
+                       if (expr_type == TypeManager.byte_type ||
+                               expr_type == TypeManager.short_type ||
+                               expr_type == TypeManager.int32_type) {
+                               ec.ig.Emit (OpCodes.Ldc_I4_0);
+                               ec.ig.Emit (OpCodes.Cgt_Un);
+                               return;
+                       }
+
+                       if (expr_type == TypeManager.int64_type) {
+                               ec.ig.Emit (OpCodes.Ldc_I8, (long) 0);
+                               ec.ig.Emit (OpCodes.Cgt_Un);
+                               return;
+                       }
+
+                       if (expr_type == TypeManager.float_type)
+                               ec.ig.Emit (OpCodes.Ldc_R4, (float) 0);
+                       else if (expr_type == TypeManager.double_type) 
+                               ec.ig.Emit (OpCodes.Ldc_R8, (double) 0);
+               
+                       ec.ig.Emit (OpCodes.Ceq);
+                       ec.ig.Emit (OpCodes.Ldc_I4_0);
+                       ec.ig.Emit (OpCodes.Ceq);
+               }                       
+       }
+
+       //
+       // VB.NET specific
+       //
+       public class FloatingToFixedCast : ConvCast {
+               public FloatingToFixedCast (EmitContext ec, Expression child, Type return_type, Mode mode)
+                       : base (ec, new HelperMethodInvocation (ec, child.Location, TypeManager.double_type, TypeManager.math_round_double,
+                                                           (child.Type == TypeManager.float_type) ? 
+                                                           new OpcodeCast (child, TypeManager.double_type, OpCodes.Conv_R8) : child), 
+                               return_type, mode)
+               {
+               }
+       }
+       
        
        /// <summary>
        ///   SimpleName expressions are formed of a single word and only happen at the beginning 
@@ -2275,6 +2494,11 @@ namespace Mono.CSharp {
        ///   section 10.8.1 (Fully Qualified Names).
        /// </summary>
        public abstract class FullNamedExpression : Expression {
+               public override FullNamedExpression ResolveAsTypeStep (EmitContext ec)
+               {
+                       return this;
+               }
+
                public abstract string FullName {
                        get;
                }