summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-04-26 09:18:39 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-04-26 09:18:39 +0900
commitc99b72b20d3c3814248c9654c934a06e5dff96e5 (patch)
tree2b166e19616f3f114b4ad2f2838b028bd38b1e32 /src
parentfa0e41a84d472de9e37ae8ad609e94a1ab905c53 (diff)
parent09dad05a72661727fcef688d110220fc443e80f2 (diff)
downloadmruby-c99b72b20d3c3814248c9654c934a06e5dff96e5.tar.gz
mruby-c99b72b20d3c3814248c9654c934a06e5dff96e5.zip
Merge branch 'suppress_intern' of https://github.com/crimsonwoods/mruby into crimsonwoods-suppress_intern
Diffstat (limited to 'src')
-rw-r--r--src/class.c109
-rw-r--r--src/kernel.c26
-rw-r--r--src/symbol.c29
3 files changed, 141 insertions, 23 deletions
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)