On Tuesday 04 September 2001 08:32 pm, Dan Sugalski wrote:
> Absolutely nothing. The issue is speed. Looking back by name is, well,
> slow. The speed advantage that lexicals have is that we know both what pad
> a variable lives in and what offset in the pad it's living at. We don't
> have to do any runtime lookup--it's all compile time. If we lose that
> compile-time resolution, things get a lot slower. (Runtime lexical name
> lookup is a lot slower than runtime global lookup because we potentially
> have a lot of pads to walk up)
>
> Certainly doable. Just potentially slow, which is what I'm worried about.
> Making it not slow has both potential significant complexity and memory
> usage. If we have to, that's fine. Just want to make sure the cost is
> known before the decision's made. :)
Well, the ultimate trade-off for speed is memory. Right now, pads are
differential - what are the list of things that were defined in my lexical
scope. Those things are evaluated at compile-time to the pad ancestry (how
far up was something defined) and the pad offset (where within that pad) the
value of a lexical exists.
my $foo;
{
my $bar;
{
my $baz = $foo + $bar;
}
}
(Although I don't know why I'm explaining this to you, because you know this
far better than I do.)
Anyway, that's really...
[0][0];
{
[1][0];
{
[2][0] = [0][0] + [1][0];
}
}
# Pad 0 = [ foo ]
# Pad 1 = [ bar ]
# Pad 2 = [ baz]
...awful. But you get the idea.
Of course, you can't inject a new lexical foo at the inner-most loop because
it's already looking two pads up.
But what if we went ahead and made pads additive - comprehensive, so to
speak?
[0][0];
{
# Dup pad 0, and build on it.
[1][1];
{
# Dup pad 1, and build on it.
[2][2] = [2][0] + [2][1];
}
}
# Pad 0 = [ foo ]
# Pad 1 = [ foo, bar ]
# Pad 2 = [ foo, bar, baz ]
Yes, this is akin to redeclaring every lexical variable every time you
introduce a new scope. Not pretty, I know. But if you want run-time
semantics with compile-time resolution....
Let's see what this buys us.... Enough for another gig of RAM, I hope.
To replace the innermost foo, all you do is change where [2][0] points.
To delete the innermost foo, all you do is replace it with the value from
the next most innermost foo, which (if you implement this as an array), at
the same offset. Of course, if the variable was introduced at that scope,
then you point to the global instead.
To add to the innermost scope.... Hmm. I'm not dumb enough to suggest
copying all the globals in there...... Okay, how about this? Package
qualified globals will always resolve in a global variable, so they continue
to handle lookups like before. So that leaves us unqualified globals to
take the brunt of the performance hit, which I'm okay with... so far.
Now, the unqualified globals need to first check to see if they've been
lexicalized. If they have been, they'd appear in the pad at an offset
beyond where the next higher pad left off. (Since otherwise, they'd have a
pad entry already.) Since most of the time, that would be empty, it'd only
be a brief glimpse before pursuing the global. If there are some, then it
would have to scan for itself, and use whatever was appropriate.
It's ugly.... but quick... er.
--
Bryan C. Warnock
[EMAIL PROTECTED]