proc.c: Binding#local_variables

* proc.c (bind_local_variables): allowing binding to list its
  local variables.  patch by Jack Danger Canty <jackdanger AT
  squareup.com> at [ruby-core:56543].  [Feature #8773]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44392 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2013-12-24 16:03:12 +00:00
Родитель 2e6ffdf957
Коммит a11831a9a5
3 изменённых файлов: 70 добавлений и 0 удалений

Просмотреть файл

@ -1,3 +1,9 @@
Wed Dec 25 01:03:00 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* proc.c (bind_local_variables): allowing binding to list its
local variables. patch by Jack Danger Canty <jackdanger AT
squareup.com> at [ruby-core:56543]. [Feature #8773]
Tue Dec 24 23:20:38 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/fileutils/fileasserts.rb (assert_ownership_user): new

53
proc.c
Просмотреть файл

@ -446,6 +446,58 @@ check_local_id(VALUE bindval, volatile VALUE *pname)
return lid;
}
/*
* call-seq:
* binding.local_variables -> Array
*
* Returns the +symbol+ names of the binding's local variables
*
* def foo
* a = 1
* 2.times do |n|
* binding.local_variables #=> [:a, :n]
* end
* end
*
* This method is short version of the following code.
*
* binding.eval("local_variables")
*
*/
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;
GetEnvPtr(envval, env);
do {
const rb_iseq_t *iseq;
int i;
ID id;
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;
}
/*
* call-seq:
* binding.local_variable_get(symbol) -> obj
@ -2718,6 +2770,7 @@ Init_Binding(void)
rb_define_method(rb_cBinding, "clone", binding_clone, 0);
rb_define_method(rb_cBinding, "dup", binding_dup, 0);
rb_define_method(rb_cBinding, "eval", bind_eval, -1);
rb_define_method(rb_cBinding, "local_variables", bind_local_variables, 0);
rb_define_method(rb_cBinding, "local_variable_get", bind_local_variable_get, 1);
rb_define_method(rb_cBinding, "local_variable_set", bind_local_variable_set, 2);
rb_define_method(rb_cBinding, "local_variable_defined?", bind_local_variable_defined_p, 1);

Просмотреть файл

@ -83,6 +83,17 @@ class TestVariable < Test::Unit::TestCase
end.call
end
def local_variables_of(bind)
this_should_not_be_in_bind = 2
bind.local_variables
end
def test_local_variables_from_other_method_binding
feature8773 = '[Feature #8773]'
x = 1
assert_equal([:x], local_variables_of(binding), feature8773)
end
def test_global_variable_0
assert_in_out_err(["-e", "$0='t'*1000;print $0"], "", /\At+\z/, [])
end