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