protected override Expression ResolveConversions(ResolveContext ec) { // // LAMESPEC: Under dynamic context no target conversion is happening // This allows more natual dynamic behaviour but breaks compatibility // with static binding // if (target is RuntimeValueExpression) { return(this); } TypeSpec target_type = target.Type; // // 1. the return type is implicitly convertible to the type of target // if (Convert.ImplicitConversionExists(ec, source, target_type)) { source = Convert.ImplicitConversion(ec, source, target_type, loc); return(this); } // // Otherwise, if the selected operator is a predefined operator // Binary b = source as Binary; if (b == null && source is ReducedExpression) { b = ((ReducedExpression)source).OriginalExpression as Binary; } if (b != null) { // // 2a. the operator is a shift operator // // 2b. the return type is explicitly convertible to the type of x, and // y is implicitly convertible to the type of x // if ((b.Oper & Binary.Operator.ShiftMask) != 0 || Convert.ImplicitConversionExists(ec, right, target_type)) { source = Convert.ExplicitConversion(ec, source, target_type, loc); return(this); } } if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { Arguments arg = new Arguments(1); arg.Add(new Argument(source)); return(new SimpleAssign(target, new DynamicConversion(target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve(ec)); } right.Error_ValueCannotBeConverted(ec, loc, target_type, false); return(null); }
protected override Expression ResolveConversions(EmitContext ec) { Type target_type = target.Type; // // 1. the return type is implicitly convertible to the type of target // if (Convert.ImplicitConversionExists(ec, source, target_type)) { source = Convert.ImplicitConversion(ec, source, target_type, loc); return(this); } // // Otherwise, if the selected operator is a predefined operator // Binary b = source as Binary; if (b != null) { // // 2a. the operator is a shift operator // // 2b. the return type is explicitly convertible to the type of x, and // y is implicitly convertible to the type of x // if ((b.Oper & Binary.Operator.ShiftMask) != 0 || Convert.ImplicitConversionExists(ec, original_source, target_type)) { source = Convert.ExplicitConversion(ec, source, target_type, loc); return(this); } } original_source.Error_ValueCannotBeConverted(ec, loc, target_type, false); return(null); }
/// <summary> /// Performs an explicit conversion of the expression `expr' whose /// type is expr.Type to `target_type'. /// </summary> static public Expression ExplicitConversion (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc) { Expression e = ExplicitConversionCore (ec, expr, target_type, loc); if (e != null) { // // Don't eliminate explicit precission casts // if (e == expr) { if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float) return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); } return e; } TypeSpec expr_type = expr.Type; if (target_type.IsNullableType) { TypeSpec target; if (expr_type.IsNullableType) { target = Nullable.NullableInfo.GetUnderlyingType (target_type); Expression unwrap = Nullable.Unwrap.Create (expr); e = ExplicitConversion (ec, unwrap, target, expr.Location); if (e == null) return null; return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec); } if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) { return new UnboxCast (expr, target_type); } target = TypeManager.GetTypeArguments (target_type) [0]; e = ExplicitConversionCore (ec, expr, target, loc); if (e != null) return Nullable.Wrap.Create (e, target_type); } else if (expr_type.IsNullableType) { e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); if (e != null) return e; e = Nullable.Unwrap.Create (expr, false); e = ExplicitConversionCore (ec, e, target_type, loc); if (e != null) return EmptyCast.Create (e, target_type); } e = ExplicitUserConversion (ec, expr, target_type, loc); if (e != null) return e; expr.Error_ValueCannotBeConverted (ec, loc, target_type, true); return null; }
/// <summary> /// Same as ExplicitConversion, only it doesn't include user defined conversions /// </summary> static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location l) { int errors = ec.Report.Errors; Expression ne = ImplicitConversionStandard (ec, expr, target_type, l); if (ec.Report.Errors > errors) return null; if (ne != null) return ne; ne = ExplicitNumericConversion (ec, expr, target_type); if (ne != null) return ne; ne = ExplicitReferenceConversion (expr, expr.Type, target_type); if (ne != null) return ne; if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void) return EmptyCast.Create (expr, target_type); expr.Error_ValueCannotBeConverted (ec, l, target_type, true); return null; }
/// <summary> /// Attempts to implicitly convert `source' into `target_type', using /// ImplicitConversion. If there is no implicit conversion, then /// an error is signaled /// </summary> static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source, TypeSpec target_type, Location loc) { Expression e = ImplicitConversion (ec, source, target_type, loc); if (e != null) return e; source.Error_ValueCannotBeConverted (ec, loc, target_type, false); return null; }
protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) { initializer = initializer.Resolve (bc); if (initializer == null) return null; var c = initializer as Constant; if (c == null) { initializer.Error_ExpressionMustBeConstant (bc, initializer.Location, li.Name); return null; } c = c.ConvertImplicitly (bc, li.Type); if (c == null) { if (TypeManager.IsReferenceType (li.Type)) initializer.Error_ConstantCanBeInitializedWithNullOnly (bc, li.Type, initializer.Location, li.Name); else initializer.Error_ValueCannotBeConverted (bc, initializer.Location, li.Type, false); return null; } li.ConstantValue = c; return initializer; }
// // Converts `source' to an int, uint, long or ulong. // protected Expression ConvertExpressionToArrayIndex(ResolveContext ec, Expression source) { if (source.type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (source)); return new DynamicConversion (TypeManager.int32_type, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec); } Expression converted; using (ec.Set (ResolveContext.Options.CheckedScope)) { converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc); if (converted == null) { source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false); return null; } } // // Only positive constants are allowed at compile time // Constant c = converted as Constant; if (c != null && c.IsNegative) Error_NegativeArrayIndex (ec, source.loc); // No conversion needed to array index if (converted.Type == TypeManager.int32_type) return converted; return new ArrayIndexCast (converted).Resolve (ec); }
/// <summary> /// Attempts to implicitly convert `source' into `target_type', using /// ImplicitConversion. If there is no implicit conversion, then /// an error is signaled /// </summary> public static Expression ImplicitConversionRequired(ResolveContext ec, Expression source, TypeSpec target_type, Location loc) { Expression e = ImplicitConversion (ec, source, target_type, loc); if (e != null) return e; if (source.Type == InternalType.Dynamic) { Arguments args = new Arguments (1); args.Add (new Argument (source)); return new DynamicConversion (target_type, 0, args, loc).Resolve (ec); } source.Error_ValueCannotBeConverted (ec, loc, target_type, false); return null; }
/// <summary> /// Same as ExplicitConversion, only it doesn't include user defined conversions /// </summary> public static Expression ExplicitConversionStandard(ResolveContext ec, Expression expr, TypeSpec target_type, Location l) { int errors = ec.Report.Errors; Expression ne = ImplicitConversionStandard (ec, expr, target_type, l); if (ec.Report.Errors > errors) return null; if (ne != null) return ne; ne = ExplicitNumericConversion (expr, target_type); if (ne != null) return ne; ne = ExplicitReferenceConversion (expr, expr.Type, target_type); if (ne != null) return ne; if (ec.IsUnsafe && expr.Type == TypeManager.void_ptr_type && target_type.IsPointer) return EmptyCast.Create (expr, target_type); expr.Error_ValueCannotBeConverted (ec, l, target_type, true); return null; }
/// <summary> /// Resolves the expression `e' into a boolean expression: either through /// an implicit conversion, or through an `operator true' invocation /// </summary> public static Expression ResolveBoolean (EmitContext ec, Expression e, Location loc) { e = e.Resolve (ec); if (e == null) return null; if (e.Type == TypeManager.bool_type) return e; Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null); if (converted != null) return converted; // // If no implicit conversion to bool exists, try using `operator true' // converted = Expression.GetOperatorTrue (ec, e, loc); if (converted == null){ e.Error_ValueCannotBeConverted (ec, loc, TypeManager.bool_type, false); return null; } return converted; }
// // Converts `source' to an int, uint, long or ulong. // public Expression ConvertExpressionToArrayIndex (EmitContext ec, Expression source) { Expression converted; using (ec.With (EmitContext.Flags.CheckState, true)) { converted = Convert.ImplicitConversion (ec, source, TypeManager.int32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint32_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.int64_type, source.loc); if (converted == null) converted = Convert.ImplicitConversion (ec, source, TypeManager.uint64_type, source.loc); if (converted == null) { source.Error_ValueCannotBeConverted (ec, source.loc, TypeManager.int32_type, false); return null; } } // // Only positive constants are allowed at compile time // Constant c = converted as Constant; if (c != null) { if (c.IsNegative) { Error_NegativeArrayIndex (source.loc); } return c; } return new ArrayIndexCast (converted).Resolve (ec); }
/// <summary> /// Resolves the expression `e' into a boolean expression: either through /// an implicit conversion, or through an `operator true' invocation /// </summary> public static Expression ResolveBoolean (ResolveContext ec, Expression e, Location loc) { e = e.Resolve (ec); if (e == null) return null; if (e.Type == TypeManager.bool_type) return e; if (TypeManager.IsDynamicType (e.Type)) { Arguments args = new Arguments (1); args.Add (new Argument (e)); return new DynamicUnaryConversion ("IsTrue", args, loc).Resolve (ec); } Expression converted = Convert.ImplicitConversion (ec, e, TypeManager.bool_type, Location.Null); if (converted != null) return converted; // // If no implicit conversion to bool exists, try using `operator true' // converted = Expression.GetOperatorTrue (ec, e, loc); if (converted == null){ e.Error_ValueCannotBeConverted (ec, loc, TypeManager.bool_type, false); return null; } return converted; }
/// <summary> /// Performs an explicit conversion of the expression `expr' whose /// type is expr.Type to `target_type'. /// </summary> static public Expression ExplicitConversion (ResolveContext ec, Expression expr, Type target_type, Location loc) { Expression e = ExplicitConversionCore (ec, expr, target_type, loc); if (e != null) { // // Don't eliminate explicit precission casts // if (e == expr) { if (target_type == TypeManager.float_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); if (target_type == TypeManager.double_type) return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); } return e; } Type expr_type = expr.Type; if (TypeManager.IsNullableType (target_type)) { if (TypeManager.IsNullableType (expr_type)) { Type target = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (target_type)[0]); Expression unwrap = Nullable.Unwrap.Create (expr); e = ExplicitConversion (ec, unwrap, target, expr.Location); if (e == null) return null; return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec); } else if (expr_type == TypeManager.object_type) { return new UnboxCast (expr, target_type); } else { Type target = TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (target_type) [0]); e = ExplicitConversionCore (ec, expr, target, loc); if (e != null) return Nullable.Wrap.Create (e, target_type); } } else if (TypeManager.IsNullableType (expr_type)) { e = Nullable.Unwrap.Create (expr, false); bool use_class_cast; if (ImplicitBoxingConversionExists (e, target_type, out use_class_cast)) return new BoxedCast (expr, target_type); e = ExplicitConversionCore (ec, e, target_type, loc); if (e != null) return EmptyCast.Create (e, target_type); } e = ExplicitUserConversion (ec, expr, target_type, loc); if (e != null) return e; expr.Error_ValueCannotBeConverted (ec, loc, target_type, true); return null; }