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).
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. 2014-10-14 17:41 GMT+02:00 Eliot Miranda <[email protected]>: > 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 >
