Thanks eliot

I'm refreshing my fuzzy understanding of closure implementation details (I 
would love to avoid to have students, kids, bosses and … around to get some 
calm time :).

I will start rereading your blog.

> tempAt: in Method context uses <primitive: 210>, which is failing.  Maybe 
> there is a new primitive we are not aware of for Blocks...
> 
> No, 210 is what is needed.   The issue is my implementation of temporary 
> initialization in blocks, which simply uses pushNil to allocate and 
> initialize each temp. So if one inspects [|a|a:=2] and sends it self method 
> symbolic you get:
> 
> 13 <8F 00 00 05> closureNumCopied: 0 numArgs: 0 bytes 17 to 21
> 17    <73> pushConstant: nil
> 18    <77> pushConstant: 2
> 19    <81 40> storeIntoTemp: 0
> 21    <7D> blockReturn
> 22 <7C> returnTop
> 
> And when you say self asContext pc you get 17, which is *before* the nil is 
> pushed.  So you'll want to modify tempNamed: to compare the index of the 
> temporary with the stack pointer and answer nil if the index is beyond the 
> stack pointer.

Is it correct? I think so but I'm learning ContextPart

tempNamed: aName
        "Returns the value of the temporaries, aName."
        "Implementation notes:  
        temporary initialization in blocks simply uses pushNil to allocate and 
initialize each temp. So if one inspects [|a|a:=2] and sends it self method 
symbolic you get:

13 <8F 00 00 05> closureNumCopied: 0 numArgs: 0 bytes 17 to 21
17      <73> pushConstant: nil
18      <77> pushConstant: 2
19      <81 40> storeIntoTemp: 0
21      <7D> blockReturn
22 <7C> returnTop

And when we check self asContext pc we get 17, which is *before* the nil is 
pushed. Therefore we should pay attention when querying a temporary if the 
temporary allocation was executed."

        | index |
        index := (self tempNames indexOf: aName).
        ^ index >= stackp 
                ifTrue: [ nil]
                ifFalse: [self tempAt: (self tempNames indexOf: aName)]
        
        

> 
> The same bug exists in Squeak, e.g. the below gave an error until I fixed 
> DebuggerMethodMap>>namedTempAt:in:


I checked and this method is the same in pharo and latest squeak
namedTempAt: index in: aContext
        "Answer the value of the temp at index in aContext where index is 
relative
         to the array of temp names answered by tempNamesForContext:"
        ^self
                privateTempAt: index
                in: aContext
                startpcsToBlockExtents: aContext method startpcsToBlockExtents



> | b |
> b := [ |a| a:=2 ].
> { b asContext tempNames. b method debuggerMap tempsAndValuesForContext: b 
> asContext }
> #(#('b' 'a') 'b:      [closure] in UndefinedObject>>DoIt
> a:    nil
> ')
> 
> 
> Why did I use pushNil to allocate temps?  It was not a good choice; it means 
> for example that to determine how many temps a block has one has to parse all 
> the bytecodes and see where the stack pointer is at the end (since initial 
> pushNils are ambiguous; an initial pushNil might be producing a parameter or 
> result or initializing a temp).  But not using pushNil would have meant a 
> more complex bytecode for closure creation plus another inst var in 
> BlockClosure.  I made another similar misstep in not storing the method in a 
> BlockClosure, hence preventing simple implementation of clean blocks (one 
> needs to synthesize an outerContext also).  We live and learn.

Do you mean that the closure cannot access directly method but should do go to 
its outer context to access the methods.
When this is needed to set the instruction pointer?



Another thoughts while writing the chapter on block execution..

Am I correct to say: we need contexts (to me contexts are activation objects by 
opposition to bindings which could be used to represent scope) to query local 
temps of a closure because they will be allocated at execution while 
the temporaries that are shared are defined in their defining environment (now 
the trick is that in Smalltalk environment is represented as a context). 

I get why I'm often slow because I did not implemented closure in Smalltalk 
only in lisp 

foo 

        |b|
        b := 3. 
        ^ [ |a | a :=2.  a]  

In my stupid lisp implementation an environment is represented by bindings and 
closure points to their own environment
so 
        [ |a | a :=2.  a]  
        points to 
                (b.3) (toplevel)  (and not top-level)

and for closure execution we just added temporaly a binding for a to the 
closure environment. 
                eval a:=2. a in (a) (b.3) (toplevel)  




Reply via email to