mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
implement attr_reader and attr_writer in C; use cfunc closure to speed-up
This commit is contained in:
+1
-24
@@ -1,28 +1,5 @@
|
||||
class Module
|
||||
# 15.2.2.4.13
|
||||
def attr_reader(*names)
|
||||
names.each do |name|
|
||||
name = name.to_s
|
||||
raise(NameError, "#{name.inspect} is not allowed as an instance variable name") if name.include?('@') || name.include?('?') || name.include?('$')
|
||||
|
||||
attr_name = '@'+name
|
||||
define_method(name){self.instance_variable_get(attr_name)}
|
||||
end
|
||||
nil
|
||||
end
|
||||
# 15.2.2.4.14
|
||||
def attr_writer(*names)
|
||||
names.each do |name|
|
||||
name = name.to_s
|
||||
raise(NameError, "#{name.inspect} is not allowed as an instance variable name") if name.include?('@') || name.include?('?') || name.include?('$')
|
||||
|
||||
attr_name = '@'+name
|
||||
name = (name+"=").intern
|
||||
define_method(name){|v|self.instance_variable_set(attr_name,v)}
|
||||
end
|
||||
nil
|
||||
end
|
||||
# 15.2.2.4.12
|
||||
# 15.2.2.4.12
|
||||
def attr_accessor(*names)
|
||||
attr_reader(*names)
|
||||
attr_writer(*names)
|
||||
|
||||
+97
-10
@@ -393,6 +393,21 @@ to_hash(mrb_state *mrb, mrb_value val)
|
||||
return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
|
||||
}
|
||||
|
||||
static mrb_sym
|
||||
to_sym(mrb_state *mrb, mrb_value ss)
|
||||
{
|
||||
if (mrb_type(ss) == MRB_TT_SYMBOL) {
|
||||
return mrb_symbol(ss);
|
||||
}
|
||||
else if (mrb_string_p(ss)) {
|
||||
return mrb_intern_str(mrb, to_str(mrb, ss));
|
||||
}
|
||||
else {
|
||||
mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
retrieve arguments from mrb_state.
|
||||
|
||||
@@ -635,16 +650,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
|
||||
mrb_value ss;
|
||||
|
||||
ss = *sp++;
|
||||
if (mrb_type(ss) == MRB_TT_SYMBOL) {
|
||||
*symp = mrb_symbol(ss);
|
||||
}
|
||||
else if (mrb_string_p(ss)) {
|
||||
*symp = mrb_intern_str(mrb, to_str(mrb, ss));
|
||||
}
|
||||
else {
|
||||
mrb_value obj = mrb_funcall(mrb, ss, "inspect", 0);
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
|
||||
}
|
||||
*symp = to_sym(mrb, ss);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -1050,6 +1056,85 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
|
||||
return m;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
attr_reader(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
|
||||
return mrb_iv_get(mrb, obj, to_sym(mrb, name));
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
struct RClass *c = mrb_class_ptr(mod);
|
||||
mrb_value *argv;
|
||||
mrb_int argc, i;
|
||||
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
for (i=0; i<argc; i++) {
|
||||
mrb_value name, str;
|
||||
mrb_sym method, sym;
|
||||
|
||||
method = to_sym(mrb, argv[i]);
|
||||
name = mrb_sym2str(mrb, method);
|
||||
str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
|
||||
mrb_str_cat_cstr(mrb, str, "@");
|
||||
mrb_str_cat_str(mrb, str, name);
|
||||
sym = mrb_intern_str(mrb, str);
|
||||
mrb_iv_check(mrb, sym);
|
||||
name = mrb_symbol_value(sym);
|
||||
mrb_define_method_raw(mrb, c, method,
|
||||
mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name));
|
||||
}
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
attr_writer(mrb_state *mrb, mrb_value obj)
|
||||
{
|
||||
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
|
||||
mrb_value val;
|
||||
|
||||
mrb_get_args(mrb, "o", &val);
|
||||
mrb_iv_set(mrb, obj, to_sym(mrb, name), val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
|
||||
{
|
||||
struct RClass *c = mrb_class_ptr(mod);
|
||||
mrb_value *argv;
|
||||
mrb_int argc, i;
|
||||
|
||||
mrb_get_args(mrb, "*", &argv, &argc);
|
||||
for (i=0; i<argc; i++) {
|
||||
mrb_value name, str, attr;
|
||||
mrb_sym method, sym;
|
||||
|
||||
method = to_sym(mrb, argv[i]);
|
||||
|
||||
/* prepare iv name (@name) */
|
||||
name = mrb_sym2str(mrb, method);
|
||||
str = mrb_str_buf_new(mrb, RSTRING_LEN(name)+1);
|
||||
mrb_str_cat_cstr(mrb, str, "@");
|
||||
mrb_str_cat_str(mrb, str, name);
|
||||
sym = mrb_intern_str(mrb, str);
|
||||
mrb_iv_check(mrb, sym);
|
||||
attr = mrb_symbol_value(sym);
|
||||
|
||||
/* prepare method name (name=) */
|
||||
str = mrb_str_buf_new(mrb, RSTRING_LEN(str));
|
||||
mrb_str_cat_str(mrb, str, name);
|
||||
mrb_str_cat_cstr(mrb, str, "=");
|
||||
method = mrb_intern_str(mrb, str);
|
||||
|
||||
mrb_define_method_raw(mrb, c, method,
|
||||
mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr));
|
||||
}
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
|
||||
{
|
||||
@@ -2033,6 +2118,8 @@ mrb_init_class(mrb_state *mrb)
|
||||
mrb_define_method(mrb, mod, "public", mrb_mod_dummy_visibility, MRB_ARGS_ANY()); /* 15.2.2.4.38 */
|
||||
mrb_define_method(mrb, mod, "remove_class_variable", mrb_mod_remove_cvar, MRB_ARGS_REQ(1)); /* 15.2.2.4.39 */
|
||||
mrb_define_method(mrb, mod, "remove_method", mrb_mod_remove_method, MRB_ARGS_ANY()); /* 15.2.2.4.41 */
|
||||
mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, MRB_ARGS_ANY()); /* 15.2.2.4.13 */
|
||||
mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, MRB_ARGS_ANY()); /* 15.2.2.4.14 */
|
||||
mrb_define_method(mrb, mod, "to_s", mrb_mod_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, mod, "inspect", mrb_mod_to_s, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, mod, "alias_method", mrb_mod_alias, MRB_ARGS_ANY()); /* 15.2.2.4.8 */
|
||||
|
||||
Reference in New Issue
Block a user