[前][次][番号順一覧][スレッド一覧]

ruby-changes:28208

From: nobu <ko1@a...>
Date: Fri, 12 Apr 2013 15:21:49 +0900 (JST)
Subject: [ruby-changes:28208] nobu:r40260 (trunk): vm_insnhelper.c: non-symbol key

nobu	2013-04-12 15:21:35 +0900 (Fri, 12 Apr 2013)

  New Revision: 40260

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40260

  Log:
    vm_insnhelper.c: non-symbol key
    
    * vm_insnhelper.c (vm_callee_setup_keyword_arg): non-symbol key is not
      a keyword argument, keep it as an positional argument.

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_keyword.rb
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 40259)
+++ ChangeLog	(revision 40260)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Apr 12 15:21:24 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* vm_insnhelper.c (vm_callee_setup_keyword_arg): non-symbol key is not
+	  a keyword argument, keep it as an positional argument.
+
 Fri Apr 12 11:58:00 2013  Zachary Scott  <zachary@z...>
 
 	* array.c: Document synonymous methods, by windwiny [GH-277]
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 40259)
+++ vm_insnhelper.c	(revision 40260)
@@ -1070,24 +1070,56 @@ vm_caller_setup_args(const rb_thread_t * https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1070
     }
 }
 
+static int
+separate_symbol(st_data_t key, st_data_t value, st_data_t arg)
+{
+    VALUE *kwdhash = (VALUE *)arg;
+
+    if (!SYMBOL_P(key)) kwdhash++;
+    if (!*kwdhash) *kwdhash = rb_hash_new();
+    rb_hash_aset(*kwdhash, (VALUE)key, (VALUE)value);
+    return ST_CONTINUE;
+}
+
+static VALUE
+extract_keywords(VALUE *orighash)
+{
+    VALUE parthash[2] = {0, 0};
+    VALUE hash = *orighash;
+
+    if (RHASH_EMPTY_P(hash)) {
+	*orighash = 0;
+	return hash;
+    }
+    st_foreach(RHASH_TBL(hash), separate_symbol, (st_data_t)&parthash);
+    *orighash = parthash[1];
+    return parthash[0];
+}
+
 static inline int
 vm_callee_setup_keyword_arg(const rb_iseq_t *iseq, int argc, VALUE *orig_argv, VALUE *kwd)
 {
-    VALUE keyword_hash;
+    VALUE keyword_hash, orig_hash;
     int i, j;
 
     if (argc > 0 &&
-	!NIL_P(keyword_hash = rb_check_hash_type(orig_argv[argc-1]))) {
-	argc--;
-	keyword_hash = rb_hash_dup(keyword_hash);
+	!NIL_P(orig_hash = rb_check_hash_type(orig_argv[argc-1])) &&
+	(keyword_hash = extract_keywords(&orig_hash)) != 0) {
+	if (!orig_hash) {
+	    argc--;
+	}
+	else {
+	    orig_argv[argc-1] = orig_hash;
+	}
 	i = 0;
 	if (iseq->arg_keyword_required) {
 	    VALUE missing = Qnil;
 	    for (; i < iseq->arg_keyword_required; i++) {
-		if (st_lookup(RHASH_TBL(keyword_hash), ID2SYM(iseq->arg_keyword_table[i]), 0))
+		VALUE keyword = ID2SYM(iseq->arg_keyword_table[i]);
+		if (st_lookup(RHASH_TBL(keyword_hash), (st_data_t)keyword, 0))
 		    continue;
 		if (NIL_P(missing)) missing = rb_ary_tmp_new(1);
-		rb_ary_push(missing, ID2SYM(iseq->arg_keyword_table[i]));
+		rb_ary_push(missing, keyword);
 	    }
 	    if (!NIL_P(missing)) {
 		keyword_error("missing", missing);
Index: test/ruby/test_keyword.rb
===================================================================
--- test/ruby/test_keyword.rb	(revision 40259)
+++ test/ruby/test_keyword.rb	(revision 40260)
@@ -23,6 +23,7 @@ class TestKeywordArguments < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_keyword.rb#L23
   def test_f2
     assert_equal([:xyz, "foo", 424242], f2(:xyz))
     assert_raise(ArgumentError) { f2({}) } # [ruby-dev:46712] [Bug #7529]
+    assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42))
   end
 
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]