diff options
| author | dearblue <[email protected]> | 2021-02-22 23:32:18 +0900 |
|---|---|---|
| committer | dearblue <[email protected]> | 2021-02-22 23:32:18 +0900 |
| commit | 792f6ac6700469ddf9be8f87ca3376082f9af7f3 (patch) | |
| tree | f04a5ffe00d4f442286a833b06d472941b20c93c /src/proc.c | |
| parent | 935ffa46a3a89a5f1662e5a4111ca0ed19566698 (diff) | |
| download | mruby-792f6ac6700469ddf9be8f87ca3376082f9af7f3.tar.gz mruby-792f6ac6700469ddf9be8f87ca3376082f9af7f3.zip | |
Adjustment of the current HEAD and bindings, and separation
Make changes to make `Binding` work.
At the same time, it separates `Binding#eval`, which depends on `mruby-eval`, from `mruby-binding-core`.
Diffstat (limited to 'src/proc.c')
| -rw-r--r-- | src/proc.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/proc.c b/src/proc.c index 870d5ea16..89fcd3d28 100644 --- a/src/proc.c +++ b/src/proc.c @@ -10,6 +10,8 @@ #include <mruby/opcode.h> #include <mruby/data.h> #include <mruby/presym.h> +#include <mruby/array.h> +#include <mruby/hash.h> static const mrb_code call_iseq[] = { OP_CALL, @@ -305,6 +307,71 @@ mrb_proc_arity(const struct RProc *p) return arity; } +mrb_value +mrb_proc_local_variables(mrb_state *mrb, const struct RProc *proc) +{ + const mrb_irep *irep; + mrb_value vars; + size_t i; + + if (proc == NULL || MRB_PROC_CFUNC_P(proc)) { + return mrb_ary_new(mrb); + } + vars = mrb_hash_new(mrb); + while (proc) { + if (MRB_PROC_CFUNC_P(proc)) break; + irep = proc->body.irep; + if (irep->lv) { + for (i = 0; i + 1 < irep->nlocals; ++i) { + if (irep->lv[i]) { + mrb_sym sym = irep->lv[i]; + const char *name = mrb_sym_name(mrb, sym); + switch (name[0]) { + case '*': case '&': + break; + default: + mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value()); + break; + } + } + } + } + if (MRB_PROC_SCOPE_P(proc)) break; + proc = proc->upper; + } + + return mrb_hash_keys(mrb, vars); +} + +const struct RProc * +mrb_proc_get_caller(mrb_state *mrb, struct REnv **envp) +{ + struct mrb_context *c = mrb->c; + mrb_callinfo *ci = (c->ci > c->cibase) ? c->ci - 1 : c->cibase; + const struct RProc *proc = ci->proc; + + if (!proc || MRB_PROC_CFUNC_P(proc)) { + if (envp) *envp = NULL; + } + else { + struct RClass *tc = MRB_PROC_TARGET_CLASS(proc); + struct REnv *e = mrb_vm_ci_env(ci); + + if (e == NULL) { + int nstacks = proc->body.irep->nlocals; + e = mrb_env_new(mrb, c, ci, nstacks, ci->stack, tc); + ci->u.env = e; + } + else if (tc) { + e->c = tc; + mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc); + } + if (envp) *envp = e; + } + + return proc; +} + void mrb_init_proc(mrb_state *mrb) { |
