diff --git a/CHANGELOG.md b/CHANGELOG.md index 74fe2c50306f..de7d9e3d9842 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Compatibility: * Do not autosplat a proc that accepts a single positional argument and keywords (#3039, @andrykonchin). * Support passing anonymous * and ** parameters as method call arguments (#3039, @andrykonchin). * Handle either positional or keywords arguments by default in `Struct.new` (#3039, @rwstauner). +* Support `lambda` argument in `Proc#parameters` (#3039, @thomasmarshall, @goyox86). Performance: diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb index 6a8d01e0442e..9513daa17a33 100644 --- a/spec/ruby/core/proc/parameters_spec.rb +++ b/spec/ruby/core/proc/parameters_spec.rb @@ -33,6 +33,16 @@ it "regards named parameters in lambda as optional if lambda: false keyword used" do -> x { }.parameters(lambda: false).first.first.should == :opt end + + it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do + proc {|x| }.parameters(lambda: 123).first.first.should == :req + -> x { }.parameters(lambda: 123).first.first.should == :req + end + + it "ignores the lambda keyword if it is nil" do + proc {|x|}.parameters(lambda: nil).first.first.should == :opt + -> x { }.parameters(lambda: nil).first.first.should == :req + end end it "regards optional keyword parameters in procs as optional" do diff --git a/spec/tags/core/proc/parameters_tags.txt b/spec/tags/core/proc/parameters_tags.txt index 2d28854ff8e1..07834e1c3c9d 100644 --- a/spec/tags/core/proc/parameters_tags.txt +++ b/spec/tags/core/proc/parameters_tags.txt @@ -1,6 +1,3 @@ -fails:Proc#parameters sets the first element of each sub-Array to :req for required argument if lambda keyword used -fails:Proc#parameters regards named parameters in procs as required if lambda keyword used -fails:Proc#parameters regards named parameters in lambda as optional if lambda: false keyword used fails:Proc#parameters adds rest arg with name * for "star" argument fails:Proc#parameters adds keyrest arg with ** as a name for "double star" argument fails:Proc#parameters adds block arg with name & for anonymous block argument diff --git a/src/main/java/org/truffleruby/core/proc/ProcNodes.java b/src/main/java/org/truffleruby/core/proc/ProcNodes.java index 8cab3f6c5b8f..324b597c80ca 100644 --- a/src/main/java/org/truffleruby/core/proc/ProcNodes.java +++ b/src/main/java/org/truffleruby/core/proc/ProcNodes.java @@ -203,18 +203,18 @@ boolean lambda(RubyProc proc) { } - @CoreMethod(names = "parameters") - public abstract static class ParametersNode extends CoreMethodArrayArgumentsNode { + @Primitive(name = "proc_parameters") + public abstract static class ParametersNode extends PrimitiveArrayArgumentsNode { - @TruffleBoundary @Specialization - RubyArray parameters(RubyProc proc) { + RubyArray parameters(RubyProc proc, Object lambdaObject) { final ArgumentDescriptor[] argsDesc = proc.getArgumentDescriptors(); - final boolean isLambda = proc.type == ProcType.LAMBDA; + final boolean isLambda = (lambdaObject == nil) + ? proc.type == ProcType.LAMBDA + : !lambdaObject.equals(Boolean.FALSE); return ArgumentDescriptorUtils .argumentDescriptorsToParameters(getLanguage(), getContext(), argsDesc, isLambda); } - } @CoreMethod(names = "source_location") diff --git a/src/main/ruby/truffleruby/core/proc.rb b/src/main/ruby/truffleruby/core/proc.rb index 90e7fed6e8b1..bc3b06fcb6a6 100644 --- a/src/main/ruby/truffleruby/core/proc.rb +++ b/src/main/ruby/truffleruby/core/proc.rb @@ -128,4 +128,8 @@ def <<(other) end end end + + def parameters(lambda: nil) + Primitive.proc_parameters(self, lambda) + end end