"Andrew" == Andrew C Greenberg werdna@mucow.com writes:
Andrew> It's possible that I'm just not getting it, but it would appear that Andrew> the pseudo-code for #whileTrue; and #whileFalse: is incorrect. Even Andrew> if I were right, it is still the height of pedantry on my part to call Andrew> this a bug, since the code is never executed due to compiler inlining. Andrew> Nevertheless, perhaps it would be more aesthetically pleasing to have Andrew> pseudo-code here that would work if the compiler did not inline loops?
Andrew> The present code in BlockContext is:
whileTrue: aBlock "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is true."
^ [self value] whileTrue: [aBlock value]
Andrew> But it would appear to me that this code would infinite loop for so Andrew> long as these valuations do not result in a walkback. In either case Andrew> the behavior appears both undefined and incorrect for most Andrew> BlockContext instances and arguments. Perhaps something like the Andrew> following would yield the desired result?
Andrew> ^ self value ifTrue: [aBlock value. self whileTrue: aBlock]
Andrew> (and in the case of #whileFalse, use #ifFalse instead).
It's very likely that the author of BlockContext>>whileTrue: knew and was counting on the compiler to in-line the call, and never call the method explicitly, *even for* the code in the method!
In that case, the code in the method is executed only for a #perform:... and in fact, the code executed is appropriately optimized.
Your change makes sense if the compiler did not recognize this as a special case, although it would suffer from recursion trouble if there was no tail-recursion optimization (which there isn't, if I recall from the last time I asked about this same thing).
At 10:54 AM -0800 1/1/01, Randal L. Schwartz wrote:
"Andrew" == Andrew C Greenberg werdna@mucow.com writes:
Andrew> It's possible that I'm just not getting it, but it would appear that Andrew> the pseudo-code for #whileTrue; and #whileFalse: is incorrect. Even Andrew> if I were right, it is still the height of pedantry on my part to call Andrew> this a bug, since the code is never executed due to compiler inlining. Andrew> Nevertheless, perhaps it would be more aesthetically pleasing to have Andrew> pseudo-code here that would work if the compiler did not inline loops?
Andrew> The present code in BlockContext is:
whileTrue: aBlock "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is true."
^ [self value] whileTrue: [aBlock value]
Your change makes sense if the compiler did not recognize this as a special case, although it would suffer from recursion trouble if there was no tail-recursion optimization (which there isn't, if I recall from the last time I asked about this same thing).
It would appear that the assumption of inlining would benefit both sets of code, and would suffer the same tail-recursion problem in both cases if it did not. The difference I see is that I understand why the more traditional:
^self value ifTrue: [aBlock value. self whileTrue: aBlock]
would work, but I don't understand how the existing code could EVER work. It is apparent that I am missing something. Please clarify.
At 8:14 AM -0500 1/2/01, Andrew C. Greenberg wrote:
At 10:54 AM -0800 1/1/01, Randal L. Schwartz wrote:
> "Andrew" == Andrew C Greenberg werdna@mucow.com writes:
Andrew> It's possible that I'm just not getting it, but it would appear that Andrew> the pseudo-code for #whileTrue; and #whileFalse: is incorrect. Even Andrew> if I were right, it is still the height of pedantry on my part to call Andrew> this a bug, since the code is never executed due to compiler inlining. Andrew> Nevertheless, perhaps it would be more aesthetically pleasing to have Andrew> pseudo-code here that would work if the compiler did not inline loops?
Andrew> The present code in BlockContext is:
whileTrue: aBlock "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is true."
^ [self value] whileTrue: [aBlock value]
Your change makes sense if the compiler did not recognize this as a special case, although it would suffer from recursion trouble if there was no tail-recursion optimization (which there isn't, if I recall from the last time I asked about this same thing).
It would appear that the assumption of inlining would benefit both sets of code, and would suffer the same tail-recursion problem in both cases if it did not. The difference I see is that I understand why the more traditional:
^self value ifTrue: [aBlock value. self whileTrue: aBlock]
would work, but I don't understand how the existing code could EVER work. It is apparent that I am missing something. Please clarify.
Sorry. Lightbulb went off when I looked at the bytecodes for each alternative. Clearly, the status quo generates the desired result precisely because of the assumption of inlining of the bytecodes and blocks, to wit:
5 <70> self 6 <C9> send: value 7 <9C> jumpFalse: 13 8 <10> pushTemp: 0 9 <C9> send: value 10 <87> pop 11 <A3 F8> jumpTo: 5 13 <73> pushConstant: nil 14 <7C> returnTop
Perhaps the comment could be clearer?
squeak-dev@lists.squeakfoundation.org