Squeak4.2-10892-beta image

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Squeak4.2-10892-beta image

Chris Muller-3
I've just posted a new beta image at:

   ftp://ftp.squeak.org/4.2/

This one does not have wrecked PackageInfo's, and has most (but not
all) of the aesthetic changes for 4.2.

The test suite is looking better:

 'CompilerExceptionsTest>>#testUnusedVariable
DecompilerTests>>#testDecompileLoopWithMovingLimit
DecompilerTests>>#testDecompilerInClassesMAtoMM
DecompilerTests>>#testDecompilerInClassesSNtoSZ
ExceptionTests>>#testHandlerFromAction
MCPackageTest>>#testUnload
MirrorPrimitiveTests>>#testMirrorAt
MirrorPrimitiveTests>>#testMirrorInstVarAt
MorphicUIBugTest>>#testShowAllBinParts
ProcessTest>>#testAtomicSuspend
SMDependencyTest>>#test2
StandardSystemFontsTest>>#testRestoreDefaultFonts
'

We must be getting close.  We could use help in fixing some of these
final tests, or otherwise testing on your own applications.

Thanks,
  Chris

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Levente Uzonyi-2
On Wed, 12 Jan 2011, Chris Muller wrote:

> I've just posted a new beta image at:
>
>   ftp://ftp.squeak.org/4.2/
>
> This one does not have wrecked PackageInfo's, and has most (but not
> all) of the aesthetic changes for 4.2.
>
> The test suite is looking better:
>
> 'CompilerExceptionsTest>>#testUnusedVariable

This one is new, I'd be happy if someone could have a look at it.

> DecompilerTests>>#testDecompileLoopWithMovingLimit

This is hard to fix, maybe impossible.

> DecompilerTests>>#testDecompilerInClassesMAtoMM
> DecompilerTests>>#testDecompilerInClassesSNtoSZ

There are fixes in the Inbox for these 2, I'll integrate them soon.

> ExceptionTests>>#testHandlerFromAction

Also a new one. We probably won't fix it in this release.

> MCPackageTest>>#testUnload

This one is failing randomly. It would be nice if we could save the
stack trace when it's failing.

> MirrorPrimitiveTests>>#testMirrorAt
> MirrorPrimitiveTests>>#testMirrorInstVarAt

These are VM related unexpected passes. For some reason these two are
passing with SqueakVM 4.0.2.

> MorphicUIBugTest>>#testShowAllBinParts

Random.

> ProcessTest>>#testAtomicSuspend

New one. I guess it's VM related.

> SMDependencyTest>>#test2

Random.

> StandardSystemFontsTest>>#testRestoreDefaultFonts

Random.


So we have:
4 that fail randomly
3 VM related
3 waiting to be fixed
2 fixed

So in the end we shouldn't have more than 3. :)


Levente

> '
>
> We must be getting close.  We could use help in fixing some of these
> final tests, or otherwise testing on your own applications.
>
> Thanks,
>  Chris
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Nicolas Cellier
>> DecompilerTests>>#testDecompileLoopWithMovingLimit
>
> This is hard to fix, maybe impossible.
>

Without a Debugger, I must admit it's not that easy.
With a Debugger, just step into it...

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Levente Uzonyi-2
On Wed, 12 Jan 2011, Nicolas Cellier wrote:

>>> DecompilerTests>>#testDecompileLoopWithMovingLimit
>>
>> This is hard to fix, maybe impossible.
>>
>
> Without a Debugger, I must admit it's not that easy.
> With a Debugger, just step into it...

Well, I never tried it, but somehow got the impression that if you fix
this, you'll break the decompilation of the #to:do: version of the loop.
But that won't break, because in that case the loop won't be inlined.


Levente

>
> Nicolas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Nicolas Cellier
In reply to this post by Levente Uzonyi-2
2011/1/12 Levente Uzonyi <[hidden email]>:

> On Wed, 12 Jan 2011, Chris Muller wrote:
>
>> I've just posted a new beta image at:
>>
>>  ftp://ftp.squeak.org/4.2/
>>
>> This one does not have wrecked PackageInfo's, and has most (but not
>> all) of the aesthetic changes for 4.2.
>>
>> The test suite is looking better:
>>
>> 'CompilerExceptionsTest>>#testUnusedVariable
>
> This one is new, I'd be happy if someone could have a look at it.
>

