diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-08-01 11:39:18 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-08-01 15:37:21 +0900 |
| commit | 9e10afe1d0ee1fb751182e42044e891b4b13f9a4 (patch) | |
| tree | 880a62052f924ad037dedaca434e474f820a91ed /src | |
| parent | 16aafdd8660dc301b49254e7ccaa887ab3a458de (diff) | |
| download | mruby-9e10afe1d0ee1fb751182e42044e891b4b13f9a4.tar.gz mruby-9e10afe1d0ee1fb751182e42044e891b4b13f9a4.zip | |
Implements `Module::nesting' (15.2.2.3.2); ref #600, #3200
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 3 | ||||
| -rw-r--r-- | src/gc.c | 3 | ||||
| -rw-r--r-- | src/vm.c | 35 |
3 files changed, 37 insertions, 4 deletions
diff --git a/src/class.c b/src/class.c index 57f64dcc5..54754092e 100644 --- a/src/class.c +++ b/src/class.c @@ -2314,6 +2314,8 @@ mrb_mod_module_function(mrb_state *mrb, mrb_value mod) mrb_value mrb_obj_id_m(mrb_state *mrb, mrb_value self); /* implementation of instance_eval */ mrb_value mrb_obj_instance_eval(mrb_state*, mrb_value); +/* implementation of Module.nesting */ +mrb_value mrb_mod_s_nesting(mrb_state*, mrb_value); void mrb_init_class(mrb_state *mrb) @@ -2407,6 +2409,7 @@ mrb_init_class(mrb_state *mrb) mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); mrb_define_class_method(mrb, mod, "constants", mrb_mod_s_constants, MRB_ARGS_ANY()); /* 15.2.2.3.1 */ + mrb_define_class_method(mrb, mod, "nesting", mrb_mod_s_nesting, MRB_ARGS_REQ(0)); /* 15.2.2.3.2 */ mrb_undef_method(mrb, cls, "append_features"); mrb_undef_method(mrb, cls, "extend_object"); @@ -647,6 +647,9 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj) mrb_gc_mark(mrb, (struct RBasic*)p->env); mrb_gc_mark(mrb, (struct RBasic*)p->target_class); + if (!MRB_PROC_CFUNC_P(p)) { + mrb_gc_mark(mrb, (struct RBasic*)p->body.irep->outer); + } } break; @@ -778,6 +778,25 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const return mrb_exec_irep(mrb, self, p); } +mrb_value +mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod) +{ + struct RProc *proc; + mrb_value ary; + + mrb_get_args(mrb, ""); + ary = mrb_ary_new(mrb); + proc = mrb->c->ci[-1].proc; /* callee proc */ + while (proc) { + mrb_assert(!MRB_PROC_CFUNC_P(proc)); + if (MRB_PROC_CLASS_P(proc) && proc->target_class) { + mrb_ary_push(mrb, ary, mrb_obj_value(proc->target_class)); + } + proc = proc->body.irep->outer; + } + return ary; +} + static struct RBreak* break_new(mrb_state *mrb, struct RProc *p, mrb_value val) { @@ -2701,16 +2720,20 @@ RETRY_TRY_BLOCK: CASE(OP_LAMBDA) { /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */ struct RProc *p; + int a = GETARG_A(i); + int b = GETARG_b(i); int c = GETARG_c(i); + mrb_irep *nirep = irep->reps[b]; + nirep->outer = mrb->c->ci->proc; if (c & OP_L_CAPTURE) { - p = mrb_closure_new(mrb, irep->reps[GETARG_b(i)]); + p = mrb_closure_new(mrb, nirep); } else { - p = mrb_proc_new(mrb, irep->reps[GETARG_b(i)]); + p = mrb_proc_new(mrb, nirep); } if (c & OP_L_STRICT) p->flags |= MRB_PROC_STRICT; - regs[GETARG_A(i)] = mrb_obj_value(p); + regs[a] = mrb_obj_value(p); mrb_gc_arena_restore(mrb, ai); NEXT; } @@ -2765,13 +2788,17 @@ RETRY_TRY_BLOCK: CASE(OP_EXEC) { /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ int a = GETARG_A(i); + int bx = GETARG_Bx(i); mrb_callinfo *ci; mrb_value recv = regs[a]; struct RProc *p; + mrb_irep *nirep = irep->reps[bx]; + nirep->outer = mrb->c->ci->proc; /* prepare closure */ - p = mrb_closure_new(mrb, irep->reps[GETARG_Bx(i)]); + p = mrb_closure_new(mrb, nirep); p->c = NULL; + p->flags |= MRB_PROC_CLASS; /* prepare stack */ ci = cipush(mrb); |
