diff options
Diffstat (limited to 'struct.c')
-rw-r--r-- | struct.c | 61 |
1 files changed, 27 insertions, 34 deletions
@@ -10,6 +10,11 @@ **********************************************************************/ #include "internal.h" +#include "vm_core.h" +#include "method.h" + +rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg); +rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg); VALUE rb_cStruct; static ID id_members; @@ -105,12 +110,6 @@ rb_struct_getmember(VALUE obj, ID id) UNREACHABLE; } -static VALUE -rb_struct_ref(VALUE obj) -{ - return rb_struct_getmember(obj, rb_frame_this_func()); -} - static VALUE rb_struct_ref0(VALUE obj) {return RSTRUCT_GET(obj, 0);} static VALUE rb_struct_ref1(VALUE obj) {return RSTRUCT_GET(obj, 1);} static VALUE rb_struct_ref2(VALUE obj) {return RSTRUCT_GET(obj, 2);} @@ -145,32 +144,6 @@ rb_struct_modify(VALUE s) } static VALUE -rb_struct_set(VALUE obj, VALUE val) -{ - VALUE members, slot, fsym; - long i, len; - ID fid = rb_frame_this_func(); - ID this_func = fid; - - members = rb_struct_members(obj); - len = RARRAY_LEN(members); - rb_struct_modify(obj); - fid = rb_id_attrget(fid); - if (!fid) not_a_member(this_func); - fsym = ID2SYM(fid); - for (i=0; i<len; i++) { - slot = RARRAY_AREF(members, i); - if (slot == fsym) { - RSTRUCT_SET(obj, i, val); - return val; - } - } - not_a_member(fid); - - UNREACHABLE; -} - -static VALUE anonymous_struct(VALUE klass) { VALUE nstr; @@ -199,6 +172,24 @@ new_struct(VALUE name, VALUE super) return rb_define_class_id_under(super, id, super); } +static void +define_aref_method(VALUE nstr, VALUE name, VALUE off) +{ + rb_iseq_t *iseq = rb_method_for_self_aref(name, off); + + rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC); + RB_GC_GUARD(iseq->self); +} + +static void +define_aset_method(VALUE nstr, VALUE name, VALUE off) +{ + rb_iseq_t *iseq = rb_method_for_self_aset(name, off); + + rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC); + RB_GC_GUARD(iseq->self); +} + static VALUE setup_struct(VALUE nstr, VALUE members) { @@ -216,13 +207,15 @@ setup_struct(VALUE nstr, VALUE members) len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(ptr_members[i]); + VALUE off = LONG2NUM(i); + if (i < N_REF_FUNC) { rb_define_method_id(nstr, id, ref_func[i], 0); } else { - rb_define_method_id(nstr, id, rb_struct_ref, 0); + define_aref_method(nstr, ptr_members[i], off); } - rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1); + define_aset_method(nstr, ID2SYM(rb_id_attrset(id)), off); } return nstr; |