This is due to latest improvements from Eliot.
Now the BlockNode have their own tempsMark (set by
Parser>>#temporaryBlockVariablesFor:).
The Parser only records top level tempsMark in Parser>>#temporaries.

If you look at the code in Parser>>#removeUnusedTemps, you see some
defensive programming
        ((tempsMark between: 1 and: str size)
                and: [(str at: tempsMark) = $|]) ifFalse: [^ self].

But hey, the top level does not have any tempsMark, so the method
prematurely returns without checking for some unused in the blocks.
self
        justTriedCompiling: 'griffle | | ^[ | goo | ]'
        andItCorrectlyRaised: UnusedVariable.

Shall we remove the tempsMark protection ?

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Bert Freudenberg
In reply to this post by Chris Muller-3

On 12.01.2011, at 21:11, Chris Muller wrote:

> I've just posted a new beta image at:
>
>   ftp://ftp.squeak.org/4.2/

Btw, this is the same as

        http://ftp.squeak.org/4.2/

and I for one find http more convenient than ftp nowadays ...

- Bert -


> This one does not have wrecked PackageInfo's, and has most (but not
> all) of the aesthetic changes for 4.2.
>
> The test suite is looking better:
>
> 'CompilerExceptionsTest>>#testUnusedVariable
> DecompilerTests>>#testDecompileLoopWithMovingLimit
> DecompilerTests>>#testDecompilerInClassesMAtoMM
> DecompilerTests>>#testDecompilerInClassesSNtoSZ
> ExceptionTests>>#testHandlerFromAction
> MCPackageTest>>#testUnload
> MirrorPrimitiveTests>>#testMirrorAt
> MirrorPrimitiveTests>>#testMirrorInstVarAt
> MorphicUIBugTest>>#testShowAllBinParts
> ProcessTest>>#testAtomicSuspend
> SMDependencyTest>>#test2
> StandardSystemFontsTest>>#testRestoreDefaultFonts
> '
>
> We must be getting close.  We could use help in fixing some of these
> final tests, or otherwise testing on your own applications.
>
> Thanks,
>  Chris
>


Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Nicolas Cellier
In reply to this post by Nicolas Cellier
Follow up on unused temps :

Wanna play with temps ? Try this :

testUnusedVariable
        self
                compiling: 'griffle | goo | ^nil'
                shouldRaise: UnusedVariable;
                compiling: 'griffle | | ^[ | goo | ]'
                shouldRaise: UnusedVariable;
                compiling: 'griffle | | [ | goo | goo := nil. goo] yourself. ^[ | goo | ]'
                shouldRaise: UnusedVariable;
                compiling: 'griffle | | [ | goo | ] yourself. ^[ | goo | goo := nil. goo]'
                shouldRaise: UnusedVariable

What happens is that Parser.scopeTable has a single entry for 'goo'.
Consequently, the last registered goo wins.
In the 3rd case, the last goo is unused, so hasRef = false, so
UnusedVariable is raised.
In the 4th case, the last goo nowHasRef, and we don't get any UnusedVariable.

Until we get a scopeTable mapping each temp of each block, we gonna
live in trouble.

Nicolas

2011/1/12 Nicolas Cellier <[hidden email]>:

> 2011/1/12 Levente Uzonyi <[hidden email]>:
>> On Wed, 12 Jan 2011, Chris Muller wrote:
>>
>>> I've just posted a new beta image at:
>>>
>>>  ftp://ftp.squeak.org/4.2/
>>>
>>> This one does not have wrecked PackageInfo's, and has most (but not
>>> all) of the aesthetic changes for 4.2.
>>>
>>> The test suite is looking better:
>>>
>>> 'CompilerExceptionsTest>>#testUnusedVariable
>>
>> This one is new, I'd be happy if someone could have a look at it.
>>
>
> This is due to latest improvements from Eliot.
> Now the BlockNode have their own tempsMark (set by
> Parser>>#temporaryBlockVariablesFor:).
> The Parser only records top level tempsMark in Parser>>#temporaries.
>
> If you look at the code in Parser>>#removeUnusedTemps, you see some
> defensive programming
>        ((tempsMark between: 1 and: str size)
>                and: [(str at: tempsMark) = $|]) ifFalse: [^ self].
>
> But hey, the top level does not have any tempsMark, so the method
> prematurely returns without checking for some unused in the blocks.
> self
>        justTriedCompiling: 'griffle | | ^[ | goo | ]'
>        andItCorrectlyRaised: UnusedVariable.
>
> Shall we remove the tempsMark protection ?
>
> Nicolas
>

Reply | Threaded
Open this post in threaded view
|

Decompiling with temps

Bert Freudenberg
Here's another decompiler problem that I actually ran into in production code. When decompiling this method, either the block-local temp should remain block-local, or one of the vars needs to be renamed:

blockLocalsAndArgs
        | product |
        product := 1.
        1 to: 2 do: [:i |
                i = 1
                        ifTrue: [ | factor | factor := 6.
                                product := product * factor ]
                        ifFalse: [ #(9) do: [:factor |
                                product := product * factor ] ] ].
        ^ product = 13r42

