From 8682b06953e580d301bfc7b3b28fd03054e0875d Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Thu, 25 Apr 2013 09:27:00 +0900 Subject: add new functions to check if symbols are interned without registration. --- src/symbol.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src') diff --git a/src/symbol.c b/src/symbol.c index 55bb4885a..3d841a636 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -72,6 +72,30 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } +mrb_bool +mrb_cstr_interned(mrb_state *mrb, const char *name) +{ + return mrb_interned(mrb, name, strlen(name)); +} + +mrb_bool +mrb_interned(mrb_state *mrb, const char *name, size_t len) +{ + khash_t(n2s) *h = mrb->name2sym; + symbol_name sname; + + sname.len = len; + sname.name = name; + + return (kh_get(n2s, h, sname) != kh_end(h)) ? TRUE : FALSE; +} + +mrb_bool +mrb_str_interned(mrb_state *mrb, mrb_value str) +{ + return mrb_interned(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); +} + /* lenp must be a pointer to a size_t variable */ const char* mrb_sym2name_len(mrb_state *mrb, mrb_sym sym, size_t *lenp) -- cgit v1.2.3 From bd1b925931b2456cf19ee7296de554f518326c4e Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Thu, 25 Apr 2013 09:51:20 +0900 Subject: modify the type of return value (mrb_bool => mrb_value). --- include/mruby.h | 6 +++--- src/symbol.c | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/include/mruby.h b/include/mruby.h index e249a0455..0d948b7a0 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -195,9 +195,9 @@ mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, mrb_sym, int, mrb_value* mrb_sym mrb_intern_cstr(mrb_state*,const char*); mrb_sym mrb_intern2(mrb_state*,const char*,size_t); mrb_sym mrb_intern_str(mrb_state*,mrb_value); -mrb_bool mrb_cstr_interned(mrb_state*,const char*); -mrb_bool mrb_interned(mrb_state*,const char*,size_t); -mrb_bool mrb_str_interned(mrb_state*,mrb_value); +mrb_value mrb_cstr_interned(mrb_state*,const char*); +mrb_value mrb_interned(mrb_state*,const char*,size_t); +mrb_value mrb_str_interned(mrb_state*,mrb_value); const char *mrb_sym2name(mrb_state*,mrb_sym); const char *mrb_sym2name_len(mrb_state*,mrb_sym,size_t*); mrb_value mrb_sym2str(mrb_state*,mrb_sym); diff --git a/src/symbol.c b/src/symbol.c index 3d841a636..f1dff6a8d 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -72,25 +72,30 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } -mrb_bool +mrb_value mrb_cstr_interned(mrb_state *mrb, const char *name) { return mrb_interned(mrb, name, strlen(name)); } -mrb_bool +mrb_value mrb_interned(mrb_state *mrb, const char *name, size_t len) { khash_t(n2s) *h = mrb->name2sym; symbol_name sname; + khiter_t k; sname.len = len; sname.name = name; - return (kh_get(n2s, h, sname) != kh_end(h)) ? TRUE : FALSE; + k = kh_get(n2s, h, sname); + if (k != kh_end(h)) { + return mrb_symbol_value(kh_value(h, k)); + } + return mrb_nil_value(); } -mrb_bool +mrb_value mrb_str_interned(mrb_state *mrb, mrb_value str) { return mrb_interned(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); -- cgit v1.2.3 From a517a7f314efcdeb5dec306d0ccab6084cf2a439 Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Thu, 25 Apr 2013 10:36:32 +0900 Subject: modify functions to suppress symbol registration into intern pool. --- src/class.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/class.c b/src/class.c index c2d17e2fc..4647db4b2 100644 --- a/src/class.c +++ b/src/class.c @@ -206,7 +206,11 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id int mrb_class_defined(mrb_state *mrb, const char *name) { - return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_intern(mrb, name)); + mrb_value sym = mrb_cstr_interned(mrb, name); + if (mrb_nil_p(sym)) { + return FALSE; + } + return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym)); } static struct RClass * @@ -1463,7 +1467,7 @@ mod_define_method(mrb_state *mrb, mrb_value self) } static void -check_cv_name(mrb_state *mrb, mrb_sym id) +check_cv_name_sym(mrb_state *mrb, mrb_sym id) { const char *s; size_t len; @@ -1474,6 +1478,32 @@ check_cv_name(mrb_state *mrb, mrb_sym id) } } +static void +check_cv_name_str(mrb_state *mrb, mrb_value str) +{ + const char *s = RSTRING_PTR(str); + size_t const len = RSTRING_LEN(str); + if (len < 3 || !(s[0] == '@' && s[1] == '@')) { + mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str); + } +} + +static mrb_value +get_sym_or_str_arg(mrb_state *mrb) +{ + mrb_value sym_or_str; + + mrb_get_args(mrb, "o", &sym_or_str); + + if (mrb_symbol_p(sym_or_str) || mrb_string_p(sym_or_str)) { + return sym_or_str; + } else { + mrb_value obj = mrb_funcall(mrb, sym_or_str, "inspect", 0); + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj); + return mrb_nil_value(); + } +} + /* 15.2.2.4.16 */ /* * call-seq: @@ -1492,12 +1522,23 @@ check_cv_name(mrb_state *mrb, mrb_sym id) static mrb_value mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod) { - mrb_sym id; + mrb_value id; mrb_bool defined_p; - mrb_get_args(mrb, "n", &id); - check_cv_name(mrb, id); - defined_p = mrb_cv_defined(mrb, mod, id); + id = get_sym_or_str_arg(mrb); + if (mrb_symbol_p(id)) { + check_cv_name_sym(mrb, mrb_symbol(id)); + defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(id)); + } else { + mrb_value sym; + check_cv_name_str(mrb, id); + sym = mrb_str_interned(mrb, id); + if (mrb_nil_p(sym)) { + defined_p = FALSE; + } else { + defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(sym)); + } + } return mrb_bool_value(defined_p); } @@ -1522,7 +1563,7 @@ mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod) mrb_sym id; mrb_get_args(mrb, "n", &id); - check_cv_name(mrb, id); + check_cv_name_sym(mrb, id); return mrb_cv_get(mrb, mod, id); } @@ -1551,7 +1592,7 @@ mrb_mod_cvar_set(mrb_state *mrb, mrb_value mod) mrb_sym id; mrb_get_args(mrb, "no", &id, &value); - check_cv_name(mrb, id); + check_cv_name_sym(mrb, id); mrb_cv_set(mrb, mod, id, value); return value; } @@ -1586,7 +1627,7 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod) mrb_sym id; mrb_get_args(mrb, "n", &id); - check_cv_name(mrb, id); + check_cv_name_sym(mrb, id); val = mrb_iv_remove(mrb, mod, id); if (!mrb_undef_p(val)) return val; @@ -1633,11 +1674,20 @@ mrb_mod_remove_cvar(mrb_state *mrb, mrb_value mod) static mrb_value mrb_mod_method_defined(mrb_state *mrb, mrb_value mod) { - mrb_sym id; + mrb_value id; mrb_bool method_defined_p; - mrb_get_args(mrb, "n", &id); - method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), id); + id = get_sym_or_str_arg(mrb); + if (mrb_symbol_p(id)) { + method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id)); + } else { + mrb_value sym = mrb_str_interned(mrb, id); + if (mrb_nil_p(sym)) { + method_defined_p = FALSE; + } else { + method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(sym)); + } + } return mrb_bool_value(method_defined_p); } @@ -1684,7 +1734,7 @@ mrb_mod_remove_method(mrb_state *mrb, mrb_value mod) } static void -check_const_name(mrb_state *mrb, mrb_sym id) +check_const_name_sym(mrb_state *mrb, mrb_sym id) { const char *s; size_t len; @@ -1695,15 +1745,34 @@ check_const_name(mrb_state *mrb, mrb_sym id) } } +static void +check_const_name_str(mrb_state *mrb, mrb_value str) +{ + if (RSTRING_LEN(str) < 1 || !ISUPPER(*RSTRING_PTR(str))) { + mrb_name_error(mrb, mrb_intern_str(mrb, str), "wrong constant name %S", str); + } +} + mrb_value mrb_mod_const_defined(mrb_state *mrb, mrb_value mod) { - mrb_sym id; + mrb_value id; mrb_bool const_defined_p; - mrb_get_args(mrb, "n", &id); - check_const_name(mrb, id); - const_defined_p = mrb_const_defined(mrb, mod, id); + id = get_sym_or_str_arg(mrb); + if (mrb_type(id) == MRB_TT_SYMBOL) { + check_const_name_sym(mrb, mrb_symbol(id)); + const_defined_p = mrb_const_defined(mrb, mod, mrb_symbol(id)); + } else { + mrb_value sym; + check_const_name_str(mrb, id); + sym = mrb_str_interned(mrb, id); + if (mrb_nil_p(sym)) { + const_defined_p = FALSE; + } else { + const_defined_p = mrb_const_defined(mrb, mod, mrb_symbol(sym)); + } + } return mrb_bool_value(const_defined_p); } @@ -1714,7 +1783,7 @@ mrb_mod_const_get(mrb_state *mrb, mrb_value mod) mrb_sym id; mrb_get_args(mrb, "n", &id); - check_const_name(mrb, id); + check_const_name_sym(mrb, id); return mrb_const_get(mrb, mod, id); } @@ -1725,7 +1794,7 @@ mrb_mod_const_set(mrb_state *mrb, mrb_value mod) mrb_value value; mrb_get_args(mrb, "no", &id, &value); - check_const_name(mrb, id); + check_const_name_sym(mrb, id); mrb_const_set(mrb, mod, id, value); return value; } @@ -1737,7 +1806,7 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod) mrb_value val; mrb_get_args(mrb, "n", &id); - check_const_name(mrb, id); + check_const_name_sym(mrb, id); val = mrb_iv_remove(mrb, mod, id); if (mrb_undef_p(val)) { mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id)); -- cgit v1.2.3 From 09dad05a72661727fcef688d110220fc443e80f2 Mon Sep 17 00:00:00 2001 From: crimsonwoods Date: Thu, 25 Apr 2013 15:56:53 +0900 Subject: suppress intern inside of 'respond_to?'. --- src/kernel.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/kernel.c b/src/kernel.c index 5ce5669c3..222a9ab6b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -966,15 +966,35 @@ obj_respond_to(mrb_state *mrb, mrb_value self) int argc; mrb_value mid, priv; mrb_sym id, rtm_id; - mrb_bool respond_to_p; + mrb_bool respond_to_p = TRUE; mrb_get_args(mrb, "*", &argv, &argc); mid = argv[0]; if (argc > 1) priv = argv[1]; else priv = mrb_nil_value(); - id = mrb_to_id(mrb, mid); - respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv)); + if (mrb_symbol_p(mid)) { + id = mrb_symbol(mid); + } else { + mrb_value tmp; + if (!mrb_string_p(mid)) { + tmp = mrb_check_string_type(mrb, mid); + if (mrb_nil_p(tmp)) { + tmp = mrb_inspect(mrb, mid); + mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp); + } + } + tmp = mrb_str_interned(mrb, mid); + if (mrb_nil_p(tmp)) { + respond_to_p = FALSE; + } else { + id = mrb_intern_str(mrb, mid); + } + } + + if (respond_to_p) { + respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv)); + } if (!respond_to_p) { rtm_id = mrb_intern2(mrb, "respond_to_missing?", 19); -- cgit v1.2.3