From: "James M. Lawrence" Date: 2011-02-03T11:24:42+09:00 Subject: [ruby-core:35064] [Ruby 1.9-Bug#4352] [patch] Fix eval(s, b) backtrace; make eval(s, b) consistent with eval(s) Issue #4352 has been updated by James M. Lawrence. > Why do you think only a binding location as a problem? The initial problem I encountered was eval %{def g ; end}, nil, "(eval)", 99 p method(:g).source_location #=> ["(eval)", 99] eval %{def f ; end}, binding, "(eval)", 99 p method(:f).source_location #=> ["prob.rb", 1] I needed source_location to be ["(eval)", 99] in the latter case, which is solved by the patch. This could be also be done by making eval recognize the difference between an empty file argument and an "(eval)" file argument, however the problem seemed more fundamental. eval should not implicitly slurp file/line info from the binding. Creating a "dishonest" backtrace is something that should be done explicitly by the user, as in eval(s, b, *b.source_location) In the last the example in the original post, the existence of raiser.rb:10 is an outright falsehood. Pointing to a nonexistent line number should not be the default behavior of eval(s, b). Since source_location claims to be "the ruby source filename and line number containing this proc", I was thinking that source_location could give the "true" location, ignoring the file/line "lies" passed to eval. But this was wrong--indeed I want the "lies" to be reflected in source_location. My problem is with eval implicitly grabbing file/line from the binding, which is just what the patch solves. As mentioned above, this would be nice too: class Binding def source_location eval "[__FILE__, __LINE__]" end end diff --git a/proc.c b/proc.c index 7b1d147..0042caf 100644 --- a/proc.c +++ b/proc.c @@ -305,6 +305,24 @@ binding_clone(VALUE self) return bindval; } +/* + * call-seq: + * binding.source_location -> [String, Fixnum] + * + * Returns the ruby source filename and line number associated with + * this binding. + */ +static VALUE +binding_source_location(VALUE self) +{ + rb_binding_t *src; + VALUE loc[2]; + GetBindingPtr(self, src); + loc[0] = rb_str_dup_frozen(src->filename); + loc[1] = INT2FIX(src->line_no); + return rb_ary_new4(2, loc); +} + VALUE rb_binding_new(void) { @@ -2227,6 +2245,7 @@ Init_Binding(void) rb_undef_method(CLASS_OF(rb_cBinding), "new"); rb_define_method(rb_cBinding, "clone", binding_clone, 0); rb_define_method(rb_cBinding, "dup", binding_dup, 0); + rb_define_method(rb_cBinding, "source_location", binding_source_location, 0); rb_define_method(rb_cBinding, "eval", bind_eval, -1); rb_define_global_function("binding", rb_f_binding, 0); } ---------------------------------------- http://redmine.ruby-lang.org/issues/show/4352 ---------------------------------------- http://redmine.ruby-lang.org