This works fine if decompiled without temps but the standard in Squeak is to use the actual temp names - just accept this as a method and switch to decompiled view.

The best fix might be if the decompiler always declared the variables in the inner-most block possible. Maybe moving the declarations is not even that hard to do as a post-process on the AST?

- Bert -

On 13.01.2011, at 00:51, Nicolas Cellier wrote:

> Follow up on unused temps :
>
> Wanna play with temps ? Try this :
>
> testUnusedVariable
> self
> compiling: 'griffle | goo | ^nil'
> shouldRaise: UnusedVariable;
> compiling: 'griffle | | ^[ | goo | ]'
> shouldRaise: UnusedVariable;
> compiling: 'griffle | | [ | goo | goo := nil. goo] yourself. ^[ | goo | ]'
> shouldRaise: UnusedVariable;
> compiling: 'griffle | | [ | goo | ] yourself. ^[ | goo | goo := nil. goo]'
> shouldRaise: UnusedVariable
>
> What happens is that Parser.scopeTable has a single entry for 'goo'.
> Consequently, the last registered goo wins.
> In the 3rd case, the last goo is unused, so hasRef = false, so
> UnusedVariable is raised.
> In the 4th case, the last goo nowHasRef, and we don't get any UnusedVariable.
>
> Until we get a scopeTable mapping each temp of each block, we gonna
> live in trouble.
>
> Nicolas



Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Levente Uzonyi-2
In reply to this post by Nicolas Cellier
On Thu, 13 Jan 2011, Nicolas Cellier wrote:

> Follow up on unused temps :
>
> Wanna play with temps ? Try this :
>
> testUnusedVariable
> self
> compiling: 'griffle | goo | ^nil'
> shouldRaise: UnusedVariable;
> compiling: 'griffle | | ^[ | goo | ]'
> shouldRaise: UnusedVariable;
> compiling: 'griffle | | [ | goo | goo := nil. goo] yourself. ^[ | goo | ]'
> shouldRaise: UnusedVariable;
> compiling: 'griffle | | [ | goo | ] yourself. ^[ | goo | goo := nil. goo]'
> shouldRaise: UnusedVariable
>
> What happens is that Parser.scopeTable has a single entry for 'goo'.
> Consequently, the last registered goo wins.
> In the 3rd case, the last goo is unused, so hasRef = false, so
> UnusedVariable is raised.
> In the 4th case, the last goo nowHasRef, and we don't get any UnusedVariable.
>
> Until we get a scopeTable mapping each temp of each block, we gonna
> live in trouble.
Right. I'd probably create a separate class for the Encoder's scopeTable,
because it's accessed in various ways from several places and it's hard to
see what change will have side effects in the current code. But I'm a
total newbie in this area, so I may be wrong.


Levente

