From 2f22944dfbb385f04fe8a7855be31d4871374c91 Mon Sep 17 00:00:00 2001 From: yugui Date: Wed, 28 Jan 2009 11:09:14 +0000 Subject: merges r21651 from trunk into ruby_1_9_1. * eval.c, vm_eval.c (rb_f_local_variables): move definition from eval.c to vm_eval.c because vm_collect_local_variables_in_heap() should be static function. * vm.c (vm_collect_local_variables_in_heap): make it static. git-svn-id: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_9_1@21846 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- vm_eval.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'vm_eval.c') diff --git a/vm_eval.c b/vm_eval.c index 851eaaf9f..b0a9b29ae 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -19,6 +19,7 @@ static inline VALUE vm_backtrace(rb_thread_t *th, int lev); static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex); static VALUE vm_exec(rb_thread_t *th); static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref); +static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary); static inline VALUE vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid, @@ -1321,10 +1322,67 @@ rb_make_backtrace(void) return vm_backtrace(GET_THREAD(), -1); } +/* + * call-seq: + * local_variables => array + * + * Returns the names of the current local variables. + * + * fred = 1 + * for i in 1..10 + * # ... + * end + * local_variables #=> ["fred", "i"] + */ + +static VALUE +rb_f_local_variables(void) +{ + VALUE ary = rb_ary_new(); + 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; + + while (cfp) { + if (cfp->iseq) { + for (i = 0; i < cfp->iseq->local_table_size; i++) { + ID lid = cfp->iseq->local_table[i]; + if (lid) { + const char *vname = rb_id2name(lid); + /* should skip temporary variable */ + if (vname) { + rb_ary_push(ary, ID2SYM(lid)); + } + } + } + } + if (cfp->lfp != cfp->dfp) { + /* block */ + VALUE *dfp = GC_GUARDED_PTR_REF(cfp->dfp[0]); + + if (vm_collect_local_variables_in_heap(th, dfp, ary)) { + break; + } + else { + while (cfp->dfp != dfp) { + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + } + } + } + else { + break; + } + } + return ary; +} + void Init_vm_eval(void) { rb_define_global_function("eval", rb_f_eval, -1); + rb_define_global_function("local_variables", rb_f_local_variables, 0); + rb_define_global_function("catch", rb_f_catch, -1); rb_define_global_function("throw", rb_f_throw, -1); -- cgit