mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
34a95669da
* compile.c (iseq_set_arguments, iseq_compile_each): support required keyword arguments. [ruby-core:51454] [Feature #7701] * iseq.c (rb_iseq_parameters): ditto. * parse.y (f_kw, f_block_kw): ditto. this syntax is still experimental, the notation may change. * vm_core.h (rb_iseq_struct): ditto. * vm_insnhelper.c (vm_callee_setup_keyword_arg): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39735 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
314 lines
10 KiB
Ruby
314 lines
10 KiB
Ruby
require 'test/unit'
|
|
require_relative 'envutil'
|
|
|
|
class TestKeywordArguments < Test::Unit::TestCase
|
|
def f1(str: "foo", num: 424242)
|
|
[str, num]
|
|
end
|
|
|
|
def test_f1
|
|
assert_equal(["foo", 424242], f1)
|
|
assert_equal(["bar", 424242], f1(str: "bar"))
|
|
assert_equal(["foo", 111111], f1(num: 111111))
|
|
assert_equal(["bar", 111111], f1(str: "bar", num: 111111))
|
|
assert_raise(ArgumentError) { f1(str: "bar", check: true) }
|
|
assert_raise(ArgumentError) { f1("string") }
|
|
end
|
|
|
|
|
|
def f2(x, str: "foo", num: 424242)
|
|
[x, str, num]
|
|
end
|
|
|
|
def test_f2
|
|
assert_equal([:xyz, "foo", 424242], f2(:xyz))
|
|
assert_raise(ArgumentError) { f2({}) } # [ruby-dev:46712] [Bug #7529]
|
|
end
|
|
|
|
|
|
def f3(str: "foo", num: 424242, **h)
|
|
[str, num, h]
|
|
end
|
|
|
|
def test_f3
|
|
assert_equal(["foo", 424242, {}], f3)
|
|
assert_equal(["bar", 424242, {}], f3(str: "bar"))
|
|
assert_equal(["foo", 111111, {}], f3(num: 111111))
|
|
assert_equal(["bar", 111111, {}], f3(str: "bar", num: 111111))
|
|
assert_equal(["bar", 424242, {:check=>true}], f3(str: "bar", check: true))
|
|
assert_raise(ArgumentError) { f3("string") }
|
|
end
|
|
|
|
|
|
define_method(:f4) {|str: "foo", num: 424242| [str, num] }
|
|
|
|
def test_f4
|
|
assert_equal(["foo", 424242], f4)
|
|
assert_equal(["bar", 424242], f4(str: "bar"))
|
|
assert_equal(["foo", 111111], f4(num: 111111))
|
|
assert_equal(["bar", 111111], f4(str: "bar", num: 111111))
|
|
assert_raise(ArgumentError) { f4(str: "bar", check: true) }
|
|
assert_raise(ArgumentError) { f4("string") }
|
|
end
|
|
|
|
|
|
define_method(:f5) {|str: "foo", num: 424242, **h| [str, num, h] }
|
|
|
|
def test_f5
|
|
assert_equal(["foo", 424242, {}], f5)
|
|
assert_equal(["bar", 424242, {}], f5(str: "bar"))
|
|
assert_equal(["foo", 111111, {}], f5(num: 111111))
|
|
assert_equal(["bar", 111111, {}], f5(str: "bar", num: 111111))
|
|
assert_equal(["bar", 424242, {:check=>true}], f5(str: "bar", check: true))
|
|
assert_raise(ArgumentError) { f5("string") }
|
|
end
|
|
|
|
|
|
def f6(str: "foo", num: 424242, **h, &blk)
|
|
[str, num, h, blk]
|
|
end
|
|
|
|
def test_f6 # [ruby-core:40518]
|
|
assert_equal(["foo", 424242, {}, nil], f6)
|
|
assert_equal(["bar", 424242, {}, nil], f6(str: "bar"))
|
|
assert_equal(["foo", 111111, {}, nil], f6(num: 111111))
|
|
assert_equal(["bar", 111111, {}, nil], f6(str: "bar", num: 111111))
|
|
assert_equal(["bar", 424242, {:check=>true}, nil], f6(str: "bar", check: true))
|
|
a = f6 {|x| x + 42 }
|
|
assert_equal(["foo", 424242, {}], a[0, 3])
|
|
assert_equal(43, a.last.call(1))
|
|
end
|
|
|
|
def f7(*r, str: "foo", num: 424242, **h)
|
|
[r, str, num, h]
|
|
end
|
|
|
|
def test_f7 # [ruby-core:41772]
|
|
assert_equal([[], "foo", 424242, {}], f7)
|
|
assert_equal([[], "bar", 424242, {}], f7(str: "bar"))
|
|
assert_equal([[], "foo", 111111, {}], f7(num: 111111))
|
|
assert_equal([[], "bar", 111111, {}], f7(str: "bar", num: 111111))
|
|
assert_equal([[1], "foo", 424242, {}], f7(1))
|
|
assert_equal([[1, 2], "foo", 424242, {}], f7(1, 2))
|
|
assert_equal([[1, 2, 3], "foo", 424242, {}], f7(1, 2, 3))
|
|
assert_equal([[1], "bar", 424242, {}], f7(1, str: "bar"))
|
|
assert_equal([[1, 2], "bar", 424242, {}], f7(1, 2, str: "bar"))
|
|
assert_equal([[1, 2, 3], "bar", 424242, {}], f7(1, 2, 3, str: "bar"))
|
|
end
|
|
|
|
define_method(:f8) { |opt = :ion, *rest, key: :word|
|
|
[opt, rest, key]
|
|
}
|
|
|
|
def test_f8
|
|
assert_equal([:ion, [], :word], f8)
|
|
assert_equal([1, [], :word], f8(1))
|
|
assert_equal([1, [2], :word], f8(1, 2))
|
|
end
|
|
|
|
def f9(r, o=42, *args, p, k: :key, **kw, &b)
|
|
[r, o, args, p, k, kw, b]
|
|
end
|
|
|
|
def test_f9
|
|
assert_equal([1, 42, [], 2, :key, {}, nil], f9(1, 2))
|
|
assert_equal([1, 2, [], 3, :key, {}, nil], f9(1, 2, 3))
|
|
assert_equal([1, 2, [3], 4, :key, {}, nil], f9(1, 2, 3, 4))
|
|
assert_equal([1, 2, [3, 4], 5, :key, {str: "bar"}, nil], f9(1, 2, 3, 4, 5, str: "bar"))
|
|
end
|
|
|
|
def test_method_parameters
|
|
assert_equal([[:key, :str], [:key, :num]], method(:f1).parameters);
|
|
assert_equal([[:req, :x], [:key, :str], [:key, :num]], method(:f2).parameters);
|
|
assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], method(:f3).parameters);
|
|
assert_equal([[:key, :str], [:key, :num]], method(:f4).parameters);
|
|
assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], method(:f5).parameters);
|
|
assert_equal([[:key, :str], [:key, :num], [:keyrest, :h], [:block, :blk]], method(:f6).parameters);
|
|
assert_equal([[:rest, :r], [:key, :str], [:key, :num], [:keyrest, :h]], method(:f7).parameters);
|
|
assert_equal([[:opt, :opt], [:rest, :rest], [:key, :key]], method(:f8).parameters) # [Bug #7540] [ruby-core:50735]
|
|
assert_equal([[:req, :r], [:opt, :o], [:rest, :args], [:req, :p], [:key, :k],
|
|
[:keyrest, :kw], [:block, :b]], method(:f9).parameters)
|
|
end
|
|
|
|
def test_lambda
|
|
f = ->(str: "foo", num: 424242) { [str, num] }
|
|
assert_equal(["foo", 424242], f[])
|
|
assert_equal(["bar", 424242], f[str: "bar"])
|
|
assert_equal(["foo", 111111], f[num: 111111])
|
|
assert_equal(["bar", 111111], f[str: "bar", num: 111111])
|
|
end
|
|
|
|
|
|
def p1
|
|
Proc.new do |str: "foo", num: 424242|
|
|
[str, num]
|
|
end
|
|
end
|
|
|
|
def test_p1
|
|
assert_equal(["foo", 424242], p1[])
|
|
assert_equal(["bar", 424242], p1[str: "bar"])
|
|
assert_equal(["foo", 111111], p1[num: 111111])
|
|
assert_equal(["bar", 111111], p1[str: "bar", num: 111111])
|
|
assert_raise(ArgumentError) { p1[str: "bar", check: true] }
|
|
assert_equal(["foo", 424242], p1["string"] )
|
|
end
|
|
|
|
|
|
def p2
|
|
Proc.new do |x, str: "foo", num: 424242|
|
|
[x, str, num]
|
|
end
|
|
end
|
|
|
|
def test_p2
|
|
assert_equal([nil, "foo", 424242], p2[])
|
|
assert_equal([:xyz, "foo", 424242], p2[:xyz])
|
|
end
|
|
|
|
|
|
def p3
|
|
Proc.new do |str: "foo", num: 424242, **h|
|
|
[str, num, h]
|
|
end
|
|
end
|
|
|
|
def test_p3
|
|
assert_equal(["foo", 424242, {}], p3[])
|
|
assert_equal(["bar", 424242, {}], p3[str: "bar"])
|
|
assert_equal(["foo", 111111, {}], p3[num: 111111])
|
|
assert_equal(["bar", 111111, {}], p3[str: "bar", num: 111111])
|
|
assert_equal(["bar", 424242, {:check=>true}], p3[str: "bar", check: true])
|
|
assert_equal(["foo", 424242, {}], p3["string"])
|
|
end
|
|
|
|
|
|
def p4
|
|
Proc.new do |str: "foo", num: 424242, **h, &blk|
|
|
[str, num, h, blk]
|
|
end
|
|
end
|
|
|
|
def test_p4
|
|
assert_equal(["foo", 424242, {}, nil], p4[])
|
|
assert_equal(["bar", 424242, {}, nil], p4[str: "bar"])
|
|
assert_equal(["foo", 111111, {}, nil], p4[num: 111111])
|
|
assert_equal(["bar", 111111, {}, nil], p4[str: "bar", num: 111111])
|
|
assert_equal(["bar", 424242, {:check=>true}, nil], p4[str: "bar", check: true])
|
|
a = p4.call {|x| x + 42 }
|
|
assert_equal(["foo", 424242, {}], a[0, 3])
|
|
assert_equal(43, a.last.call(1))
|
|
end
|
|
|
|
|
|
def p5
|
|
Proc.new do |*r, str: "foo", num: 424242, **h|
|
|
[r, str, num, h]
|
|
end
|
|
end
|
|
|
|
def test_p5
|
|
assert_equal([[], "foo", 424242, {}], p5[])
|
|
assert_equal([[], "bar", 424242, {}], p5[str: "bar"])
|
|
assert_equal([[], "foo", 111111, {}], p5[num: 111111])
|
|
assert_equal([[], "bar", 111111, {}], p5[str: "bar", num: 111111])
|
|
assert_equal([[1], "foo", 424242, {}], p5[1])
|
|
assert_equal([[1, 2], "foo", 424242, {}], p5[1, 2])
|
|
assert_equal([[1, 2, 3], "foo", 424242, {}], p5[1, 2, 3])
|
|
assert_equal([[1], "bar", 424242, {}], p5[1, str: "bar"])
|
|
assert_equal([[1, 2], "bar", 424242, {}], p5[1, 2, str: "bar"])
|
|
assert_equal([[1, 2, 3], "bar", 424242, {}], p5[1, 2, 3, str: "bar"])
|
|
end
|
|
|
|
|
|
def p6
|
|
Proc.new do |o1, o2=42, *args, p, k: :key, **kw, &b|
|
|
[o1, o2, args, p, k, kw, b]
|
|
end
|
|
end
|
|
|
|
def test_p6
|
|
assert_equal([nil, 42, [], nil, :key, {}, nil], p6[])
|
|
assert_equal([1, 42, [], 2, :key, {}, nil], p6[1, 2])
|
|
assert_equal([1, 2, [], 3, :key, {}, nil], p6[1, 2, 3])
|
|
assert_equal([1, 2, [3], 4, :key, {}, nil], p6[1, 2, 3, 4])
|
|
assert_equal([1, 2, [3, 4], 5, :key, {str: "bar"}, nil], p6[1, 2, 3, 4, 5, str: "bar"])
|
|
end
|
|
|
|
def test_proc_parameters
|
|
assert_equal([[:key, :str], [:key, :num]], p1.parameters);
|
|
assert_equal([[:opt, :x], [:key, :str], [:key, :num]], p2.parameters);
|
|
assert_equal([[:key, :str], [:key, :num], [:keyrest, :h]], p3.parameters);
|
|
assert_equal([[:key, :str], [:key, :num], [:keyrest, :h], [:block, :blk]], p4.parameters);
|
|
assert_equal([[:rest, :r], [:key, :str], [:key, :num], [:keyrest, :h]], p5.parameters);
|
|
assert_equal([[:opt, :o1], [:opt, :o2], [:rest, :args], [:opt, :p], [:key, :k],
|
|
[:keyrest, :kw], [:block, :b]], p6.parameters)
|
|
end
|
|
|
|
def m1(*args)
|
|
yield(*args)
|
|
end
|
|
|
|
def test_block
|
|
blk = Proc.new {|str: "foo", num: 424242| [str, num] }
|
|
assert_equal(["foo", 424242], m1(&blk))
|
|
assert_equal(["bar", 424242], m1(str: "bar", &blk))
|
|
assert_equal(["foo", 111111], m1(num: 111111, &blk))
|
|
assert_equal(["bar", 111111], m1(str: "bar", num: 111111, &blk))
|
|
end
|
|
|
|
def rest_keyrest(*args, **opt)
|
|
return *args, opt
|
|
end
|
|
|
|
def test_rest_keyrest
|
|
bug7665 = '[ruby-core:51278]'
|
|
expect = [*%w[foo bar], {zzz: 42}]
|
|
assert_equal(expect, rest_keyrest(*expect), bug7665)
|
|
assert_equal(expect, proc {|*args, **opt| next *args, opt}.call(*expect), bug7665)
|
|
end
|
|
|
|
def test_bare_kwrest
|
|
# valid syntax, but its semantics is undefined
|
|
assert_valid_syntax("def bug7662(**) end")
|
|
assert_valid_syntax("def bug7662(*, **) end")
|
|
assert_valid_syntax("def bug7662(a, **) end")
|
|
end
|
|
|
|
def test_without_paren
|
|
bug7942 = '[ruby-core:52820] [Bug #7942]'
|
|
assert_valid_syntax("def bug7942 a: 1; end")
|
|
assert_valid_syntax("def bug7942 a: 1, **; end")
|
|
|
|
o = Object.new
|
|
eval("def o.bug7942 a: 1; a; end", nil, __FILE__, __LINE__)
|
|
assert_equal(1, o.bug7942(), bug7942)
|
|
assert_equal(42, o.bug7942(a: 42), bug7942)
|
|
|
|
o = Object.new
|
|
eval("def o.bug7942 a: 1, **; a; end", nil, __FILE__, __LINE__)
|
|
assert_equal(1, o.bug7942(), bug7942)
|
|
assert_equal(42, o.bug7942(a: 42), bug7942)
|
|
end
|
|
|
|
def test_required_keyword
|
|
feature7701 = '[ruby-core:51454] [Feature #7701] required keyword argument'
|
|
o = Object.new
|
|
assert_nothing_raised(SyntaxError, feature7701) do
|
|
eval("def o.foo(a:) a; end")
|
|
end
|
|
assert_raise(ArgumentError, feature7701) {o.foo}
|
|
assert_equal(42, o.foo(a: 42), feature7701)
|
|
assert_equal([[:keyreq, :a]], o.method(:foo).parameters, feature7701)
|
|
end
|
|
|
|
def test_block_required_keyword
|
|
feature7701 = '[ruby-core:51454] [Feature #7701] required keyword argument'
|
|
b = assert_nothing_raised(SyntaxError, feature7701) do
|
|
break eval("proc {|a:| a}")
|
|
end
|
|
assert_raise(ArgumentError, feature7701) {b.call}
|
|
assert_equal(42, b.call(a: 42), feature7701)
|
|
assert_equal([[:keyreq, :a]], b.parameters, feature7701)
|
|
end
|
|
end
|