protected internal override bool TryImplicitConversion(MetaObjectBuilder metaBuilder, CallArguments args)
        {
            if (base.TryImplicitConversion(metaBuilder, args))
            {
                return(true);
            }

            var convertedTarget = args.Target as RubySymbol;

            if (convertedTarget != null)
            {
                metaBuilder.Result = Methods.ConvertSymbolToMutableString.OpCall(AstUtils.Convert(args.TargetExpression, typeof(RubySymbol)));
                return(true);
            }
            return(false);
        }
Example #2
0
File: Proc.cs Project: ltwlf/IronSP
        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
                );
        }
Example #3
0
        private void BuildCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name)
        {
            var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue);

            if (metaBuilder.Error)
            {
                return;
            }

            metaBuilder.AddRestriction(
                Ast.Equal(
                    Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), VersionProperty),
                    Ast.Constant(_version)
                    )
                );

            if (_function == IntPtr.Zero)
            {
                metaBuilder.SetError(Ast.Throw(new Func <Exception>(UninitializedFunctionError).Method.OpCall(), typeof(object)));
                return;
            }

            if (_signature.Length != actualArgs.Count)
            {
                metaBuilder.SetError(Ast.Throw(new Func <int, int, Exception>(InvalidParameterCountError).Method.OpCall(
                                                   Ast.Constant(_signature.Length), Ast.Constant(actualArgs.Count)), typeof(object)
                                               ));
                return;
            }

            var calliArgs = new AstExpressions();

            calliArgs.Add(Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), FunctionProperty));
            for (int i = 0; i < actualArgs.Count; i++)
            {
                calliArgs.Add(MarshalArgument(metaBuilder, actualArgs[i], _signature[i]));
            }

            metaBuilder.Result = Ast.Call(EmitCalliStub(), calliArgs);

            // MRI returns 0 if void return type is given:
            if (_returnType == ArgType.None)
            {
                metaBuilder.Result = Ast.Block(metaBuilder.Result, AstUtils.Constant(0));
            }
        }
        internal static bool TryImplicitConversionInternal(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            if (args.Target == null)
            {
                metaBuilder.Result = AstUtils.Constant(null, typeof(TTargetType));
                return(true);
            }

            var convertedTarget = args.Target as TTargetType;

            if (convertedTarget != null)
            {
                metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(TTargetType));
                return(true);
            }
            return(false);
        }
Example #5
0
        /// <summary>
        /// OldCallAction on Proc target.
        /// From control flow perspective it "yields" to the proc.
        /// </summary>
        internal void SetCallActionRule(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
                );
        }
        protected internal override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            // *nil -> [nil]
            if (args.Target == null)
            {
                metaBuilder.Result = Methods.MakeArray1.OpCall(AstUtils.Constant(null));
                return(true);
            }

            var convertedTarget = args.Target as IList;

            if (convertedTarget != null)
            {
                metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(IList));
                return(true);
            }
            return(false);
        }
Example #7
0
            public override MetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ action, MetaObject /*!*/[] /*!*/ args)
            {
                RubyCallSignature callSignature;

                if (RubyCallSignature.TryCreate(action.Arguments, out callSignature))
                {
                    return(action.FallbackInvoke(this, args));
                }

                var metaBuilder = new MetaObjectBuilder();

                var context = new MetaObject(
                    Methods.GetContextFromBlockParam.OpCall(AstUtils.Convert(Expression, typeof(BlockParam))),
                    Restrictions.Empty,
                    RubyOps.GetContextFromBlockParam((BlockParam)Value)
                    );

                BlockParam.SetCallActionRule(metaBuilder, new CallArguments(context, this, args, callSignature));
                return(metaBuilder.CreateMetaObject(action, args));
            }
Example #8
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
                );
        }
        public void OverloadResolution_Block1()
        {
            var scope = Context.EmptyScope;
            var proc  = new Proc(ProcKind.Proc, null, scope, new BlockDispatcher0(BlockSignatureAttributes.None, null, 0).
                                 SetMethod(new BlockCallTarget0((x, y) => null)));

            var arguments = new[] {
                // 1.times
                new CallArguments(Context, MO(scope), new[] { MO(1) }, RubyCallSignature.WithScope(0)),
                // 1.times &nil
                new CallArguments(Context, MO(scope), new[] { MO(1), MO(null) }, RubyCallSignature.WithScopeAndBlock(0)),
                // 1.times &p
                new CallArguments(Context, MO(1), new[] { MO(proc) }, RubyCallSignature.WithBlock(0)),
                // obj.times &p
                new CallArguments(Context, MO("foo"), new[] { MO(proc) }, RubyCallSignature.WithBlock(0)),
            };

            var results = new[] {
                "Times2",
                "Times1",
                "Times3",
                "Times4",
            };

            var metaBuilder = new MetaObjectBuilder(null);

            for (int i = 0; i < arguments.Length; i++)
            {
                RubyOverloadResolver resolver;

                var methods = GetStaticMethodsStartingWith(typeof(OverloadsWithBlock), "Times");

                var bindingTarget = RubyMethodGroupInfo.ResolveOverload(
                    metaBuilder, arguments[i], "times", methods, SelfCallConvention.SelfIsParameter,
                    false, out resolver
                    );

                Assert(bindingTarget.Success);
                Assert(bindingTarget.Overload.Name == results[i]);
            }
        }
