In-Reply-To: Message from Geoffrey Broadwell <[EMAIL PROTECTED]>
   of "Wed, 24 Sep 2008 16:47:44 PDT." 
   <[EMAIL PROTECTED]>

> On Wed, 2008-09-24 at 18:09 -0500, Patrick R. Michaud wrote:
>> On Thu, Sep 25, 2008 at 12:10:35AM +0200, Reini Urban wrote:
>>> 2008/9/24 Patrick R. Michaud <[EMAIL PROTECTED]>:

>>>> So, in order to get the behavior you're describing from the
>>>> interactive prompt, we'll probably need more than just Perl 6's
>>>> 'eval'.  In particular, the interactive prompt mode will need to
>>>> be able to maintain it's own dynamic lexical pad (i.e., a
>>>> DynLexPad) and have some way of extracting any lexical changes
>>>> from whatever code string it evaluates.

>>> I wouldn't call them DynLexPad or lexicals at all, I would call
>>> them just globals.  lexvars could shadow them though, but this a
>>> user problem then.

>> This approach might expose some rough edges, though -- things like
>> MY::, OUTER::, *::, etc. might not work as expected, or those
>> constructs would have to know when they're dealing with
>> "interactive mode pseudo-lexical-globals" instead of what the rest
>> of the system is using.

>> Still, we might consider something along these lines -- perhaps as
>> a stopgap approach if nothing else.

> Don't we have to solve all this to get the Perl 6 debugger
> working anyway?  

Although I'm unsure why that might be, I also recognize the possibility
that there may well exist hypothetical documents, unread by me, which
mandate some scenario or behavior wherein the answer to your question 
can only be yes.  

However, from a perl5 perspective, the answer is surely not.

I'm going to do a quick review of *why* that answer is "surely not" before
then going on to consider whether perhaps this *might* not apply to perl6
and ask that, should this indeed be what's afoot, that I be gently enlightened.

So please bear with me or skip over, as you prefer.

*In perl5*--and PLEASE hold that proviso for nearly the remainder of this
letter; you'll immediately recognize once it no longer applies--all
C<eval>s provide a scope that, though separate and complete, is
nevertheless deemed to be logically nested within its own surrounding
scope.  This behavior is no different than the expected one seen in common
C<while BLOCK> and <if BLOCK> constructs, nor does it differ from the
somewhat less common C<do BLOCK> and C<sub BLOCK> constructs.

Notably, the eval construct does this *NO MATTER WHETHER* it should occur
in its dynamically compiled C<eval STRING> guise, or in its hm, hm... 
earlier-compiled[?] C<eval BLOCK> form.  No distinction between these two
occurs as far as scoping: both are self-contained but nested.

Granted, distinctions unrelated to scoping do occur: the most
important being *when* certain classes of exceptions are thrown.  

C<eval BLOCK> throws compile-time exceptions at compile time but catches
those thrown during run-time.  C<eval STRING> throws no exceptions at all,
catching both sorts rather indiscriminately. 

(Shhh: no fatalistic out-of-memory mumbles, please.)

This is at significant distinction with the scoping behavior(s!) 
exhibited by the otherwise similarly paired C<do BLOCK> and 
companion C<do STRING> constructs.

For while C<do BLOCK> creates a nested scope just as most other BLOCKs you
can think of do, including both BLOCK and STRING varieties of eval, a
C<do STRING> critically differs form all these others by alone providing 
a scope *WHOLLY*UNRELATED* to the one textually surrounding its own execution 
(or caller, if you prefer).

I said critical because of the highly desirable, impermeable partitioning
of scope-related namespace also exhibited by both of C<do STRING>'s
derivative constructs, C<require> and C<use>.

However, the timing of exception reporting is unchanged.  Both C<do/eval
BLOCK> report compile-time errors during compile time (inarguably the
optimal point for such reporting :-).  And both C<do/eval STRING>
constructs, which wait until run-time to compile their strings (indirectly
after filename catting for C<do>), indiscriminately catch all exceptions 
(or, if you prefer, concealing them in an easily overlooked $@) occurring
during compilation phase and execution phase alike.

I regret making those readers already savvy with these fundamentals suffer
through reading the preceding preambulatory text, but I was worried that
without its exposition, I risked not all of us starting on equal footing.

