summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-01 17:57:37 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-07-01 17:57:37 +0000
commit1a2b90d5e6c7b6ecd1d4c0ba9445fb730b39776b (patch)
tree973b19a521528d0a87c2c77e7f57cd6707f1cb38
parent0fdb18e513b53e71911c57a7b5fddd86c3a17704 (diff)
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
-rw-r--r--ChangeLog7
-rw-r--r--proc.c28
-rw-r--r--test/ruby/test_proc.rb4
-rw-r--r--vm.c12
-rw-r--r--vm_core.h1
-rw-r--r--vm_eval.c28
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 <nobu@ruby-lang.org>
+
+ * 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 <nobu@ruby-lang.org>
* 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);
}
/*