On Tue, Oct 14, 2014 at 11:15 AM, Nicolai Hess <nicolaihess@web.de> wrote:
Thank you eliot, marcus

Yes I know your blog it is a great source of information.
I am curious how the squeak compiler/debugger handles this (I'll look into it).

There's no scope at run-time, only at compile time.�� AT compile time the BlockNodes for optimized blocks get checked for the optimized selectors (ifTrue: whileTrue and: et al) and have a flag set if they can be optimized (have the right number of arguments).�� At run-time there's no evidence of an optimized block.�� One is left in the enclosing method/block activation.

About opal and optimized block scope:��
Yes, I like the way this "special" non-scope is modelled with
its own scope class.
But somehow the whileTrue: receiver block is handled different than
the ifTrue: block argument.

How so?�� Is it the source extent that is wrong?

2014-10-14 17:41 GMT+02:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Marcus,

On Tue, Oct 14, 2014 at 4:09 AM, Marcus Denker <marcus.denker@inria.fr> wrote:

> On 12 Oct 2014, at 11:49, Nicolai Hess <nicolaihess@web.de> wrote:
>
> I tried to solve issues
> "13260 inspecting variables in the debugger fails in some cases" and
> "14058 Inconsistent information in debugger"
> and found some oddities in the way opal (compiler and the debuggermap)
> handles tempory variables.
> I am not sure if these are bugs.
>
> 1. order of temporaries:
> Evaluating this method
> |a b c|
> a:=1.
> b:=2.
> c:=3.
> thisContext tempNames logCr.
> ["in a block ! " thisContext tempNames logCr . a+b+c ] value.
>
> prints in the transcript
> #(#a #b #c)
> #(#a #b #c)
>
> - ok, both contexts, the method and block context, use the same
> ordering for the tempories
>
> writing on one variable in the block context require an indirection vector for
> the variable
>
> |a b c|
> a:=1.
> b:=2.
> c:=3.
> thisContext tempNames logCr.
> [b:=1. thisContext tempNames�� logCr. a+b+c ] value.
>
> here the variable b is written within the block context. This method prints
> #(#b #a #c)
> #(#a #c #b)
>
> - strange the variable order has changed and is not the same in both contexts.
>

Yes, but behind the scenes a lot is going on��� when you assign a variable in a block, this
variable can not be allocated like a normal temp. There is instead an array (temp vector) allocated where this
variable lives. Then *this array* has a ���temp��� and is accessed in the block like the variables
in the case of no assignment.
��
Niolai, you're probably aware of it but there's an extensive write up of the design on my blog:


This means that there can not be an order: some variables live in arrays, others in the context.
The only thing that you have is a scope that nows how a name maps to a specific offset or two
(offset of temp of the ���temp vector + offset inside this temp vector).

I disagree slightly.�� The Squeak compiler maintains order, both in temps and in indirect temps.�� But whether a temp is direct or indirect depends on a simple analysis of a single method.�� I still think it is part of the Smalltalk culture to KISS and e.g. maintain the order of temps.

One could beautify it a bit by sorting the names according to the original definition order, though.
(we should look onto that).

The current exception system needs to access temps, e.g. ensure:'s and ifCurtailed:'s complete and on:do:'s��handlerActive.�� Isn't it really important to maintain ordering?�� It certainly makes introspection easier.�� One can go through a name-based interface but that is likely to be much much slower in what is a perfrmance-critical part of the system.
��

But even if we do, this does not mean that b has offset 2 in the example, as it lives in an array...

Right.
��


> 2. OCOptimizedBlockScope
>
> Consider a whileTrue: call
> ["A-Block"] whileTrue:["B-Block"]
> or an ifTrue:
> ("some boolean value") ifTrue:["C-Block"]
> stepping into the blocks with the debugger and reading the
> values for a tempoariy variable shows that every block has
> an OCOpotimizedBlockScope as its scope.
> Are all�� 3 blocks the same kind of "optimized blocks"? because ->
>
Yes, we tried two ideas
The first move only real existing scopes, that means, instead of an optimised scope
point to the scope that all these optimized blocks are flattened into.
But that was not nice and we could not get it to work.
Instead, we opted into modelling the concept of�� the optimised scope: on the AST
level, the block has a scope (like all blocks), but when you add an entry (or query),
it will forward to the ���real��� existing scope.

I still like it, it makes things very explicit.

> 3. Blocks within optimized blocks
> This method prints the number of tempories on the Transcript
> (the on:do: call is just a dummy for an "block within a block"
> but the important part is the usage of the three variables
> in the do-block)
>
> |a b c|
> a:=1.
> b:=2.
> c:=3.
> (c>0) ifTrue:[
>�� �� ��[ a asString ] on:Error do:[:ex | a value:a value:b value:c].
> ].
> thisContext method numTemps logCr.
> a
>
> The output on the transcript is "3"
> - ok
>
> This method is like the one above, but the nested block
> is in the receiver of the whileTrue:[] call (again, an optimized block, right?)
>
> |a b c|
> a:=1.
> b:=2.
> c:=3.
>
> [
>�� �� ��[ a asString ] on:Error do:[:ex | a value:a value:b value:c].
>�� �� �� c <0 ] whileTrue:[].
> thisContext method numTemps logCr.
> a
>
> The output on the Transcript is "1"
> And it depends on the number of used variables in the do-Block
> The same method but with the do-Block
> do:[:ex | a value:a value:b]
> would print 2 as number of temporaries.
>


Hmm��� I need to think about this one. It looks strange, yes.

�� �� �� �� Marcus







--
best,
Eliot




--
best,
Eliot