AddTypeRestriction() public method

public AddTypeRestriction ( Type type, Expression expression ) : void
type System.Type
expression Expression
return void
Ejemplo n.º 1
0
            public override DynamicMetaObject /*!*/ FallbackInvoke(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args,
                                                                   DynamicMetaObject errorSuggestion)
            {
                // Used in combination with GetMember to compose InvokeMember operation.
                // Gets here only if the target is not a callable meta-object.

                var metaBuilder = new MetaObjectBuilder(this, target, args);
                var callArgs    = new CallArguments(_context, target, args, CallInfo);

                metaBuilder.AddTypeRestriction(target.GetLimitType(), target.Expression);

                RubyOverloadResolver.NormalizeArguments(metaBuilder, callArgs, 0, 0);
                if (!metaBuilder.Error)
                {
                    // no arguments => just return the target:
                    metaBuilder.Result = target.Expression;
                }
                else
                {
                    // any arguments found (expected none):
                    metaBuilder.SetMetaResult(errorSuggestion, false);
                }

                return(metaBuilder.CreateMetaObject(this));
            }
Ejemplo n.º 2
0
        internal static bool TryBuildConversionToDelegate(MetaObjectBuilder /*!*/ metaBuilder, RubyMetaObject /*!*/ target, Type /*!*/ delegateType, MethodInfo /*!*/ delegateFactory)
        {
            if (!typeof(Delegate).IsAssignableFrom(delegateType) || delegateType.GetMethod("Invoke") == null)
            {
                return(false);
            }

            var type = target.Value.GetType();

            metaBuilder.AddTypeRestriction(type, target.Expression);
            metaBuilder.Result = delegateFactory.OpCall(AstUtils.Constant(delegateType), Ast.Convert(target.Expression, type));
            return(true);
        }
Ejemplo n.º 3
0
        internal static void BuildConversion(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args)
        {
            const string ToS = "to_s";

            if (TryImplicitConversion(metaBuilder, args)) {
                metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
                return;
            }

            RubyMemberInfo conversionMethod, methodMissing = null;

            RubyClass targetClass = args.RubyContext.GetImmediateClassOf(args.Target);
            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext,
                    new[] { ToS, Symbols.MethodMissing }
                );

                conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, VisibilityContext.AllVisible).Info;

                // find method_missing - we need to add "to_s" method to the missing methods table:
                if (conversionMethod == null) {
                    methodMissing = targetClass.ResolveMethodMissingForSite(ToS, RubyMethodVisibility.None);
                }
            }

            // invoke target.to_s and if successful convert the result to string unless it is already:
            if (conversionMethod != null) {
                conversionMethod.BuildCall(metaBuilder, args, ToS);
            } else {
                RubyCallAction.BuildMethodMissingCall(metaBuilder, args, ToS, methodMissing, RubyMethodVisibility.None, false, true);
            }

            if (metaBuilder.Error) {
                return;
            }

            metaBuilder.Result = Methods.ToSDefaultConversion.OpCall(
                AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)),
                AstUtils.Box(args.TargetExpression),
                AstUtils.Box(metaBuilder.Result)
            );
        }
Ejemplo n.º 4
0
        protected override void Build(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            const string ToS = "to_s";

            // no conversion for a subclass of string:
            var stringTarget = args.Target as MutableString;
            if (stringTarget != null) {
                metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
                metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(MutableString));
                return;
            }

            RubyMemberInfo conversionMethod, methodMissing = null;

            RubyClass targetClass = args.RubyContext.GetImmediateClassOf(args.Target);
            using (targetClass.Context.ClassHierarchyLocker()) {
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext);
                conversionMethod = targetClass.ResolveMethodForSiteNoLock(ToS, RubyClass.IgnoreVisibility).Info;

                // find method_missing - we need to add "to_xxx" methods to the missing methods table:
                if (conversionMethod == null) {
                    methodMissing = targetClass.ResolveMethodMissingForSite(ToS, RubyMethodVisibility.None);
                }
            }
            
            // invoke target.to_s and if successful convert the result to string unless it is already:
            if (conversionMethod != null) {
                conversionMethod.BuildCall(metaBuilder, args, ToS);

                if (metaBuilder.Error) {
                    return;
                }
            } else {
                RubyCallAction.BindToMethodMissing(metaBuilder, args, ToS, methodMissing, RubyMethodVisibility.None, false, true);
            }

            metaBuilder.Result = Methods.ToSDefaultConversion.OpCall(
                AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), 
                AstFactory.Box(args.TargetExpression), 
                AstFactory.Box(metaBuilder.Result)
            );
        }
