At 06:14 PM 8/1/2002 +0200, Jerome Vouillon wrote: >On Wed, Jul 31, 2002 at 11:40:39AM -0600, Jonathan Sillito wrote: > > So here is my take on a slightly simpler example: > > > > sub foo { > > my $x = 13; > > return sub { print "$x\n"; }; > > } > > > > $foo() > >Melvin, I think it would really help if you could explain us how you >would compile this code. Also, you should describe precisely what >"invoke" and "new_pad" (and maybe the other scratchpad-related >opcodes) do as far as scratchpads are concerned.
Here is an attempt. I'm assuming the stack of pads is a singly-linked list of pads with children pointing to parents, and multiple children can refer to the same parent. If they are created on the fly, the creation of a Sub or Closure will simply hold a pointer to its parent, and pads will be garbage collected. Disclaimer: I'm only speaking my ideas which may not coincide with what Dan has in mind. # Assuming we have no symbol table or pad "descriptor" # then to do it dynamically with the new_pad/store_lex ops... foo: new_pad # lexical scope 1 new P0, .PerlInt set P0, 13 store_lex "$x", P0 # or store_lex 0, P0 new P1, .PerlSub # captures the current lexical pad tree/stack set P1, anon_closure # set bytecode address store P1 # return value ret # ret may close current pad which now is only # referred to by anon_closure anon_closure: new_pad # activate new pad which inherits previous pad # for any lexicals. # lexical scope 2 fetch_lex P0, "$x" # or fetch_lex P0, 0 print P0 print "\n" ret new P0, .PerlSub, foo # lexical scope 0 invoke P0 restore P1 # get closure sub returned from foo into P1 invoke P1 # closure contains a lexical stack of: [0,1] and will # push lex scope 2 which in this example doesn't # create any new lexicals. end