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

Интерпретация входного потока


Собственно работа форт-системы заключается в распознавании и исполнении слов-команд, которые программист вводит с терминала. Ввод осуществляется построчно: набрав нужный текст, программист нажимает специальную управляющую клавишу, сообщая тем самым о завершении ввода. Форт-система размещает введенный текст в специальном буфере для ввода с терминала, который располагается в адресном пространстве оперативной памяти. Адрес начала этого буфера дает стандартное слово TIB (сокращение от TEXT INPUT BUFFER — буфер для ввода текста), его длина хранится в стандартной переменной #TIB. Данный буфер представляет собой входной поток, из которого слово WORD выбирает слова. По исчерпании входного потока форт-система вводит в этот буфер новый текст, получаемый от программиста. При возникновении какой-либо ошибочной ситуации форт-система прекращает дальнейшую интерпретацию текущего содержимого этого буфера и, выдав соответствующее сообщение программисту, заполняет буфер новым текстом, который после этого вводит программист.

Альтернативой вводу текста с терминала является ввод из внешней памяти форт-системы. Переключением входного потока на внешнюю память и обратно на терминал управляет стандартная переменная BLK (сокращение от BLOCK — блок), значение которой проверяется каждый раз в слове WORD. Если это нуль, то в качестве входного потока служит буфер TIB, в противном случае это значение рассматривается как номер блока внешней памяти, который используется как входной поток (этот блок переносится в оперативную память словом BLOCK). Текущая позиция во входном потоке хранится в стандартной переменной >IN (от IN — вход) и в случае ввода с терминала изменяется в пределах от 0 до значения #TIB, а при вводе из внешней памяти — в диапазоне от 0 до 1024.

Обычно конец входного потока в оперативной памяти отмечается нулевым кодом (именно для этого в буферном пуле после памяти для данных блока резервируется еще одна ячейка). Слово WORD, «натыкаясь» на нулевой код, возвращает в качестве результата пустую строку с нулевым значением счетчика литер, при этом в список FORTH включается словарная статья для такого «пустого» слова.
Оно имеет признак немедленного исполнения и поэтому всегда исполняется назависимо от текущего состояния текстового интерпретатора. Его исполнение состоит в прекращении интерпретации данного входного потока и тем самым позволяет избежать дополнительных проверок на исчерпание. Обычно в реализациях языка Форт определяется слово INTERPRET (интерпретировать), выполняющее интерпретацию текущего входного потока. Оно представляет собой бесконечный цикл по вводу и исполнению (или компиляции) слов:

: INTERPRET ( ---> ) BEGIN BL WORD FIND ?DUP IF ( ПРОВЕРИТЬ ПРИЗНАК IMMEDIATE) 1+ IF EXECUTE ELSE STATE @ IF , ELSE EXECUTE THEN THEN ELSE ( МОЖЕТ БЫТЬ ЭТО ЧИСЛО?) NUMBER DPL @ 1+ IF [COMPILE] 2LITERAL ELSE DROP [COMPILE] LITERAL THEN THEN AGAIN ;

В приведенном примере конструкция BEGIN-AGAIN определяет бесконечный цикл.

Слово AGAIN выполняет безусловный переход на начало цикла.

В случае если очередное введенное слово не найдено в словаре, исполняется слово NUMBER, которое пытается воспринять его как запись числа в соответствии с текущим основанием системы счисления — значением переменной BASE. Если это удалось, то слово NUMBER возвращает значение числа как значение двойной длины и дополнительно в переменной DPL сообщает позицию десятичной точки в нем (-1, если точки в записи числа не было). В противном случае возникает ошибочная ситуация «Слово не найдено», и интерпретация прекращается. Если же введенное слово оказалось числом, то в зависимости от наличия в нем точки оно рассматривается как число двойной или одинарной точности. Таким образом, пустое слово-ограничитель входного потока-прекращает исполнение слова INTERPRET и возобновляет исполнение слова, его вызвавшего:

: X ( ---> ) R> DROP ; IMMEDIATE

Здесь X обозначает пустое слово.

Таким образом, работу форт-системы можно задать таким бесконечным циклом:

: ФОРТ-СИСТЕМА ( ---> ) BEGIN CR ." >" ( ПРИГЛАШЕНИЕ К ВВОДУ) TIB 80 EXPECT ( ВВЕСТИ ТЕКСТ С ТЕРМИНАЛА) SPAN @ #TIB ! ( УСТАНОВИТЬ ЕГО ДЛИНУ) 0 TIB #TIB @ + C! ( УСТАНОВИТЬ ОГРАНИЧИТЕЛЬ) 0 >IN ! 0 BLK ! ( УСТАНОВИТЬ ВХОДНОЙ ПОТОК) INTERPRET ( ИНТЕРПРЕТИРОВАТЬ ВВЕДЕННЫЙ ТЕКСТ) STATE @ 0= IF ." OK" THEN ( ПОДТВЕРЖДЕНИЕ) AGAIN ;



Для переключения входного потока на внешнюю память стандарт предусматривает слово LOAD (загрузить) :

: LOAD ( N:НОМЕР ---> ИНТЕРПРЕТИРОВАТЬ ЭКРАН) >IN @ >R BLK @ >R ( СОХРАНИТЬ ТЕКУЩИЙ) BLK ! 0 >IN ! ( УСТАНОВИТЬ НОВЫЙ) INTERPRET ( ПРОИНТЕРПРЕТИРОВАТЬ ЕГО) R> BLK ! R> >IN ! ; ( ВЕРНУТЬСЯ К ПРЕЖНЕМУ)

Параметром слова LOAD является номер экрана (блока) для интерпретации. Очевидно, что приведенное нами выше определение допускает рекурсивное использование слова LOAD внутри экранов во внешней памяти.

Некоторые реализации предусматривают слово THRU (сквозь) для последовательной интерпретации диапазона экранов:

: THRU ( N1,N2 ---> ИНТЕРПРЕТИРОВАТЬ ЭКРАНЫ) ( ОТ N1 ДО N2 ВКЛЮЧИТЕЛЬНО) 1+ SWAP DO I LOAD LOOP ;

Для продолжения интерпретации следующего экрана часто используется слово -->, логически сцепляющее следующей экран с данным:

: --> ( ---> ) BLK @ 0= ABORT" НЕДОПУСТИМОЕ ИСПОЛЬЗОВАНИЕ -->" 0 >IN ! BLK @ 1+ BLK ! ; IMMEDIATE

В этом случае интерпретации сцепленных экранов нужно «загрузить» словом LOAD только первый из этих экранов.


Содержание раздела