sub f ($x) { (&g ::= sub { $x }), (&g := sub { $x } afterwards -- during refresh!) } -- To clone is to run refreshPad on the sub's own pad. -- Also, to clone is to snapshot the env's lexical as our lexical. -- Problem is what the OUTER means; envLexical hides outer for us. -- Solution: actually add OUTER symbols at that point? -- Another solution: _also_ snapshot envLexPad? -- reentry from outer would use different Pad, and writeTVar to its TVar(?) -- so snapshotting envLexPad into [Pad] is safe (but only during runtime!). -- Actually under O(1) access we can simply have [Pad] instead of merged Pad. -- symbolic deref would need traversal no? -- otoh, it's rare enough that we don't actually care. -- but our Var is current symbolic. -- A subroutine when it's fully formed will always have its own pad as static. (copied from envCompPad.) -- A subroutine when it's cloned wil use env's outer as outer. -- envLexPads :: LexPads -- subLexPads :: LexPads $c = sub ($x) { sub j { $x }; } j; [Either MPad Pad] subLexPads :: Either [MPad] [Pad] subLexical :: Pad subEntered :: TVar Bool envLexPads :: ... envCompPads :: ... data LexPads = PCompiling [MPad] -- can't cache properly with this PRuntime { pads :: [Pad] merged :: Pad fresh :: (TVar Bool) -- this is the "sharing" anchor } -- cached merged for symbolic deref too. MAIN (our &f) { &f ::= sub { } } At end of compilation, the envCompPad flag is turned off and a proto->store refresh is done to MAIN. It changes itself into a PRuntime [{&f}] {&f} pad, by reading from each M{} and attempt a proto->store refresh. During proto->store for Code (in code_clone), the same thing recursively happens for the inner symbols visible in that block. Since all scopes reachable via "our" is registered in some inner pad's lexical scope, this process corrects all pads except for anons, which will be snapshotted during "closure" time anyway, which will cause all its symbols undergo a proto->store but not itself. However, anon expressions would actually resnapshot envLexPads anyway, which is not the same as the proto->store refresh. Which is correct, yay. Upon "close", subLexPads inherits from envLexPads. Upon "apply", envLexical carries PRuntime's cache over. otherwise it snapshots PCompiling for fun. Upon "refresh", each proto VCode gets rebound again to PRuntime: envLexPads. (however if envCompPad is still going on we don't refresh anything.) the first time of C->R the fresh is init to false, but all the pad entries is cloned from proto into store; this recursively triggers reclosure of VCode symbols, including static ones and lexical ones. Another way to think about it is that calls to f during compilation doesn't count against its reshness ratings... -- obviously comp-time code and runtime code are two differnent types. -- To "close over" a scope is to take a snapshot of its current bindings? -- If my outer scope is still under compilation, don't actually populate subLexical -- If my outer scope has finished compilation, free to close subLexical now. -- So maybe "freshness" is overrated. Maybe it's simply that refreshPad is not run for lexicals during compilation? This is to say pe_store stays the same. we say so because all we have is a MPad and refreshing it is silly... -- Also maybe the freshness flag is carried on the sub rather than the lexpad? my $x = f(3); say g(); # 3 say $x(); # 3 my $y = f(4); say g(); # 4! say $x(); # 3 say $y(); # 4