Example #10
0
        private static void BuildOverriddenInitializerCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, RubyMemberInfo /*!*/ initializer)
        {
            var instanceExpr = metaBuilder.Result;

            metaBuilder.Result = null;

            var instanceVariable = metaBuilder.GetTemporary(instanceExpr.Type, "#instance");

            // We know an exact type of the new instance and that there is no singleton for that instance.
            // We also have the exact method we need to call ("initialize" is a RubyMethodInfo).
            // => no tests are necessary:
            args.SetTarget(instanceVariable, null);

            if (initializer is RubyMethodInfo)
            {
                initializer.BuildCall(metaBuilder, args, Symbols.Initialize);
            }
            else
            {
                // TODO: we need more refactoring of RubyMethodGroupInfo.BuildCall to be able to inline this:
                metaBuilder.Result = Ast.Dynamic(
                    RubyCallAction.Make("initialize",
                                        new RubyCallSignature(args.Signature.ArgumentCount, args.Signature.Flags | RubyCallFlags.HasImplicitSelf)
                                        ),
                    typeof(object),
                    args.GetCallSiteArguments(instanceVariable)
                    );
            }

            if (!metaBuilder.Error)
            {
                // PropagateRetrySingleton(instance = new <type>(), instance.initialize(<args>))
                metaBuilder.Result = Methods.PropagateRetrySingleton.OpCall(
                    Ast.Assign(instanceVariable, instanceExpr),
                    metaBuilder.Result
                    );
                RubyMethodInfo.ApplyBlockFlowHandlingInternal(metaBuilder, args);
            }
        }
