This might be useful for those coding their own Forth interpreter.
It could be called:
"How fig-Forth secretly escapes an infinite loop."
Or, alternately:
"One more almost undocumented, hidden, 'feature' of a threaded Forth
interpreter ..."
First, let me provide the background. A few of you may recall that my Forth
interpreter in C was parsing a word at a time, instead of reading a line and
parsing it into words. I was attempting to fix this. So, my QUIT resembles
this (with corrections and without various kludges):
: QUIT RESET [ BEGIN QUERY INTERPRET STATE @ 0= IF ." OK" ENDIF AGAIN ;
That's similar to fig-Forth, but without some stuff, e.g., BLK.
My QUERY just processed one word at a time. So, I was using QUERY
everywhere QUERY and WORD would normally be used. To implement
line-processing, I needed an additional loop somewhere to repeat the process
of parsing words from a line of text. Where should I locate it? What type
of loop is it? Again, I looked to fig-Forth (paraphrased):
: QUIT
( whatever )
BEGIN
( whatever )
QUERY INTERPRET
( whatever )
." OK"
( whatever )
AGAIN
;
: INTERPRET
BEGIN
-FIND
( whatever )
AGAIN
;
Ah, the additonal loop is in INTERPRET, but wait a minute ... The astute
among you will notice what I noticed. In QUIT, INTERPRET returns after
being called to print "OK". However, INTERPRET also has an infinite loop -
that BEGIN AGAIN sequence. How does INTERPRET to return to QUIT with an
infinite loop in it? Well, I searched for the answer, alot. ABORT ? No,
that would call QUIT. QUIT ? No, that wouldn't return to the location to
print "OK." R> DROP ? There doesn't seem to be any of those in the main
code ... Just an R> somewhere? I didn't see that either. Most R> usage
seemed to be in matched sequences with >R . Sigh ... TWO nested infinite
loops! And, one of them exits? Ok, what is going on here? If R> DROP was
somewhere but not in INTERPRET, then it could be in one of the words
INTERPRET uses. No! It's not there either ... Let me check x86 and CP/M
fig-Forth. OMG, the assembly does the same thing!
After searching a bit, I noticed that fig-Forth word called X that seems to
do what is needed.
fig-Forth's definition of X:
"
: X BLK @ ( END-OF-TEXT IS NULL *)
IF ( DISC ) 1 BLK +! 0 IN ! BLK @ 7 AND 0=
IF ( SCR END ) ?EXEC R> DROP ENDIF ( disc dependent )
ELSE ( TERMINAL ) R> DROP
ENDIF ; ! IMMEDIATE -->
"
See, X contains the required R> DROP needed by INTERPRET and it mentions
"TERMINAL". But, X is not used *anywhere* in the fig-Forth code. Since
it's not used, it seemed I was back to square one ... Although, the
fig-Forth description seemed to confirm it is used for that ... somehow ...
fig-Forth's description of X:
"
X
This is a psuedonym for the "null" or dictionary entry for
a name of one character of ascii null. It is the
execution procedure to terminate interpretation of a line
of text from the terminal or within a disc buffer, as both
buffers always have a null at the end.
"
What?! ...
It turns out that X is how fig-Forth escapes *ONE* of the infinite loops,
the one in INTERPRET. It's just that the explanation of what is being done
is not widespread. Fortunately, I located the following. This is how X
works:
"The other subtlety relates to how the loops are terminated. Note that the
INTERPRET loop shown above never terminates! We all know that it really
does terminate, and the mechanism is pretty kludgey. What happens is that
there is a null character at the end of every line of text in the input
stream, and at the end of every BLOCK of text from mass storage. The text
interpreter picks up this null character just like a normal word. The
dictionary contains an entry which matches this "null word". The associated
code is executed, and it plays around with the return stack in such a way
that the INTERPRET loop is exited without its ever knowing about it."
- from 1984 document by Mitch Bradley
- posted to comp.lang.forth in 1993 by Stephan Bevan
http://groups.google.com/group/comp.lang.forth/msg/c15f99be974e6687
Another copy appears to be here:
ftp://ftp.taygeta.com/pub/forth/Archive/various/interpreter.txt
HTH,
Rod Pemberton