Ejemplo n.º 5
0
            public override DynamicMetaObject/*!*/ FallbackInvoke(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, 
                DynamicMetaObject errorSuggestion) {

                // Used in combination with GetMember to compose InvokeMember operation.
                // Gets here only if the target is not a callable meta-object. 

                var metaBuilder = new MetaObjectBuilder(this, target, args);
                var callArgs = new CallArguments(_context, target, args, CallInfo);

                metaBuilder.AddTypeRestriction(target.GetLimitType(), target.Expression);

                var normalizedArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, callArgs, 0, 0);
                if (!metaBuilder.Error) {
                    // no arguments => just return the target:
                    metaBuilder.Result = target.Expression;
                } else {
                    // any arguments found (expected none):
                    metaBuilder.SetMetaResult(errorSuggestion, false);
                }
                
                return metaBuilder.CreateMetaObject(this);
            }
Ejemplo n.º 6
0
        internal void BuildInvoke(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            Assert.NotNull(metaBuilder, args);

            var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(Proc));

            // test for target type:
            metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);

            BuildCall(
                metaBuilder,
                convertedTarget,                       // proc object  
                Methods.GetProcSelf.OpCall(convertedTarget),  // self captured by the block closure
                args
            );
        }
Ejemplo n.º 7
0
        internal void SetRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            Assert.NotNull(metaBuilder, args);
            Debug.Assert(args.SimpleArgumentCount == 0 && !args.Signature.HasBlock && !args.Signature.HasSplattedArgument && !args.Signature.HasRhsArgument);
            Debug.Assert(args.Signature.HasScope);

            var ec = args.RubyContext;

            // implicit conversions should only depend on a static type:
            if (TryImplicitConversion(metaBuilder, args))
            {
                if (args.Target == null)
                {
                    metaBuilder.AddRestriction(Ast.Equal(args.TargetExpression, Ast.Constant(null, args.TargetExpression.Type)));
                }
                else
                {
                    metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
                }
                return;
            }

            // check for type version:
            metaBuilder.AddTargetTypeTest(args);

            string     toMethodName            = ToMethodName;
            Expression targetClassNameConstant = Ast.Constant(ec.GetClassOf(args.Target).Name);

            // Kernel#respond_to? method is not overridden => we can optimize
            RubyMemberInfo respondToMethod = ec.ResolveMethod(args.Target, Symbols.RespondTo, true).InvalidateSitesOnOverride();

            if (respondToMethod == null ||
                // the method is defined in library, hasn't been replaced by user defined method (TODO: maybe we should make this check better)
                (respondToMethod.DeclaringModule == ec.KernelModule && respondToMethod is RubyMethodGroupInfo))
            {
                RubyMemberInfo conversionMethod = ec.ResolveMethod(args.Target, toMethodName, false).InvalidateSitesOnOverride();
                if (conversionMethod == null)
                {
                    // error:
                    SetError(metaBuilder, targetClassNameConstant, args);
                    return;
                }
                else
                {
                    // invoke target.to_xxx() and validate it; returns an instance of TTargetType:
                    conversionMethod.BuildCall(metaBuilder, args, toMethodName);

                    if (!metaBuilder.Error && ConversionResultValidator != null)
                    {
                        metaBuilder.Result = ConversionResultValidator.OpCall(targetClassNameConstant, AstFactory.Box(metaBuilder.Result));
                    }
                    return;
                }
            }
            else if (!RubyModule.IsMethodVisible(respondToMethod, false))
            {
                // respond_to? is private:
                SetError(metaBuilder, targetClassNameConstant, args);
                return;
            }

            // slow path: invoke respond_to?, to_xxx and result validation:

            var conversionCallSite = Ast.Dynamic(
                RubyCallAction.Make(toMethodName, RubyCallSignature.WithScope(0)),
                typeof(object),
                args.ScopeExpression, args.TargetExpression
                );

            Expression opCall;

            metaBuilder.Result = Ast.Condition(
                // If

                // respond_to?()
                Methods.IsTrue.OpCall(
                    Ast.Dynamic(
                        RubyCallAction.Make(Symbols.RespondTo, RubyCallSignature.WithScope(1)),
                        typeof(object),
                        args.ScopeExpression, args.TargetExpression, Ast.Constant(SymbolTable.StringToId(toMethodName))
                        )
                    ),

                // Then

                // to_xxx():
                opCall = (ConversionResultValidator == null) ? conversionCallSite :
                         ConversionResultValidator.OpCall(targetClassNameConstant, conversionCallSite),

                // Else

                AstUtils.Convert(
                    (ConversionResultValidator == null) ? args.TargetExpression :
                    Ast.Convert(
                        Ast.Throw(Methods.CreateTypeConversionError.OpCall(targetClassNameConstant, Ast.Constant(TargetTypeName))),
                        typeof(object)
                        ),
                    opCall.Type
                    )
                );
        }