And now at last to the matter at hand.  When "the debugger" (meaning, the
run-time agent's debugger-hooks, whatever these should be used for) "stops"
(well, other times, too, like actions, but anyway), it pauses with the pad
that applies to that point in the code to be *its* pad--its scope.  It runs
auxiliarly code it compiles on the fly (because you typed in Perl code
instead of any specific debugger "command") as an C<eval STRING>.  

Since yours is the same (starting) pad as the code whose line you've
stopped at, your C<eval STRING> has complete access to that pad in a way
that a C<do STRING> would not.  This allows you to type in expressions and
have names resolve first according to the pad you are logically stopped
with in.  Notably, it also allows for perl5 modules like PadWalker (the
sorry butt of many a Star Wars joke) to grant access to pads yours derives
from; or if you prefer, from those in textually surrounding code.

As previously mentioned, all four of these C<eval/do STRING/BLOCK>
constructs are also free to create new AND TEMPORALLY-LIMITED pad entries
of their very own.  That's why I tell people that if they prefer to
simplify the world by equating scopes and blocks, they'll need to think of
the STRING forms of C<do> and C<eval> more as {STRING} instead,
scope-inducing braces tacitly delimiting their STRINGs.

The advantage of this is that it allows new pad entries of their very own, 
pads that in C<eval STRING> are pad nested/derivative of the constructs
point of execution, for altogether disparate for c<do STRING>.

The disadvantage, if it can be called that, is that the notional 
close curly closes the scope, and hence renders its own unique pad 
entries out of sight--and thus out of bounds for later named access.

This is the status quo in perl5.  Its debugger('s hook(s)) needs no
oddly special flavor of some sort *non-scoping* C<eval STRING> construct
to do what it does--which, I think, it does to the satisfaction of most
of its users.  It has full access to the current pad, but any entries
new to it evaporate as it scope closes.  

This is why it does no good to enter "commands" to the debugger
the likes of any of these:

    use strict

    no warnings

    use bigrat

    my $variable

Perhaps you saying that you would *like* to see the perl6 debugger provide
a facility under which scoped constructs like these could seem to outlive
their scope, probably by making an allowance so that some sort of variant
C<eval STRING> construct be made available that's not a disguised C<eval
{STRING}>, as currently occurs.

That to me seems something markedly different from the prospect
that one needs such a thing "to make the debugger work".  The perl5 
debugger "words", despite the nonexistence of such a facility.

However, I have no idea whether Parrot might not change all of this
existing situation around completely.  I'm completely ignorant of 
this, but I'd not be astonished to learn it did.

If you told me yes, that's what happens, and then pushed me into guessing
why, I'd only get as far as making the uneducated guess that this must
somehow be due to *its* own assumptions, constraints, or expectations about
just what it means to execute newly eval code "in scope".

Is this so, or is it not so?

> (Aside from which, it would be useful to have this capability properly
> exposed, for writing shell-style UIs that can escape to raw Perl.)

Can't see you feel to be stopping you from doing that now, considering that
many existence-proofs show they already do this.  You must be talking about
some sneaky way to violate the inviolable boundary of scope.

Possibly you have just cause due to understanding of the Parrot engine and
special rules it enforces coming up against general expectations that a
perl6 debugger (er, debugger hooks) must at bare minimum at least match, if
not exceed, the perl5 debugger's current capabilities.  If this is what's
going on, then so be it: I confess my ignorance and request enlightenment.

Nevertheless, I cannot help but be reminded of all those who for many
decades now have perennially asked for shell-style UIs possessed of
magical superDUPER powers (for not even a setuid-0 program can do this
save by so tawdry a pawing of /dev/kmem as to make it embarrassingly
difficult to face yourself in the mirror the next morning; ask me for
stories some time) to alter their *parent's* per-proc attributes, like
cwd, umask, envariables, etc.

That is, they wish for changes in their own process to somehow propagate
*upwards* in a most unnatural fashion to affect those who created them,
rather than downwards following the natural order of things to affect their
unborn children.

We usually tell a person making such a request to kindly study how 
the `tset -s` command works, and then go thou and do likewise. :-)

--tom

Reply via email to