Example #11
0
        /// <summary>
        /// From control flow perspective it "calls" the proc.
        /// </summary>
        internal static void BuildCall(
            MetaObjectBuilder /*!*/ metaBuilder,
            Expression /*!*/ procExpression,     // proc object
            Expression /*!*/ selfExpression,     // self passed to the proc
            CallArguments /*!*/ args             // user arguments passed to the proc
            )
        {
            var bfcVariable = metaBuilder.GetTemporary(typeof(BlockParam), "#bfc");

            metaBuilder.Result = Ast.Block(
                Ast.Assign(bfcVariable, Methods.CreateBfcForProcCall.OpCall(AstUtils.Convert(procExpression, typeof(Proc)))),
                Methods.MethodProcCall.OpCall(bfcVariable,
                                              AstFactory.YieldExpression(
                                                  args.RubyContext,
                                                  args.GetSimpleArgumentExpressions(),
                                                  args.GetSplattedArgumentExpression(),
                                                  args.GetRhsArgumentExpression(),
                                                  bfcVariable,
                                                  selfExpression
                                                  )
                                              )
                );
        }
 internal protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
 {
     return(TryImplicitConversionInternal(metaBuilder, args));
 }
 protected virtual void SetError(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, Expression /*!*/ targetClassNameConstant, Type /*!*/ resultType)
 {
     metaBuilder.SetError(Methods.CreateTypeConversionError.OpCall(targetClassNameConstant, AstUtils.Constant(TargetTypeName)));
 }
 internal protected abstract bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args);
        internal static void BuildConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, Type /*!*/ resultType,
                                             params ProtocolConversionAction /*!*/[] /*!*/ conversions)
        {
            Assert.NotNull(metaBuilder, args, conversions);
            Debug.Assert(args.SimpleArgumentCount == 0 && !args.Signature.HasBlock && !args.Signature.HasSplattedArgument && !args.Signature.HasRhsArgument);
            Debug.Assert(!args.Signature.HasScope);

            // implicit conversions should only depend on the static type:
            foreach (var conversion in conversions)
            {
                if (conversion.TryImplicitConversion(metaBuilder, args))
                {
                    metaBuilder.AddObjectTypeRestriction(args.Target, args.TargetExpression);

                    if (!metaBuilder.Error)
                    {
                        metaBuilder.Result = ConvertResult(metaBuilder.Result, resultType);
                    }
                    return;
                }
            }

            RubyClass                targetClass = args.RubyContext.GetImmediateClassOf(args.Target);
            Expression               targetClassNameConstant = AstUtils.Constant(targetClass.GetNonSingletonClass().Name, typeof(string));
            MethodResolutionResult   respondToMethod, methodMissing = MethodResolutionResult.NotFound;
            ProtocolConversionAction selectedConversion = null;
            RubyMemberInfo           conversionMethod   = null;

            using (targetClass.Context.ClassHierarchyLocker()) {
                // check for type version:
                metaBuilder.AddTargetTypeTest(args.Target, targetClass, args.TargetExpression, args.MetaContext,
                                              ArrayUtils.Insert(Symbols.RespondTo, Symbols.MethodMissing, ArrayUtils.ConvertAll(conversions, (c) => c.ToMethodName))
                                              );

                // we can optimize if Kernel#respond_to? method is not overridden:
                respondToMethod = targetClass.ResolveMethodForSiteNoLock(Symbols.RespondTo, VisibilityContext.AllVisible);
                if (respondToMethod.Found && respondToMethod.Info.DeclaringModule == targetClass.Context.KernelModule && respondToMethod.Info is RubyLibraryMethodInfo)   // TODO: better override detection
                {
                    respondToMethod = MethodResolutionResult.NotFound;

                    // get the first applicable conversion:
                    foreach (var conversion in conversions)
                    {
                        selectedConversion = conversion;
                        conversionMethod   = targetClass.ResolveMethodForSiteNoLock(conversion.ToMethodName, VisibilityContext.AllVisible).Info;
                        if (conversionMethod != null)
                        {
                            break;
                        }
                        else
                        {
                            // find method_missing - we need to add "to_xxx" methods to the missing methods table:
                            if (!methodMissing.Found)
                            {
                                methodMissing = targetClass.ResolveMethodNoLock(Symbols.MethodMissing, VisibilityContext.AllVisible);
                            }
                            methodMissing.InvalidateSitesOnMissingMethodAddition(conversion.ToMethodName, targetClass.Context);
                        }
                    }
                }
            }

            if (!respondToMethod.Found)
            {
                if (conversionMethod == null)
                {
                    // error:
                    selectedConversion.SetError(metaBuilder, args, targetClassNameConstant, resultType);
                    return;
                }
                else
                {
                    // invoke target.to_xxx() and validate it; returns an instance of TTargetType:
                    conversionMethod.BuildCall(metaBuilder, args, selectedConversion.ToMethodName);

                    if (!metaBuilder.Error)
                    {
                        metaBuilder.Result = ConvertResult(
                            selectedConversion.MakeValidatorCall(args, targetClassNameConstant, metaBuilder.Result),
                            resultType
                            );
                    }
                    return;
                }
            }

            // slow path: invoke respond_to?, to_xxx and result validation:
            for (int i = conversions.Length - 1; i >= 0; i--)
            {
                string toMethodName = conversions[i].ToMethodName;

                var conversionCallSite = AstUtils.LightDynamic(
                    RubyCallAction.Make(args.RubyContext, toMethodName, RubyCallSignature.WithImplicitSelf(0)),
                    args.TargetExpression
                    );

                metaBuilder.Result = Ast.Condition(
                    // If

                    // respond_to?()
                    Methods.IsTrue.OpCall(
                        AstUtils.LightDynamic(
                            RubyCallAction.Make(args.RubyContext, Symbols.RespondTo, RubyCallSignature.WithImplicitSelf(1)),
                            args.TargetExpression,
                            Ast.Constant(args.RubyContext.CreateSymbol(toMethodName, RubyEncoding.Binary))
                            )
                        ),

                    // Then

                    // to_xxx():
                    ConvertResult(
                        conversions[i].MakeValidatorCall(args, targetClassNameConstant, conversionCallSite),
                        resultType
                        ),

                    // Else

                    (i < conversions.Length - 1) ? metaBuilder.Result :
                    conversions[i].MakeErrorExpression(args, targetClassNameConstant, resultType)
                    );
            }
        }
 protected override bool Build(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool defaultFallback)
 {
     Debug.Assert(defaultFallback, "custom fallback not supported");
     BuildConversion(metaBuilder, args, ReturnType, this);
     return(true);
 }
Example #17
0
 internal override void BuildInvoke(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
 {
     args.InsertMethodName(_methodNameArg);
     base.BuildInvoke(metaBuilder, args);
 }
        internal protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args)
        {
            object target = args.Target;

            return(target != null && (metaBuilder.Result = Convert(ReturnType, args)) != null);
        }
Example #19
0
 public DeferredTypeProxy(MetaObjectBuilder builder)
 {
     _name = builder.Name;
 }
