From 1a2b90d5e6c7b6ecd1d4c0ba9445fb730b39776b Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 1 Jul 2014 17:57:37 +0000 Subject: vm.c: rb_vm_env_local_variables * vm.c (rb_vm_env_local_variables): returns array of local variable name symbols in the environment by envval. * proc.c (bind_local_variables): use rb_vm_env_local_variables. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46648 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++++ proc.c | 28 +--------------------------- test/ruby/test_proc.rb | 4 +++- vm.c | 12 ++++++++++++ vm_core.h | 1 + vm_eval.c | 28 ++++++++++++++++++++-------- 6 files changed, 44 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3ab54e179e..a542807515 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Jul 2 02:57:27 2014 Nobuyoshi Nakada + + * vm.c (rb_vm_env_local_variables): returns array of local + variable name symbols in the environment by envval. + + * proc.c (bind_local_variables): use rb_vm_env_local_variables. + Wed Jul 2 02:23:52 2014 Nobuyoshi Nakada * proc.c (bind_receiver): new method to return the bound receiver diff --git a/proc.c b/proc.c index f81483c7b1..faede42d49 100644 --- a/proc.c +++ b/proc.c @@ -467,36 +467,10 @@ check_local_id(VALUE bindval, volatile VALUE *pname) static VALUE bind_local_variables(VALUE bindval) { - VALUE ary = rb_ary_new(); - const rb_binding_t *bind; - const rb_env_t *env; - VALUE envval; GetBindingPtr(bindval, bind); - - envval = bind->env; - - do { - const rb_iseq_t *iseq; - int i; - ID id; - - GetEnvPtr(envval, env); - iseq = env->block.iseq; - - for (i = 0; i < iseq->local_table_size; i++) { - id = iseq->local_table[i]; - if (id) { - const char *vname = rb_id2name(id); - if (vname) { - rb_ary_push(ary, ID2SYM(id)); - } - } - } - } while ((envval = env->prev_envval) != 0); - - return ary; + return rb_vm_env_local_variables(bind->env); } /* diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb index 91279d9d75..28ba8c9b57 100644 --- a/test/ruby/test_proc.rb +++ b/test/ruby/test_proc.rb @@ -1253,7 +1253,9 @@ class TestProc < Test::Unit::TestCase def test_local_variables b = get_binding - assert_equal(%i[if case when begin end a], b.local_variables) + assert_equal(%i'if case when begin end a', b.local_variables) + a = tap {|;a, b| break binding.local_variables} + assert_equal(%i[a b], a.sort) end def test_local_variables_nested diff --git a/vm.c b/vm.c index a84320b4e3..32beb34d5a 100644 --- a/vm.c +++ b/vm.c @@ -566,6 +566,18 @@ vm_collect_local_variables_in_heap(rb_thread_t *th, const VALUE *ep, const struc } } +VALUE +rb_vm_env_local_variables(VALUE envval) +{ + struct local_var_list vars; + const rb_env_t *env; + + GetEnvPtr(envval, env); + local_var_list_init(&vars); + collect_local_variables_in_env(env, &vars); + return local_var_list_finish(&vars); +} + static void vm_rewrite_ep_in_errinfo(rb_thread_t *th); static VALUE vm_make_proc_from_block(rb_thread_t *th, rb_block_t *block); static VALUE vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp, VALUE *blockprocptr); diff --git a/vm_core.h b/vm_core.h index f5cc498d3b..63e53a5d11 100644 --- a/vm_core.h +++ b/vm_core.h @@ -856,6 +856,7 @@ VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, const rb_block_t *blockptr); VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass); VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); +VALUE rb_vm_env_local_variables(VALUE envval); VALUE rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp); VALUE *rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars); void rb_vm_inc_const_missing_count(void); diff --git a/vm_eval.c b/vm_eval.c index 6b38d40d93..a67c75cb6d 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1876,6 +1876,24 @@ rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, int *stateptr) return val; } +static void +local_var_list_init(struct local_var_list *vars) +{ + vars->tbl = rb_hash_new(); + RHASH(vars->tbl)->ntbl = st_init_numtable(); /* compare_by_identity */ + RBASIC_CLEAR_CLASS(vars->tbl); +} + +static VALUE +local_var_list_finish(struct local_var_list *vars) +{ + /* TODO: not to depend on the order of st_table */ + VALUE ary = rb_hash_keys(vars->tbl); + rb_hash_clear(vars->tbl); + vars->tbl = 0; + return ary; +} + static int local_var_list_update(st_data_t *key, st_data_t *value, st_data_t arg, int existing) { @@ -1912,15 +1930,12 @@ static VALUE rb_f_local_variables(void) { struct local_var_list vars; - VALUE ary; rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp)); int i; - vars.tbl = rb_hash_new(); - RHASH(vars.tbl)->ntbl = st_init_numtable(); /* compare_by_identity */ - RBASIC_CLEAR_CLASS(vars.tbl); + local_var_list_init(&vars); while (cfp) { if (cfp->iseq) { for (i = 0; i < cfp->iseq->local_table_size; i++) { @@ -1944,10 +1959,7 @@ rb_f_local_variables(void) break; } } - /* TODO: not to depend on the order of st_table */ - ary = rb_hash_keys(vars.tbl); - rb_hash_clear(vars.tbl); - return ary; + return local_var_list_finish(&vars); } /* -- cgit v1.2.3