Thanks eliot http://code.google.com/p/pharo/issues/detail?id=2436
In 1.1 | a | a := 4. b := [ :a | a ]. c := b value: a. we cannot shadow a Stef On May 17, 2010, at 2:47 AM, Eliot Miranda wrote: > > > On Sun, May 16, 2010 at 3:32 PM, Andreas Raab <[email protected]> wrote: > Hi Ken - > > Very interesting. Looks like an issue with OutOfScopeNotification. The > problem appears to be that this code: > > "..." [ :a | a ]. > "..." a. > > generates an OutOfScopeNotification that is being suppressed in workspaces > (I'm not exactly sure why that is). This is of course is interesting because > of the highly unusual situation of a temp shadowing a global instead of > another temp / ivar. For example, this wouldn't compile: > > | a | > [ :a | a ]. > > But stranglely, this does: > > [ :Object | Object ]. > > so your example code is roughly equivalent to running: > > b := [ :Object | Object ]. > c := b value: Object. > > When you run this line by line it works 'as expected' and when you run it as > a single doIt you get the result of c being a "[closure] in > UndefinedObject>>DoIt" due to the OutOfScopeNotification. > > Hope this explains the issue - as for how to fix it, I have no clue :-) > > Yes, the bug is that Encoder>>encodeVariable:sourceRange:ifUnknown: doesn't > continue from a caught OutOfScopeNotification by answering the ifUnknown: > action. Instead it returns the out-of-scope block temp. This is a rather > serious compiler bug that I'd left unfixed because it only bites in > workspaces (apologies) and I didn't have a small example to analyse before > (thanks Ken!). The code generated is actually equivalent to > > b := [ :a | a ]. > c := b value: <temp 0>. > > Since there aren't any temps, temp 0 is top of stack, which just happens to > be the closure just created by the preceding bytecode. e.g. look at bytecode > 49 in the following: > > a := 4. b := [ :a | a ]. c := b value: a. { a. b. c } thisContext method > symbolic > > The fix is simple. When an OutOfScopeNotification is caught the Encoder > should still answer what ever it should for an out of scope variable. In > Encoder>>encodeVariable:sourceRange:ifUnknown: the statements > > (varNode isTemp and: [varNode scope < 0]) ifTrue: [ > OutOfScopeNotification signal ifFalse: [ ^self notify: 'out of > scope']. > ]. > ^ varNode > > should read > > (varNode isTemp and: [varNode scope < 0]) ifTrue: > [^OutOfScopeNotification signal > ifTrue: [action value] > ifFalse: [self notify: 'out of scope']]. > ^varNode > > Find attached: > > !Encoder methodsFor: 'encoding' stamp: 'eem 5/16/2010 17:33'! > encodeVariable: name sourceRange: range ifUnknown: action > | varNode | > varNode := scopeTable > at: name > ifAbsent: > [(self lookupInPools: name > ifFound: [:assoc | > varNode := self global: assoc name: name]) > ifTrue: [varNode] > ifFalse: [^action > value]]. > range ifNotNil: > [name first canBeGlobalVarInitial ifTrue: > [globalSourceRanges addLast: { name. range. false }]]. > > (varNode isTemp and: [varNode scope < 0]) ifTrue: > [^OutOfScopeNotification signal > ifTrue: [action value] > ifFalse: [self notify: 'out of scope']]. > ^varNode! ! > > P.S. this is probably applicable to any Squeak bytecode compiler (including > eToys). The only change in my closure compiler from Andreas' 2003 version > was changing "name first isUppercase" to "name first canBeGlobalVarInitial". > > > P.P.S. Again Ken, thanks for a comprehensible example. It always bit me in > huge doits I was using to analyse the entire system's compiled methods, and > invariably crashed the VM. I never took the time to isolate the bug, I just > fixed the doit and continued. Turns out to be very simple. > > best > Eliot > > > Cheers, > - Andreas > > > > On 5/16/2010 12:35 PM, Ken Causey wrote: > Well, it's nothing new but this one has stumped me: > > http://bugs.squeak.org/view.php?id=7532 > > Initially I (and Frank) thought the reporter was mistaken until we > understood that the problem shows up when you execute the main code all > in one do-it. I've since modified the original report to make this > clearer. > > So here it is: > > a := 4. > b := [ :a | a ]. > c := b value: a. > > If you SELECT ALL OF THIS AND EXECUTE IT ALL AT ONE TIME (crucial > detail). The result is that a is 4, b is a BlockClosure, and c is a > BlockClosure not 4 as expected. Execute each statement separately and c > is 4. > > Alternately, from a suggestion from jmckeon, if you specify a different > symbol for the block argument: > > a := 4. > b := [ :d | d ]. > c := b value: a. > > when executed all at one time works as you would expect: a is 4, b is a > BlockClosure, and c is 4. (and d is nil) > > So what's up? > > Ken > > > > > > > <Encoder-encodeVariablesourceRangeifUnknown.st>_______________________________________________ > Pharo-project mailing list > [email protected] > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project _______________________________________________ Pharo-project mailing list [email protected] http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
