On Wed, Nov 23, 2011 at 8:06 AM, Brock <awwa...@thelackthereof.org> wrote:

> On Sun, 20 Nov 2011 Rocky Bernstein wrote:
> > I've briefly looked at PadWalker which can look at "my" and "our"
> > variables on a call stack. And while this is very useful, it is not
> > the same as being able to evaluate a string in the context of a stack
> > frame.
> >
> > Has anyone tried to create such an eval? A simple suggested interface
> > would be to pass it an integer which indicates the call stack frame to
> > use.
>
> You might take a look at Eval::WithLexicals and how it is used in
> Plack::Middleware::InteractiveDebugger (which, upon die(), lets the user
> open a web-based REPL at any level of the call stack). Looks like there
> is some manual work you have to do though.
>

Thanks! I think I now understand how it's done. Sort of.

Devel::StrackTrace::WithLexicals uses PadWalker to create a hash of of all
the lexical variables for a given call frame. Eval::WithLexicals is then
passed that hash. By the way, this is similar to how Python's eval works.

And then comes the complicated part, Eval::WithLexicals uses that hash
somehow in a string eval. How this works is not obvious to me, but the next
couple of days I'll probably figure this out as I have a  good debugger
that can track nicely through string evals which is used a bit here.
Eval::WithLexicals (and Eval::WithLexicals::WithHintPersistence ) then
needs to put changed values back someplace. (Perhaps this id done via
B::svref_2object.)

So one thing that needs to be checked in my use is that the values do
indeed get put back into the right place in the call stack and not just say
in the hash created by Devel::StackTrace::WithLexicals.

Another thing that seems to be something that could go wrong is in handling
local variables, because PadWaker doesn't handle local variables.

Suppose I have a local variable $a defined in main and a couple of calls
down I have another local $a --alsi in package main::. I am not sure how I
would be able to access the outer or main-most $a to read the value.

(Actually here is a bad way and one that is sort of used in the first Ruby
debugger: On every call create a closure with all of the values. This is
horrendously slow.)

And looking at WithLexical.pm's code, there is this comment in
_record_caller_data():
    # PadWalker ignores eval block and eval string so we must do so too.

So this could also be another source of discrepancy people may run into.

Given all of this -- and I am sorry if this was a bit long -- it seems that
life would be much simpler and more reliable if Perl just had a eval_n
function which did the evaluations n levels down the call stack.

Looking at the C code, one can get a PERL_CONTEXT from the call stack and
somehow one just needs to make sure that this is what is used by this new
eval_n routine.

Reply via email to