Hi Marcus, On Tue, Oct 14, 2014 at 4:09 AM, Marcus Denker <[email protected]> wrote:
> > > On 12 Oct 2014, at 11:49, Nicolai Hess <[email protected]> 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: http://www.mirandabanda.org/cogblog/2008/06/07/closures-part-i/ http://www.mirandabanda.org/cogblog/2008/07/22/closures-part-ii-the-bytecodes/ http://www.mirandabanda.org/cogblog/2008/07/24/closures-part-iii-the-compiler/ (especially section "The Closure Analysis") 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
