mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
@@ -45,6 +45,8 @@ typedef struct mrb_irep {
|
||||
struct mrb_irep_debug_info* debug_info;
|
||||
|
||||
size_t ilen, plen, slen, rlen, refcnt;
|
||||
|
||||
struct RProc *outer; /* Refers outer scope */
|
||||
} mrb_irep;
|
||||
|
||||
#define MRB_ISEQ_NO_FREE 1
|
||||
|
||||
@@ -57,6 +57,8 @@ struct RProc {
|
||||
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
|
||||
#define MRB_PROC_ORPHAN 512
|
||||
#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
|
||||
#define MRB_PROC_CLASS 1024
|
||||
#define MRB_PROC_CLASS_P(p) (((p)->flags & MRB_PROC_CLASS) != 0)
|
||||
|
||||
#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -29,6 +29,18 @@ end
|
||||
|
||||
# TODO not implemented ATM assert('Module.nesting', '15.2.2.3.2') do
|
||||
|
||||
assert('Module.nesting', '15.2.2.2.2') do
|
||||
module Test4ModuleNesting
|
||||
module Test4ModuleNesting2
|
||||
assert_equal [Test4ModuleNesting2, Test4ModuleNesting],
|
||||
Module.nesting
|
||||
end
|
||||
end
|
||||
module Test4ModuleNesting::Test4ModuleNesting2
|
||||
assert_equal [Test4ModuleNesting::Test4ModuleNesting2], Module.nesting
|
||||
end
|
||||
end
|
||||
|
||||
assert('Module#ancestors', '15.2.2.4.9') do
|
||||
class Test4ModuleAncestors
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user