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