Реализуется с помощью следующих слов:
BEGIN ( --> )
UNTIL (f --> )
Применяется следующим образом:
BEGIN
( слова, которые необходимо выполнять в цикле )
( условие, оставляющее на вершине стека флаг )
UNTIL
Флаг и условие - как для слова IF.
Реализуется с помощью следующих слов:
BEGIN ( --> )
WHILE ( f --> )
REPEAT ( --> )
Применяется следующим образом:
BEGIN
( условие, оставляющее на вершине стека флаг )
WHILE
( слова, которые необходимо выполнять в цикле )
REPEAT
Аналог оператора for в c++ или Delphi. Реализуется с помощью следующих слов:
DO ( n3 n2 n1 --> )
( n3 - граница прекращения цикла
n2 - начальное значение
n1 - приращение
)
LEAVE
+LOOP ( --> )
I ( --> текущее_значение )
Применяется следующим образом:
граница начало приращение DO
тело цикла, использвание I, LEAVE
+LOOP
Пример использования:
: DO_LOOP_test
"DO +LOOP test должно выполниться 4 раза" .
0
21 11 2,5 DO
I .
1 +
+LOOP
"Выполнено " . . "раз" .
"DO_LOOP test done" .
" " .
;
DO_LOOP_test
Результат выполнения:
DO +LOOP test должно выполниться 4 раза
11
13,5
16
18,5
Выполнено
4
раз
DO_LOOP test done
Execute Ok!
Здесь 11 - начало, 2,5 - приращение, 21 - граница. Слово DO берет эти значения из стека, сохраняет их в стеке возврата. Затем выполняется тело цикла. Можно с помощью слова I занести текущее значение в стек. Слово +LOOP увеличивает текущее значение на величину приращения. Если Текущее значение перешагнет через границу или будет равно ему, цикл прекращается и управление передается следующему после +LOOP слову. Если нет - управление передается следующему за DO слову.
Такая организация позволяет осуществлять работу с указателями, например:
10 0 1 DO I . +LOOP
а также цикл в обратном направлении.
Слово LEAVE передает управление на слово, следующее за +LOOP, внутри которого оно находится.
Обращаю внимание, что DO - I - +LOOP - конструкция, отличающаяся от соответствующей конструкции стандартного Форта. В этой конструкции приаращение задается перед словом DO, а не перед словом +LOOP, как в стандарте. Также отличие в том, что нет слова LOOP, определенного в стандарте, позволяющего задать приращение +1.
Более сложный пример демонстрирует действие слова LEAVE:
"system.sf" REQUIRE
: DO_LOOP_LEAVE_test
"DO LEAVE +LOOP test должно выполниться 3 раза" .
0
30 11 2,5 DO
I .
1 +
I 15 > IF ( если текущее значение больше 15, то выходим, это число произвольное условие для демонстрации )
LEAVE
ELSE
NOP
ENDIF
+LOOP
"Выполнено " . . "раз" .
"DO_LOOP test done" .
" " .
;
Еще пример использования циклов - расчет факториала:
"system.sf" REQUIRE
: FACT
DUP 2
< IF
DROP 1
ELSE
DUP
BEGIN
1 -
SWAP OVER
* SWAP
DUP 1
= UNTIL
DROP
ENDIF
;
: BEGIN_UNTIL_TEST
"BEGIN UNTIL test" .
"factorial of " . 1 DUP . FACT .
"factorial of " . 2 DUP "factorial of " . . FACT .
"factorial of " . 3 DUP . FACT .
"factorial of " . 20 DUP . FACT .
"BEGIN UNTIL test done" .
" " .
;
BEGIN_UNTIL_TEST
Вот уже на этом примере хорошо виден один из серьезных недостатков Форта: По тексту программы крайне сложно представить значения, находящиеся в стеке, их количество и назначение, что какое значение в стеке означает. Данный недостаток вынуждает очень тщательно комментировать программу с указанием значений в стеке. Далее идет пример, взятый из книги.
: NOD ( A,B --> C:НАИБОЛЬШИЙ ОБЩИЙ ДЕЛИТЕЛЬ)
2DUP IF < SWAP THEN ( ТЕПЕРЬ A>=B )
BEGIN DUP ( A,B,B )
WHILE ( ПОКА B НЕ НОЛЬ )
2DUP MOD ( A,B,C:ОСТАТОК )
ROT ( B,C,A )
DROP ( A',B' A'=B,B'=C )
REPEAT DROP ( НОД )
;
10 NOD .
200 NOD .
Вышеприведенные слова определены в модуле "system.sf" с помощью системных слов более глубокого уровня: BRANCH, ?BRANCH, EXIT, _DO, _+LOOP, I, LEAVE, >MARK, >RESOLVE, <MARK, <RESOLVE. С помощью этих слов можно определить более изощренные структуры для циклов. За подробностями обращайтесь к литературе.