summaryrefslogtreecommitdiffhomepage
path: root/src/proc.c
diff options
context:
space:
mode:
authordearblue <[email protected]>2021-02-22 23:32:18 +0900
committerdearblue <[email protected]>2021-02-22 23:32:18 +0900
commit792f6ac6700469ddf9be8f87ca3376082f9af7f3 (patch)
treef04a5ffe00d4f442286a833b06d472941b20c93c /src/proc.c
parent935ffa46a3a89a5f1662e5a4111ca0ed19566698 (diff)
downloadmruby-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.c67
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)
{