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)); }
/// <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)); }