mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Make Symbol#to_proc calls handle keyword arguments
Make rb_sym_proc_call take a flag for whether a keyword argument is used, and use the new rb_funcall_with_block_kw function to pass that information.
This commit is contained in:
parent
38dae1d510
commit
6f9b86616a
4 changed files with 77 additions and 5 deletions
|
@ -2140,7 +2140,7 @@ VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc);
|
|||
#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
|
||||
#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
|
||||
size_t rb_str_memsize(VALUE);
|
||||
VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc);
|
||||
VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc);
|
||||
VALUE rb_sym_to_proc(VALUE sym);
|
||||
char *rb_str_to_cstr(VALUE str);
|
||||
VALUE rb_str_eql(VALUE str1, VALUE str2);
|
||||
|
|
4
string.c
4
string.c
|
@ -10887,7 +10887,7 @@ sym_to_sym(VALUE sym)
|
|||
}
|
||||
|
||||
MJIT_FUNC_EXPORTED VALUE
|
||||
rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc)
|
||||
rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc)
|
||||
{
|
||||
VALUE obj;
|
||||
|
||||
|
@ -10895,7 +10895,7 @@ rb_sym_proc_call(ID mid, int argc, const VALUE *argv, VALUE passed_proc)
|
|||
rb_raise(rb_eArgError, "no receiver given");
|
||||
}
|
||||
obj = argv[0];
|
||||
return rb_funcall_with_block(obj, mid, argc - 1, argv + 1, passed_proc);
|
||||
return rb_funcall_with_block_kw(obj, mid, argc - 1, argv + 1, passed_proc, kw_splat);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -447,6 +447,79 @@ class TestKeywordArguments < Test::Unit::TestCase
|
|||
assert_equal([1, h3], c.send(:m, **h3))
|
||||
end
|
||||
|
||||
def test_sym_proc_kwsplat
|
||||
kw = {}
|
||||
h = {'a'=>1}
|
||||
h2 = {'a'=>1}
|
||||
h3 = {'a'=>1, :a=>1}
|
||||
|
||||
c = Object.new
|
||||
def c.m(*args)
|
||||
args
|
||||
end
|
||||
assert_equal([], :m.to_proc.call(c, **{}))
|
||||
assert_equal([], :m.to_proc.call(c, **kw))
|
||||
assert_equal([h], :m.to_proc.call(c, **h))
|
||||
assert_equal([h2], :m.to_proc.call(c, **h2))
|
||||
assert_equal([h3], :m.to_proc.call(c, **h3))
|
||||
|
||||
c.singleton_class.remove_method(:m)
|
||||
def c.m; end
|
||||
assert_nil(:m.to_proc.call(c, **{}))
|
||||
assert_nil(:m.to_proc.call(c, **kw))
|
||||
assert_raise(ArgumentError) { :m.to_proc.call(c, **h) }
|
||||
assert_raise(ArgumentError) { :m.to_proc.call(c, **h2) }
|
||||
assert_raise(ArgumentError) { :m.to_proc.call(c, **h3) }
|
||||
|
||||
c.singleton_class.remove_method(:m)
|
||||
def c.m(args)
|
||||
args
|
||||
end
|
||||
assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) }
|
||||
assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) }
|
||||
assert_equal(h, :m.to_proc.call(c, **h))
|
||||
assert_equal(h2, :m.to_proc.call(c, **h2))
|
||||
assert_equal(h3, :m.to_proc.call(c, **h3))
|
||||
|
||||
c.singleton_class.remove_method(:m)
|
||||
def c.m(**args)
|
||||
args
|
||||
end
|
||||
assert_equal(kw, :m.to_proc.call(c, **{}))
|
||||
assert_equal(kw, :m.to_proc.call(c, **kw))
|
||||
assert_equal(h, :m.to_proc.call(c, **h))
|
||||
assert_equal(h2, :m.to_proc.call(c, **h2))
|
||||
assert_equal(h3, :m.to_proc.call(c, **h3))
|
||||
|
||||
c.singleton_class.remove_method(:m)
|
||||
def c.m(arg, **args)
|
||||
[arg, args]
|
||||
end
|
||||
assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) }
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
|
||||
assert_equal([kw, kw], :m.to_proc.call(c, **kw))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
|
||||
assert_equal([h, kw], :m.to_proc.call(c, **h))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
|
||||
assert_equal([h2, kw], :m.to_proc.call(c, **h2))
|
||||
end
|
||||
assert_warn(/The keyword argument is passed as the last hash parameter.* for `m'/m) do
|
||||
assert_equal([h3, kw], :m.to_proc.call(c, **h3))
|
||||
end
|
||||
|
||||
c.singleton_class.remove_method(:m)
|
||||
def c.m(arg=1, **args)
|
||||
[arg=1, args]
|
||||
end
|
||||
assert_equal([1, kw], :m.to_proc.call(c, **{}))
|
||||
assert_equal([1, kw], :m.to_proc.call(c, **kw))
|
||||
assert_equal([1, h], :m.to_proc.call(c, **h))
|
||||
assert_equal([1, h2], :m.to_proc.call(c, **h2))
|
||||
assert_equal([1, h3], :m.to_proc.call(c, **h3))
|
||||
end
|
||||
|
||||
def test_method_missing_kwsplat
|
||||
kw = {}
|
||||
h = {'a'=>1}
|
||||
|
|
|
@ -2884,8 +2884,7 @@ vm_yield_with_cfunc(rb_execution_context_t *ec,
|
|||
static VALUE
|
||||
vm_yield_with_symbol(rb_execution_context_t *ec, VALUE symbol, int argc, const VALUE *argv, int kw_splat, VALUE block_handler)
|
||||
{
|
||||
/* XXX: need to pass kw_splat? */
|
||||
return rb_sym_proc_call(SYM2ID(symbol), argc, argv, rb_vm_bh_to_procval(ec, block_handler));
|
||||
return rb_sym_proc_call(SYM2ID(symbol), argc, argv, kw_splat, rb_vm_bh_to_procval(ec, block_handler));
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
Loading…
Reference in a new issue