>
> Nicolas
>
> 2011/1/12 Nicolas Cellier <[hidden email]>:
>> 2011/1/12 Levente Uzonyi <[hidden email]>:
>>> On Wed, 12 Jan 2011, Chris Muller wrote:
>>>
>>>> I've just posted a new beta image at:
>>>>
>>>>  ftp://ftp.squeak.org/4.2/
>>>>
>>>> This one does not have wrecked PackageInfo's, and has most (but not
>>>> all) of the aesthetic changes for 4.2.
>>>>
>>>> The test suite is looking better:
>>>>
>>>> 'CompilerExceptionsTest>>#testUnusedVariable
>>>
>>> This one is new, I'd be happy if someone could have a look at it.
>>>
>>
>> This is due to latest improvements from Eliot.
>> Now the BlockNode have their own tempsMark (set by
>> Parser>>#temporaryBlockVariablesFor:).
>> The Parser only records top level tempsMark in Parser>>#temporaries.
>>
>> If you look at the code in Parser>>#removeUnusedTemps, you see some
>> defensive programming
>>        ((tempsMark between: 1 and: str size)
>>                and: [(str at: tempsMark) = $|]) ifFalse: [^ self].
>>
>> But hey, the top level does not have any tempsMark, so the method
>> prematurely returns without checking for some unused in the blocks.
>> self
>>        justTriedCompiling: 'griffle | | ^[ | goo | ]'
>>        andItCorrectlyRaised: UnusedVariable.
>>
>> Shall we remove the tempsMark protection ?
>>
>> Nicolas
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Eliot Miranda-2


2011/1/13 Levente Uzonyi <[hidden email]>
On Thu, 13 Jan 2011, Nicolas Cellier wrote:

Follow up on unused temps :

Wanna play with temps ? Try this :

testUnusedVariable
       self
               compiling: 'griffle | goo | ^nil'
               shouldRaise: UnusedVariable;
               compiling: 'griffle | | ^[ | goo | ]'
               shouldRaise: UnusedVariable;
               compiling: 'griffle | | [ | goo | goo := nil. goo] yourself. ^[ | goo | ]'
               shouldRaise: UnusedVariable;
               compiling: 'griffle | | [ | goo | ] yourself. ^[ | goo | goo := nil. goo]'
               shouldRaise: UnusedVariable

What happens is that Parser.scopeTable has a single entry for 'goo'.
Consequently, the last registered goo wins.
In the 3rd case, the last goo is unused, so hasRef = false, so
UnusedVariable is raised.
In the 4th case, the last goo nowHasRef, and we don't get any UnusedVariable.

Until we get a scopeTable mapping each temp of each block, we gonna
live in trouble.

Right. I'd probably create a separate class for the Encoder's scopeTable, because it's accessed in various ways from several places and it's hard to see what change will have side effects in the current code. But I'm a total newbie in this area, so I may be wrong.

That's a good idea.  One goal for anyone who tries to do anything in this area is to collapse optimized temps.  e.g. in the following

    1 to: self size do: [:i| ...].
     1 to: self size do: [:j| ...]

or
    1 to: self size do: [:i| ...].
    1 to: self size do: [:i| ...].

the current scope table makes it really hard to use the same temp slot for either i and j or both i's.  Since these temps are out of scope after their blocks their temps should be reused.  But the compiler keeps the in-scope/out-of-scope info in the temp nodes themselves, so this can't be done.

Collapsing temps of different names is probably not feasible because there's no way to add teh necessary scope information to the debugger temp names string and so no way of saying "temp #T is called 'i' from bytecode M to bytecode N but is called 'j' from bytecode O to bytecode P".  But collapsing temps with the same name is straight-forward and judging by all the code I've eyeballed in working on the closure compiler I'd say it was worth it, not least because certain large methods would limbo under the 56 slot max temp limit which wouldn't otherwise.  remember that GeniePlugin method that couldn't be compiled until it was refactored.

Eliot

Levente



Nicolas

2011/1/12 Nicolas Cellier <[hidden email]>:
2011/1/12 Levente Uzonyi <[hidden email]>:
On Wed, 12 Jan 2011, Chris Muller wrote:

I've just posted a new beta image at:

 ftp://ftp.squeak.org/4.2/

This one does not have wrecked PackageInfo's, and has most (but not
all) of the aesthetic changes for 4.2.

The test suite is looking better:

'CompilerExceptionsTest>>#testUnusedVariable

This one is new, I'd be happy if someone could have a look at it.


