void rb_attr(VALUE klass, ID id, int read, int write, int ex) { const char *name; int noex; if (!ex) { noex = NOEX_PUBLIC; } else { // TODO honor current scope ex noex = NOEX_PUBLIC; } if (!rb_is_local_id(id) && !rb_is_const_id(id)) { rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); } name = rb_id2name(id); if (!name) { rb_raise(rb_eArgError, "argument needs to be symbol or string"); } rb_vm_define_attr((Class)klass, name, read, write, noex); if (write) { rb_objc_define_kvo_setter(klass, id); } }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i, len; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); #if !WITH_OBJC rb_make_metaclass(nstr, RBASIC(klass)->klass); #endif rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_ivar_set(nstr, id_members, members); rb_objc_define_method(*(VALUE *)nstr, "alloc", struct_alloc, 0); rb_objc_define_method(*(VALUE *)nstr, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "[]", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "members", rb_struct_s_members_m, 0); len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(RARRAY_AT(members, i)); if (rb_is_local_id(id) || rb_is_const_id(id)) { long j = i; /* Needed for block data reference. */ /* Struct attribute reader */ rb_objc_define_method(nstr, rb_id2name(id), pl_imp_implementationWithBlock(^(VALUE obj) { return RSTRUCT_PTR(obj)[j]; }), 0); /* Struct attribute writer */ rb_objc_define_method(nstr, rb_id2name(rb_id_attrset(id)), pl_imp_implementationWithBlock(^(VALUE obj, VALUE val) { VALUE *ptr = RSTRUCT_PTR(obj); rb_struct_modify(obj); GC_WB(&ptr[i], val); return val; }), 1);
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i, count; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); #if !WITH_OBJC rb_make_metaclass(nstr, RBASIC(klass)->klass); #endif rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY_LEN(members))); rb_iv_set(nstr, "__members__", members); rb_objc_define_method(*(VALUE *)nstr, "alloc", struct_alloc, 0); rb_objc_define_method(*(VALUE *)nstr, "new", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "[]", rb_class_new_instance_imp, -1); rb_objc_define_method(*(VALUE *)nstr, "members", rb_struct_s_members_m, 0); for (i = 0, count = RARRAY_LEN(members); i < count; i++) { ID id = SYM2ID(RARRAY_AT(members, i)); if (rb_is_local_id(id) || rb_is_const_id(id)) { if (i < N_REF_FUNC) { rb_objc_define_method(nstr, rb_id2name(id), ref_func[i], 0); } else { rb_objc_define_method(nstr, rb_id2name(id), rb_struct_ref, 0); } rb_objc_define_method(nstr, rb_id2name(rb_id_attrset(id)), rb_struct_set, 1); } } return nstr; }
static int collect_local_variables_in_iseq(rb_iseq_t *iseq, const VALUE ary) { int i; if (!iseq) return 0; for (i = 0; i < iseq->local_table_size; i++) { ID lid = iseq->local_table[i]; if (rb_is_local_id(lid)) { rb_ary_push(ary, ID2SYM(lid)); } } return 1; }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr, *ptr_members; ID id; long i, len; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); rb_make_metaclass(nstr, RBASIC(klass)->klass); rb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = rb_str_to_str(name); id = rb_to_id(name); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", StringValuePtr(name)); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_id_under(klass, id, klass); } rb_ivar_set(nstr, id_members, members); rb_define_alloc_func(nstr, struct_alloc); rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i< len; i++) { ID id = SYM2ID(ptr_members[i]); if (rb_is_local_id(id) || rb_is_const_id(id)) { 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); } rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1); } } return nstr; }
void rb_attr(VALUE klass, ID id, int read, int write, int ex) { if (!rb_is_local_id(id) && !rb_is_const_id(id)) { rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); } const char *name = rb_id2name(id); if (name == NULL) { rb_raise(rb_eArgError, "argument needs to be symbol or string"); } rb_vm_define_attr((Class)klass, name, read, write); if (write) { rb_objc_define_kvo_setter(klass, id); } }
static VALUE make_struct(VALUE name, VALUE members, VALUE klass) { VALUE nstr; ID id; long i; OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); rb_make_metaclass(nstr, RBASIC(klass)->klass); rb_class_inherited(klass, nstr); } else { char *cname = StringValuePtr(name); id = rb_intern(cname); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", cname); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", cname); rb_mod_remove_const(klass, ID2SYM(id)); } nstr = rb_define_class_under(klass, rb_id2name(id), klass); } rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(members)->len)); rb_iv_set(nstr, "__members__", members); rb_define_alloc_func(nstr, struct_alloc); rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); for (i=0; i< RARRAY(members)->len; i++) { ID id = SYM2ID(RARRAY(members)->ptr[i]); if (rb_is_local_id(id) || rb_is_const_id(id)) { if (i<10) { rb_define_method_id(nstr, id, ref_func[i], 0); } else { rb_define_method_id(nstr, id, rb_struct_ref, 0); } rb_define_method_id(nstr, rb_id_attrset(id), rb_struct_set, 1); } } return nstr; }
static VALUE inspect_struct(VALUE s, VALUE dummy, int recur) { VALUE cname = rb_class_name(rb_obj_class(s)); VALUE members, str = rb_str_new2("#<struct "); VALUE *ptr, *ptr_members; long i, len; char first = RSTRING_PTR(cname)[0]; if (recur || first != '#') { rb_str_append(str, cname); } if (recur) { return rb_str_cat2(str, ":...>"); } members = rb_struct_members(s); ptr_members = RARRAY_PTR(members); ptr = RSTRUCT_PTR(s); len = RSTRUCT_LEN(s); for (i=0; i<len; i++) { VALUE slot; ID id; if (i > 0) { rb_str_cat2(str, ", "); } else if (first != '#') { rb_str_cat2(str, " "); } slot = ptr_members[i]; id = SYM2ID(slot); if (rb_is_local_id(id) || rb_is_const_id(id)) { rb_str_append(str, rb_id2str(id)); } else { rb_str_append(str, rb_inspect(slot)); } rb_str_cat2(str, "="); rb_str_append(str, rb_inspect(ptr[i])); } rb_str_cat2(str, ">"); OBJ_INFECT(str, s); return str; }
void rb_attr(VALUE klass, ID id, int read, int write, int ex) { const char *name; ID attriv; VALUE aname; int noex; if (!ex) { noex = NOEX_PUBLIC; } else { if (SCOPE_TEST(NOEX_PRIVATE)) { noex = NOEX_PRIVATE; rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ? "attribute accessor as module_function" : "private attribute?"); } else if (SCOPE_TEST(NOEX_PROTECTED)) { noex = NOEX_PROTECTED; } else { noex = NOEX_PUBLIC; } } if (!rb_is_local_id(id) && !rb_is_const_id(id)) { rb_name_error(id, "invalid attribute name `%s'", rb_id2name(id)); } name = rb_id2name(id); if (!name) { rb_raise(rb_eArgError, "argument needs to be symbol or string"); } aname = rb_sprintf("@%s", name); rb_enc_copy(aname, rb_id2str(id)); attriv = rb_intern_str(aname); if (read) { rb_add_method(klass, id, NEW_IVAR(attriv), noex); } if (write) { rb_add_method(klass, rb_id_attrset(id), NEW_ATTRSET(attriv), noex); } }
static VALUE inspect_struct(VALUE s, VALUE dummy, int recur) { const char *cname = rb_class2name(rb_obj_class(s)); VALUE str, members; long i; if (recur) { return rb_sprintf("#<struct %s:...>", cname); } members = rb_struct_members(s); if (cname[0] == '#') { str = rb_str_new2("#<struct "); } else { str = rb_sprintf("#<struct %s ", cname); } for (i=0; i<RSTRUCT_LEN(s); i++) { VALUE slot; ID id; if (i > 0) { rb_str_cat2(str, ", "); } slot = RARRAY_AT(members, i); id = SYM2ID(slot); if (rb_is_local_id(id) || rb_is_const_id(id)) { rb_str_buf_append(str, rb_id2str(id)); } else { rb_str_buf_append(str, rb_inspect(slot)); } rb_str_cat2(str, "="); rb_str_buf_append(str, rb_inspect(RSTRUCT_PTR(s)[i])); } rb_str_cat2(str, ">"); OBJ_INFECT(str, s); return str; }
static VALUE inspect_struct(VALUE s) { const char *cname = rb_class2name(rb_obj_class(s)); VALUE str, members; long i; members = rb_struct_members(s); str = rb_str_buf_new2("#<struct "); rb_str_cat2(str, cname); rb_str_cat2(str, " "); for (i=0; i<RSTRUCT(s)->len; i++) { VALUE slot; ID id; const char *p; if (i > 0) { rb_str_cat2(str, ", "); } slot = RARRAY(members)->ptr[i]; id = SYM2ID(slot); if (rb_is_local_id(id) || rb_is_const_id(id)) { p = rb_id2name(id); rb_str_cat2(str, p); } else { rb_str_append(str, rb_inspect(slot)); } rb_str_cat2(str, "="); rb_str_append(str, rb_inspect(RSTRUCT(s)->ptr[i])); } rb_str_cat2(str, ">"); OBJ_INFECT(str, s); return str; }