Esempio n. 1
0
        public virtual Proc /*!*/ ToProc(RubyScope /*!*/ scope)
        {
            ContractUtils.RequiresNotNull(scope, "scope");

            if (_procDispatcher == null)
            {
                var site = CallSite <Func <CallSite, object, object, object> > .Create(
                    // TODO: use InvokeBinder
                    RubyCallAction.Make(
                        scope.RubyContext, "call",
                        new RubyCallSignature(1, RubyCallFlags.HasImplicitSelf | RubyCallFlags.HasSplattedArgument)
                        )
                    );

                var block = new BlockCallTargetUnsplatN((blockParam, self, args, unsplat) => {
                    // block takes no parameters but unsplat => all actual arguments are added to unsplat:
                    Debug.Assert(args.Length == 0);

                    return(site.Target(site, this, unsplat));
                });

                _procDispatcher = new BlockDispatcherUnsplatN(0,
                                                              BlockDispatcher.MakeAttributes(BlockSignatureAttributes.HasUnsplatParameter, _info.GetArity()),
                                                              null, 0
                                                              );

                _procDispatcher.SetMethod(block);
            }

            // TODO:
            // MRI: source file/line are that of the to_proc method call:
            return(new Proc(ProcKind.Block, scope.SelfObject, scope, _procDispatcher));
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a proc that invokes a method of given name.
        /// <code>
        /// Proc.new do |*args|
        ///   raise ArgumentException if args.size == 0
        ///   obj.methodName(args.delete_at(0), args)
        /// end
        /// </code>
        /// </summary>
        public static Proc /*!*/ CreateMethodInvoker(RubyScope /*!*/ scope, string /*!*/ methodName)
        {
            ContractUtils.RequiresNotNull(scope, "scope");

            // TODO:
            // This should pass a proc parameter (use BlockDispatcherUnsplatProcN).
            // MRI 1.9.2 doesn't do so though (see http://redmine.ruby-lang.org/issues/show/3792).

            var site = CallSite <Func <CallSite, object, object, object, object> > .Create(
                RubyCallAction.Make(
                    scope.RubyContext, methodName,
                    new RubyCallSignature(0, RubyCallFlags.HasScope | RubyCallFlags.HasSplattedArgument)
                    )
                );

            var block = new BlockCallTargetUnsplatN((blockParam, self, args, unsplat) => {
                Debug.Assert(args.Length == 0);
                if (unsplat.Count == 0)
                {
                    throw RubyExceptions.CreateArgumentError("no receiver given");
                }
                object target = unsplat[0];
                unsplat.RemoveAt(0);
                return(site.Target(site, scope, target, unsplat));
            });

            var procDispatcher = new BlockDispatcherUnsplatN(0,
                                                             BlockDispatcher.MakeAttributes(BlockSignatureAttributes.HasUnsplatParameter, -1),
                                                             null, 0
                                                             );

            procDispatcher.SetMethod(block);
            return(new Proc(ProcKind.Proc, scope.SelfObject, scope, procDispatcher));
        }