modules/mruby/src/proc.c in webruby-0.2.7 vs modules/mruby/src/proc.c in webruby-0.9.1

- old
+ new

@@ -5,11 +5,11 @@ */ #include "mruby.h" #include "mruby/class.h" #include "mruby/proc.h" -#include "opcode.h" +#include "mruby/opcode.h" static mrb_code call_iseq[] = { MKOP_A(OP_CALL, 0), }; @@ -32,21 +32,31 @@ mrb_irep_incref(mrb, irep); return p; } -static inline void +static struct REnv* +env_new(mrb_state *mrb, int nlocals) +{ + struct REnv *e; + + e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env); + MRB_SET_ENV_STACK_LEN(e, nlocals); + e->mid = mrb->c->ci->mid; + e->cioff = mrb->c->ci - mrb->c->cibase; + e->stack = mrb->c->stack; + + return e; +} + +static void closure_setup(mrb_state *mrb, struct RProc *p, int nlocals) { struct REnv *e; if (!mrb->c->ci->env) { - e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)mrb->c->ci->proc->env); - e->flags= (unsigned int)nlocals; - e->mid = mrb->c->ci->mid; - e->cioff = mrb->c->ci - mrb->c->cibase; - e->stack = mrb->c->stack; + e = env_new(mrb, nlocals); mrb->c->ci->env = e; } else { e = mrb->c->ci->env; } @@ -60,39 +70,80 @@ closure_setup(mrb, p, mrb->c->ci->proc->body.irep->nlocals); return p; } -struct RProc * +MRB_API struct RProc * mrb_proc_new_cfunc(mrb_state *mrb, mrb_func_t func) { struct RProc *p; p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class); p->body.func = func; p->flags |= MRB_PROC_CFUNC; + p->env = 0; return p; } -struct RProc * -mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals) +MRB_API struct RProc * +mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv) { struct RProc *p = mrb_proc_new_cfunc(mrb, func); + struct REnv *e; + int i; - closure_setup(mrb, p, nlocals); + p->env = e = env_new(mrb, argc); + MRB_ENV_UNSHARE_STACK(e); + e->stack = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * argc); + if (argv) { + for (i = 0; i < argc; ++i) { + e->stack[i] = argv[i]; + } + } + else { + for (i = 0; i < argc; ++i) { + SET_NIL_VALUE(e->stack[i]); + } + } return p; } -void +MRB_API struct RProc * +mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals) +{ + return mrb_proc_new_cfunc_with_env(mrb, func, nlocals, NULL); +} + +MRB_API mrb_value +mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx) +{ + struct RProc *p = mrb->c->ci->proc; + struct REnv *e = p->env; + + if (!MRB_PROC_CFUNC_P(p)) { + mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from non-cfunc proc."); + } + if (!e) { + mrb_raise(mrb, E_TYPE_ERROR, "Can't get cfunc env from cfunc Proc without REnv."); + } + if (idx < 0 || MRB_ENV_STACK_LEN(e) <= idx) { + mrb_raisef(mrb, E_INDEX_ERROR, "Env index out of range: %S (expected: 0 <= index < %S)", + mrb_fixnum_value(idx), mrb_fixnum_value(MRB_ENV_STACK_LEN(e))); + } + + return e->stack[idx]; +} + +MRB_API void mrb_proc_copy(struct RProc *a, struct RProc *b) { a->flags = b->flags; a->body = b->body; if (!MRB_PROC_CFUNC_P(a)) { a->body.irep->refcnt++; - }; + } a->target_class = b->target_class; a->env = b->env; } static mrb_value @@ -146,13 +197,24 @@ static mrb_value mrb_proc_arity(mrb_state *mrb, mrb_value self) { struct RProc *p = mrb_proc_ptr(self); mrb_code *iseq = mrb_proc_iseq(mrb, p); - mrb_aspec aspec = GETARG_Ax(*iseq); + mrb_aspec aspec; int ma, ra, pa, arity; + if (MRB_PROC_CFUNC_P(p)) { + /* TODO cfunc aspec not implemented yet */ + return mrb_fixnum_value(-1); + } + + /* arity is depend on OP_ENTER */ + if (GET_OPCODE(*iseq) != OP_ENTER) { + return mrb_fixnum_value(0); + } + + aspec = GETARG_Ax(*iseq); ma = MRB_ASPEC_REQ(aspec); ra = MRB_ASPEC_REST(aspec); pa = MRB_ASPEC_POST(aspec); arity = ra ? -(ma + pa + 1) : ma + pa; @@ -193,19 +255,13 @@ { struct RProc *m; mrb_irep *call_irep = (mrb_irep *)mrb_malloc(mrb, sizeof(mrb_irep)); static const mrb_irep mrb_irep_zero = { 0 }; - if (call_irep == NULL) - return; - *call_irep = mrb_irep_zero; call_irep->flags = MRB_ISEQ_NO_FREE; call_irep->iseq = call_iseq; call_irep->ilen = 1; - - mrb->proc_class = mrb_define_class(mrb, "Proc", mrb->object_class); - MRB_SET_INSTANCE_TT(mrb->proc_class, MRB_TT_PROC); mrb_define_method(mrb, mrb->proc_class, "initialize", mrb_proc_initialize, MRB_ARGS_NONE()); mrb_define_method(mrb, mrb->proc_class, "initialize_copy", mrb_proc_init_copy, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->proc_class, "arity", mrb_proc_arity, MRB_ARGS_NONE());