2016-08-16 23:19 GMT+02:00 John Brant <[email protected]>: > 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. > > Since or: and: are pretty much like ifTrue: ifFalse: they should better be treated as specially.
> 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 > > Yes, you're right, that's a Compiler bug. The result shall not change whether blocks are optimized or not. > > On Aug 16, 2016, at 3:23 PM, Nicolas Cellier <nicolas.cellier.aka.nice@ > gmail.com> 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 > > > > > > > > >
