When having a definition with
... aaa IF bbb THEN ccc ...
inside, and it's decompiled, something like the following will show up:
... aaa, JOF addr, bbb, ccc, ...
IF has turned into
JOF (jump on false)
followed by a (relative) address.
THEN has completely vanished,
which makes sense because the address already points to
ccc ,
most likely in the form of an offset.
The needed address however, is not yet known at the moment
IF is reached.
How did the compiler pull that of?
In fact, the compiler doesn't,
IF and
THEN have
taken care of it themselves.
: IF ( -- ) ?COMPILING \ Explanation follows
POSTPONE JOF
HERE IFADMIN COMADMIN!
0 , ; IMMEDIATE
: THEN ( -- ) ?COMPILING
HERE COMADMIN@
IFADMIN ?PAIRS
OFFSET! ; IMMEDIATE
-
?COMPILING causes an error message when not compiling.
-
IFADMIN is a constant used for recognition purposes.
-
COMADMIN! ( addr const -- ) sends admin (a packet of two numbers) to the compiler.
-
COMADMIN@ ( -- addr const ) asks back the last packet sent.
-
?PAIRS ( x y - ) gives an error message when x <> y.
-
OFFSET! ( addr1 addr2 -- ) stores addr1 as an offset in addr2.
All non-standard names in this article are made up.
They're only used to clarify what happens.
In any particular Forth these names and details will differ.
However, the global way of working will match the above description.
BEGIN and
UNTIL should not pose a problem any more.
: BEGIN ( -- )
HERE BEGINADMIN COMADMIN! ; IMMEDIATE