summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
authoryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-01-28 11:09:14 +0000
committeryugui <yugui@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-01-28 11:09:14 +0000
commite6b9c72d637cb4dcf84011c7e637c3a61ddeca7c (patch)
tree5c495ee3113a6cf6cad377d97060cd38b34f8cab /vm_eval.c
parent6311c5a8e40c26198e91406d9bba782796d9504f (diff)
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: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_9_1@21846 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 851eaaf9ff..b0a9b29aee 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);