X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fbmcs%2Fecore.cs;h=51ca97ab8f19dc831396befd7e65866feed728a4;hb=448c3ad93f9a0f4125ad3a924c192c12fe4504bd;hp=41987d0d1d60b525932f8b71314ac441b68de02f;hpb=b4b657acad8f88aed65d9eccc797f7f8295b4845;p=mono.git diff --git a/mcs/bmcs/ecore.cs b/mcs/bmcs/ecore.cs index 41987d0d1d6..51ca97ab8f1 100644 --- a/mcs/bmcs/ecore.cs +++ b/mcs/bmcs/ecore.cs @@ -815,7 +815,7 @@ namespace Mono.CSharp { /// Returns an expression that can be used to invoke operator true /// on the expression if it exists. /// - 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. /// - 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"); } + + + /// + /// Converts a String to an equivalent SimpleName or a + /// MemberAccess expression + /// + + 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 { } } + + /// + /// HelperMethodInvocation of methods or delegates. Used by the + /// VB.NET compiler specifically to emit calls to the + /// Microsoft.VisualBasic.CompilerServices helper routines + /// + + 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); + } + } + + /// + /// 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. + /// + + 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) + { + } + } + /// /// 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). /// public abstract class FullNamedExpression : Expression { + public override FullNamedExpression ResolveAsTypeStep (EmitContext ec) + { + return this; + } + public abstract string FullName { get; }