This is due to latest improvements from Eliot.
Now the BlockNode have their own tempsMark (set by
Parser>>#temporaryBlockVariablesFor:).
The Parser only records top level tempsMark in Parser>>#temporaries.

If you look at the code in Parser>>#removeUnusedTemps, you see some
defensive programming
       ((tempsMark between: 1 and: str size)
               and: [(str at: tempsMark) = $|]) ifFalse: [^ self].

But hey, the top level does not have any tempsMark, so the method
prematurely returns without checking for some unused in the blocks.
self
       justTriedCompiling: 'griffle | | ^[ | goo | ]'
       andItCorrectlyRaised: UnusedVariable.

Shall we remove the tempsMark protection ?

Nicolas








Reply | Threaded
Open this post in threaded view
|

Re: Decompiling with temps

Eliot Miranda-2
In reply to this post by Bert Freudenberg


On Thu, Jan 13, 2011 at 2:29 AM, Bert Freudenberg <[hidden email]> wrote:
Here's another decompiler problem that I actually ran into in production code. When decompiling this method, either the block-local temp should remain block-local, or one of the vars needs to be renamed:

blockLocalsAndArgs
       | product |
       product := 1.
       1 to: 2 do: [:i |
               i = 1
                       ifTrue: [ | factor | factor := 6.
                               product := product * factor ]
                       ifFalse: [ #(9) do: [:factor |
                               product := product * factor ] ] ].
       ^ product = 13r42

This works fine if decompiled without temps but the standard in Squeak is to use the actual temp names - just accept this as a method and switch to decompiled view.

The best fix might be if the decompiler always declared the variables in the inner-most block possible. Maybe moving the declarations is not even that hard to do as a post-process on the AST?

Right.  And there's now a visitor method for determining that scope, TempScopeEditor>>#blockNode:isEnclosingScopeFor:.  But I've been too lazy^H^H^H^Hbusy to apply it in the context of the decompiler.  Feel free to feel motivated...

best
Eliot
 

- Bert -

On 13.01.2011, at 00:51, Nicolas Cellier wrote:

> Follow up on unused temps :
>
> Wanna play with temps ? Try this :
>
> testUnusedVariable
>       self
>               compiling: 'griffle | goo | ^nil'
>               shouldRaise: UnusedVariable;
>               compiling: 'griffle | | ^[ | goo | ]'
>               shouldRaise: UnusedVariable;
>               compiling: 'griffle | | [ | goo | goo := nil. goo] yourself. ^[ | goo | ]'
>               shouldRaise: UnusedVariable;
>               compiling: 'griffle | | [ | goo | ] yourself. ^[ | goo | goo := nil. goo]'
>               shouldRaise: UnusedVariable
>
> What happens is that Parser.scopeTable has a single entry for 'goo'.
> Consequently, the last registered goo wins.
> In the 3rd case, the last goo is unused, so hasRef = false, so
> UnusedVariable is raised.
> In the 4th case, the last goo nowHasRef, and we don't get any UnusedVariable.
>
> Until we get a scopeTable mapping each temp of each block, we gonna
> live in trouble.
>
> Nicolas






Reply | Threaded
Open this post in threaded view
|

Re: Decompiling with temps

Eliot Miranda-2


On Thu, Jan 13, 2011 at 9:33 AM, Eliot Miranda <[hidden email]> wrote:


On Thu, Jan 13, 2011 at 2:29 AM, Bert Freudenberg <[hidden email]> wrote:
Here's another decompiler problem that I actually ran into in production code. When decompiling this method, either the block-local temp should remain block-local, or one of the vars needs to be renamed:

blockLocalsAndArgs
       | product |
       product := 1.
       1 to: 2 do: [:i |
               i = 1
                       ifTrue: [ | factor | factor := 6.
                               product := product * factor ]
                       ifFalse: [ #(9) do: [:factor |
                               product := product * factor ] ] ].
       ^ product = 13r42

This works fine if decompiled without temps but the standard in Squeak is to use the actual temp names - just accept this as a method and switch to decompiled view.

The best fix might be if the decompiler always declared the variables in the inner-most block possible. Maybe moving the declarations is not even that hard to do as a post-process on the AST?

Right.  And there's now a visitor method for determining that scope, TempScopeEditor>>#blockNode:isEnclosingScopeFor:.  But I've been too lazy^H^H^H^Hbusy to apply it in the context of the decompiler.  Feel free to feel motivated...

No, no, no, no, no, no, no.  The visitor is VariableScopeFinder and the method is ofVariable: so aParseNode accept: (VariableScopeFinder new ofVariable: var) answers nil or the smallest enclosing scope for var in aParseNode.  See Parser>>declareUndeclaredTemps.


best
Eliot
 

- Bert -

On 13.01.2011, at 00:51, Nicolas Cellier wrote:

