diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-04-26 09:18:39 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2013-04-26 09:18:39 +0900 |
| commit | c99b72b20d3c3814248c9654c934a06e5dff96e5 (patch) | |
| tree | 2b166e19616f3f114b4ad2f2838b028bd38b1e32 | |
| parent | fa0e41a84d472de9e37ae8ad609e94a1ab905c53 (diff) | |
| parent | 09dad05a72661727fcef688d110220fc443e80f2 (diff) | |
| download | mruby-c99b72b20d3c3814248c9654c934a06e5dff96e5.tar.gz mruby-c99b72b20d3c3814248c9654c934a06e5dff96e5.zip | |
Merge branch 'suppress_intern' of https://github.com/crimsonwoods/mruby into crimsonwoods-suppress_intern
| -rw-r--r-- | include/mruby.h | 3 | ||||
| -rw-r--r-- | src/class.c | 109 | ||||
| -rw-r--r-- | src/kernel.c | 26 | ||||
| -rw-r--r-- | src/symbol.c | 29 |
4 files changed, 144 insertions, 23 deletions
diff --git a/include/mruby.h b/include/mruby.h index 652fbe34c..19743eed4 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -208,6 +208,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_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/class.c b/src/class.c index 69dc42534..5d22dbbc4 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)); diff --git a/src/kernel.c b/src/kernel.c index e4d820f4a..637a7b952 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); diff --git a/src/symbol.c b/src/symbol.c index bd6cc9683..1633a3c65 100644 --- a/src/symbol.c +++ b/src/symbol.c @@ -72,6 +72,35 @@ mrb_intern_str(mrb_state *mrb, mrb_value str) return mrb_intern2(mrb, RSTRING_PTR(str), RSTRING_LEN(str)); } +mrb_value +mrb_cstr_interned(mrb_state *mrb, const char *name) +{ + return mrb_interned(mrb, name, strlen(name)); +} + +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; + + k = kh_get(n2s, h, sname); + if (k != kh_end(h)) { + return mrb_symbol_value(kh_value(h, k)); + } + return mrb_nil_value(); +} + +mrb_value +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) |
