static void rb_export_method(VALUE klass, ID name, ID noex) { NODE *fbody; VALUE origin; if (klass == rb_cObject) { rb_secure(4); } fbody = search_method(klass, name, &origin); if (!fbody && TYPE(klass) == T_MODULE) { fbody = search_method(rb_cObject, name, &origin); } if (!fbody || !fbody->nd_body) { rb_print_undef(klass, name, 0); } if (fbody->nd_body->nd_noex != noex) { if (nd_type(fbody->nd_body->nd_body) == NODE_CFUNC) { rb_vm_check_redefinition_opt_method(fbody); } if (klass == origin) { fbody->nd_body->nd_noex = noex; } else { rb_add_method(klass, name, NEW_ZSUPER(), noex); } } }
void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) { Check_Type(klass, T_CLASS); rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PRIVATE); }
static void rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) { rb_method_entry_t *me; if (klass == rb_cObject) { rb_secure(4); } me = search_method(klass, name); if (!me && RB_TYPE_P(klass, T_MODULE)) { me = search_method(rb_cObject, name); } if (UNDEFINED_METHOD_ENTRY_P(me)) { rb_print_undef(klass, name, 0); } if (me->flag != noex) { rb_vm_check_redefinition_opt_method(me, klass); if (klass == me->klass) { me->flag = noex; } else { rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex); } } }
static void rb_export_method(VALUE klass, ID name, rb_method_flag_t noex) { rb_method_entry_t *me; VALUE defined_class; me = search_method(klass, name, &defined_class); if (!me && RB_TYPE_P(klass, T_MODULE)) { me = search_method(rb_cObject, name, &defined_class); } if (UNDEFINED_METHOD_ENTRY_P(me) || UNDEFINED_REFINED_METHOD_P(me->def)) { rb_print_undef(klass, name, 0); } if (me->flag != noex) { rb_vm_check_redefinition_opt_method(me, klass); if (klass == defined_class || RCLASS_ORIGIN(klass) == defined_class) { me->flag = noex; if (me->def->type == VM_METHOD_TYPE_REFINED) { me->def->body.orig_me->flag = noex; } rb_clear_method_cache_by_class(klass); } else { rb_add_method(klass, name, VM_METHOD_TYPE_ZSUPER, 0, noex); } } }
void rb_undef_alloc_func(VALUE klass) { // TODO #if 0 Check_Type(klass, T_CLASS); rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, 0, NOEX_UNDEF); #endif }
void rb_undef(VALUE klass, ID id) { // TODO #if 0 VALUE origin; NODE *body; #if 0 // TODO if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { rb_secure(4); } #endif if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); } rb_frozen_class_p(klass); if (id == object_id || id == __send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); } /* TODO: warn if a very important method of NSObject is undefined * by default, pure objc methods are not exposed by introspections API */ body = search_method(klass, id, &origin); if (!body || !body->nd_body) { const char *s0 = " class"; VALUE c = klass; if (RCLASS_SINGLETON(c)) { VALUE obj = rb_iv_get(klass, "__attached__"); switch (TYPE(obj)) { case T_MODULE: case T_CLASS: c = obj; s0 = ""; } } else if (TYPE(c) == T_MODULE) { s0 = " module"; } rb_name_error(id, "undefined method `%s' for%s `%s'", rb_id2name(id), s0, rb_class2name(c)); } rb_add_method(klass, id, 0, NOEX_PUBLIC); if (RCLASS_SINGLETON(klass)) { rb_funcall(rb_iv_get(klass, "__attached__"), singleton_undefined, 1, ID2SYM(id)); } else { rb_funcall(klass, undefined, 1, ID2SYM(id)); } #endif }
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 void vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, rb_num_t is_singleton, NODE *cref) { VALUE klass = cref->nd_clss; int noex = (int)cref->nd_visi; rb_iseq_t *miseq; GetISeqPtr(iseqval, miseq); if (miseq->klass) { iseqval = rb_iseq_clone(iseqval, 0); RB_GC_GUARD(iseqval); GetISeqPtr(iseqval, miseq); } if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class/module to add method"); } if (is_singleton) { if (FIXNUM_P(obj) || SYMBOL_P(obj)) { rb_raise(rb_eTypeError, "can't define singleton method \"%s\" for %s", rb_id2name(id), rb_obj_classname(obj)); } rb_check_frozen(obj); klass = rb_singleton_class(obj); noex = NOEX_PUBLIC; } /* dup */ COPY_CREF(miseq->cref_stack, cref); miseq->cref_stack->nd_visi = NOEX_PUBLIC; miseq->klass = klass; miseq->defined_method_id = id; rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex); if (!is_singleton && noex == NOEX_MODFUNC) { rb_add_method(rb_singleton_class(klass), id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC); } INC_VM_STATE_VERSION(); }
void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE)) { // TODO #if 0 Check_Type(klass, T_CLASS); rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, NEW_CFUNC(func, 0), NOEX_PUBLIC); #endif }
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex) { if (func != rb_f_notimplement) { rb_method_cfunc_t opt; opt.func = func; opt.argc = argc; rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex); } else { rb_define_notimplement_method_id(klass, mid, noex); } }
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex) { if (argc < -2 || 15 < argc) rb_raise(rb_eArgError, "arity out of range: %d for -2..15", argc); if (func != rb_f_notimplement) { rb_method_cfunc_t opt; opt.func = func; opt.argc = argc; rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC, &opt, noex); } else { rb_define_notimplement_method_id(klass, mid, noex); } }
void rb_add_refined_method_entry(VALUE refined_class, ID mid) { rb_method_entry_t *me = lookup_method_table(refined_class, mid); if (me) { make_method_entry_refined(me); rb_clear_method_cache_by_class(refined_class); } else { rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, NOEX_PUBLIC); } }
void rb_attr(VALUE klass, ID id, int read, int write, int ex) { VALUE attriv; VALUE aname; rb_method_flag_t 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; } } aname = rb_id2str(rb_check_attr_id(id)); if (NIL_P(aname)) { rb_raise(rb_eArgError, "argument needs to be symbol or string"); } attriv = (VALUE)rb_intern_str(rb_sprintf("@%"PRIsVALUE, aname)); if (read) { rb_add_method(klass, id, VM_METHOD_TYPE_IVAR, (void *)attriv, noex); } if (write) { rb_add_method(klass, rb_id_attrset(id), VM_METHOD_TYPE_ATTRSET, (void *)attriv, noex); } }
void rb_undef(VALUE klass, ID id) { VALUE origin; NODE *body; if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); } rb_frozen_class_p(klass); if (id == object_id || id == __send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); } body = search_method(klass, id, &origin); if (!body || !body->nd_body) { const char *s0 = " class"; VALUE c = klass; if (FL_TEST(c, FL_SINGLETON)) { VALUE obj = rb_iv_get(klass, "__attached__"); switch (TYPE(obj)) { case T_MODULE: case T_CLASS: c = obj; s0 = ""; } } else if (TYPE(c) == T_MODULE) { s0 = " module"; } rb_name_error(id, "undefined method `%s' for%s `%s'", rb_id2name(id), s0, rb_class2name(c)); } rb_add_method(klass, id, 0, NOEX_PUBLIC); if (FL_TEST(klass, FL_SINGLETON)) { rb_funcall(rb_iv_get(klass, "__attached__"), singleton_undefined, 1, ID2SYM(id)); } else { rb_funcall(klass, undefined, 1, ID2SYM(id)); } }
static void clone_method(VALUE klass, ID mid, const rb_method_entry_t *me) { VALUE newiseqval; if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { rb_iseq_t *iseq; newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass); GetISeqPtr(newiseqval, iseq); OBJ_WRITE(iseq->self, &iseq->cref_stack, rewrite_cref_stack(me->def->body.iseq->cref_stack, me->klass, klass)); rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); RB_GC_GUARD(newiseqval); } else { rb_method_entry_set(klass, mid, me, me->flag); } }
static int clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) { VALUE newiseqval; if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) { rb_iseq_t *iseq; newiseqval = rb_iseq_clone(me->def->body.iseq->self, data->klass); GetISeqPtr(newiseqval, iseq); rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); RB_GC_GUARD(newiseqval); } else { rb_method_entry_set(data->klass, mid, me, me->flag); } return ST_CONTINUE; }
static int clone_method(ID mid, const rb_method_entry_t *me, struct clone_method_data *data) { switch (me->type) { case VM_METHOD_TYPE_ISEQ: { VALUE newiseqval = rb_iseq_clone(me->body.iseq->self, data->klass); rb_iseq_t *iseq; GetISeqPtr(newiseqval, iseq); rb_add_method(data->klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag); break; } default: rb_add_method_me(data->klass, mid, me, me->flag); break; } return ST_CONTINUE; }
void rb_undef(VALUE klass, ID id) { rb_method_entry_t *me; if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class to undef method"); } if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { rb_secure(4); } if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) { rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'", rb_id2name(id)); } rb_frozen_class_p(klass); if (id == object_id || id == id__send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); } me = search_method(klass, id); if (UNDEFINED_METHOD_ENTRY_P(me)) { const char *s0 = " class"; VALUE c = klass; if (FL_TEST(c, FL_SINGLETON)) { VALUE obj = rb_ivar_get(klass, attached); switch (TYPE(obj)) { case T_MODULE: case T_CLASS: c = obj; s0 = ""; } } else if (RB_TYPE_P(c, T_MODULE)) { s0 = " module"; } rb_name_error(id, "undefined method `%s' for%s `%s'", rb_id2name(id), s0, rb_class2name(c)); } rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); CALL_METHOD_HOOK(klass, undefined, id); }
static int add_method_iter(VALUE name, VALUE value, VALUE module) { NODE * n; rb_check_type(name, T_SYMBOL); if(!rb_obj_is_kind_of(value, rb_cNode)) { rb_raise( rb_eTypeError, "Expected Node, but got %s", rb_class2name(CLASS_OF(value))); } Data_Get_Struct(value, NODE, n); #if RUBY_VERSION_CODE >= 192 rb_raise(rb_eRuntimeError, "NOT SUPPORTED"); #else rb_add_method(module, SYM2ID(name), n->nd_body, n->nd_noex); #endif return ST_CONTINUE; }
static VALUE rb_mod_modfunc(int argc, VALUE *argv, VALUE module) { int i; ID id; NODE *fbody; if (TYPE(module) != T_MODULE) { rb_raise(rb_eTypeError, "module_function must be called for modules"); } secure_visibility(module); if (argc == 0) { SCOPE_SET(NOEX_MODFUNC); return module; } set_method_visibility(module, argc, argv, NOEX_PRIVATE); for (i = 0; i < argc; i++) { VALUE m = module; id = rb_to_id(argv[i]); for (;;) { fbody = search_method(m, id, &m); if (fbody == 0) { fbody = search_method(rb_cObject, id, &m); } if (fbody == 0 || fbody->nd_body == 0) { rb_bug("undefined method `%s'; can't happen", rb_id2name(id)); } if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) { break; /* normal case: need not to follow 'super' link */ } m = RCLASS_SUPER(m); if (!m) break; } rb_add_method(rb_singleton_class(module), id, fbody->nd_body->nd_body, NOEX_PUBLIC); } return module; }
void rb_undef(VALUE klass, ID id) { rb_method_entry_t *me; if (NIL_P(klass)) { rb_raise(rb_eTypeError, "no class to undef method"); } rb_frozen_class_p(klass); if (id == object_id || id == id__send__ || id == idInitialize) { rb_warn("undefining `%s' may cause serious problems", rb_id2name(id)); } me = search_method(klass, id, 0); if (UNDEFINED_METHOD_ENTRY_P(me) || UNDEFINED_REFINED_METHOD_P(me->def)) { const char *s0 = " class"; VALUE c = klass; if (FL_TEST(c, FL_SINGLETON)) { VALUE obj = rb_ivar_get(klass, attached); if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) { c = obj; s0 = ""; } } else if (RB_TYPE_P(c, T_MODULE)) { s0 = " module"; } rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'", QUOTE_ID(id), s0, rb_class_name(c)); } rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); CALL_METHOD_HOOK(klass, undefined, id); }
void rb_undef_method(VALUE klass, const char *name) { rb_add_method(klass, rb_intern(name), VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF); }
static VALUE rb_mod_define_method(int argc, VALUE *argv, VALUE mod) { ID id; VALUE body; NODE *node; int noex = NOEX_PUBLIC; if (argc == 1) { id = rb_to_id(argv[0]); body = rb_block_lambda(); } else if (argc == 2) { id = rb_to_id(argv[0]); body = argv[1]; if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) { rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Method)", rb_obj_classname(body)); } } else { rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc); } if (RDATA(body)->dmark == (RUBY_DATA_FUNC) bm_mark) { struct METHOD *method = (struct METHOD *)DATA_PTR(body); VALUE rklass = method->rklass; if (rklass != mod) { if (FL_TEST(rklass, FL_SINGLETON)) { rb_raise(rb_eTypeError, "can't bind singleton method to a different class"); } if (!RTEST(rb_class_inherited_p(mod, rklass))) { rb_raise(rb_eTypeError, "bind argument must be a subclass of %s", rb_class2name(rklass)); } } node = method->body; } else if (rb_obj_is_proc(body)) { rb_proc_t *proc; body = proc_dup(body); GetProcPtr(body, proc); if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) { proc->block.iseq->defined_method_id = id; proc->block.iseq->klass = mod; proc->is_lambda = Qtrue; } node = NEW_BMETHOD(body); } else { /* type error */ rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)"); } /* TODO: visibility */ rb_add_method(mod, id, node, noex); return body; }
void rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) { rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE); }
void rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) { rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED); }
void rb_define_method_id(VALUE klass, ID name, VALUE (*func)(ANYARGS), int argc) { rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC); }
/* * call-seq: * class.add_method(id, node or iseq, noex) #=> nil * * Adds the method as an instance method to the given class. * * To add a singleton method to a class, add the method to its singleton * class. */ static VALUE module_add_method(VALUE klass, VALUE id, VALUE node, VALUE noex) { NODE * n = 0; if(rb_safe_level() >= 2) { /* adding a method with the wrong node type can cause a crash */ rb_raise(rb_eSecurityError, "Insecure: can't add method"); } #if RUBY_VERSION_CODE >= 192 if(rb_obj_is_kind_of(node, rb_cISeq)) { rb_iseq_t *iseqdat = iseq_check(node); set_cref_stack(iseqdat, klass, noex); iseqdat->klass = klass; iseqdat->defined_method_id = SYM2ID(id); #ifdef HAVE_RB_ADD_METHOD rb_add_method(klass, SYM2ID(id), VM_METHOD_TYPE_ISEQ, iseqdat, NUM2INT(noex)); #else rb_funcall(rb_mRubyVMFrozenCore, rb_intern("core#define_method"), 3, klass, id, node); /* TODO: noex */ #endif return Qnil; } #elif RUBY_VERSION_CODE >= 190 if(rb_obj_is_kind_of(node, rb_cISeq)) { rb_iseq_t *iseqdat = iseq_check(node); /* TODO: any restrictions on what kinds of iseqs we can add here? */ set_cref_stack(iseqdat, klass, noex); iseqdat->klass = klass; iseqdat->defined_method_id = SYM2ID(id); n = NEW_METHOD(iseqdat->self, klass, NUM2INT(noex)); goto add_node; } #endif if(!rb_obj_is_kind_of(node, rb_cNode)) { rb_raise( rb_eTypeError, "Expected Node for 2nd parameter, got %s", rb_class2name(CLASS_OF(n))); } Data_Get_Struct(node, NODE, n); #if RUBY_VERSION_CODE >= 192 rb_raise(rb_eRuntimeError, "Unable to add node on this version of ruby"); #elif RUBY_VERSION_CODE >= 190 if(nd_type(n) != NODE_METHOD) { rb_raise( rb_eTypeError, "Expected METHOD node, got %s", rb_class2name(CLASS_OF(n))); } { rb_iseq_t *iseqdat = iseq_check((VALUE)n->nd_body); set_cref_stack(iseqdat, klass, noex); iseqdat->klass = klass; iseqdat->defined_method_id = SYM2ID(id); n = NEW_METHOD(iseqdat->self, klass, NUM2INT(noex)); } add_node: #endif #if RUBY_VERSION_CODE >= 192 rb_raise(rb_eRuntimeError, "Unable to add node on this version of ruby"); #else /* TODO: if noex is NOEX_MODFUNC, add this method as a module function * (that is, both as an instance and singleton method) */ rb_add_method(klass, SYM2ID(id), n, NUM2INT(noex)); return Qnil; #endif }
static void rb_define_notimplement_method_id(VALUE mod, ID id, rb_method_flag_t noex) { rb_add_method(mod, id, VM_METHOD_TYPE_NOTIMPLEMENTED, 0, noex); }
void rb_undef_alloc_func(VALUE klass) { Check_Type(klass, T_CLASS); rb_add_method(rb_singleton_class(klass), ID_ALLOCATOR, VM_METHOD_TYPE_UNDEF, 0, NOEX_UNDEF); }