From 0314f93ef402083ea5fd7cb2015f7a98cd0a3358 Mon Sep 17 00:00:00 2001 From: eregon Date: Tue, 11 Dec 2012 21:44:49 +0000 Subject: [PATCH] * iseq.c (rb_iseq_parameters): fix limit for optional arguments. * test/ruby/test_keyword.rb: tests for above. * vm_core.h (struct rb_iseq_struct): update documentation with keyword arguments. [Bug #7540] [ruby-core:50735] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38333 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 +++++++++ iseq.c | 7 +------ test/ruby/test_keyword.rb | 24 ++++++++++++++++++++++++ vm_core.h | 20 ++++++++++++-------- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index d7fa2b553a..6790af5d0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Dec 12 06:43:37 2012 Benoit Daloze + + * iseq.c (rb_iseq_parameters): fix limit for optional arguments. + + * test/ruby/test_keyword.rb: tests for above. + + * vm_core.h (struct rb_iseq_struct): update documentation + with keyword arguments. [Bug #7540] [ruby-core:50735] + Wed Dec 12 03:45:41 2012 Nobuyoshi Nakada * vm.c (vm_exec): pass exceptions while handling an exception. diff --git a/iseq.c b/iseq.c index 78e33b0d96..9fb82d49c6 100644 --- a/iseq.c +++ b/iseq.c @@ -1792,12 +1792,7 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc) rb_ary_push(args, PARAM(i, req)); } } - r = iseq->arg_rest != -1 ? iseq->arg_rest : - iseq->arg_post_len > 0 ? iseq->arg_post_start : - iseq->arg_block != -1 ? iseq->arg_block : - iseq->arg_keyword != -1 ? iseq->arg_keyword : - iseq->arg_size; - if (iseq->arg_keyword != -1) r -= iseq->arg_keywords; + r = iseq->argc + iseq->arg_opts - 1; for (; i < r; i++) { PARAM_TYPE(opt); if (rb_id2str(PARAM_ID(i))) { diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb index 9c94069d6f..b9a4afc8dd 100644 --- a/test/ruby/test_keyword.rb +++ b/test/ruby/test_keyword.rb @@ -94,6 +94,27 @@ class TestKeywordArguments < Test::Unit::TestCase 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); @@ -102,6 +123,9 @@ class TestKeywordArguments < Test::Unit::TestCase 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 diff --git a/vm_core.h b/vm_core.h index 2a22ffeff5..73b24a1e0e 100644 --- a/vm_core.h +++ b/vm_core.h @@ -241,20 +241,24 @@ struct rb_iseq_struct { * b1=(...), b2=(...), ..., bN=(...), # optional * *c, # rest * d1, d2, ..., dO, # post - * &e) # block + * e1:(...), e2:(...), ..., eK:(...), # keyword + * **f, # keyword rest + * &g) # block * => * - * argc = M - * arg_rest = M+N+1 // or -1 if no rest arg - * arg_opts = N+1 // or 0 if no optional arg + * argc = M // or 0 if no mandatory arg + * arg_opts = N+1 // or 0 if no optional arg + * arg_rest = M+N // or -1 if no rest arg * arg_opt_table = [ (arg_opts entries) ] - * arg_post_len = O // 0 if no post arguments - * arg_post_start = M+N+2 - * arg_block = M+N + 1 + O + 1 // -1 if no block arg + * arg_post_start = M+N+(*1) // or 0 if no post arguments + * arg_post_len = O // or 0 if no post arguments + * arg_keywords = K // or 0 if no keyword arg + * arg_block = M+N+(*1)+O+K // or -1 if no block arg + * arg_keyword = M+N+(*1)+O+K+(&1) // or -1 if no keyword arg/rest * arg_simple = 0 if not simple arguments. * = 1 if no opt, rest, post, block. * = 2 if ambiguous block parameter ({|a|}). - * arg_size = argument size. + * arg_size = M+N+O+(*1)+K+(&1)+(**1) argument size. */ int argc;