Skip to content

Instantly share code, notes, and snippets.

@wanabe
Created August 26, 2012 02:03
Show Gist options
  • Select an option

  • Save wanabe/3473112 to your computer and use it in GitHub Desktop.

Select an option

Save wanabe/3473112 to your computer and use it in GitHub Desktop.
diff --git a/include/mruby/irep.h b/include/mruby/irep.h
index af3346c..3dec0fd 100644
--- a/include/mruby/irep.h
+++ b/include/mruby/irep.h
@@ -29,6 +29,7 @@ typedef struct mrb_irep {
#define MRB_ISEQ_NOFREE 1
void mrb_add_irep(mrb_state *mrb, int n);
+mrb_irep *mrb_irep_new(mrb_state *mrb, int ilen, mrb_code *iseq, int plen, mrb_value *pool, int slen, mrb_sym *syms);
#if defined(__cplusplus)
} /* extern "C" { */
diff --git a/mrblib/class.rb b/mrblib/class.rb
index 4f268b6..64ee163 100644
--- a/mrblib/class.rb
+++ b/mrblib/class.rb
@@ -1,19 +1,4 @@
class Module
- # 15.2.2.4.13
- def attr_reader(*names)
- names.each{|name|
- name2 = ('@'+name.to_s).intern
- define_method(name){self.instance_variable_get(name2)}
- }
- end
- # 15.2.2.4.14
- def attr_writer(*names)
- names.each{|name|
- name2 = ('@'+name.to_s).intern
- name = (name.to_s+"=").intern
- define_method(name){|v|self.instance_variable_set(name2,v)}
- }
- end
# 15.2.2.4.12
def attr_accessor(*names)
attr_reader(*names)
diff --git a/src/class.c b/src/class.c
index 0c0c6a3..291e671 100644
--- a/src/class.c
+++ b/src/class.c
@@ -9,10 +9,13 @@
#include <stdio.h>
#include "mruby/class.h"
#include "mruby/proc.h"
+#include "mruby/irep.h"
+#include "mruby/compile.h"
#include "mruby/string.h"
#include "mruby/numeric.h"
#include "mruby/variable.h"
#include "mruby/array.h"
+#include "opcode.h"
#include "error.h"
KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal);
@@ -1355,6 +1358,92 @@ mrb_mod_const_set(mrb_state *mrb, mrb_value mod)
return value;
}
+static const char *
+mrb_cstr_len(mrb_state *mrb, mrb_value val, int *lenp)
+{
+ const char *cstr;
+
+ if(mrb_type(val) == MRB_TT_SYMBOL) {
+ return mrb_sym2name_len(mrb, SYM2ID(val), lenp);
+ }
+ else if(mrb_type(val) != MRB_TT_STRING) {
+ mrb_value obj = mrb_funcall(mrb, val, "inspect", 0);
+ mrb_raise(mrb, E_TYPE_ERROR, "%s is not a symbol",
+ mrb_string_value_ptr(mrb, obj));
+ }
+ cstr = mrb_string_value_cstr(mrb, &val);
+ *lenp = strlen(cstr);
+ return cstr;
+}
+
+static mrb_value
+mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value *argv;
+ int argc, len, i;
+ char *vname;
+ const char *name;
+ mrb_sym sym, vsym;
+ mrb_irep *irep;
+ struct RProc *proc;
+ mrb_code iseq[3] = {
+ MKOP_Ax(OP_ENTER, 0<<18),
+ MKOP_ABx(OP_GETIV, 0, 0),
+ MKOP_AB(OP_RETURN, 0, OP_R_NORMAL)
+ };
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ for (i=0; i<argc; i++) {
+ name = mrb_cstr_len(mrb, argv[i], &len);
+ vname = mrb_malloc(mrb, len + 2);
+ *vname = '@';
+ memcpy(vname + 1, name, len + 1);
+ vsym = mrb_intern(mrb, vname);
+ free(vname);
+ irep = mrb_irep_new(mrb, sizeof(iseq) / sizeof(mrb_code), iseq, 0, NULL, 1, &vsym);
+ sym = mrb_sym_value(mrb, argv[i]);
+ proc = mrb_proc_new(mrb, irep);
+ proc->flags |= MRB_PROC_STRICT;
+ mrb_define_method_raw(mrb, mrb_class_ptr(mod), sym, proc);
+ }
+ return mrb_nil_value();
+}
+
+static mrb_value
+mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
+{
+ mrb_value *argv;
+ int argc, len, i;
+ char *vname;
+ const char *name;
+ mrb_sym sym, vsym;
+ mrb_irep *irep;
+ struct RProc *proc;
+ mrb_code iseq[3] = {
+ MKOP_Ax(OP_ENTER, 1<<18),
+ MKOP_ABx(OP_SETIV, 1, 0),
+ MKOP_AB(OP_RETURN, 1, OP_R_NORMAL)
+ };
+
+ mrb_get_args(mrb, "*", &argv, &argc);
+ for (i=0; i<argc; i++) {
+ name = mrb_cstr_len(mrb, argv[i], &len);
+ vname = mrb_malloc(mrb, len + 2);
+ *vname = '@';
+ memcpy(vname + 1, name, len + 1);
+ vsym = mrb_intern(mrb, vname);
+ irep = mrb_irep_new(mrb, sizeof(iseq) / sizeof(mrb_code), iseq, 0, NULL, 1, &vsym);
+ memcpy(vname, name, len);
+ vname[len] = '=';
+ sym = mrb_intern(mrb, vname);
+ free(vname);
+ proc = mrb_proc_new(mrb, irep);
+ proc->flags |= MRB_PROC_STRICT;
+ mrb_define_method_raw(mrb, mrb_class_ptr(mod), sym, proc);
+ }
+ return mrb_nil_value();
+}
+
static mrb_value
mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
@@ -1424,6 +1513,8 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "const_get", mrb_mod_const_get, ARGS_REQ(1)); /* 15.2.2.4.21 */
mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, ARGS_REQ(2)); /* 15.2.2.4.23 */
mrb_define_method(mrb, mod, "define_method", mod_define_method, ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "attr_reader", mrb_mod_attr_reader, ARGS_ANY());
+ mrb_define_method(mrb, mod, "attr_writer", mrb_mod_attr_writer, ARGS_ANY());
mrb_define_method(mrb, mod, "===", mrb_mod_eqq, ARGS_REQ(1));
mrb_undef_method(mrb, cls, "append_features");
diff --git a/src/codegen.c b/src/codegen.c
index 38d57d5..d9ab00d 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -2474,6 +2474,26 @@ mrb_generate_code(mrb_state *mrb, node *tree)
return start;
}
+mrb_irep *
+mrb_irep_new(mrb_state *mrb, int ilen, mrb_code *iseq, int plen, mrb_value *pool, int slen, mrb_sym *syms)
+{
+ mrb_irep *irep;
+
+ mrb_add_irep(mrb, mrb->irep_len + 1);
+ irep = (mrb_irep *)mrb_calloc(mrb, sizeof(mrb_irep), 1);
+
+#define COPY_IREP_ITEM(item, type, len) \
+ irep->item = (type *)mrb_malloc(mrb, sizeof(type) * len); \
+ memcpy(irep->item, item, sizeof(type) * len); \
+ irep->len = len;
+
+ COPY_IREP_ITEM(iseq, mrb_code , ilen);
+ COPY_IREP_ITEM(pool, mrb_value, plen);
+ COPY_IREP_ITEM(syms, mrb_sym , slen);
+ mrb->irep[mrb->irep_len++] = irep;
+ return irep;
+}
+
#ifdef CODEGEN_TEST
int
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment