I’m guessing that it is using the read before written tester from the 
refactoring browser. It treats ifTrue:ifFalse:/ifFalse:ifTrue: blocks and the 
receiver blocks of whileTrue/False: specially. All other blocks are considered 
potentially not executed. Therefore, it says that the or: block may not be 
executed so the “element” reference in the whileFalse: argument block may be 
read without any assignment. 

The RB’s read before written tester is different from the compilers. The 
compiler’s version lets some things through that it shouldn’t, and I think the 
compiler should use the RB version instead. Here’s an example where the 
compiler generates incorrect code for the optimized “v” variable in the 
whileTrue:

| stream count |
count := 0.
stream := ReadStream on: #(true true true false false).
[ stream next and: [ | v | stream next ifTrue: [ v := 1 ]. v notNil ] ]
        whileTrue: [ count := count + 1 ].
count = 1 

This should answer true, but answers false. The compiler should see that “v” 
may potentially be read before written, and therefore assign it to nil at the 
beginning of the or: block like would be done for an unoptimized block 
temporary. If you perform the #whileTrue: instead (to get a real block), you 
get the correct result:

| stream count |
count := 0.
stream := ReadStream on: #(true true true false false).
[ stream next and: [ | v | stream next ifTrue: [ v := 1 ]. v notNil ] ]
        perform: #whileTrue: with: [ count := count + 1 ].
count = 1


John Brant


> On Aug 16, 2016, at 3:23 PM, Nicolas Cellier 
> <[email protected]> wrote:
> 
> initialization of element is conditional (in the or: block).
> I'm amazed, that's a new behavior, is it a consequence of using AST?
> But a dumb compiler not knowing the semantic of or: (it is a message like 
> others) could conclude that element may be used uninitialized in the 
> whileFalse block...
> A compiler that is inlining or: with a well known semantic has no excuse ;)
> 
> 2016-08-16 22:12 GMT+02:00 stepharo <[email protected]>:
> While browsing the system I saw that the following method raised a temp read 
> before written...
> 
> It did not jump to my eyes. Working on something else....
> 
> 
> PositionableStream>>upTo: anObject
>     "Answer a subcollection from the current access position to the
>     occurrence (if any, but not inclusive) of anObject in the receiver. If
>     anObject is not in the collection, answer the entire rest of the 
> receiver."
>     | newStream element |
>     newStream := (collection species new: 100) writeStream.
>     [self atEnd or: [(element := self next) = anObject]]
>         whileFalse: [newStream nextPut: element].
>     ^newStream contents
> 
> 
> 


Reply via email to