> Follow up on unused temps :
>
> Wanna play with temps ? Try this :
>
> testUnusedVariable
>       self
>               compiling: 'griffle | goo | ^nil'
>               shouldRaise: UnusedVariable;
>               compiling: 'griffle | | ^[ | goo | ]'
>               shouldRaise: UnusedVariable;
>               compiling: 'griffle | | [ | goo | goo := nil. goo] yourself. ^[ | goo | ]'
>               shouldRaise: UnusedVariable;
>               compiling: 'griffle | | [ | goo | ] yourself. ^[ | goo | goo := nil. goo]'
>               shouldRaise: UnusedVariable
>
> What happens is that Parser.scopeTable has a single entry for 'goo'.
> Consequently, the last registered goo wins.
> In the 3rd case, the last goo is unused, so hasRef = false, so
> UnusedVariable is raised.
> In the 4th case, the last goo nowHasRef, and we don't get any UnusedVariable.
>
> Until we get a scopeTable mapping each temp of each block, we gonna
> live in trouble.
>
> Nicolas







Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Igor Stasenko
In reply to this post by Eliot Miranda-2
On 13 January 2011 18:25, Eliot Miranda <[hidden email]> wrote:
>

> I've eyeballed in working on the closure compiler I'd say it was worth it,
> not least because certain large methods would limbo under the 56 slot max
> temp limit which wouldn't otherwise.

Well, if method contains so much temps, then probably a better
workaround is to fix the programmer (or replace it, if it deeply
broken),
than modify compiler in order to deal with that. :)


> 2¢
> Eliot
>>
>> Levente



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Squeak4.2-10892-beta image

Göran Krampe
In reply to this post by Chris Muller-3
On 01/12/2011 09:11 PM, Chris Muller wrote:
> SMDependencyTest>>#test2

Nuke that one, old stuff from when I was messing with deps I presume.

regards, Göran

Reply | Threaded
Open this post in threaded view
|

Re: Decompiling with temps

Balázs Kósi
In reply to this post by Eliot Miranda-2
Hi,
 
We fiddled with this a bit.

On Thu, Jan 13, 2011 at 6:52 PM, Eliot Miranda <[hidden email]> wrote:
On Thu, Jan 13, 2011 at 9:33 AM, Eliot Miranda <[hidden email]> wrote:
On Thu, Jan 13, 2011 at 2:29 AM, Bert Freudenberg <[hidden email]> wrote:
Here's another decompiler problem that I actually ran into in production code. When decompiling this method, either the block-local temp should remain block-local, or one of the vars needs to be renamed:

blockLocalsAndArgs
       | product |
       product := 1.
       1 to: 2 do: [:i |
               i = 1
                       ifTrue: [ | factor | factor := 6.
                               product := product * factor ]
                       ifFalse: [ #(9) do: [:factor |
                               product := product * factor ] ] ].
       ^ product = 13r42

This works fine if decompiled without temps but the standard in Squeak is to use the actual temp names - just accept this as a method and switch to decompiled view.

The best fix might be if the decompiler always declared the variables in the inner-most block possible. Maybe moving the declarations is not even that hard to do as a post-process on the AST

 The Decompiler modified by the attached changeset tries to do this. It gives the following output for your example:

  blockLocalsAndArgs
| product |
product := 1.
1
to: 2
do: [:i | i = 1
ifTrue: [| factor |
factor := 6.
product := product * factor]
ifFalse: [#(9 )
do: [:factor | product := product * factor]]].
^ product = 54
 
But it brakes half of the DecompilerTests. Most of them because the Decompiler inserts nil assignments to the beginnings of some blocks. eg. [ | val | ... ] becomes [ | val | val := nil. .... ].
 
And there is this snippet of code:
 
| aBlock |
aBlock := Compiler evaluate: '| x y |  [:a :b | x := a. y := b. x+y]'.
aBlock decompile
 
which breaks an assertion in the Decompiler itself.
 
So this is far from complete.

 
Right.  And there's now a visitor method for determining that scope, TempScopeEditor>>#blockNode:isEnclosingScopeFor:.  But I've been too lazy^H^H^H^Hbusy to apply it in the context of the decompiler.  Feel free to feel motivated...

