[comp.lang.forth] An elegant ?DO

ccplumb@watnot.UUCP (11/20/86)

A while ago, in my second posting about "Forth control structures - a proposal"
in net.lang.forth, I made some seriously ugly suggestions for implementing
?DO.  Tom Almy (tektronix!tekgvs!toma) pointed out to me that ther is a *much*
nicer way to do it:

If you just have ?DO put the address that needs to be patched to point to past
the end of the loop in the DO-LIST, LOOP (or +LOOP) will handle this quite
nicely, along with resolving the LEAVEs.  Code for this is as follows:

: ?DO ( -- old-list-header back-branch-ptr)
	COMPILE (?DO)	( ) ( ?DO run-time part)
	DO-LIST DUP @	( 'DO-LIST old-list-header) ( save old list header)
	SWAP DUP 0!	( old-list-header 'DO-LIST) ( Clear DO-LIST)
	>LISTMARK	( old-list-header) ( put current address in DO-LIST)
	<MARK		( old-list-header back-branch-ptr) (leave address for
				LOOP to branch back to)
	; IMMEDIATE

(?DO) is defined in the posting I referred to.  The rest of the code there
should be *ignored*. (I'm kind of embarassed for writing it.)


Another point: You can check to see if all the control statements have been
closed by looking at the various linked-list headers when you close a
definition. Just define:

: CHECK-LISTS ( --)
	IF-LIST @
	ABORT" Unclosed IF - THEN needed"
	BEGIN-LIST @
	ABORT" Unclosed BEGIN - REPEAT or UNTIL needed"
	DO-LIST @
	ABORT" Unclosed DO - LOOP needed"
	;

 ...and include it in the definition of ; , DOES> , ;CODE , etc. (for any other
words you may have that wrap up a definition.  They probably all call ; to do
their work for them, so if you can change that in the source, it should fix
everything.)

P.S. If you haven't got the original postings, this probably makes no sense -
I'd be glad to mail them to you and un-confuse you.

	-Colin Plumb (ccplumb@watnot.UUCP)

Zippy says:
...I see TOILET SEATS...