Ejemplo n.º 8
0
        private Expression/*!*/ MarshalArgument(MetaObjectBuilder/*!*/ metaBuilder, DynamicMetaObject/*!*/ arg, ArgType parameterType) {
            object value = arg.Value;
            if (value == null) {
                metaBuilder.AddRestriction(Ast.Equal(arg.Expression, AstUtils.Constant(null)));
            } else {
                metaBuilder.AddTypeRestriction(value.GetType(), arg.Expression);
            }

            switch (parameterType) {
                case ArgType.Buffer:
                    if (value == null) {
                        return AstUtils.Constant(null, typeof(byte[]));
                    }

                    if (value is int && (int)value == 0) {
                        metaBuilder.AddRestriction(Ast.Equal(AstUtils.Convert(arg.Expression, typeof(int)), AstUtils.Constant(0)));
                        return AstUtils.Constant(null, typeof(byte[]));
                    }

                    if (value.GetType() == typeof(MutableString)) {
                        return Methods.GetMutableStringBytes.OpCall(
                            AstUtils.Convert(arg.Expression, typeof(MutableString))
                        );
                    } 
                    
                    return Methods.GetMutableStringBytes.OpCall(
                        AstUtils.LightDynamic(ConvertToStrAction.Make(_context), typeof(MutableString), arg.Expression)
                    );

                case ArgType.Int32:
                    if (value is int) {
                        return AstUtils.Convert(arg.Expression, typeof(int));
                    }

                    return Ast.Convert(
                        Ast.Call(
                            AstUtils.LightDynamic(ConvertToIntAction.Make(_context), typeof(IntegerValue), arg.Expression), 
                            Methods.IntegerValue_ToUInt32Unchecked
                        ), 
                        typeof(int)
                    );
            }
            throw Assert.Unreachable;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// "yields" to the proc.
        /// </summary>
        internal void BuildInvoke(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args) {
            Assert.NotNull(metaBuilder, args);
            Debug.Assert(!args.Signature.HasBlock);

            var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(BlockParam));

            // test for target type:
            metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);

            metaBuilder.Result = AstFactory.YieldExpression(
                args.GetSimpleArgumentExpressions(),
                args.GetSplattedArgumentExpression(),
                args.GetRhsArgumentExpression(),
                convertedTarget,                              // block param
                Ast.Property(convertedTarget, SelfProperty)   // self
            );
        }
Ejemplo n.º 10
0
        internal static bool TryBuildConversionToDelegate(MetaObjectBuilder/*!*/ metaBuilder, RubyMetaObject/*!*/ metaTarget, Type/*!*/ delegateType, MethodInfo/*!*/ delegateFactory) {
            MethodInfo invoke;
            if (!typeof(Delegate).IsAssignableFrom(delegateType) || (invoke = delegateType.GetMethod("Invoke")) == null) {
                return false;
            }

            var type = metaTarget.Value.GetType();
            metaBuilder.AddTypeRestriction(type, metaTarget.Expression);
            metaBuilder.Result = delegateFactory.OpCall(AstUtils.Constant(delegateType), Ast.Convert(metaTarget.Expression, type));
            return true;
        }
Ejemplo n.º 11
0
        internal static void SetCallActionRule(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, bool testTarget) {
            Assert.NotNull(metaBuilder, args);

            var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(Proc));

            // test for target type:
            if (testTarget) {
                metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression);
            }

            SetProcCallRule(
                metaBuilder,
                convertedTarget,                              // proc object  
                Ast.Property(convertedTarget, SelfProperty),  // self captured by the block closure
                null,
                args
            );
        }