No, no, no, no, no, no, no.  The visitor is VariableScopeFinder and the method is ofVariable: so aParseNode accept: (VariableScopeFinder new ofVariable: var) answers nil or the smallest enclosing scope for var in aParseNode.  See Parser>>declareUndeclaredTemps.
 
The changeset contains the following changes:
 - A new subclass of VariableScopeFinder: TempVariableScopeFinder. It finds scopes for tempvar nodes not just for undeclared nodes.
 - In DecompilerConstructorForClosures>>#codeMethod:block:tempVars:primitive:class: instead of 
     [ block temporaries: temporaries ], we execute
     [ temporaries := self pushDownTemps: temporaries toTheirInnermostPossibleScopesIn: block ]
 - The method pushDownTemps:toTheirInnermostPossibleScopesIn: which tries to do what it's name suggests and returns with the temps remaining in the top level scope.
 
Is this the right direction?
 
Cheers, Balázs




pushDownTemps.st (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Decompiling with temps

Balázs Kósi
On Fri, Jan 14, 2011 at 2:42 PM, Balázs Kósi <[hidden email]> wrote:

>
> Hi,
>
> We fiddled with this a bit.
>>
>> On Thu, Jan 13, 2011 at 6:52 PM, Eliot Miranda <[hidden email]> wrote:
>>>
>>> On Thu, Jan 13, 2011 at 9:33 AM, Eliot Miranda <[hidden email]> wrote:
>>>>
>>>> On Thu, Jan 13, 2011 at 2:29 AM, Bert Freudenberg <[hidden email]> wrote:
>>>>>
>>>>> Here's another decompiler problem that I actually ran into in production code. When decompiling this method, either the block-local temp should remain block-local, or one of the vars needs to be renamed:
>>>>>
>>>>> blockLocalsAndArgs
>>>>>        | product |
>>>>>        product := 1.
>>>>>        1 to: 2 do: [:i |
>>>>>                i = 1
>>>>>                        ifTrue: [ | factor | factor := 6.
>>>>>                                product := product * factor ]
>>>>>                        ifFalse: [ #(9) do: [:factor |
>>>>>                                product := product * factor ] ] ].
>>>>>        ^ product = 13r42
>>>>>
>>>>> This works fine if decompiled without temps but the standard in Squeak is to use the actual temp names - just accept this as a method and switch to decompiled view.
>>>>>
>>>>> The best fix might be if the decompiler always declared the variables in the inner-most block possible. Maybe moving the declarations is not even that hard to do as a post-process on the AST
>
>  The Decompiler modified by the attached changeset tries to do this. It gives the following output for your example:
>   blockLocalsAndArgs
> | product |
> product := 1.
> 1
> to: 2
> do: [:i | i = 1
> ifTrue: [| factor |
> factor := 6.
> product := product * factor]
> ifFalse: [#(9 )
> do: [:factor | product := product * factor]]].
> ^ product = 54
>
> But it brakes half of the DecompilerTests. Most of them because the Decompiler inserts nil assignments to the beginnings of some blocks. eg. [ | val | ... ] becomes [ | val | val := nil. .... ].
>
> And there is this snippet of code:
>
> | aBlock |
> aBlock := Compiler evaluate: '| x y |  [:a :b | x := a. y := b. x+y]'.
> aBlock decompile
>
> which breaks an assertion in the Decompiler itself.
>
> So this is far from complete.
>>
>>
>>>>
>>>> Right.  And there's now a visitor method for determining that scope, TempScopeEditor>>#blockNode:isEnclosingScopeFor:.  But I've been too lazy^H^H^H^Hbusy to apply it in the context of the decompiler.  Feel free to feel motivated...
>>>
>>> No, no, no, no, no, no, no.  The visitor is VariableScopeFinder and the method is ofVariable: so aParseNode accept: (VariableScopeFinder new ofVariable: var) answers nil or the smallest enclosing scope for var in aParseNode.  See Parser>>declareUndeclaredTemps.
>
>
> The changeset contains the following changes:
>  - A new subclass of VariableScopeFinder: TempVariableScopeFinder. It finds scopes for tempvar nodes not just for undeclared nodes.
>  - In DecompilerConstructorForClosures>>#codeMethod:block:tempVars:primitive:class: instead of
>      [ block temporaries: temporaries ], we execute
>      [ temporaries := self pushDownTemps: temporaries toTheirInnermostPossibleScopesIn: block ]
>  - The method pushDownTemps:toTheirInnermostPossibleScopesIn: which tries to do what it's name suggests and returns with the temps remaining in the top level scope.
>
> Is this the right direction?
>
> Cheers, Balázs
I resend it in plain text, because
http://lists.squeakfoundation.org/pipermail/squeak-dev/2011-January/156794.html
says
"Skipped content of type multipart/alternative"