Example #20
0
        public static MetaTypeProxy Create(MetaObjectBuilder builder)
        {
            Check.ArgumentNotNull(builder, "builder");

            return new DeferredTypeProxy(builder);
        }
 // return the target object on error:
 protected override void SetError(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, Expression /*!*/ targetClassNameConstant, Type /*!*/ resultType)
 {
     metaBuilder.Result = Ast.Convert(Methods.MakeArray1.OpCall(AstUtils.Box(args.TargetExpression)), typeof(IList));
 }
Example #22
0
        public void OverloadResolution_Numeric1()
        {
            var metaBuilder = new MetaObjectBuilder(null);

            Context.ObjectClass.SetConstant("X", Context.GetClass(typeof(Overloads1.X)));

            object c   = Engine.Execute(@"class C < X; new; end");
            var    sym = Context.CreateAsciiSymbol("x");
            var    ms  = MutableString.CreateAscii("x");

            var cases = new[] {
                // F
                new { Args = new[] { MO(1) }, Overloads = "F*", Result = "F1" },
                new { Args = new[] { MO((byte)1) }, Overloads = "F*", Result = "F1" },
                new { Args = new[] { MO(1L) }, Overloads = "F*", Result = "F2" },
                new { Args = new[] { MO(1.2F) }, Overloads = "F*", Result = "F3" },

                // G
                new { Args = new[] { MO(1) }, Overloads = "G*", Result = "G1" },
                new { Args = new[] { MO((byte)1) }, Overloads = "G*", Result = "G1" },
                new { Args = new[] { MO(1L) }, Overloads = "G*", Result = "G2" },
                new { Args = new[] { MO(1.2F) }, Overloads = "G*", Result = "G3" },
                new { Args = new[] { MO(c) }, Overloads = "G*", Result = "G1" },

                // I
                new { Args = new[] { MO(c) }, Overloads = "I*", Result = "I3" },

                // J
                new { Args = new[] { MO(1) }, Overloads = "J*", Result = "J1" },
                new { Args = new[] { MO((BigInteger)1000) }, Overloads = "J*", Result = "J2" },
                new { Args = new[] { MO((byte)12) }, Overloads = "J*", Result = "J1" },
                new { Args = new[] { MO(c) }, Overloads = "J*", Result = "J3" },
                new { Args = new[] { MO(1.0) }, Overloads = "J*", Result = "J3" },

                // K
                new { Args = new[] { MO(1) }, Overloads = "K*", Result = "K2" },
                new { Args = new[] { MO(c) }, Overloads = "K*", Result = "K1" },
                new { Args = new[] { MO("x") }, Overloads = "K*", Result = "K1" },

                // L
                new { Args = new[] { MO(sym), MO(sym) }, Overloads = "L*", Result = "L1" },
                new { Args = new[] { MO("x"), MO(sym) }, Overloads = "L*", Result = "L2" },
                new { Args = new[] { MO(ms), MO(sym) }, Overloads = "L*", Result = "L3" },
                new { Args = new[] { MO(null), MO(sym) }, Overloads = "L*", Result = "L3" },
                new { Args = new[] { MO(c), MO(sym) }, Overloads = "L*", Result = "L3" },

                // M
                new { Args = new[] { MO(1) }, Overloads = "M*", Result = "M1" },
                new { Args = new[] { MO(Overloads1.E.A) }, Overloads = "M*", Result = "M2" },

                // N
                new { Args = new[] { MO(MutableString.CreateAscii("x")) }, Overloads = "N*", Result = "N1" },
            };

            for (int i = 0; i < cases.Length; i++)
            {
                var args      = new CallArguments(Context, MO(new Overloads1()), cases[i].Args, RubyCallSignature.Simple(cases[i].Args.Length));
                var resolver  = new RubyOverloadResolver(metaBuilder, args, SelfCallConvention.SelfIsInstance, false);
                var overloads = GetInstanceMethods(typeof(Overloads1), cases[i].Overloads);
                var result    = resolver.ResolveOverload(i.ToString(), overloads, NarrowingLevel.None, NarrowingLevel.All);

                Assert(result.Success && result.Overload.Name == cases[i].Result);
            }
        }
 // return null if the object doesn't handle the conversion:
 protected override void SetError(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, Expression /*!*/ targetClassNameConstant, Type /*!*/ resultType)
 {
     metaBuilder.Result = AstUtils.Constant(null, resultType);
 }
Example #24
0
 protected override bool Build(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool defaultFallback)
 {
     Debug.Assert(defaultFallback, "custom fallback not supported");
     ProtocolConversionAction.BuildConversion(metaBuilder, args, _resultType, _conversions);
     return(true);
 }