Язык Форт и его реализации



         

Стек возвратови реализация структур управления - часть 6


: BEGIN ( ---> A,2 ) <MARK 2 ; IMMEDIATE : UNTIL ( A1,2 ---> ) 2 ?PAIRS COMPILE ?BRANCH <RESOLVE ; IMMEDIATE : WHILE ( A1,2 ---> A1,A2,3 ) 2 ?PAIRS COMPILE ?BRANCH >MARK 3 ; IMMEDIATE : REPEAT ( A1,A2,3 ---> ) 3 ?PAIRS COMPILE BRANCH SWAP <RESOLVE >RESOLVE ; IMMEDIATE

Очевидно, что реализованные таким образом стандартные структуры управления могут произвольно глубоко вкладываться друг в друга; несоответствие скобочных структур будет немедленно замечено, и программист получит сообщение об ошибке.

Рис. 2.6. Компиляция циклов

Циклы со счетчиком (рис. 2.6) реализуются аналогичным образом через вспомогательные слова (DO), (LOOP) и (+LOOP), компилируемые в шитый код вместе с адресом перехода:

: DO ( ---> A1,A2,4 ) COMPILE (DO) >MARK <MARK 4 ; IMMEDIATE : LOOP ( A1,A2,4 ---> ) 4 ?PAIRS COMPILE (LOOP) <RESOLVE >RESOLVE ; IMMEDIATE : +LOOP ( A1,A2,4 ---> ) 4 ?PAIRS COMPILE (+LOOP) <RESOLVE >RESOLVE ; IMMEDIATE

Слово (DO), с которого начинается исполнение скомпилированного цикла со счетчиком, переносит на стек возвратов следующий за ним адрес конца цикла (он нужен для немедленного выхода из цикла по слову LEAVE) и параметры данного цикла — начальное и граничное значения счетчика, снимая их с вершины стека данных. Эти значения находятся на вершине стека возвратов в течение всего времени исполнения тела цикла.

Слово (LOOP), завершающее скомпилированный цикл, продвигает текущее значение счетчика и в случае повторения цикла переводит указатель интерпретации на начало тела по скомпилированному вслед за ним адресу перехода, а при завершении цикла сбрасывает стек возвратов в исходное состояние.

Аналогично работает и слово (+LOOP), которое дополнительно снимает со стека данных значение шага цикла. Разумеется, реализация этих слов должна соответствовать принятому способу задания переходов в шитом коде. Для прямых адресов перехода соответствующие определения можно задать так:

: (DO) ( A2:ГРАНИЧНОЕ,A1:НАЧАЛЬНОЕ ---> ) R> ( A2,A1,R:ВОЗВРАТ) DUP @ >R ( ДЛЯ LEAVE) ROT >R ( ГРАНИЧНОЕ) SWAP >R ( НАЧАЛЬНОЕ) 2+ >R ( ОБОЙТИ АДРЕС В ШИТОМ КОДЕ) ) : (LOOP) ( ---> ) R> R> R@ ( R:ВОЗВРАТ,I:ТЕКУЩЕЕ,A2:ГРАНИЧНОЕ) - 0 1.


Содержание  Назад  Вперед