pushDownTemps.st (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Decompiling with temps

Eliot Miranda-2
In reply to this post by Balázs Kósi


On Fri, Jan 14, 2011 at 5:42 AM, Balázs Kósi <[hidden email]> wrote:
Hi,
 
We fiddled with this a bit.

On Thu, Jan 13, 2011 at 6:52 PM, Eliot Miranda <[hidden email]> wrote:
On Thu, Jan 13, 2011 at 9:33 AM, Eliot Miranda <[hidden email]> wrote:
On Thu, Jan 13, 2011 at 2:29 AM, Bert Freudenberg <[hidden email]> wrote:
Here's another decompiler problem that I actually ran into in production code. When decompiling this method, either the block-local temp should remain block-local, or one of the vars needs to be renamed:

blockLocalsAndArgs
       | product |
       product := 1.
       1 to: 2 do: [:i |
               i = 1
                       ifTrue: [ | factor | factor := 6.
                               product := product * factor ]
                       ifFalse: [ #(9) do: [:factor |
                               product := product * factor ] ] ].
       ^ product = 13r42

This works fine if decompiled without temps but the standard in Squeak is to use the actual temp names - just accept this as a method and switch to decompiled view.

The best fix might be if the decompiler always declared the variables in the inner-most block possible. Maybe moving the declarations is not even that hard to do as a post-process on the AST

 The Decompiler modified by the attached changeset tries to do this. It gives the following output for your example:

  blockLocalsAndArgs
| product |
product := 1.
1
to: 2
do: [:i | i = 1
ifTrue: [| factor |
factor := 6.
product := product * factor]
ifFalse: [#(9 )
do: [:factor | product := product * factor]]].
^ product = 54
 
But it brakes half of the DecompilerTests. Most of them because the Decompiler inserts nil assignments to the beginnings of some blocks. eg. [ | val | ... ] becomes [ | val | val := nil. .... ].

It should only do this for inlined blocks that are in loops (to:do:, to:by:do: whileTrue: whileTrue whileFalse whileFalse:).  I would modify the decompiler to strip the val := nil, since it is implicit; all temps are implicitly initialized to nil on entry to their scope.  The compiler inserts the val := nil assignments to achieve this for blocks inlined in loops.  If it didn't a subsequent enumeration of the block could see the value of a local from a previous iteration.

e.g.

1 to: 10 do: [:i| | local | self assert: local isNil. local := i]

There is a test for this in the Compiler tests somewhere.

 
And there is this snippet of code:
 
| aBlock |
aBlock := Compiler evaluate: '| x y |  [:a :b | x := a. y := b. x+y]'.
aBlock decompile
 
which breaks an assertion in the Decompiler itself.
 
So this is far from complete.

 
Right.  And there's now a visitor method for determining that scope, TempScopeEditor>>#blockNode:isEnclosingScopeFor:.  But I've been too lazy^H^H^H^Hbusy to apply it in the context of the decompiler.  Feel free to feel motivated...

No, no, no, no, no, no, no.  The visitor is VariableScopeFinder and the method is ofVariable: so aParseNode accept: (VariableScopeFinder new ofVariable: var) answers nil or the smallest enclosing scope for var in aParseNode.  See Parser>>declareUndeclaredTemps.
 
The changeset contains the following changes:
 - A new subclass of VariableScopeFinder: TempVariableScopeFinder. It finds scopes for tempvar nodes not just for undeclared nodes.
 - In DecompilerConstructorForClosures>>#codeMethod:block:tempVars:primitive:class: instead of 
     [ block temporaries: temporaries ], we execute
     [ temporaries := self pushDownTemps: temporaries toTheirInnermostPossibleScopesIn: block ]
 - The method pushDownTemps:toTheirInnermostPossibleScopesIn: which tries to do what it's name suggests and returns with the temps remaining in the top level scope.
 
Is this the right direction?

Yes!
 
 
Cheers, Balázs

thank you!

best
Eliot