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