* 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
This commit is contained in:
eregon 2012-12-11 21:44:49 +00:00
Родитель 64bbd55c85
Коммит 0314f93ef4
4 изменённых файлов: 46 добавлений и 14 удалений

Просмотреть файл

@ -1,3 +1,12 @@
Wed Dec 12 06:43:37 2012 Benoit Daloze <eregontp@gmail.com>
* 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 <nobu@ruby-lang.org>
* vm.c (vm_exec): pass exceptions while handling an exception.

7
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))) {

Просмотреть файл

@ -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

Просмотреть файл

@ -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;