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