diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2012-12-20 07:35:34 -0800 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2012-12-20 07:35:34 -0800 |
| commit | e48ed9c9649340544156dba57e3a6f29f536066b (patch) | |
| tree | 6d4e2ebcc3332897df0d7abc1a2bca9f8516d566 /src | |
| parent | 3c28241bd76466bafec5555028283e3fc6f2799a (diff) | |
| parent | e6a47323b8d67fdf85f095c30b2d66a00d2d2ca5 (diff) | |
| download | mruby-e48ed9c9649340544156dba57e3a6f29f536066b.tar.gz mruby-e48ed9c9649340544156dba57e3a6f29f536066b.zip | |
Merge pull request #655 from skandhas/pr-add-Module_class_variable_get
Add Module#class_variable_get for mruby
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 40 | ||||
| -rw-r--r-- | src/variable.c | 24 |
2 files changed, 58 insertions, 6 deletions
diff --git a/src/class.c b/src/class.c index 339920b6e..19a697bc8 100644 --- a/src/class.c +++ b/src/class.c @@ -1445,6 +1445,45 @@ mrb_sym_value(mrb_state *mrb, mrb_value val) } static void +check_cv_name(mrb_state *mrb, mrb_sym id) +{ + const char *s; + int len; + + s = mrb_sym2name_len(mrb, id, &len); + if (len < 3 || !(s[0] == '@' && s[1] == '@')) { + mrb_name_error(mrb, id, "`%s' is not allowed as a class variable name", s); + } +} + +/* 15.2.2.4.17 */ +/* + * call-seq: + * mod.class_variable_get(symbol) -> obj + * + * Returns the value of the given class variable (or throws a + * <code>NameError</code> exception). The <code>@@</code> part of the + * variable name should be included for regular class variables + * + * class Fred + * @@foo = 99 + * end + * Fred.class_variable_get(:@@foo) #=> 99 + */ + +static mrb_value +mrb_mod_cvar_get(mrb_state *mrb, mrb_value mod) +{ + mrb_value sym; + mrb_sym id; + mrb_get_args(mrb, "o", &sym); + + id = mrb_sym_value(mrb,sym); + check_cv_name(mrb, id); + return mrb_cv_get(mrb, mod, id); +} + +static void check_const_name(mrb_state *mrb, mrb_sym id) { const char *s; @@ -1545,6 +1584,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, ARGS_NONE()); /* 15.2.3.3.4 */ mrb_define_method(mrb, cls, "new", mrb_instance_new, ARGS_ANY()); /* 15.2.3.3.3 */ mrb_define_method(mrb, cls, "inherited", mrb_bob_init, ARGS_REQ(1)); + mrb_define_method(mrb, mod, "class_variable_get", mrb_mod_cvar_get, ARGS_REQ(1)); /* 15.2.2.4.17 */ mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, ARGS_REQ(1)); /* 15.2.2.4.25 */ mrb_define_method(mrb, mod, "extended", mrb_bob_init, ARGS_REQ(1)); /* 15.2.2.4.26 */ mrb_define_method(mrb, mod, "include", mrb_mod_include, ARGS_ANY()); /* 15.2.2.4.27 */ diff --git a/src/variable.c b/src/variable.c index 992663408..147373bd4 100644 --- a/src/variable.c +++ b/src/variable.c @@ -673,26 +673,38 @@ mrb_mod_class_variables(mrb_state *mrb, mrb_value mod) return ary; } - mrb_value -mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) +mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) { - struct RClass *c = mrb->ci->proc->target_class; - - if (!c) c = mrb->ci->target_class; while (c) { if (c->iv) { iv_tbl *t = c->iv; mrb_value v; if (iv_get(mrb, t, sym, &v)) - return v; + return v; } c = c->super; } return mrb_nil_value(); } +mrb_value +mrb_cv_get(mrb_state *mrb, mrb_value mod, mrb_sym sym) +{ + return mrb_mod_cv_get(mrb, mrb_class_ptr(mod), sym); +} + +mrb_value +mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym) +{ + struct RClass *c = mrb->ci->proc->target_class; + + if (!c) c = mrb->ci->target_class; + + return mrb_mod_cv_get(mrb, c, sym); +} + void mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v) { |
