X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmbas%2Fecore.cs;h=3dbfbfcd5051ff8e96f8db77ee0f32eb7afb9354;hb=747952ff2eea2f8f2599ab8651741e18959e2a64;hp=76fa1a96765f904b7ed1730c948342e315e5f15b;hpb=9a50d5213f2439228358ee90a2651426b50ac34f;p=mono.git diff --git a/mcs/mbas/ecore.cs b/mcs/mbas/ecore.cs index 76fa1a96765..3dbfbfcd505 100644 --- a/mcs/mbas/ecore.cs +++ b/mcs/mbas/ecore.cs @@ -8,7 +8,7 @@ // // -namespace Mono.CSharp { +namespace Mono.MonoBASIC { using System; using System.Collections; using System.Diagnostics; @@ -82,7 +82,7 @@ namespace Mono.CSharp { /// The AddressOf method should generate code that loads /// the address of the object and leaves it on the stack. /// - /// The `mode' argument is used to notify the expression + /// The 'mode' argument is used to notify the expression /// of whether this will be used to read from the address or /// write to the address. /// @@ -108,7 +108,7 @@ namespace Mono.CSharp { bool IsAssigned (EmitContext ec, Location loc); /// - /// Checks whether field `name' in this struct has been assigned. + /// Checks whether field 'name' in this struct has been assigned. /// bool IsFieldAssigned (EmitContext ec, string name, Location loc); @@ -122,7 +122,7 @@ namespace Mono.CSharp { void SetAssigned (EmitContext ec); /// - /// Tells the flow analysis code that field `name' in this struct + /// Tells the flow analysis code that field 'name' in this struct /// has already been assigned atthe current code position. /// void SetFieldAssigned (EmitContext ec, string name); @@ -230,7 +230,7 @@ namespace Mono.CSharp { /// /// Utility wrapper routine for Warning, only prints the warning if - /// warnings of level `level' are enabled. + /// warnings of level 'level' are enabled. /// public void Warning (int warning, int level, string s) { @@ -241,8 +241,8 @@ namespace Mono.CSharp { static public void Error_CannotConvertType (Location loc, Type source, Type target) { Report.Error (30, loc, "Cannot convert type '" + - TypeManager.CSharpName (source) + "' to '" + - TypeManager.CSharpName (target) + "'"); + TypeManager.MonoBASIC_Name (source) + "' to '" + + TypeManager.MonoBASIC_Name (target) + "'"); } /// @@ -268,7 +268,7 @@ namespace Mono.CSharp { /// There are two side effects expected from calling /// Resolve(): the the field variable "eclass" should /// be set to any value of the enumeration - /// `ExprClass' and the type variable should be set + /// 'ExprClass' and the type variable should be set /// to a valid type (this is the type of the /// expression). /// @@ -302,14 +302,16 @@ namespace Mono.CSharp { bool old_do_flow_analysis = ec.DoFlowAnalysis; if ((flags & ResolveFlags.DisableFlowAnalysis) != 0) ec.DoFlowAnalysis = false; - + Expression e; - if (this is SimpleName) - e = ((SimpleName) this).DoResolveAllowStatic (ec); - else - e = DoResolve (ec); - - ec.DoFlowAnalysis = old_do_flow_analysis; + try { + if (this is SimpleName) + e = ((SimpleName) this).DoResolveAllowStatic (ec); + else + e = DoResolve (ec); + } finally { + ec.DoFlowAnalysis = old_do_flow_analysis; + } if (e == null) return null; @@ -323,17 +325,17 @@ namespace Mono.CSharp { ec.ContainerType, ec.ContainerType, AllMemberTypes, AllBindingFlags | BindingFlags.NonPublic, s.Name); if (lookup != null) - Error (122, "`" + s.Name + "' " + + Error (30390, "'" + s.Name + "' " + "is inaccessible because of its protection level"); else - Error (103, "The name `" + s.Name + "' could not be " + - "found in `" + ec.DeclSpace.Name + "'"); + Error (30451, "The name '" + s.Name + "' could not be " + + "found in '" + ec.DeclSpace.Name + "'"); return null; } return s; } - + if ((e is TypeExpr) || (e is ComposedCast)) { if ((flags & ResolveFlags.Type) == 0) { e.Error118 (flags); @@ -353,8 +355,12 @@ namespace Mono.CSharp { case ExprClass.MethodGroup: if ((flags & ResolveFlags.MethodGroup) == 0) { - ((MethodGroupExpr) e).ReportUsageError (); - return null; + MethodGroupExpr mg = (MethodGroupExpr) e; + Invocation i = new Invocation (mg, new ArrayList(), Location.Null); + Expression te = i.Resolve(ec); + //((MethodGroupExpr) e).ReportUsageError (); + //return null; + return te; } break; @@ -408,8 +414,8 @@ namespace Mono.CSharp { SimpleName s = (SimpleName) e; Report.Error ( - 103, loc, - "The name `" + s.Name + "' could not be found in `" + + 30451, loc, + "The name '" + s.Name + "' could not be found in '" + ec.DeclSpace.Name + "'"); return null; } @@ -419,8 +425,12 @@ namespace Mono.CSharp { " ExprClass is Invalid after resolve"); if (e.eclass == ExprClass.MethodGroup) { - ((MethodGroupExpr) e).ReportUsageError (); - return null; + MethodGroupExpr mg = (MethodGroupExpr) e; + Invocation i = new Invocation (mg, new ArrayList(), Location.Null); + Expression te = i.Resolve(ec); + return te; + //((MethodGroupExpr) e).ReportUsageError (); + //return null; } if (e.type == null) @@ -524,7 +534,7 @@ namespace Mono.CSharp { // FIXME: Probably implement a cache for (t,name,current_access_set)? // // This code could use some optimizations, but we need to do some - // measurements. For example, we could use a delegate to `flag' when + // measurements. For example, we could use a delegate to 'flag' when // something can not any longer be a method-group (because it is something // else). // @@ -536,7 +546,7 @@ namespace Mono.CSharp { // // null on error. // - // FIXME: When calling MemberLookup inside an `Invocation', we should pass + // FIXME: When calling MemberLookup inside an 'Invocation', we should pass // the arguments here and have MemberLookup return only the methods that // match the argument count/type, unlike we are doing now (we delay this // decision). @@ -555,10 +565,10 @@ namespace Mono.CSharp { } // - // Lookup type `t' for code in class `invocation_type'. Note that it's important - // to set `invocation_type' correctly since this method also checks whether the - // invoking class is allowed to access the member in class `t'. When you want to - // explicitly do a lookup in the base class, you must set both `t' and `invocation_type' + // Lookup type 't' for code in class 'invocation_type'. Note that it's important + // to set 'invocation_type' correctly since this method also checks whether the + // invoking class is allowed to access the member in class 't'. When you want to + // explicitly do a lookup in the base class, you must set both 't' and 'invocation_type' // to the base class (although a derived class can access protected members of its base // class it cannot do so through an instance of the base class (error CS1540)). // @@ -594,12 +604,12 @@ namespace Mono.CSharp { public const BindingFlags AllBindingFlags = BindingFlags.Public | BindingFlags.Static | - BindingFlags.Instance; + BindingFlags.Instance | + BindingFlags.IgnoreCase; public static Expression MemberLookup (EmitContext ec, Type t, string name, Location loc) { - return MemberLookup (ec, ec.ContainerType, t, name, - AllMemberTypes, AllBindingFlags, loc); + return MemberLookup (ec, ec.ContainerType, t, name, AllMemberTypes, AllBindingFlags, loc); } public static Expression MethodLookup (EmitContext ec, Type t, string name, Location loc) @@ -640,12 +650,12 @@ namespace Mono.CSharp { AllBindingFlags | BindingFlags.NonPublic, loc); if (e == null){ Report.Error ( - 117, loc, "`" + t + "' does not contain a definition " + - "for `" + name + "'"); + 30456, loc, "'" + t + "' does not contain a definition " + + "for '" + name + "'"); } else { - Report.Error ( - 122, loc, "`" + t + "." + name + - "' is inaccessible due to its protection level"); + Report.Error ( + 30390, loc, "'" + t + "." + name + + "' is inaccessible due to its protection level"); } return null; @@ -778,14 +788,32 @@ namespace Mono.CSharp { // // Attempt to do the implicit constant expression conversions - if (expr is IntConstant){ + if (expr is BoolConstant || expr is IntConstant || expr is LongConstant || expr is DoubleConstant || expr is FloatConstant){ Expression e; - e = TryImplicitIntConversion (target_type, (IntConstant) expr); + e = TryImplicitNumericConversion (target_type, (Constant) expr); if (e != null) return e; - } else if (expr is LongConstant && target_type == TypeManager.uint64_type){ + if (target_type == TypeManager.byte_type || + target_type == TypeManager.short_type || + target_type == TypeManager.int32_type || + target_type == TypeManager.int64_type || + target_type == TypeManager.float_type) { + + string val = null; + if (expr is IntConstant) + val = ((IntConstant) expr).Value.ToString(); + if (expr is LongConstant) + val = ((LongConstant) expr).Value.ToString(); + if (expr is FloatConstant) + val = ((FloatConstant) expr).Value.ToString(); + if (expr is DoubleConstant) + val = ((DoubleConstant) expr).Value.ToString(); + Error_ConstantValueCannotBeConverted(loc, val, target_type); + return null; + } + } else if (expr is LongConstant && target_type == TypeManager.uint64_type) { // // Try the implicit constant expression conversion // from long to ulong, instead of a nice routine, @@ -798,7 +826,36 @@ namespace Mono.CSharp { Type real_target_type = target_type; - if (expr_type == TypeManager.sbyte_type){ + if (target_type == TypeManager.bool_type) { + + if (expr_type == TypeManager.decimal_type) { + return RTConversionExpression (ec, "System.Convert",".ToBoolean" , expr, loc); + } + + if ((expr_type != TypeManager.char_type) && + (expr_type != TypeManager.string_type)) + return new NumericToBoolCast (expr, expr.Type); + } + + if (expr_type == TypeManager.bool_type){ + // + if (real_target_type == TypeManager.sbyte_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.byte_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.int32_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.int64_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.double_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.float_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.short_type) + return new BoolToNumericCast (expr, target_type); + if (real_target_type == TypeManager.decimal_type) + return RTConversionExpression(ec, "DecimalType.FromBoolean", expr, loc); + } else if (expr_type == TypeManager.sbyte_type){ // // From sbyte to short, int, long, float, double. // @@ -917,13 +974,56 @@ namespace Mono.CSharp { return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); if (real_target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + } else if (expr_type == TypeManager.string_type){ + + if (real_target_type == TypeManager.bool_type) + return RTConversionExpression (ec, "BooleanType.FromString" , expr, loc); + if (real_target_type == TypeManager.decimal_type) + return RTConversionExpression (ec, "DecimalType.FromString" , expr, loc); + if (real_target_type == TypeManager.float_type) + return RTConversionExpression (ec, "SingleType.FromString" , expr, loc); + if (real_target_type == TypeManager.short_type) + return RTConversionExpression (ec, "ShortType.FromString" , expr, loc); + if (real_target_type == TypeManager.int64_type) + return RTConversionExpression (ec, "LongType.FromString" , expr, loc); + if (real_target_type == TypeManager.int32_type) + return RTConversionExpression (ec, "IntegerType.FromString" , expr, loc); + if (real_target_type == TypeManager.double_type) + return RTConversionExpression (ec, "DoubleType.FromString" , expr, loc); + if (real_target_type == TypeManager.byte_type) + return RTConversionExpression (ec, "ByteType.FromString" , expr, loc); } else if (expr_type == TypeManager.float_type){ // // float to double // + if (real_target_type == TypeManager.decimal_type) + return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc); if (real_target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); - } + + } else if (expr_type == TypeManager.double_type){ + + if (real_target_type == TypeManager.decimal_type) + return RTConversionExpression (ec, "System.Convert", ".ToDecimal" , expr, loc); + } else if (expr_type == TypeManager.decimal_type){ + + if (real_target_type == TypeManager.bool_type) + return RTConversionExpression (ec, "BooleanType.FromDecimal" , expr, loc); + if (real_target_type == TypeManager.short_type) + return RTConversionExpression(ec, "System.Convert", ".ToInt16", expr, loc); + if (real_target_type == TypeManager.byte_type) + return RTConversionExpression(ec, "System.Convert", ".ToByte", expr, loc); + if (real_target_type == TypeManager.int32_type) + return RTConversionExpression(ec, "System.Convert", ".ToInt32", expr, loc); + if (real_target_type == TypeManager.int64_type) + return RTConversionExpression(ec, "System.Convert", ".ToInt64", expr, loc); + if (real_target_type == TypeManager.float_type) + return RTConversionExpression(ec, "System.Convert", ".ToSingle", expr, loc); + if (real_target_type == TypeManager.double_type) + return RTConversionExpression(ec, "System.Convert", ".ToDouble", expr, loc); + if (real_target_type == TypeManager.char_type) + return RTConversionExpression(ec, "System.Convert", ".ToChar", expr, loc); + } return null; } @@ -932,10 +1032,8 @@ namespace Mono.CSharp { // Tests whether an implicit reference conversion exists between expr_type // and target_type // - public static bool ImplicitReferenceConversionExists (Expression expr, Type target_type) + public static bool ImplicitReferenceConversionExists (Expression expr, Type expr_type, Type target_type) { - Type expr_type = expr.Type; - // // This is the boxed case. // @@ -1015,10 +1113,12 @@ namespace Mono.CSharp { if (StandardConversionExists (expr, target_type) == true) return true; +#if false Expression dummy = ImplicitUserConversion (ec, expr, target_type, Location.Null); if (dummy != null) return true; +#endif return false; } @@ -1029,16 +1129,37 @@ namespace Mono.CSharp { /// public static bool StandardConversionExists (Expression expr, Type target_type) { - Type expr_type = expr.Type; + return WideningConversionExists (expr, expr.type, target_type); + } + + public static bool WideningConversionExists (Type expr_type, Type target_type) + { + return WideningConversionExists (null, expr_type, target_type); + } - if (expr_type == TypeManager.void_type) + public static bool WideningConversionExists (Expression expr, Type target_type) + { + return WideningConversionExists (expr, expr.Type, target_type); + } + + public static bool WideningConversionExists (Expression expr, Type expr_type, Type target_type) + { + + if (expr_type == null || expr_type == TypeManager.void_type) return false; if (expr_type == target_type) return true; - // First numeric conversions + // Conversions from enum to underlying type are widening. + if (expr_type.IsSubclassOf (TypeManager.enum_type)) + expr_type = TypeManager.EnumToUnderlying (expr_type); + if (expr_type == target_type) + return true; + + // First numeric conversions + if (expr_type == TypeManager.sbyte_type){ // // From sbyte to short, int, long, float, double. @@ -1056,6 +1177,7 @@ namespace Mono.CSharp { // From byte to short, ushort, int, uint, long, ulong, float, double // if ((target_type == TypeManager.short_type) || + (target_type == TypeManager.bool_type) || (target_type == TypeManager.ushort_type) || (target_type == TypeManager.int32_type) || (target_type == TypeManager.uint32_type) || @@ -1071,6 +1193,7 @@ namespace Mono.CSharp { // From short to int, long, float, double // if ((target_type == TypeManager.int32_type) || + (target_type == TypeManager.bool_type) || (target_type == TypeManager.int64_type) || (target_type == TypeManager.double_type) || (target_type == TypeManager.float_type) || @@ -1095,6 +1218,7 @@ namespace Mono.CSharp { // From int to long, float, double // if ((target_type == TypeManager.int64_type) || + (target_type == TypeManager.bool_type) || (target_type == TypeManager.double_type) || (target_type == TypeManager.float_type) || (target_type == TypeManager.decimal_type)) @@ -1105,6 +1229,7 @@ namespace Mono.CSharp { // From uint to long, ulong, float, double // if ((target_type == TypeManager.int64_type) || + (target_type == TypeManager.bool_type) || (target_type == TypeManager.uint64_type) || (target_type == TypeManager.double_type) || (target_type == TypeManager.float_type) || @@ -1117,6 +1242,7 @@ namespace Mono.CSharp { // From long/ulong to float, double // if ((target_type == TypeManager.double_type) || + (target_type == TypeManager.bool_type) || (target_type == TypeManager.float_type) || (target_type == TypeManager.decimal_type)) return true; @@ -1132,18 +1258,27 @@ namespace Mono.CSharp { (target_type == TypeManager.int64_type) || (target_type == TypeManager.float_type) || (target_type == TypeManager.double_type) || + (target_type == TypeManager.string_type) || (target_type == TypeManager.decimal_type)) return true; + } else if (expr_type == TypeManager.decimal_type) { + if (target_type == TypeManager.float_type || + target_type == TypeManager.double_type) + return true; } else if (expr_type == TypeManager.float_type){ // - // float to double + // float to double, decimal // if (target_type == TypeManager.double_type) return true; - } + } else if (expr_type == TypeManager.double_type){ + + if ((target_type == TypeManager.bool_type)) + return true; + } - if (ImplicitReferenceConversionExists (expr, target_type)) + if (ImplicitReferenceConversionExists (expr, expr_type, target_type)) return true; if (expr is IntConstant){ @@ -1290,7 +1425,7 @@ namespace Mono.CSharp { // // If any operator converts from S then Sx = S // - Type source_type = source.Type; + Type source_type= source.Type; foreach (MethodBase mb in me.Methods){ ParameterData pd = Invocation.GetParameterData (mb); Type param_type = pd.ParameterType (0); @@ -1447,7 +1582,7 @@ namespace Mono.CSharp { /// /// Computes the MethodGroup for the user-defined conversion - /// operators from source_type to target_type. `look_for_explicit' + /// operators from source_type to target_type. 'look_for_explicit' /// controls whether we should also include the list of explicit /// operators /// @@ -1596,9 +1731,9 @@ namespace Mono.CSharp { } /// - /// 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'. + /// 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'. /// static public Expression ConvertImplicit (EmitContext ec, Expression expr, Type target_type, Location loc) @@ -1606,6 +1741,7 @@ namespace Mono.CSharp { Type expr_type = expr.Type; Expression e; + if (expr_type == target_type) return expr; @@ -1615,23 +1751,503 @@ namespace Mono.CSharp { e = ConvertImplicitStandard (ec, expr, target_type, loc); if (e != null) return e; - + e = ImplicitUserConversion (ec, expr, target_type, loc); + if (e != null) return e; + + e = NarrowingConversion (ec, expr, target_type, loc); + if (e != null) + return e; return null; } + /// + /// Converts the resolved expression 'expr' into the + /// 'target_type' using the Microsoft.VisualBasic runtime. + /// It returns a new expression that can be used + /// in a context that expects a 'target_type'. + /// + static private Expression RTConversionExpression (EmitContext ec, string s, Expression expr, Location loc) + { + Expression etmp, e; + ArrayList args; + Argument arg; + + etmp = Mono.MonoBASIC.Parser.DecomposeQI("Microsoft.VisualBasic.CompilerServices." + s, loc); + args = new ArrayList(); + arg = new Argument (expr, Argument.AType.Expression); + args.Add (arg); + e = (Expression) new Invocation (etmp, args, loc); + e = e.Resolve(ec); + return (e); + } + + static private Expression RTConversionExpression (EmitContext ec, string ns, string method, Expression expr, Location loc) + { + Expression etmp, e; + ArrayList args; + Argument arg; + + etmp = Mono.MonoBASIC.Parser.DecomposeQI(ns+method, loc); + args = new ArrayList(); + arg = new Argument (expr, Argument.AType.Expression); + args.Add (arg); + e = (Expression) new Invocation (etmp, args, loc); + e = e.Resolve(ec); + return (e); + } + + + static public bool NarrowingConversionExists (EmitContext ec, Expression expr, Type target_type) + { + Type expr_type = expr.Type; + + if (target_type == TypeManager.sbyte_type){ + // + // To sbyte from short, int, long, float, double. + // + if ((expr_type == TypeManager.int32_type) || + (expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.short_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if (target_type == TypeManager.byte_type){ + // + // To byte from short, ushort, int, uint, long, ulong, float, double + // + if ((expr_type == TypeManager.short_type) || + (expr_type == TypeManager.ushort_type) || + (expr_type == TypeManager.int32_type) || + (expr_type == TypeManager.uint32_type) || + (expr_type == TypeManager.uint64_type) || + (expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if (target_type == TypeManager.short_type){ + // + // To short from int, long, float, double + // + if ((expr_type == TypeManager.int32_type) || + (expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if (target_type == TypeManager.ushort_type){ + // + // To ushort from int, uint, long, ulong, float, double + // + if ((expr_type == TypeManager.uint32_type) || + (expr_type == TypeManager.uint64_type) || + (expr_type == TypeManager.int32_type) || + (expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if (target_type == TypeManager.int32_type){ + // + // To int from long, float, double + // + if ((expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if (target_type == TypeManager.uint32_type){ + // + // To uint from long, ulong, float, double + // + if ((expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.uint64_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if ((target_type == TypeManager.uint64_type) || + (target_type == TypeManager.int64_type)) { + // + // To long/ulong from float, double + // + if ((expr_type == TypeManager.double_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.decimal_type)) + return true; + + } else if (target_type == TypeManager.char_type){ + // + // To char from ushort, int, uint, long, ulong, float, double, decimal,string + // + if ((expr_type == TypeManager.ushort_type) || + (expr_type == TypeManager.int32_type) || + (expr_type == TypeManager.uint32_type) || + (expr_type == TypeManager.uint64_type) || + (expr_type == TypeManager.int64_type) || + (expr_type == TypeManager.float_type) || + (expr_type == TypeManager.double_type) || + (expr_type == TypeManager.decimal_type) || + (expr_type == TypeManager.string_type)) + + return true; + + } else if (target_type == TypeManager.float_type){ + // + // To float from double + // + if (expr_type == TypeManager.double_type) + return true; + } + + return (NarrowingConversion (ec, expr, target_type,Location.Null)) != null; + } + static public Expression NarrowingConversion (EmitContext ec, Expression expr, + Type target_type, Location loc) + { + Type expr_type = expr.Type; + + if (target_type == TypeManager.sbyte_type){ + // + // To sbyte from short, int, long, float, double. + // + if (expr_type == TypeManager.int32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I1); + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I1); + if (expr_type == TypeManager.short_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_I1); + + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I1); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I1); + } + + } else if (target_type == TypeManager.byte_type){ + // + // To byte from short, ushort, int, uint, long, ulong, float, double + // + if (expr_type == TypeManager.short_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I2_U1); + if (expr_type == TypeManager.ushort_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_U1); + if (expr_type == TypeManager.int32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U1); + if (expr_type == TypeManager.uint32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U1); + if (expr_type == TypeManager.uint64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U1); + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U1); + + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U1); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U1); + } + + } else if (target_type == TypeManager.short_type) { + // + // To short from int, long, float, double + // + if (expr_type == TypeManager.int32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_I2); + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I2); + + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I2); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I2); + } + + } else if (target_type == TypeManager.ushort_type) { + // + // To ushort from int, uint, long, ulong, float, double + // + if (expr_type == TypeManager.uint32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_U2); + if (expr_type == TypeManager.uint64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_U2); + if (expr_type == TypeManager.int32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_U2); + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U2); + + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U2); + } + + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U2); + } + + } else if (target_type == TypeManager.int32_type){ + // + // To int from long, float, double + // + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_I4); + + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I4); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I4); + } + + } else if (target_type == TypeManager.uint32_type){ + // + // To uint from long, ulong, float, double + // + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_U4); + if (expr_type == TypeManager.uint64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_I4); + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U4); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U4); + } + + } else if (target_type == TypeManager.uint64_type) { + // + // To long/ulong from float, double + // + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8); + } + + } else if (target_type == TypeManager.int64_type) { + // + // To long/ulong from float, double + // + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8); + } + + } else if (target_type == TypeManager.char_type){ + // + // To char from ushort, int, uint, long, ulong, float, double + // + if (expr_type == TypeManager.ushort_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U2_CH); + if (expr_type == TypeManager.int32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I4_CH); + if (expr_type == TypeManager.uint32_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U4_CH); + if (expr_type == TypeManager.uint64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.U8_CH); + if (expr_type == TypeManager.int64_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.I8_CH); + + if (expr_type == TypeManager.float_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_CH); + } + if (expr_type == TypeManager.double_type) { + Expression rounded_expr = RTConversionExpression(ec, "System.Math", ".Round", expr, loc); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_CH); + } + + } else if (target_type == TypeManager.float_type){ + // + // To float from double + // + if (expr_type == TypeManager.double_type) + return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4); + } + + TypeCode dest_type = Type.GetTypeCode (target_type); + TypeCode src_type = Type.GetTypeCode (expr_type); + Expression e = null; + + switch (dest_type) { + case TypeCode.String: + switch (src_type) { + case TypeCode.SByte: + case TypeCode.Byte: + e = RTConversionExpression(ec, "StringType.FromByte", expr, loc); + break; + case TypeCode.UInt16: + case TypeCode.Int16: + e = RTConversionExpression(ec, "StringType.FromShort", expr, loc); + break; + case TypeCode.UInt32: + case TypeCode.Int32: + e = RTConversionExpression(ec, "StringType.FromInteger", expr, loc); + break; + case TypeCode.UInt64: + case TypeCode.Int64: + e = RTConversionExpression(ec, "StringType.FromLong", expr, loc); + break; + case TypeCode.Char: + e = RTConversionExpression(ec, "StringType.FromChar", expr, loc); + break; + case TypeCode.Single: + e = RTConversionExpression(ec, "StringType.FromSingle", expr, loc); + break; + case TypeCode.Double: + e = RTConversionExpression(ec, "StringType.FromDouble", expr, loc); + break; + case TypeCode.Boolean: + e = RTConversionExpression(ec, "StringType.FromBoolean", expr, loc); + break; + case TypeCode.DateTime: + e = RTConversionExpression(ec, "StringType.FromDate", expr, loc); + break; + case TypeCode.Decimal: + e = RTConversionExpression(ec, "StringType.FromDecimal", expr, loc); + break; + case TypeCode.Object: + e = RTConversionExpression(ec, "StringType.FromObject", expr, loc); + break; + } + break; + + case TypeCode.Int32: + case TypeCode.UInt32: + switch (src_type) { + case TypeCode.String: + e = RTConversionExpression(ec, "IntegerType.FromString", expr, loc); + break; + case TypeCode.Object: + e = RTConversionExpression(ec, "IntegerType.FromObject", expr, loc); + break; + } + break; + + case TypeCode.Int16: + case TypeCode.UInt16: + switch (src_type) { + case TypeCode.String: + e = RTConversionExpression(ec, "ShortType.FromString", expr, loc); + break; + case TypeCode.Object: + e = RTConversionExpression(ec, "ShortType.FromObject", expr, loc); + break; + } + break; + case TypeCode.Byte: + // Ok, this *is* broken + e = RTConversionExpression(ec, "ByteType.FromObject", expr, loc); + break; + case TypeCode.DateTime: + switch (src_type) { + case TypeCode.String: + e = RTConversionExpression(ec, "DateType.FromString", expr, loc); + break; + case TypeCode.Object: + e = RTConversionExpression(ec, "DateType.FromObject", expr, loc); + break; + } + break; + case TypeCode.Char: + switch (src_type) { + + case TypeCode.String: + e = RTConversionExpression(ec, "CharType.FromString", expr, loc); + break; + + } + break; + } + + // We must examine separately some types that + // don't have a TypeCode but are supported + // in the runtime + if (expr_type == typeof(System.String) && target_type == typeof (System.Char[])) { + e = RTConversionExpression(ec, "CharArrayType.FromString", expr, loc); + } + if (e != null) + return e; + // VB.NET Objects can be converted to anything by default + // unless, that is, an exception at runtime blows it all + if (src_type == TypeCode.Object) { + Expression cast_type = Mono.MonoBASIC.Parser.DecomposeQI(target_type.ToString(), loc); + Cast ce = new Cast (cast_type, expr, loc); + ce.IsRuntimeCast = true; + return ce.Resolve (ec); + } + return null; + } + + static public Expression ConvertNothingToDefaultValues (EmitContext ec, Expression expr, + Type target_type, Location loc) + { + switch (Type.GetTypeCode (target_type)) { + case TypeCode.Boolean : + return new BoolConstant (false); + case TypeCode.Byte : + return new ByteConstant (0); + case TypeCode.Char : + return new CharConstant ((char)0); + case TypeCode.SByte : + return new SByteConstant (0); + case TypeCode.Int16 : + return new ShortConstant (0); + case TypeCode.Int32 : + return new IntConstant (0); + case TypeCode.Int64 : + return new LongConstant (0); + case TypeCode.Decimal : + return new DecimalConstant (System.Decimal.Zero); + case TypeCode.Single : + return new FloatConstant (0.0F); + case TypeCode.Double : + return new DoubleConstant (0.0); + } + + return null; + } + /// - /// Attempts to apply the `Standard Implicit - /// Conversion' rules to the expression `expr' into - /// the `target_type'. It returns a new expression + /// Attempts to apply the 'Standard Implicit + /// Conversion' rules to the expression 'expr' into + /// the 'target_type'. It returns a new expression /// that can be used in a context that expects a - /// `target_type'. + /// 'target_type'. /// - /// This is different from `ConvertImplicit' in that the + /// This is different from 'ConvertImplicit' in that the /// user defined implicit conversions are excluded. /// static public Expression ConvertImplicitStandard (EmitContext ec, Expression expr, @@ -1640,10 +2256,19 @@ namespace Mono.CSharp { Type expr_type = expr.Type; Expression e; + if (expr is NullLiteral) { + if (target_type == TypeManager.string_type) + return expr; + e = ConvertNothingToDefaultValues (ec, expr, target_type, loc); + if (e != null) + return e; + } + if (expr_type == target_type) return expr; e = ImplicitNumericConversion (ec, expr, target_type, loc); + if (e != null) return e; @@ -1651,11 +2276,14 @@ namespace Mono.CSharp { if (e != null) return e; - if (target_type.IsSubclassOf (TypeManager.enum_type) && expr is IntLiteral){ - IntLiteral i = (IntLiteral) expr; - - if (i.Value == 0) - return new EmptyCast (expr, target_type); + if (expr.Type.IsSubclassOf (TypeManager.enum_type)) { + expr_type = TypeManager.EnumToUnderlying (expr.Type); + expr = new EmptyCast (expr, expr_type); + if (expr_type == target_type) + return expr; + e = ImplicitNumericConversion (ec, expr, target_type, loc); + if (e != null) + return e; } if (ec.InUnsafe) { @@ -1683,32 +2311,63 @@ namespace Mono.CSharp { } /// - /// Attemps to perform an implict constant conversion of the IntConstant + /// Attemps to perform an implict constant conversion of the any Numeric Constant /// into a different data type using casts (See Implicit Constant /// Expression Conversions) /// - static protected Expression TryImplicitIntConversion (Type target_type, IntConstant ic) - { - int value = ic.Value; + static protected Expression TryImplicitNumericConversion (Type target_type, Constant ic) + { + double value = 0; + if (ic is BoolConstant) { + bool val = (bool) ((BoolConstant)ic).Value; + if (val) { + if (target_type == TypeManager.byte_type) + value = Byte.MaxValue; + else + value = -1; + } + } + if (ic is IntConstant) + value = (double)((IntConstant)ic).Value; + + if (ic is LongConstant) + value = (double) ((LongConstant)ic).Value; + + if (ic is FloatConstant) { + value = (double) ((FloatConstant)ic).Value; + } + + if (ic is DoubleConstant) { + value = ((DoubleConstant)ic).Value; + } // // FIXME: This could return constants instead of EmptyCasts // - if (target_type == TypeManager.sbyte_type){ + if (target_type == TypeManager.bool_type){ + if (value != 0) + return new BoolConstant (true); + return new BoolConstant (false); + } else if (target_type == TypeManager.sbyte_type){ if (value >= SByte.MinValue && value <= SByte.MaxValue) - return new SByteConstant ((sbyte) value); + return new SByteConstant ((sbyte) System.Math.Round (value)); } else if (target_type == TypeManager.byte_type){ - if (Byte.MinValue >= 0 && value <= Byte.MaxValue) - return new ByteConstant ((byte) value); + if (value >= Byte.MinValue && value <= Byte.MaxValue) + return new ByteConstant ((byte) System.Math.Round (value)); } else if (target_type == TypeManager.short_type){ if (value >= Int16.MinValue && value <= Int16.MaxValue) - return new ShortConstant ((short) value); + return new ShortConstant ((short) System.Math.Round (value)); } else if (target_type == TypeManager.ushort_type){ if (value >= UInt16.MinValue && value <= UInt16.MaxValue) - return new UShortConstant ((ushort) value); + return new UShortConstant ((ushort) System.Math.Round (value)); + } else if (target_type == TypeManager.int32_type){ + if (value >= Int32.MinValue && value <= Int32.MaxValue) + return new IntConstant ((int) System.Math.Round (value)); } else if (target_type == TypeManager.uint32_type){ if (value >= 0) - return new UIntConstant ((uint) value); + return new UIntConstant ((uint) System.Math.Round (value)); + } else if (target_type == TypeManager.int64_type){ + return new LongConstant ((long) System.Math.Round (value)); } else if (target_type == TypeManager.uint64_type){ // // we can optimize this case: a positive int32 @@ -1716,7 +2375,11 @@ namespace Mono.CSharp { // to do it. // if (value >= 0) - return new ULongConstant ((ulong) value); + return new ULongConstant ((ulong)System.Math.Round ( value)); + } else if (target_type == TypeManager.float_type){ + return new FloatConstant ((float) value); + } else if (target_type == TypeManager.double_type){ + return new DoubleConstant ((double) value); } if (value == 0 && ic is IntLiteral && TypeManager.IsEnumType (target_type)){ @@ -1739,15 +2402,17 @@ namespace Mono.CSharp { static public void Error_CannotConvertImplicit (Location loc, Type source, Type target) { - string msg = "Cannot convert implicitly from `"+ - TypeManager.CSharpName (source) + "' to `" + - TypeManager.CSharpName (target) + "'"; + string msg = "Cannot convert implicitly from '"+ + TypeManager.MonoBASIC_Name (source) + "' to '" + + TypeManager.MonoBASIC_Name (target) + "'"; + + throw new Exception (msg); - Report.Error (29, loc, msg); + Report.Error (30512, loc, msg); } /// - /// Attemptes to implicityly convert `target' into `type', using + /// Attemptes to implicityly convert 'target' into 'type', using /// ConvertImplicit. If there is no implicit conversion, then /// an error is signaled /// @@ -1757,9 +2422,11 @@ namespace Mono.CSharp { Expression e; e = ConvertImplicit (ec, source, target_type, loc); + if (e != null) return e; + if (source is DoubleLiteral && target_type == TypeManager.float_type){ Report.Error (664, loc, "Double literal cannot be implicitly converted to " + @@ -1936,50 +2603,52 @@ namespace Mono.CSharp { // ushort, int, uint, long, ulong, char // or decimal // + Expression rounded_expr = RTConversionExpression(ec, "System.Math",".Round" , expr, loc); if (real_target_type == TypeManager.sbyte_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I1); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I1); if (real_target_type == TypeManager.byte_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U1); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U1); if (real_target_type == TypeManager.short_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I2); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I2); if (real_target_type == TypeManager.ushort_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U2); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U2); if (real_target_type == TypeManager.int32_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I4); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I4); if (real_target_type == TypeManager.uint32_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U4); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U4); if (real_target_type == TypeManager.int64_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_I8); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_I8); if (real_target_type == TypeManager.uint64_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_U8); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_U8); if (real_target_type == TypeManager.char_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R4_CH); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R4_CH); } else if (expr_type == TypeManager.double_type){ // // From double to byte, byte, short, // ushort, int, uint, long, ulong, // char, float or decimal // + Expression rounded_expr = RTConversionExpression(ec, "System.Math",".Round" , expr, loc); if (real_target_type == TypeManager.sbyte_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I1); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I1); if (real_target_type == TypeManager.byte_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U1); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U1); if (real_target_type == TypeManager.short_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I2); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I2); if (real_target_type == TypeManager.ushort_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U2); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U2); if (real_target_type == TypeManager.int32_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I4); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I4); if (real_target_type == TypeManager.uint32_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U4); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U4); if (real_target_type == TypeManager.int64_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_I8); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_I8); if (real_target_type == TypeManager.uint64_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_U8); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_U8); if (real_target_type == TypeManager.char_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_CH); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_CH); if (real_target_type == TypeManager.float_type) - return new ConvCast (ec, expr, target_type, ConvCast.Mode.R8_R4); + return new ConvCast (ec, rounded_expr, target_type, ConvCast.Mode.R8_R4); } // decimal is taken care of by the op_Explicit methods. @@ -2180,11 +2849,11 @@ namespace Mono.CSharp { } /// - /// Performs an explicit conversion of the expression `expr' whose - /// type is expr.Type to `target_type'. + /// Performs an explicit conversion of the expression 'expr' whose + /// type is expr.Type to 'target_type'. /// static public Expression ConvertExplicit (EmitContext ec, Expression expr, - Type target_type, Location loc) + Type target_type, bool runtimeconv, Location loc) { Type expr_type = expr.Type; Expression ne = ConvertImplicitStandard (ec, expr, target_type, loc); @@ -2227,6 +2896,10 @@ namespace Mono.CSharp { if (t != null) return t; + t = NarrowingConversion (ec, e, target_type, loc); + if (t != null) + return t; + Error_CannotConvertType (loc, expr_type, target_type); return null; } @@ -2284,7 +2957,13 @@ namespace Mono.CSharp { if (ne != null) return ne; - Error_CannotConvertType (loc, expr_type, target_type); + if (!(runtimeconv)) { + ne = NarrowingConversion (ec, expr, target_type, loc); + if (ne != null) + return ne; + + Error_CannotConvertType (loc, expr_type, target_type); + } return null; } @@ -2307,6 +2986,10 @@ namespace Mono.CSharp { if (ne != null) return ne; + ne = NarrowingConversion (ec, expr, target_type, l); + if (ne != null) + return ne; + Error_CannotConvertType (l, expr.Type, target_type); return null; } @@ -2339,7 +3022,7 @@ namespace Mono.CSharp { } /// - /// Reports that we were expecting `expr' to be of class `expected' + /// Reports that we were expecting 'expr' to be of class 'expected' /// public void Error118 (string expected) { @@ -2347,8 +3030,8 @@ namespace Mono.CSharp { kind = ExprClassName (eclass); - Error (118, "Expression denotes a `" + kind + - "' where a `" + expected + "' was expected"); + Error (118, "Expression denotes a '" + kind + + "' where a '" + expected + "' was expected"); } public void Error118 (ResolveFlags flags) @@ -2383,14 +3066,14 @@ namespace Mono.CSharp { string kind = ExprClassName (eclass); - Error (119, "Expression denotes a `" + kind + "' where " + - "a `" + sb.ToString () + "' was expected"); + Error (119, "Expression denotes a '" + kind + "' where " + + "a '" + sb.ToString () + "' was expected"); } static void Error_ConstantValueCannotBeConverted (Location l, string val, Type t) { - Report.Error (31, l, "Constant value `" + val + "' cannot be converted to " + - TypeManager.CSharpName (t)); + Report.Error (31, l, "Constant value '" + val + "' cannot be converted to " + + TypeManager.MonoBASIC_Name (t)); } public static void UnsafeError (Location loc) @@ -2401,7 +3084,7 @@ namespace Mono.CSharp { /// /// Converts the IntConstant, UIntConstant, LongConstant or /// ULongConstant into the integral target_type. Notice - /// that we do not return an `Expression' we do return + /// that we do not return an 'Expression' we do return /// a boxed integral type. /// /// FIXME: Since I added the new constants, we need to @@ -2710,7 +3393,7 @@ namespace Mono.CSharp { } // - // The stack contains the pointer and the value of type `type' + // The stack contains the pointer and the value of type 'type' // public static void StoreFromPtr (ILGenerator ig, Type type) { @@ -2739,7 +3422,7 @@ namespace Mono.CSharp { } // - // Returns the size of type `t' if known, otherwise, 0 + // Returns the size of type 't' if known, otherwise, 0 // public static int GetTypeSize (Type t) { @@ -2779,7 +3462,7 @@ namespace Mono.CSharp { } // - // Converts `source' to an int, uint, long or ulong. + // Converts 'source' to an int, uint, long or ulong. // public Expression ExpressionToArrayArgument (EmitContext ec, Expression source, Location loc) { @@ -2837,7 +3520,7 @@ namespace Mono.CSharp { public abstract class ExpressionStatement : Expression { /// - /// Requests the expression to be emitted in a `statement' + /// Requests the expression to be emitted in a 'statement' /// context. This means that no new value is left on the /// stack after invoking this method (constrasted with /// Emit that will always leave a value on the stack). @@ -3312,6 +3995,104 @@ namespace Mono.CSharp { } } + + public class NumericToBoolCast : EmptyCast + { + Type src_type; + + public NumericToBoolCast (Expression src, Type src_type) + : base (src, TypeManager.bool_type) + + { + this.src_type = src_type; + } + + public override Expression DoResolve (EmitContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + if (src_type == TypeManager.byte_type || + src_type == TypeManager.short_type || + src_type == TypeManager.int32_type) { + + ec.ig.Emit (OpCodes.Ldc_I4_0); + ec.ig.Emit (OpCodes.Cgt_Un); + return; + } + + if (src_type == TypeManager.int64_type) { + ec.ig.Emit (OpCodes.Ldc_I8, (long) 0); + ec.ig.Emit (OpCodes.Cgt_Un); + return; + } + + if (src_type == TypeManager.float_type) { + ec.ig.Emit (OpCodes.Ldc_R4, (float) 0); + ec.ig.Emit (OpCodes.Ceq); + ec.ig.Emit (OpCodes.Ldc_I4_0); + ec.ig.Emit (OpCodes.Ceq); + return; + } + + if (src_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); + return; + } + } + } + + public class BoolToNumericCast : EmptyCast + { + Expression src; + Type target_type; + OpCode conv; + + public BoolToNumericCast (Expression src, Type target_type) + : base (src, target_type) + + { + this.target_type = target_type; + } + + public override Expression DoResolve (EmitContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + if (target_type == TypeManager.byte_type) { + conv = OpCodes.Conv_U1; + } else if (target_type == TypeManager.short_type) { + conv = OpCodes.Conv_I2; + } else if (target_type == TypeManager.int32_type) { + conv = OpCodes.Conv_I4; + } else if (target_type == TypeManager.int64_type) { + conv = OpCodes.Conv_I8; + } else if (target_type == TypeManager.float_type) { + conv = OpCodes.Conv_R4; + } else if (target_type == TypeManager.double_type) { + conv = OpCodes.Conv_R8; + } + + ec.ig.Emit (OpCodes.Ldc_I4_0); + ec.ig.Emit (OpCodes.Cgt_Un); + ec.ig.Emit (OpCodes.Neg); + ec.ig.Emit (conv); + return; + } + } + /// /// This kind of cast is used to encapsulate a child and cast it /// to the class requested @@ -3353,10 +4134,10 @@ namespace Mono.CSharp { /// creating a namespace map from the assemblies, as that requires /// the GetExportedTypes function to be called and a hashtable to /// be constructed which reduces startup time. If later we find - /// that this is slower, we should create a `NamespaceExpr' expression + /// that this is slower, we should create a 'NamespaceExpr' expression /// that fully participates in the resolution process. /// - /// For example `System.Console.WriteLine' is decomposed into + /// For example 'System.Console.WriteLine' is decomposed into /// MemberAccess (MemberAccess (SimpleName ("System"), "Console"), "WriteLine") /// /// The first SimpleName wont produce a match on its own, so it will @@ -3365,7 +4146,7 @@ namespace Mono.CSharp { /// /// System.Console will produce a TypeExpr match. /// - /// The downside of this is that we might be hitting `LookupType' too many + /// The downside of this is that we might be hitting 'LookupType' too many /// times with this scheme. /// public class SimpleName : Expression, ITypeExpression { @@ -3383,12 +4164,12 @@ namespace Mono.CSharp { Report.Error ( 236, l, "A field initializer cannot reference the non-static field, " + - "method or property `"+name+"'"); + "method or property '"+name+"'"); else Report.Error ( 120, l, "An object reference is required " + - "for the non-static field `"+name+"'"); + "for the non-static field '"+name+"'"); } // @@ -3477,7 +4258,7 @@ namespace Mono.CSharp { /// Local Variables and Parameters are handled at /// parse time, so they never occur as SimpleNames. /// - /// The `allow_static' flag is used by MemberAccess only + /// The 'allow_static' flag is used by MemberAccess only /// and it is used to inform us that it is ok for us to /// avoid the static check, because MemberAccess might end /// up resolving the Name as a Type name and the access as @@ -3491,12 +4272,12 @@ namespace Mono.CSharp { Expression SimpleNameResolve (EmitContext ec, Expression right_side, bool allow_static) { Expression e = null; - + // // Stage 1: Performed by the parser (binding to locals or parameters). // Block current_block = ec.CurrentBlock; - if (current_block != null && current_block.IsVariableDefined (Name)){ + if (ec.InvokingOwnOverload == false && current_block != null && current_block.IsVariableDefined (Name)){ LocalVariableReference var; var = new LocalVariableReference (ec.CurrentBlock, Name, loc); @@ -3556,6 +4337,49 @@ namespace Mono.CSharp { if (e == null && ec.ContainerType != null) e = MemberLookup (ec, ec.ContainerType, Name, loc); +// #52067 - Start - Trying to solve + + if (e == null) { + + ArrayList lookups = new ArrayList(); + ArrayList typelookups = new ArrayList(); + + int split = Name.LastIndexOf('.'); + if (split != -1) { + String nameSpacePart = Name.Substring(0, split); + String memberNamePart = Name.Substring(split + 1); + foreach(Type type in TypeManager.GetPertinentStandardModules(nameSpacePart)) { + e = MemberLookup(ec, type, memberNamePart, loc); + if (e != null) { + lookups.Add(e); + typelookups.Add(type); + } + } + } + + string[] NamespacesInScope = RootContext.SourceBeingCompiled.GetNamespacesInScope(ec.DeclSpace.Namespace.Name); + foreach(Type type in TypeManager.GetPertinentStandardModules(NamespacesInScope)) { + e = MemberLookup(ec, type, Name, loc); + if (e != null) { + lookups.Add(e); + typelookups.Add(type); + } + } + if (lookups.Count == 1) { + e = (Expression)lookups[0]; + } else { + if (lookups.Count > 1) { + StringBuilder sb = new StringBuilder(); + foreach(Type type in typelookups) + sb.Append("'" + type.FullName + "'"); + Error (-1, "The name '" + Name + "' can be resolved to a member of more than one standard module: " + sb.ToString() + ". Please fully qualify it."); + return null; + } + } + } + +// #52067 - End + if (e == null) return DoResolveType (ec); @@ -3576,20 +4400,23 @@ namespace Mono.CSharp { if (!me.IsStatic && (me.InstanceExpression == null)) return e; +/* FIXME If this is not commented out, it seems that it's not possible to reach class members in mBas. + Maybe a grammar-related problem? + if (!me.IsStatic && TypeManager.IsNestedChildOf (me.InstanceExpression.Type, me.DeclaringType)) { - Error (38, "Cannot access nonstatic member `" + me.Name + "' of " + - "outer type `" + me.DeclaringType + "' via nested type `" + + Error (38, "Cannot access nonstatic member '" + me.Name + "' of " + + "outer type '" + me.DeclaringType + "' via nested type '" + me.InstanceExpression.Type + "'"); return null; } - +*/ if (right_side != null) e = e.DoResolveLValue (ec, right_side); else e = e.DoResolve (ec); - return e; + return e; } if (ec.IsStatic || ec.IsFieldInitializer){ @@ -3608,8 +4435,8 @@ namespace Mono.CSharp { // find the name as a namespace // - Error (103, "The name `" + Name + - "' does not exist in the class `" + + Error (30451, "The name '" + Name + + "' does not exist in the class '" + ec.DeclSpace.Name + "'"); } @@ -3733,7 +4560,7 @@ namespace Mono.CSharp { } // - // `A method group may have associated an instance expression' + // 'A method group may have associated an instance expression' // public Expression InstanceExpression { get { @@ -3794,7 +4621,7 @@ namespace Mono.CSharp { public void ReportUsageError () { - Report.Error (654, loc, "Method `" + Methods [0].DeclaringType + "." + + Report.Error (654, loc, "Method '" + Methods [0].DeclaringType + "." + Methods [0].Name + "()' is referenced without parentheses"); } @@ -4096,7 +4923,7 @@ namespace Mono.CSharp { /// /// Expression that evaluates to a Property. The Assign class - /// might set the `Value' expression if we are in an assignment. + /// might set the 'Value' expression if we are in an assignment. /// /// This is not an LValue because we need to re-write the expression, we /// can not take data from the stack and store it. @@ -4106,13 +4933,15 @@ namespace Mono.CSharp { public bool IsBase; MethodInfo getter, setter; bool is_static; - + public ArrayList PropertyArgs; + Expression instance_expr; public PropertyExpr (EmitContext ec, PropertyInfo pi, Location l) { PropertyInfo = pi; eclass = ExprClass.PropertyAccess; + PropertyArgs = null; is_static = false; loc = l; @@ -4162,7 +4991,7 @@ namespace Mono.CSharp { { if (!PropertyInfo.CanWrite){ Report.Error (200, loc, - "The property `" + PropertyInfo.Name + + "The property '" + PropertyInfo.Name + "' can not be assigned to, as it has not set accessor"); return false; } @@ -4203,8 +5032,8 @@ namespace Mono.CSharp { override public Expression DoResolve (EmitContext ec) { if (getter == null){ - Report.Error (154, loc, - "The property `" + PropertyInfo.Name + + Report.Error (30524, loc, + "The property '" + PropertyInfo.Name + "' can not be used in " + "this context because it lacks a get accessor"); return null; @@ -4227,8 +5056,8 @@ namespace Mono.CSharp { override public Expression DoResolveLValue (EmitContext ec, Expression right_side) { if (setter == null){ - Report.Error (154, loc, - "The property `" + PropertyInfo.Name + + Report.Error (30526, loc, + "The property '" + PropertyInfo.Name + "' can not be used in " + "this context because it lacks a set accessor"); return null; @@ -4262,9 +5091,9 @@ namespace Mono.CSharp { return; } } - - Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, loc); - + if (PropertyArgs == null) + PropertyArgs = new ArrayList (); + Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, getter, null, PropertyArgs, loc); } // @@ -4274,9 +5103,9 @@ namespace Mono.CSharp { { Argument arg = new Argument (source, Argument.AType.Expression); ArrayList args = new ArrayList (); - +//HERE args.Add (arg); - Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, loc); + Invocation.EmitCall (ec, IsBase, IsStatic, instance_expr, setter, args, PropertyArgs,loc); } override public void EmitStatement (EmitContext ec) @@ -4348,6 +5177,8 @@ namespace Mono.CSharp { } } + Expression field_expr = null; + public override Expression DoResolve (EmitContext ec) { if (instance_expr != null) { @@ -4356,12 +5187,24 @@ namespace Mono.CSharp { return null; } + if (this.DeclaringType == ec.ContainerType) { + MemberInfo mi = GetFieldFromEvent (this); + if (mi == null) + return null; + field_expr = ExprClassFromMemberInfo (ec, mi, loc); + ((FieldExpr) field_expr).InstanceExpression = instance_expr; + field_expr = field_expr.DoResolve (ec); + if (field_expr == null) + return null; + } + return this; } public override void Emit (EmitContext ec) { - Report.Error (70, loc, "The event `" + Name + "' can only appear on the left hand side of += or -= (except on the defining type)"); + if (field_expr != null) + field_expr.Emit (ec); } public void EmitAddOrRemove (EmitContext ec, Expression source) @@ -4381,4 +5224,4 @@ namespace Mono.CSharp { ec, false, IsStatic, instance_expr, remove_accessor, args, loc); } } -} +}