diff options
| -rw-r--r-- | mrbgems/mruby-binding-core/mrbgem.rake | 4 | ||||
| -rw-r--r-- | mrbgems/mruby-binding-core/src/binding-core.c | 33 | ||||
| -rw-r--r-- | mrbgems/mruby-binding-core/test/binding-core.rb | 8 | ||||
| -rw-r--r-- | mrbgems/mruby-binding/mrbgem.rake | 8 | ||||
| -rw-r--r-- | mrbgems/mruby-binding/mrblib/binding.rb (renamed from mrbgems/mruby-binding-core/mrblib/binding-core.rb) | 0 | ||||
| -rw-r--r-- | mrbgems/mruby-binding/test/binding.rb | 5 | ||||
| -rw-r--r-- | mrbgems/mruby-eval/src/eval.c | 55 | ||||
| -rw-r--r-- | mrbgems/mruby-metaprog/src/metaprog.c | 37 | ||||
| -rw-r--r-- | src/proc.c | 67 |
9 files changed, 138 insertions, 79 deletions
diff --git a/mrbgems/mruby-binding-core/mrbgem.rake b/mrbgems/mruby-binding-core/mrbgem.rake index 1dbc768de..f6b34982f 100644 --- a/mrbgems/mruby-binding-core/mrbgem.rake +++ b/mrbgems/mruby-binding-core/mrbgem.rake @@ -1,7 +1,5 @@ -MRuby::Gem::Specification.new('mruby-binding') do |spec| +MRuby::Gem::Specification.new('mruby-binding-core') do |spec| spec.license = 'MIT' spec.author = 'mruby developers' spec.summary = 'Binding class' - - spec.add_dependency('mruby-eval', :core => 'mruby-eval') end diff --git a/mrbgems/mruby-binding-core/src/binding-core.c b/mrbgems/mruby-binding-core/src/binding-core.c index 4899dcc20..0113fc030 100644 --- a/mrbgems/mruby-binding-core/src/binding-core.c +++ b/mrbgems/mruby-binding-core/src/binding-core.c @@ -1,39 +1,44 @@ -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/hash.h" -#include "mruby/proc.h" -#include "mruby/variable.h" +#include <mruby.h> +#include <mruby/array.h> +#include <mruby/hash.h> +#include <mruby/proc.h> +#include <mruby/variable.h> +#include <mruby/presym.h> -mrb_value proc_local_variables(mrb_state *mrb, struct RProc *proc); +mrb_value mrb_proc_local_variables(mrb_state *mrb, const struct RProc *proc); static mrb_value binding_local_variables(mrb_state *mrb, mrb_value self) { - struct RProc *proc = mrb_proc_ptr(mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc"))); - return proc_local_variables(mrb, proc); + const struct RProc *proc = mrb_proc_ptr(mrb_iv_get(mrb, self, MRB_SYM(proc))); + return mrb_proc_local_variables(mrb, proc); } +const struct RProc *mrb_proc_get_caller(mrb_state *mrb, struct REnv **env); + static mrb_value mrb_f_binding(mrb_state *mrb, mrb_value self) { struct RObject *obj; mrb_value binding; struct RProc *proc; - mrb_int i; + struct REnv *env; obj = (struct RObject*)mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb_class_get(mrb, "Binding")); binding = mrb_obj_value(obj); - proc = mrb->c->ci[-1].proc; - mrb_iv_set(mrb, binding, mrb_intern_lit(mrb, "proc"), mrb_obj_value(proc)); - mrb_iv_set(mrb, binding, mrb_intern_lit(mrb, "recv"), self); + proc = (struct RProc*)mrb_proc_get_caller(mrb, &env); + mrb_iv_set(mrb, binding, MRB_SYM(proc), mrb_obj_value(proc)); + mrb_iv_set(mrb, binding, MRB_SYM(recv), self); + mrb_iv_set(mrb, binding, MRB_SYM(env), mrb_obj_value(env)); return binding; } void -mrb_mruby_binding_gem_init(mrb_state *mrb) +mrb_mruby_binding_core_gem_init(mrb_state *mrb) { struct RClass *binding = mrb_define_class(mrb, "Binding", mrb->object_class); mrb_undef_class_method(mrb, binding, "new"); + mrb_undef_class_method(mrb, binding, "allocate"); mrb_define_method(mrb, mrb->kernel_module, "binding", mrb_f_binding, MRB_ARGS_NONE()); @@ -41,6 +46,6 @@ mrb_mruby_binding_gem_init(mrb_state *mrb) } void -mrb_mruby_binding_gem_final(mrb_state *mrb) +mrb_mruby_binding_core_gem_final(mrb_state *mrb) { } diff --git a/mrbgems/mruby-binding-core/test/binding-core.rb b/mrbgems/mruby-binding-core/test/binding-core.rb index 3bed9b31e..d93f43619 100644 --- a/mrbgems/mruby-binding-core/test/binding-core.rb +++ b/mrbgems/mruby-binding-core/test/binding-core.rb @@ -7,11 +7,5 @@ assert("Binding#local_variables") do b = 1 binding end - assert_equal [:a, :b, :block], block.call(0).local_variables -end - -assert("Binding#eval") do - b = nil - 1.times { x, y, z = 1, 2, 3; [x,y,z]; b = binding } - assert_equal([1, 2, 3], b.eval("[x, y, z]")) + assert_equal [:a, :b, :block], block.call(0).local_variables.sort end diff --git a/mrbgems/mruby-binding/mrbgem.rake b/mrbgems/mruby-binding/mrbgem.rake new file mode 100644 index 000000000..2701c506f --- /dev/null +++ b/mrbgems/mruby-binding/mrbgem.rake @@ -0,0 +1,8 @@ +MRuby::Gem::Specification.new('mruby-binding') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Binding class' + + spec.add_dependency('mruby-binding-core', :core => 'mruby-binding-core') + spec.add_dependency('mruby-eval', :core => 'mruby-eval') +end diff --git a/mrbgems/mruby-binding-core/mrblib/binding-core.rb b/mrbgems/mruby-binding/mrblib/binding.rb index b07480db1..b07480db1 100644 --- a/mrbgems/mruby-binding-core/mrblib/binding-core.rb +++ b/mrbgems/mruby-binding/mrblib/binding.rb diff --git a/mrbgems/mruby-binding/test/binding.rb b/mrbgems/mruby-binding/test/binding.rb new file mode 100644 index 000000000..73742400f --- /dev/null +++ b/mrbgems/mruby-binding/test/binding.rb @@ -0,0 +1,5 @@ +assert("Binding#eval") do + b = nil + 1.times { x, y, z = 1, 2, 3; [x,y,z]; b = binding } + assert_equal([1, 2, 3], b.eval("[x, y, z]")) +end diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c index 89a2b3b10..8cc37904a 100644 --- a/mrbgems/mruby-eval/src/eval.c +++ b/mrbgems/mruby-eval/src/eval.c @@ -19,24 +19,37 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi { mrbc_context *cxt; struct mrb_parser_state *p; - struct RProc *proc, *scope; + struct RProc *proc; + const struct RProc *scope; struct REnv *e; mrb_callinfo *ci; /* callinfo of eval caller */ struct RClass *target_class = NULL; struct mrb_context *c = mrb->c; - mrb_bool is_binding = FALSE; if (!mrb_nil_p(binding)) { + mrb_value scope_obj; if (!mrb_class_defined(mrb, "Binding") || !mrb_obj_is_kind_of(mrb, binding, mrb_class_get(mrb, "Binding"))) { - mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected binding)", - mrb_obj_value(mrb_obj_class(mrb, binding))); + mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %C (expected binding)", + mrb_obj_class(mrb, binding)); + } + scope_obj = mrb_iv_get(mrb, binding, MRB_SYM(proc)); + mrb_assert(mrb_proc_p(scope_obj)); + scope = mrb_proc_ptr(scope_obj); + if (MRB_PROC_CFUNC_P(scope)) { + e = NULL; + } + else { + mrb_value env = mrb_iv_get(mrb, binding, MRB_SYM(env)); + mrb_assert(mrb_env_p(env)); + e = (struct REnv *)mrb_obj_ptr(env); + mrb_assert(e != NULL); } - scope = mrb_proc_ptr(mrb_iv_get(mrb, binding, mrb_intern_lit(mrb, "proc"))); - is_binding = TRUE; } else { - scope = c->ci[-1].proc; + ci = (c->ci > c->cibase) ? c->ci - 1 : c->cibase; + scope = ci->proc; + e = NULL; } cxt = mrbc_context_new(mrb); @@ -45,8 +58,7 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi mrbc_filename(mrb, cxt, file ? file : "(eval)"); cxt->capture_errors = TRUE; cxt->no_optimize = TRUE; - ci = (c->ci > c->cibase) ? c->ci - 1 : c->cibase; - cxt->upper = ci->proc && MRB_PROC_CFUNC_P(ci->proc) ? NULL : ci->proc; + cxt->upper = scope && MRB_PROC_CFUNC_P(scope) ? NULL : scope; p = mrb_parse_nstring(mrb, s, len, cxt); @@ -90,18 +102,19 @@ create_proc_from_string(mrb_state *mrb, const char *s, mrb_int len, mrb_value bi } if (scope) { target_class = MRB_PROC_TARGET_CLASS(scope); - } - if (scope && !MRB_PROC_CFUNC_P(scope)) { - if ((e = mrb_vm_ci_env(ci)) != NULL) { - /* do nothing, because e is assigned already */ - } - else { - e = mrb_env_new(mrb, c, ci, scope->body.irep->nlocals, ci->stack, target_class); - ci->u.env = e; + if (!MRB_PROC_CFUNC_P(scope)) { + if (e == NULL) { + /* when `binding` is nil */ + e = mrb_vm_ci_env(ci); + if (e == NULL) { + e = mrb_env_new(mrb, c, ci, ci->proc->body.irep->nlocals, ci->stack, target_class); + ci->u.env = e; + } + } + proc->e.env = e; + proc->flags |= MRB_PROC_ENVSET; + mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e); } - proc->e.env = e; - proc->flags |= MRB_PROC_ENVSET; - mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e); } proc->upper = scope; mrb_vm_ci_target_class_set(mrb->c->ci, target_class); @@ -146,7 +159,7 @@ f_eval(mrb_state *mrb, mrb_value self) proc = create_proc_from_string(mrb, s, len, binding, file, line); if (!mrb_nil_p(binding)) { - self = mrb_iv_get(mrb, binding, mrb_intern_lit(mrb, "recv")); + self = mrb_iv_get(mrb, binding, MRB_SYM(recv)); } mrb_assert(!MRB_PROC_CFUNC_P(proc)); return exec_irep(mrb, self, proc); diff --git a/mrbgems/mruby-metaprog/src/metaprog.c b/mrbgems/mruby-metaprog/src/metaprog.c index f2f2e7dda..99a1b46da 100644 --- a/mrbgems/mruby-metaprog/src/metaprog.c +++ b/mrbgems/mruby-metaprog/src/metaprog.c @@ -117,6 +117,8 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self) return val; } +mrb_value mrb_proc_local_variables(mrb_state *mrb, const struct RProc *proc); + /* 15.3.1.2.7 */ /* 15.3.1.3.28 */ /* @@ -133,40 +135,7 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self) static mrb_value mrb_local_variables(mrb_state *mrb, mrb_value self) { - const struct RProc *proc; - const mrb_irep *irep; - mrb_value vars; - size_t i; - - proc = mrb->c->ci[-1].proc; - - 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); + return mrb_proc_local_variables(mrb, mrb->c->ci[-1].proc); } KHASH_DECLARE(st, mrb_sym, char, FALSE) 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) { |
