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