public override Expression /*!*/ Convert(DynamicMetaObject /*!*/ metaObject, Type restrictedType, ParameterInfo info, Type /*!*/ toType)
        {
            Expression expr     = metaObject.Expression;
            Type       fromType = restrictedType ?? expr.Type;

            // block:
            if (fromType == typeof(MissingBlockParam))
            {
                Debug.Assert(toType == typeof(BlockParam) || toType == typeof(MissingBlockParam));
                return(AstUtils.Constant(null));
            }

            if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam))
            {
                return(AstUtils.Constant(null));
            }

            // protocol conversions:
            if (info != null && info.IsDefined(typeof(DefaultProtocolAttribute), false))
            {
                var action = RubyConversionAction.TryGetDefaultConversionAction(Context, toType);
                if (action != null)
                {
                    // TODO: inline implicit conversions:
                    return(AstUtils.LightDynamic(action, toType, expr));
                }

                // Do not throw an exception here to allow generic type parameters to be used with D.P. attribute.
                // The semantics should be to use DP if available for the current instantiation and ignore it otherwise.
            }

            if (restrictedType != null)
            {
                if (restrictedType == typeof(DynamicNull))
                {
                    if (!toType.IsValueType || toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable <>))
                    {
                        return(AstUtils.Constant(null, toType));
                    }
                    else if (toType == typeof(bool))
                    {
                        return(AstUtils.Constant(false));
                    }
                }

                if (toType.IsAssignableFrom(restrictedType))
                {
                    // expr can be converted to restrictedType, which can be converted toType => we can convert expr to toType:
                    return(AstUtils.Convert(expr, CompilerHelpers.GetVisibleType(toType)));
                }

                // if there is a simple conversion from restricted type, convert the expression to the restricted type and use that conversion:
                Type visibleRestrictedType = CompilerHelpers.GetVisibleType(restrictedType);
                if (Converter.CanConvertFrom(metaObject, visibleRestrictedType, toType, false, NarrowingLevel.None, false, false).IsConvertible)
                {
                    expr = AstUtils.Convert(expr, visibleRestrictedType);
                }
            }

            return(Converter.ConvertExpression(expr, toType, _args.RubyContext, _args.MetaContext.Expression, _implicitProtocolConversions));
        }
示例#2
0
 public CallSite <Func <CallSite, object, TResult> > /*!*/ GetSite(RubyConversionAction /*!*/ conversion)
 {
     return(RubyUtils.GetCallSite(ref Site, conversion));
 }