<br><br><div class="gmail_quote">On Fri, Jan 14, 2011 at 5:42 AM, Balázs Kósi <span dir="ltr">&lt;<a href="mailto:rebmekop@gmail.com">rebmekop@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="gmail_quote">Hi,</div><div class="gmail_quote"><div> </div><div>We fiddled with this a bit.</div><div class="im"><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div><div class="gmail_quote"><div>On Thu, Jan 13, 2011 at 6:52 PM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div class="gmail_quote"><div>On Thu, Jan 13, 2011 at 9:33 AM, Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span> wrote:<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div class="gmail_quote"><div>On Thu, Jan 13, 2011 at 2:29 AM, Bert Freudenberg <span dir="ltr">&lt;<a href="mailto:bert@freudenbergs.de" target="_blank">bert@freudenbergs.de</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">




Here&#39;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:<br>
<br>
blockLocalsAndArgs<br>
        | product |<br>
        product := 1.<br>
        1 to: 2 do: [:i |<br>
                i = 1<br>
                        ifTrue: [ | factor | factor := 6.<br>
                                product := product * factor ]<br>
                        ifFalse: [ #(9) do: [:factor |<br>
                                product := product * factor ] ] ].<br>
        ^ product = 13r42<br>
<br>
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.<br>
<br>
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</blockquote></div></div></blockquote>

</div></div></blockquote></div></div></div></blockquote><div><br></div></div><div> The Decompiler modified by the attached changeset tries to do this. It gives the following output for your example:</div><div class="im">
<div><br></div><div>  blockLocalsAndArgs</div>
<div><span style="white-space:pre-wrap">        </span>| product |</div><div><span style="white-space:pre-wrap">        </span>product := 1.</div><div><span style="white-space:pre-wrap">        </span>1</div><div><span style="white-space:pre-wrap">                </span>to: 2</div>

<div><span style="white-space:pre-wrap">                </span>do: [:i | i = 1</div><div><span style="white-space:pre-wrap">                                </span>ifTrue: [| factor |</div><div><span style="white-space:pre-wrap">                                        </span>factor := 6.</div><div>

<span style="white-space:pre-wrap">                                        </span>product := product * factor]</div><div><span style="white-space:pre-wrap">                                </span>ifFalse: [#(9 )</div><div><span style="white-space:pre-wrap">                                                </span>do: [:factor | product := product * factor]]].</div>

</div><div><span style="white-space:pre-wrap">        </span>^ product = 54</div><div> </div><div>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. .... ].</div>
</div></blockquote><div><br></div><div>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&#39;t a subsequent enumeration of the block could see the value of a local from a previous iteration.</div>
<div><br></div><div>e.g.</div><div><br></div><div>1 to: 10 do: [:i| | local | self assert: local isNil. local := i]</div><div><br></div><div>There is a test for this in the Compiler tests somewhere.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="gmail_quote">
<div> </div><div>And there is this snippet of code:</div><div> </div><div>| aBlock |</div><div>aBlock := Compiler evaluate: &#39;| x y |  [:a :b | x := a. y := b. x+y]&#39;.<span style="white-space:pre-wrap">        </span></div>

<div><span style="white-space:pre-wrap"></span>aBlock decompile</div><div> </div><div>which breaks an assertion in the Decompiler itself.</div><div> </div><div>So this is far from complete.</div><div class="im"><div><br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="gmail_quote"><div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div>

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



</div></blockquote><div><br></div></div><div>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&gt;&gt;declareUndeclaredTemps.</div>


</div></blockquote><div></div></div></div></div></blockquote><div> </div></div><div>The changeset contains the following changes:</div><div> - A new subclass of VariableScopeFinder: TempVariableScopeFinder. It finds scopes for tempvar nodes not just for undeclared nodes.</div>

<div> - In DecompilerConstructorForClosures&gt;&gt;#codeMethod:block:tempVars:primitive:class: instead of </div><div>     [ block temporaries: temporaries ], we execute</div><div>     [ temporaries := self pushDownTemps: temporaries toTheirInnermostPossibleScopesIn: block ]</div>

<div> - The method pushDownTemps:toTheirInnermostPossibleScopesIn: which tries to do what it&#39;s name suggests and returns with the temps remaining in the top level scope.</div><div> </div><div>Is this the right direction?</div>
</div></blockquote><div><br></div><div>Yes!</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="gmail_quote">
<div> </div><div>Cheers, Balázs</div></div></blockquote><div><br></div><div>thank you!</div><div><br></div><div>best</div><div>Eliot </div></div><br>