On Wed, Oct 29, 2014 at 9:48 AM, <jdelgado@lsi.upc.edu> wrote:
Hi all,

------------------------------------------------
My question is:
One thing I've observed is that local/temporal variables in the blocks
passed to #ifTrue:iFfalse are not stored in the separate remote (heap
allocated) array, but in the method context (see page 328 of Deep Into
Pharo to see what I mean). Is this true?

yes.
��
why?

because the blocks don't really exist. ��they have been optimized away and the control flow implemented using conditional branches and jumps instead of ��closures and polymorphism.�� Hence there is no other scope to hold temps in other than the method context (or the block context of a block containing optimized blocks).

But realise that the remote temp vector is *only* used for variables that are referred to from more than one full scope (method or unoptimized block) that can change value after they have been closed-over.�� If a variable is closed over but doesn't change then its value is copied into the block, and ends up in a temporary slot in the block's activation, not in the indirection vector.



Thanks in advance,

Bests,

Jordi
------------------------------------------------

PS:
Now, to put that question in context, here comes a really long "rest of
the message" part.

We assume we have Continuation class >> #callcc: implemented as:
callcc: aBlock
�� �� �� �� ^ Continuation currentDo: aBlock
(#callcc: can be found in ContinuationTests, but I prefer to change
its location. It does not matter at all where it is).

A version of whileTrue: can be implemented with callcc: and no
iterative constructs, let's call it BlockClosure >> #whileTrueCC:
whileTrueCC: aBlock
�� �� ��| cont |
�� �� ��cont := Continuation callcc: [ :cc | cc ].
�� �� ��self value ifTrue: [ aBlock value.
�� �� �� �� �� �� �� �� �� �� �� �� �� cont value: cont]
�� �� �� �� �� �� �� �� ifFalse: [^ nil].

and you can use it in the same way as #whileTrue:, for example:
| n |
n := 10.
[ n > 0 ] whileTrueCC: [
�� �� �� �� �� �� ��Transcript show: n asString; cr.
�� �� �� �� �� �� ��n := n-1 ]

I observed some strange behavior dealing with local variables and
continuations. Assume we have:

Version 1)
whileTrueCC: aBlock
�� �� ��| cont tmp |
�� �� ��tmp := 0.
�� �� ��cont := Continuation callcc: [ :cc | cc ].
�� �� ��self value ifTrue: [ aBlock value.
�� �� �� �� �� �� �� �� �� �� �� �� �� Transcript show: 'inside whileTrueCC: -> ', tmp
asString; cr.
�� �� �� �� �� �� �� �� �� �� �� �� �� tmp := tmp + 1.
�� �� �� �� �� �� �� �� �� �� �� �� �� cont value: cont]
�� �� �� �� �� �� �� �� ifFalse: [^ nil].

Version 2)
whileTrueCC: aBlock
�� �� ��| cont tmp |
�� �� ��tmp := 0.
�� �� ��[ tmp ].�� "<-------- Only difference wrt Version 1 !!!! It does
nothing, apparently"
�� �� ��cont := Continuation callcc: [ :cc | cc ].
�� �� ��self value ifTrue: [ aBlock value.
�� �� �� �� �� �� �� �� �� �� �� �� �� Transcript show: 'inside whileTrueCC: -> ', tmp
asString; cr.
�� �� �� �� �� �� �� �� �� �� �� �� �� tmp := tmp + 1.
�� �� �� �� �� �� �� �� �� �� �� �� �� cont value: cont]
�� �� �� �� �� �� �� �� ifFalse: [^ nil].

I try both versions with:
| n |
n := 4.
[ n > 0 ] whileTrueCC: [ n := n-1 ]

Version 1:
It writes in the Transcript:
inside whileTrueCC: -> 0
inside whileTrueCC: -> 0
inside whileTrueCC: -> 0
inside whileTrueCC: -> 0

Version 2:
It writes in the Transcript:
inside whileTrueCC: -> 0
inside whileTrueCC: -> 1
inside whileTrueCC: -> 2
inside whileTrueCC: -> 3

Which is ok, according to what I understood from Deep Into Pharo. The
thing is, why the ifTrue: block does not make tmp behave as when we close
it with '[ tmp ]' in version 2?

See above.�� The compiler is not smart enough to realise that the value of [tmp] is discarded, so it thinks there is a block created that closed over tmp which may be evaluated at any time (because it could get assigned to a variable and used later).�� So tmp is modified *after* it has been closed over (in the while block) and hence the compiler puts it in a temp vector.


PS 2: The behavior is *exactly* the same in Version 2 if I close tmp
*after* grabbing the continuation, that is, if I go
�� �� ��cont := Continuation callcc: [ :cc | cc ].
�� �� [ tmp ].�� "<-------- Only difference wrt Version 1 !!!! It does
nothing, apparently"
instead of
�� �� [ tmp ].�� "<-------- Only difference wrt Version 1 !!!! It does
nothing, apparently"
�� �� ��cont := Continuation callcc: [ :cc | cc ].


--
best,
Eliot