From: Robert Feldt Date: 2001-03-06T16:09:47+09:00 Subject: [ruby-talk:12097] RCR: replacing 'caller' Hi, IMHO, 'caller' would be much more useful if you could know/access the method and object that called you. Therefore I submit this RCR: Replace 'caller' with 'call_stack' returning an array of arrays each with the format: [object_called, method_called_id, args, file_with_call, line_for_call] 'call_stack' takes a level parameter (almost) in the same way as 'caller'. Example: def m(a,b) puts call_stack.inspect end def m2(a,b) m(a,b) end m2(1,true) would print [[main, :m, [1, true], "../call_stack/t2.rb", 5], [main, :m2, [1, true], "../call_stack/t2.rb", 8]] It might also be useful to add any blocks associated with calls (I'm skeptical if this adds enough value for the added complexity). Maybe there's a risk in including the args. I'm not sure... Probably there's a risk in any of this since Matz hasn't previously included it? Below is the diff to eval.c in latest snapshot implementing call_stack. Regards, Robert --- eval.c.orig Tue Mar 6 06:00:04 2001 +++ eval.c Tue Mar 6 07:52:24 2001 @@ -4687,6 +4687,54 @@ } static VALUE +call_stack(lev) + int lev; +{ + struct FRAME *frame = ruby_frame; + VALUE ary = rb_ary_new(); + VALUE inner_ary; + + while (lev-- > 0) { + frame = frame->prev; + if (!frame) { + ary = Qnil; + break; + } + } + while (frame && frame->file) { + inner_ary = rb_ary_new(); + rb_ary_push(inner_ary, frame->self); + rb_ary_push(inner_ary, ID2SYM(frame->last_func)); + rb_ary_push(inner_ary, rb_ary_new4(frame->argc, frame->argv)); + rb_ary_push(inner_ary, rb_str_new2(frame->file)); + rb_ary_push(inner_ary, INT2FIX(frame->line)); + // Add block if block_given? ie. check iter stack and traverse block + // stack accordingly... + rb_ary_push(ary, inner_ary); + frame = frame->prev; + } + + return ary; +} + +static VALUE +rb_f_call_stack(argc, argv) + int argc; + VALUE *argv; +{ + VALUE level; + int lev; + + rb_scan_args(argc, argv, "01", &level); + + if (NIL_P(level)) lev = 1; + else lev = NUM2INT(level); + if (lev < 0) rb_raise(rb_eArgError, "negative level(%d)", lev); + + return call_stack(lev); +} + +static VALUE rb_f_caller(argc, argv) int argc; VALUE *argv; @@ -5869,6 +5917,7 @@ rb_define_global_function("fail", rb_f_raise, -1); rb_define_global_function("caller", rb_f_caller, -1); + rb_define_global_function("call_stack", rb_f_call_stack, -1); rb_define_global_function("exit", rb_f_exit, -1); rb_define_global_function("abort", rb_f_abort, 0);