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

Stephan Rudlof sr at evolgo.de
Mon Jan 1 20:59:52 UTC 2001


"Andrew C. Greenberg" 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.

For me it is a bug, since it wouldn't work without inlining literal blocks.

> Nevertheless, perhaps it would be more aesthetically
> pleasing to have pseudo-code here that would work if the compiler did
> not inline loops?
> 
> 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.

Agreed for the case of *not* inlining literal blocks.

> In either case
> the behavior appears both undefined and incorrect for most
> BlockContext instances and arguments.

Here I disagree. If we are relying on inlining it should work.

> 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).

This looks semantically correct for me.
The only problem here is a potential stack overflow, since every evaluation
of aBlock leads to a recursive call of #whileTrue:. Here a loop with a
condition is realized by recursion. Probably in practice we must have
compiler intelligence to avoid recursion with corresponding ST code relying
on this. As an (worse) alternative we could have a primitive here.

>From VisualWorks® NonCommercial, Release 5i.1 of January 24, 2000:
---
BlockClosure>>
whileTrue: aBlock 
	"Evaluate the argument, aBlock, as long as the value   
	of the receiver is true."

	^self value
		ifTrue:
			[aBlock value.
			[self value] whileTrue: [aBlock value]]

	"This method is inlined if both the receiver and the argument are literal
	blocks. In all other cases, the code above is run. Note that the code
	above is defined recursively. However, to avoid actually building an
	activation record each time this method is invoked recursively, we have
	used the '[...] whileTrue: [..]' form in the last line, rather than the
more
	concise 'self whileTrue: aBlock'. Using literal blocks for both the
receiver
	and the argument allows the compiler to inline #whileTrue:, which (in the
	absence of type inferencing) could not be done if we were to use
	'self whileTrue: aBlock'."
---
This variant avoids recursion if the compiler inlines literal blocks *and*
should work without inlining - though very inefficient regarding time and
memory (more inefficient than Andrew's suggestion) -, too.

I vote for the VW variant.

Greetings,

Stephan
-- 
Stephan Rudlof (sr at evolgo.de)
   "Genius doesn't work on an assembly line basis.
    You can't simply say, 'Today I will be brilliant.'"
    -- Kirk, "The Ultimate Computer", stardate 4731.3





More information about the Squeak-dev mailing list