["BUG"][FIX?]Incorrect Pseudo-Code for #whileTrue:/#whileFalse:?

Bob Arning arning at charm.net
Mon Jan 1 20:25:40 UTC 2001


Andrew,

On Mon, 1 Jan 2001 13:29:44 -0500 "Andrew C. Greenberg" <werdna at 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





More information about the Squeak-dev mailing list