On Thu, Aug 01, 2002 at 10:57:34AM -0700, Sean O'Rourke wrote:
> My naive implementation would have an array of hashes for each sub, with
> one entry for each level of scope within.

I would use an array of arrays or a linked-list of arrays.  This is
hardly more difficult to implement (you just need to keep track of the
variable indices during compilation) and the generated code will be a
lot more efficient.

> This is just like the
> pad_stack, but implemented using only language features.  (Dynamic)
> lexical lookup works its way through this stack.  Static lookups can
> probably be resolved to registers, with code inserted to fetch values out
> of the pad the first time they are used, and store them back when a scope
> is exited.

You would probably need to store them back each time you perform a
function call.  I think it is good enough for the moment to always go
through the stack.

> Returning a closure would make a copy of the scope array, containing
> references to the pad hashes (here's where GC makes me happy, and where I
> may make the GC unhappy).

You don't need to make a copy at this point.  Instead, the copy should
happen each time you enter a block containing lexical variables.  (You
should also allocate and fill a new pad at this time.)

> Waving my hands somewhat more quickly, as an optimization, lexicals can
> just live in registers when the compiler sees no references to %MY or
> closures.  Nastiness like eval and caller.MY can be handled by inserting
> fixup code to reconstruct the lexical array on demand.

caller.MY is especially nasty because you have to pay for it even when
you don't use it: you can't know whether a function has to support it
just by looking at the function code.  It will be really tricky to
implement any optimization if one can write things like:
  caller(1).MY{'$y'} := $x

-- Jerome

Reply via email to