The word LOOP is described as "Resolve the destination of all unresolved occurrences of LEAVE". (emphasis mine)
Unlike IF ... ELSE ... THEN, where the number of forward references is always one, LOOP has no constraints on the quantity of LEAVE. How to implement it then?
One approach I thought of is to always keep the number of LEAVEs on top of the stack. Each LEAVE increments this counter and puts itself under it. LOOP reads the counter from the top and resolves that many references. But it seems like a cheap trick.
How do real Forth systems implement this kind of loop? I don't need teh codez (been implementing Forth as a learning experience), just the concepts.
In SP-Forth the loop control parameters comprise the index, limit, and address after LOOP. So, no need to resolve LEAVE
at compile time, it knows the address from the loop control parameters at run-time.
Another approach is to store the control-flow stack depth on DO
, place the unresolved forward reference on the control-flow stack under all other already placed values (using the stored depth) on LEAVE
, and then resolve all the placed forward references on LOOP
.
See my high-level implementation of DO LOOP
on the basis of BEGIN UNTIL
and AHEAD THEN
(spoiler warning).