Andrew,
On Mon, 1 Jan 2001 13:29:44 -0500 "Andrew C. Greenberg" werdna@mucow.com wrote:
It's possible that I'm just not getting it, but it would appear that the pseudo-code for #whileTrue; and #whileFalse: is incorrect. Even if I were right, it is still the height of pedantry on my part to call this a bug, since the code is never executed due to compiler inlining.
Actually, it is executed when the receiver is not a literal block. Code such as
| b x | x _ 0. b _ [(x _ x + 1) < 10]. b whileTrue: [Transcript show: x printString; cr].
will cause the method in BlockContext to be executed.
Nevertheless, perhaps it would be more aesthetically pleasing to have pseudo-code here that would work if the compiler did not inline loops?
With one exception, the current code does work. If you disable inlining of #whileTrue: by changing MessageMode>>transformWhile: to
transformWhile: encoder
^false
then
| x | x _ 0. [(x _ x + 1) < 10] whileTrue: [Transcript show: x printString; cr].
will use the code in BlockContext and will run successfully, UNLESS you recompile BlockContext>>whileTrue:, at which point you do encounter the infinite loop.
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]
But it would appear to me that this code would infinite loop for so long as these valuations do not result in a walkback. In either case the behavior appears both undefined and incorrect for most BlockContext instances and arguments. Perhaps something like the following would yield the desired result?
^ self value ifTrue: [aBlock value. self whileTrue: aBlock]
(and in the case of #whileFalse, use #ifFalse instead).
Umm... this could eat up memory in a hurry. Add this to BlockContext
whileTrueToo: aBlock
^ self value ifTrue: [aBlock value. self whileTrueToo: aBlock]
and then evaluate
| x | x _ 0. [x = 999 ifTrue: [self halt]. (x _ x + 1) < 1000] whileTrueToo: [].
and look at the stack in the debugger. It would seem to me that, absent the optimization of #whileTrue: (at least in #whileTrue: itself), some sort of tail recursion handling would be required and I don't think that would be easy.
Cheers, Bob
squeak-dev@lists.squeakfoundation.org