aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--iseq.c7
-rw-r--r--test/ruby/test_keyword.rb24
-rw-r--r--vm_core.h20
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 <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.
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;