Идея в следующем:
Вводим переменную:
0 USER EXIT-POINTER
Определяем слово, которое будет компилироваться в начало каждого определения через двоеточие:
: ( R> EXIT-POINTER @ >R RP@ EXIT-POINTER ! >R ;
Это слово сохраняет предыдущий указатель стека возвратов и запоминает новый, который на входе в определение.
Определяем слово, которое будет восстанавливать состояние стека возвратов:
: (EXIT) ( — ) EXIT-POINTER @ RP! R> EXIT-POINTER ! ;
Теперь вводим определяющие слова, которые будут создавать определения через двоеточие.
В SimplyForth они выглядят так:
: : ( — )
?EXEC HEADER !CSP 0 COLON-ID >CS POSTPONE ( ] ; IMMEDIATE
: :NONAME ( — cfa )
?EXEC !CSP HERE NONAME-ID >CS POSTPONE ( ] ; IMMEDIATE
: ; ( — )
?COMP CS> DUP COLON-ID = IF 2DROP ELSE NONAME-ID ?PAIRS THEN
POSTPONE (EXIT) POSTPONE RECURSIVE POSTPONE [ ?CSP ; IMMEDIATE
В других Форт-системах определения будут другими, но тут самое главное — это POSTPONE ( и POSTPONE (EXIT).
Ну и сам EXIT:
: EXIT ( — )
?COMP POSTPONE (EXIT) ; IMMEDIATE
Все, теперь EXIT не зависит от состояния стека возвратов и ему не нуден UNLOOP.