summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/string.h1
-rw-r--r--src/class.c36
-rw-r--r--test/t/module.rb8
3 files changed, 41 insertions, 4 deletions
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 8b75a2275..c3fbb063d 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -89,6 +89,7 @@ MRB_API void mrb_str_modify(mrb_state*, struct RString*);
* Finds the index of a substring in a string
*/
MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
+#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
/*
* Appends self to other. Returns self as a concatnated string.
diff --git a/src/class.c b/src/class.c
index 56f64fd4e..57f64dcc5 100644
--- a/src/class.c
+++ b/src/class.c
@@ -2161,13 +2161,43 @@ mrb_mod_const_defined(mrb_state *mrb, mrb_value mod)
}
static mrb_value
+mrb_const_get_sym(mrb_state *mrb, mrb_value mod, mrb_sym id)
+{
+ check_const_name_sym(mrb, id);
+ return mrb_const_get(mrb, mod, id);
+}
+
+static mrb_value
mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
{
+ mrb_value path;
mrb_sym id;
+ char *ptr;
+ mrb_int off, end, len;
- mrb_get_args(mrb, "n", &id);
- check_const_name_sym(mrb, id);
- return mrb_const_get(mrb, mod, id);
+ mrb_get_args(mrb, "o", &path);
+
+ if (mrb_symbol_p(path)) {
+ /* const get with symbol */
+ id = mrb_symbol(path);
+ return mrb_const_get_sym(mrb, mod, id);
+ }
+
+ /* const get with class path string */
+ path = mrb_string_type(mrb, path);
+ ptr = RSTRING_PTR(path);
+ len = RSTRING_LEN(path);
+ off = 0;
+
+ while (off < len) {
+ end = mrb_str_index_lit(mrb, path, "::", off);
+ end = (end == -1) ? len : end;
+ id = mrb_intern(mrb, ptr+off, end-off);
+ mod = mrb_const_get_sym(mrb, mod, id);
+ off = (end == len) ? end : end+2;
+ }
+
+ return mod;
}
static mrb_value
diff --git a/test/t/module.rb b/test/t/module.rb
index 419b0bfd5..04fa8d102 100644
--- a/test/t/module.rb
+++ b/test/t/module.rb
@@ -268,6 +268,12 @@ assert('Module#const_get', '15.2.2.4.21') do
end
assert_equal 42, Test4ConstGet.const_get(:Const4Test4ConstGet)
+ assert_equal 42, Test4ConstGet.const_get("Const4Test4ConstGet")
+ assert_equal 42, Object.const_get("Test4ConstGet::Const4Test4ConstGet")
+
+ assert_raise(TypeError){ Test4ConstGet.const_get(123) }
+ assert_raise(NameError){ Test4ConstGet.const_get(:I_DO_NOT_EXIST) }
+ assert_raise(NameError){ Test4ConstGet.const_get("I_DO_NOT_EXIST::ME_NEITHER") }
end
assert('Module#const_missing', '15.2.2.4.22') do
@@ -280,7 +286,7 @@ assert('Module#const_missing', '15.2.2.4.22') do
assert_equal 42, Test4ConstMissing.const_get(:ConstDoesntExist)
end
-assert('Module#const_get', '15.2.2.4.23') do
+assert('Module#const_set', '15.2.2.4.23') do
module Test4ConstSet
Const4Test4ConstSet = 42
end