diff options
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 80 |
1 files changed, 51 insertions, 29 deletions
@@ -1192,6 +1192,8 @@ rb_mod_append_features(VALUE module, VALUE include) return module; } +static VALUE refinement_import_methods(int argc, VALUE *argv, VALUE refinement); + /* * call-seq: * include(module, ...) -> self @@ -1345,9 +1347,9 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module) } superclass = refinement_superclass(superclass); c = iclass = rb_include_class_new(module, superclass); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); + RCLASS_SET_REFINED_CLASS(c, klass); - RCLASS_M_TBL(c) = RCLASS_M_TBL(module); + RCLASS_WRITE_M_TBL(c, RCLASS_M_TBL(module)); rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass); } @@ -1402,6 +1404,12 @@ rb_using_module(const rb_cref_t *cref, VALUE module) rb_clear_all_refinement_method_cache(); } +void +rb_vm_using_module(VALUE module) +{ + rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module); +} + /* * call-seq: * target -> class_or_module @@ -1442,43 +1450,24 @@ add_activated_refinement(VALUE activated_refinements, } superclass = refinement_superclass(superclass); c = iclass = rb_include_class_new(refinement, superclass); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); + RCLASS_SET_REFINED_CLASS(c, klass); refinement = RCLASS_SUPER(refinement); while (refinement && refinement != klass) { - c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c))); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); + c = rb_class_set_super(c, rb_include_class_new(refinement, RCLASS_SUPER(c))); + RCLASS_SET_REFINED_CLASS(c, klass); refinement = RCLASS_SUPER(refinement); } rb_hash_aset(activated_refinements, klass, iclass); } -/* - * call-seq: - * refine(mod) { block } -> module - * - * Refine <i>mod</i> in the receiver. - * - * Returns a module, where refined methods are defined. - */ - -static VALUE -rb_mod_refine(VALUE module, VALUE klass) +void +rb_refinement_setup(struct rb_refinements_data *data, VALUE module, VALUE klass) { VALUE refinement; ID id_refinements, id_activated_refinements, id_refined_class, id_defined_at; VALUE refinements, activated_refinements; - rb_thread_t *th = GET_THREAD(); - VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); - - if (block_handler == VM_BLOCK_HANDLER_NONE) { - rb_raise(rb_eArgError, "no block given"); - } - if (vm_block_handler_type(block_handler) != block_handler_type_iseq) { - rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine"); - } - ensure_class_or_module(klass); CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) { @@ -1496,7 +1485,7 @@ rb_mod_refine(VALUE module, VALUE klass) if (NIL_P(refinement)) { VALUE superclass = refinement_superclass(klass); refinement = rb_refinement_new(); - RCLASS_SET_SUPER(refinement, superclass); + rb_class_set_super(refinement, superclass); RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE); FL_SET(refinement, RMODULE_IS_REFINEMENT); CONST_ID(id_refined_class, "__refined_class__"); @@ -1506,8 +1495,41 @@ rb_mod_refine(VALUE module, VALUE klass) rb_hash_aset(refinements, klass, refinement); add_activated_refinement(activated_refinements, klass, refinement); } - rb_yield_refine_block(refinement, activated_refinements); - return refinement; + + data->refinement = refinement; + data->refinements = activated_refinements; +} + +/* + * call-seq: + * refine(mod) { block } -> module + * + * Refine <i>mod</i> in the receiver. + * + * Returns a module, where refined methods are defined. + */ + +static VALUE +rb_mod_refine(VALUE module, VALUE klass) +{ + /* module is the receiver of #refine, klass is a module to be refined (`mod` in the doc) */ + rb_thread_t *th = GET_THREAD(); + VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); + struct rb_refinements_data data; + + if (block_handler == VM_BLOCK_HANDLER_NONE) { + rb_raise(rb_eArgError, "no block given"); + } + if (vm_block_handler_type(block_handler) != block_handler_type_iseq) { + rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine"); + } + + ensure_class_or_module(klass); + + rb_refinement_setup(&data, module, klass); + + rb_yield_refine_block(data.refinement, data.refinements); + return data.refinement; } static void |