Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
		/// <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;
		}
Exemple #4
0
		/// <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;
		}
Exemple #5
0
		/// <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;
		}
Exemple #6
0
		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;
		}
Exemple #7
0
        //
        // 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);
        }
Exemple #8
0
        /// <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;
        }
Exemple #9
0
        /// <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;
        }
Exemple #10
0
		/// <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;
		}
Exemple #11
0
		//
		// 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;
		}