From 88604e39ac9c25ffdad2e3f03be26516fe866038 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 12 Nov 2016 05:23:05 +0900 Subject: Hash#[] to call Hash#default --- src/hash.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/hash.c') diff --git a/src/hash.c b/src/hash.c index 2ad6a9642..015b2d614 100644 --- a/src/hash.c +++ b/src/hash.c @@ -173,10 +173,8 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* not found */ if (MRB_RHASH_DEFAULT_P(hash)) { - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); - } - return RHASH_IFNONE(hash); + /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ + return mrb_funcall(mrb, hash, "default", 1, key); } return mrb_nil_value(); } @@ -385,13 +383,16 @@ mrb_hash_default(mrb_state *mrb, mrb_value hash) mrb_bool given; mrb_get_args(mrb, "|o?", &key, &given); - if (MRB_RHASH_PROCDEFAULT_P(hash)) { - if (!given) return mrb_nil_value(); - return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); - } - else { - return RHASH_IFNONE(hash); + if (MRB_RHASH_DEFAULT_P(hash)) { + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + if (!given) return mrb_nil_value(); + return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + } + else { + return RHASH_IFNONE(hash); + } } + return mrb_nil_value(); } /* 15.2.13.4.6 */ -- cgit v1.2.3 From cb5c9d34150c073b5cdde725cadd959839c9bc45 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 24 Nov 2016 18:09:04 +0900 Subject: always call Hash#default if no key found; fix #3272 --- src/hash.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/hash.c') diff --git a/src/hash.c b/src/hash.c index 015b2d614..4df2babbe 100644 --- a/src/hash.c +++ b/src/hash.c @@ -172,11 +172,8 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) } /* not found */ - if (MRB_RHASH_DEFAULT_P(hash)) { - /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ - return mrb_funcall(mrb, hash, "default", 1, key); - } - return mrb_nil_value(); + /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ + return mrb_funcall(mrb, hash, "default", 1, key); } MRB_API mrb_value -- cgit v1.2.3 From 338e0ff52d645556e644ac08b3efc6ea31868c59 Mon Sep 17 00:00:00 2001 From: Shugo Maeda Date: Wed, 7 Dec 2016 22:39:20 +0900 Subject: Copy default_proc by Hash#dup. --- src/hash.c | 14 +++++++++++++- test/t/hash.rb | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src/hash.c') diff --git a/src/hash.c b/src/hash.c index 4df2babbe..93fe656e0 100644 --- a/src/hash.c +++ b/src/hash.c @@ -225,6 +225,7 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) struct RHash* ret; khash_t(ht) *h, *ret_h; khiter_t k, ret_k; + mrb_value ifnone, vret; h = RHASH_TBL(hash); ret = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); @@ -243,7 +244,18 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash) } } - return mrb_obj_value(ret); + if (MRB_RHASH_DEFAULT_P(hash)) { + ret->flags |= MRB_HASH_DEFAULT; + } + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + ret->flags |= MRB_HASH_PROC_DEFAULT; + } + vret = mrb_obj_value(ret); + ifnone = RHASH_IFNONE(hash); + if (!mrb_nil_p(ifnone)) { + mrb_iv_set(mrb, vret, mrb_intern_lit(mrb, "ifnone"), ifnone); + } + return vret; } MRB_API mrb_value diff --git a/test/t/hash.rb b/test/t/hash.rb index b455812cf..f076db8e5 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -44,6 +44,10 @@ assert('Hash#dup') do b = a.dup a['a'] = 2 assert_equal({'a' => 1}, b) + + c = Hash.new { |h, k| h[k] = k.upcase } + d = c.dup + assert_equal("FOO", d["foo"]) end assert('Hash#default', '15.2.13.4.5') do -- cgit v1.2.3 From 10bb7ad693e7c7443de924a39c1fedb4461108ba Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sun, 11 Dec 2016 01:45:38 +0900 Subject: Implement Object#freeze --- include/mruby/class.h | 1 + include/mruby/object.h | 4 ++++ include/mruby/string.h | 5 ----- src/array.c | 4 ++++ src/hash.c | 7 +++++-- src/kernel.c | 10 ++++++++++ src/string.c | 15 ++------------- test/t/array.rb | 7 +++++++ test/t/hash.rb | 7 +++++++ test/t/kernel.rb | 5 +++++ 10 files changed, 45 insertions(+), 20 deletions(-) (limited to 'src/hash.c') diff --git a/include/mruby/class.h b/include/mruby/class.h index 246e82e59..ce953af3b 100644 --- a/include/mruby/class.h +++ b/include/mruby/class.h @@ -52,6 +52,7 @@ mrb_class(mrb_state *mrb, mrb_value v) } // TODO: figure out where to put user flags +#define MRB_FLAG_IS_FROZEN (1 << 18) #define MRB_FLAG_IS_PREPENDED (1 << 19) #define MRB_FLAG_IS_ORIGIN (1 << 20) #define MRB_CLASS_ORIGIN(c) do {\ diff --git a/include/mruby/object.h b/include/mruby/object.h index 9fbfe34f3..da44027e1 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -22,6 +22,10 @@ struct RBasic { }; #define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) +#define RBASIC_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN) +#define RBASIC_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN) +#define RBASIC_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN) + struct RObject { MRB_OBJECT_HEADER; struct iv_tbl *iv; diff --git a/include/mruby/string.h b/include/mruby/string.h index b30c1ed98..9ccf8f187 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -62,10 +62,6 @@ struct RString { #define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE) #define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE) -#define RSTR_FROZEN_P(s) ((s)->flags & MRB_STR_FROZEN) -#define RSTR_SET_FROZEN_FLAG(s) ((s)->flags |= MRB_STR_FROZEN) -#define RSTR_UNSET_FROZEN_FLAG(s) ((s)->flags &= ~MRB_STR_FROZEN) - /* * Returns a pointer from a Ruby string */ @@ -80,7 +76,6 @@ MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*); #define MRB_STR_SHARED 1 #define MRB_STR_NOFREE 2 -#define MRB_STR_FROZEN 4 #define MRB_STR_NO_UTF 8 #define MRB_STR_EMBED 16 #define MRB_STR_EMBED_LEN_MASK 0x3e0 diff --git a/src/array.c b/src/array.c index f6599bd5b..c6bac7b47 100644 --- a/src/array.c +++ b/src/array.c @@ -108,6 +108,10 @@ ary_fill_with_nil(mrb_value *ptr, mrb_int size) static void ary_modify(mrb_state *mrb, struct RArray *a) { + if (RBASIC_FROZEN_P(a)) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array"); + } + if (ARY_SHARED_P(a)) { mrb_shared_array *shared = a->aux.shared; diff --git a/src/hash.c b/src/hash.c index 93fe656e0..d0e865b5c 100644 --- a/src/hash.c +++ b/src/hash.c @@ -98,9 +98,9 @@ static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); static inline mrb_value mrb_hash_ht_key(mrb_state *mrb, mrb_value key) { - if (mrb_string_p(key) && !RSTR_FROZEN_P(mrb_str_ptr(key))) { + if (mrb_string_p(key) && !RBASIC_FROZEN_P(mrb_str_ptr(key))) { key = mrb_str_dup(mrb, key); - RSTR_SET_FROZEN_FLAG(mrb_str_ptr(key)); + RBASIC_SET_FROZEN_FLAG(mrb_str_ptr(key)); } return key; } @@ -278,6 +278,9 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash) static void mrb_hash_modify(mrb_state *mrb, mrb_value hash) { + if (RBASIC_FROZEN_P(mrb_hash_ptr(hash))) { + mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen hash"); + } mrb_hash_tbl(mrb, hash); } diff --git a/src/kernel.c b/src/kernel.c index c63e05596..78e57a17a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -450,6 +450,15 @@ mrb_obj_extend_m(mrb_state *mrb, mrb_value self) return mrb_obj_extend(mrb, argc, argv, self); } +static mrb_value +mrb_obj_freeze(mrb_state *mrb, mrb_value self) +{ + struct RBasic *b = mrb_basic_ptr(self); + + RBASIC_SET_FROZEN_FLAG(b); + return self; +} + /* 15.3.1.3.15 */ /* * call-seq: @@ -1124,6 +1133,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "eql?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.10 */ mrb_define_method(mrb, krn, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */ mrb_define_method(mrb, krn, "extend", mrb_obj_extend_m, MRB_ARGS_ANY()); /* 15.3.1.3.13 */ + mrb_define_method(mrb, krn, "freeze", mrb_obj_freeze, MRB_ARGS_NONE()); mrb_define_method(mrb, krn, "global_variables", mrb_f_global_variables, MRB_ARGS_NONE()); /* 15.3.1.3.14 */ mrb_define_method(mrb, krn, "hash", mrb_obj_hash, MRB_ARGS_NONE()); /* 15.3.1.3.15 */ mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, MRB_ARGS_REQ(1)); /* 15.3.1.3.16 */ diff --git a/src/string.c b/src/string.c index a4f8085ec..7234ecf2b 100644 --- a/src/string.c +++ b/src/string.c @@ -501,7 +501,7 @@ str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) static void check_frozen(mrb_state *mrb, struct RString *s) { - if (RSTR_FROZEN_P(s)) { + if (RBASIC_FROZEN_P(s)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); } } @@ -700,15 +700,6 @@ mrb_str_modify(mrb_state *mrb, struct RString *s) } } -static mrb_value -mrb_str_freeze(mrb_state *mrb, mrb_value str) -{ - struct RString *s = mrb_str_ptr(str); - - RSTR_SET_FROZEN_FLAG(s); - return str; -} - MRB_API mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len) { @@ -2217,7 +2208,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) char *p = RSTR_PTR(ps); if (!p || p[len] != '\0') { - if (RSTR_FROZEN_P(ps)) { + if (RBASIC_FROZEN_P(ps)) { *ptr = str = mrb_str_dup(mrb, str); ps = mrb_str_ptr(str); } @@ -2746,8 +2737,6 @@ mrb_init_string(mrb_state *mrb) mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */ mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */ mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE()); - - mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE()); } /* diff --git a/test/t/array.rb b/test/t/array.rb index 9cc2f64ad..cf7ed4704 100644 --- a/test/t/array.rb +++ b/test/t/array.rb @@ -373,3 +373,10 @@ assert("Array#rindex") do $a = [2, 3, 4, 5, 6, 7, 8, 9, 10, Sneaky.new] assert_equal 0, $a.rindex(1) end + +assert('Array#freeze') do + a = [].freeze + assert_raise(RuntimeError) do + a[0] = 1 + end +end diff --git a/test/t/hash.rb b/test/t/hash.rb index f076db8e5..c63b8c009 100644 --- a/test/t/hash.rb +++ b/test/t/hash.rb @@ -366,3 +366,10 @@ assert('Hash#rehash') do h.rehash assert_equal("b", h[[:b]]) end + +assert('Hash#freeze') do + h = {}.freeze + assert_raise(RuntimeError) do + h[:a] = 'b' + end +end diff --git a/test/t/kernel.rb b/test/t/kernel.rb index e59bd6a10..42abed9df 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -257,6 +257,11 @@ assert('Kernel#extend works on toplevel', '15.3.1.3.13') do assert_true respond_to?(:test_method) end +assert('Kernel#freeze') do + obj = Object.new + assert_equal obj, obj.freeze +end + assert('Kernel#global_variables', '15.3.1.3.14') do assert_equal Array, global_variables.class end -- cgit v1.2.3 From 92c843dd07211d698a6dac90fbd740e483ae34af Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Dec 2016 00:54:36 +0900 Subject: rename prefix RBASIC_ to MRB_; ref #3340 --- include/mruby/object.h | 6 +++--- src/array.c | 2 +- src/hash.c | 6 +++--- src/kernel.c | 2 +- src/string.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/hash.c') diff --git a/include/mruby/object.h b/include/mruby/object.h index da44027e1..9347981d4 100644 --- a/include/mruby/object.h +++ b/include/mruby/object.h @@ -22,9 +22,9 @@ struct RBasic { }; #define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v))) -#define RBASIC_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN) -#define RBASIC_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN) -#define RBASIC_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN) +#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN) +#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN) +#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN) struct RObject { MRB_OBJECT_HEADER; diff --git a/src/array.c b/src/array.c index c6bac7b47..7601e9c17 100644 --- a/src/array.c +++ b/src/array.c @@ -108,7 +108,7 @@ ary_fill_with_nil(mrb_value *ptr, mrb_int size) static void ary_modify(mrb_state *mrb, struct RArray *a) { - if (RBASIC_FROZEN_P(a)) { + if (MRB_FROZEN_P(a)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen array"); } diff --git a/src/hash.c b/src/hash.c index d0e865b5c..c65c8926e 100644 --- a/src/hash.c +++ b/src/hash.c @@ -98,9 +98,9 @@ static void mrb_hash_modify(mrb_state *mrb, mrb_value hash); static inline mrb_value mrb_hash_ht_key(mrb_state *mrb, mrb_value key) { - if (mrb_string_p(key) && !RBASIC_FROZEN_P(mrb_str_ptr(key))) { + if (mrb_string_p(key) && !MRB_FROZEN_P(mrb_str_ptr(key))) { key = mrb_str_dup(mrb, key); - RBASIC_SET_FROZEN_FLAG(mrb_str_ptr(key)); + MRB_SET_FROZEN_FLAG(mrb_str_ptr(key)); } return key; } @@ -278,7 +278,7 @@ mrb_hash_tbl(mrb_state *mrb, mrb_value hash) static void mrb_hash_modify(mrb_state *mrb, mrb_value hash) { - if (RBASIC_FROZEN_P(mrb_hash_ptr(hash))) { + if (MRB_FROZEN_P(mrb_hash_ptr(hash))) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen hash"); } mrb_hash_tbl(mrb, hash); diff --git a/src/kernel.c b/src/kernel.c index 78e57a17a..a5166deb2 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -455,7 +455,7 @@ mrb_obj_freeze(mrb_state *mrb, mrb_value self) { struct RBasic *b = mrb_basic_ptr(self); - RBASIC_SET_FROZEN_FLAG(b); + MRB_SET_FROZEN_FLAG(b); return self; } diff --git a/src/string.c b/src/string.c index 7234ecf2b..ee5aa04f3 100644 --- a/src/string.c +++ b/src/string.c @@ -501,7 +501,7 @@ str_index(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int offset) static void check_frozen(mrb_state *mrb, struct RString *s) { - if (RBASIC_FROZEN_P(s)) { + if (MRB_FROZEN_P(s)) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string"); } } @@ -2208,7 +2208,7 @@ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr) char *p = RSTR_PTR(ps); if (!p || p[len] != '\0') { - if (RBASIC_FROZEN_P(ps)) { + if (MRB_FROZEN_P(ps)) { *ptr = str = mrb_str_dup(mrb, str); ps = mrb_str_ptr(str); } -- cgit v1.2.3 From 2e0c2b58076ce24508a584091f8af9bf8c22f64d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 5 Jan 2017 16:46:08 +0900 Subject: Add mrb_hash_modify() to Hash#{delete,clear}; ref #3370 This issue was reported by https://hackerone.com/an0n-j --- src/hash.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/hash.c') diff --git a/src/hash.c b/src/hash.c index c65c8926e..98feaceac 100644 --- a/src/hash.c +++ b/src/hash.c @@ -554,6 +554,7 @@ mrb_hash_delete(mrb_state *mrb, mrb_value self) mrb_value key; mrb_get_args(mrb, "o", &key); + mrb_hash_modify(mrb, self); return mrb_hash_delete_key(mrb, self, key); } @@ -620,6 +621,7 @@ mrb_hash_clear(mrb_state *mrb, mrb_value hash) { khash_t(ht) *h = RHASH_TBL(hash); + mrb_hash_modify(mrb, hash); if (h) kh_clear(ht, mrb, h); return hash; } -- cgit v1.2.3 From 30aa5218543cd44df7c1d90a5c10cf6f622f5a8a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 14 Feb 2017 00:22:12 +0900 Subject: Do not use mrb_funcall() if Hash#default is not overridden; ref #3421 This change reduces the recursion level, but does not solve the stack overflow issue entirely. --- include/mruby.h | 1 + src/hash.c | 21 ++++++++++++++++++++- src/kernel.c | 14 ++++++++++---- 3 files changed, 31 insertions(+), 5 deletions(-) (limited to 'src/hash.c') diff --git a/include/mruby.h b/include/mruby.h index 99d06146f..6950cf904 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -1147,6 +1147,7 @@ MRB_API mrb_value mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id); MRB_API mrb_bool mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid); MRB_API mrb_bool mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c); +MRB_API mrb_bool mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func); /* diff --git a/src/hash.c b/src/hash.c index 98feaceac..b7bd648c0 100644 --- a/src/hash.c +++ b/src/hash.c @@ -159,6 +159,9 @@ mrb_hash_new(mrb_state *mrb) return mrb_hash_new_capa(mrb, 0); } +static mrb_value mrb_hash_default(mrb_state *mrb, mrb_value hash); +static mrb_value hash_default(mrb_state *mrb, mrb_value hash, mrb_value key); + MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { @@ -171,7 +174,9 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) return kh_value(h, k).v; } - /* not found */ + if (mrb_func_basic_p(mrb, hash, mrb_intern_lit(mrb, "default"), mrb_hash_default)) { + return hash_default(mrb, hash, key); + } /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ return mrb_funcall(mrb, hash, "default", 1, key); } @@ -366,6 +371,20 @@ mrb_hash_aget(mrb_state *mrb, mrb_value self) return mrb_hash_get(mrb, self, key); } +static mrb_value +hash_default(mrb_state *mrb, mrb_value hash, mrb_value key) +{ + if (MRB_RHASH_DEFAULT_P(hash)) { + if (MRB_RHASH_PROCDEFAULT_P(hash)) { + return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key); + } + else { + return RHASH_IFNONE(hash); + } + } + return mrb_nil_value(); +} + /* 15.2.13.4.5 */ /* * call-seq: diff --git a/src/kernel.c b/src/kernel.c index 8b00d701b..02bb3c99b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -28,15 +28,21 @@ typedef enum { NOEX_RESPONDS = 0x80 } mrb_method_flag_t; -static mrb_bool -mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) +MRB_API mrb_bool +mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func) { - struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s")); - if (MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s)) + struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mid); + if (MRB_PROC_CFUNC_P(me) && (me->body.func == func)) return TRUE; return FALSE; } +static mrb_bool +mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj) +{ + return mrb_func_basic_p(mrb, obj, mrb_intern_lit(mrb, "to_s"), mrb_any_to_s); +} + /* 15.3.1.3.17 */ /* * call-seq: -- cgit v1.2.3 From 04296925ac81537e029af46ed7622471d8374ce8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 15 Feb 2017 09:24:35 +0900 Subject: Use mrb_funcall_argv() instead of mrb_funcall() --- src/hash.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/hash.c') diff --git a/src/hash.c b/src/hash.c index b7bd648c0..d15faa206 100644 --- a/src/hash.c +++ b/src/hash.c @@ -167,6 +167,7 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { khash_t(ht) *h = RHASH_TBL(hash); khiter_t k; + mrb_sym mid; if (h) { k = kh_get(ht, mrb, h, key); @@ -174,11 +175,12 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) return kh_value(h, k).v; } - if (mrb_func_basic_p(mrb, hash, mrb_intern_lit(mrb, "default"), mrb_hash_default)) { + mid = mrb_intern_lit(mrb, "default"); + if (mrb_func_basic_p(mrb, hash, mid, mrb_hash_default)) { return hash_default(mrb, hash, key); } /* xxx mrb_funcall_tailcall(mrb, hash, "default", 1, key); */ - return mrb_funcall(mrb, hash, "default", 1, key); + return mrb_funcall_argv(mrb, hash, mid, 1, &key); } MRB_API mrb_value -- cgit v1.2.3