ФЛАГ СОСТОЯНИЯ
Введем последний термин, имеющий отношение к процессу компиляции, - состояние. В большинстве Форт-систем есть переменная с именем STATE (СОСТОЯНИЕ), в которой содержится «истина», если вы работаете в режиме компиляции, и «ложь», если вы работаете в режиме интерпретации. Покажем способ вывода значения переменной STATE: : .СОСТОЯНИЕ STATE ? ; IMMEDIATE
Введите: .СОСТОЯНИЕ 0 ok
В момент вызова .СОСТОЯНИЕ Форт-система находилась в режиме интерпретации (то, что .СОСТОЯНИЕ является словом немедленного исполнения, не играет роли. Интерпретатор не проверяет бит немедленного исполнения).
Теперь вызовите слово .СОСТОЯНИЕ из нового определения: : ТЕСТ .СОСТОЯНИЕ ; -1 ok
На сей раз значение STATE равно «истине», поскольку .СОСТОЯНИЕ было инициировано компилятором.
В каких случаях возникает необходимость знать состояние? Всегда, когда вы хотите создать слово, которое должно «делать вид», что его поведение одинаково как внутри определения, так и вне его, а на самом деле оно проявляет себя по-разному. В качестве примера можно привести слово ASCII. При обычном использовании это слово появляется внутри определения через двоеточие: : ТЕСТ ( -- ascii-a) ASCII A ;
При исполнении слова ТЕСТ в вершину стека вносится число 65. ASCII осуществляет преобразование во время компиляции, Оно должно быть компилирующим словом: выбирать из входного потока символ, компилировать его как литерал, чтобы последний мог быть занесен в стек во время выполнения слова ТЕСТ. Вы можете создать компилирующий вариант слова ASCII следующим образом:: ASCII ( -- с ) \ Компиляция: с ( -- ) BL WORD 1+ С@ [COMPILE] LITERAL ; IMMEDIATE
(Примечание. Стековый комментарий в первой строке определяет поведение слова во время выполнения - это синтаксис использования слова. Комментарий во второй строке показывает, что должно произойти во время компиляции, в частности должно быть выполнено считывание символа из входного потока и ничего не оставлено в стеке.)
В приведенном выше определении слово WORD выбирает из входного потока текст, ограниченный пробелом, и вносит в вершину стека адрес участка памяти, где будет храниться строка со счетчиком.
Мы считаем, что такой текст содержит только один символ, поэтому пропускаем счетчик байтов посредством 1+ и выбираем значение с помощью С@ . Затем инициируем слово LITERAL, компилирующее код периода выполнения для литерала, за которым следует само значение. Это все, что нам требуется.
Попытаемся заставить ASCII выполняться вне определения. Например, выражение ASCII A
внесет в вершину стека значение 65 (что может оказаться полезным при составлении таблиц и т. д.). Далее «попросим» ASCII выполнить что-нибудь такое, что оно еще не делало. Создадим следующий вариант определения: : ASCII ( -- с) BL WORD 1+ C@ ;
Для того чтобы одно и то же слово ASCII могло выполняться в обоих вариантах, оно должно реагировать на состояние: ASCII ( -- c) \ КОМПИЛЯЦИЯ: c ( -- ) \ Интерпретация: с ( -- с) BL WORD 1+ С@ STATE @ IF [COMPILE] LITERAL THEN ; IMMEDIATE
Такое слово называется зависимым от состояния. На первый взгляд зависимость от состояния кажется свойством разумным и даже желательным, особенно для слова ASCII, которое используется только при компиляции. Однако когда программист пытается повторно применять зависимые слова в другом определении и хочет, чтобы они выполнялись обычным образом, возникают трудности. Приведем пример использования компилирующего слова, зависимого от состояния, в определении другого компилирующего слова. По мере того как растет глубина вложенности слова, зависимого от состояния, программисту приходится затрачивать все больше усилий на то, чтобы держать под контролем, что и где должно выполняться.
Применение простых слов безопаснее, чем зависимых от состояния, так как их поведение предсказуемо. В некоторых ранее созданных системах слово ." зависело от состояния. С введением Стандарта-83 оно было разделено на два отдельных слова, управляющих использованием во время компиляции (.") и в период выполнения во время интерпретации блоков при их загрузке (.().
Слово ' постигла участь описанных выше слов и теперь это простое слово.Его функции внутри определения аналогичны функциям, выполняемым во время интерпретации: оно выявляет определение, имя которого находится во входном потоке во время исполнения. Вариант апострофа, функционирующего как компилирующее слово, называется ['].
Некоторые разработчики Форта считают, что зависимость от состояния не имеет права на существование. Применительно к ASCII возможны два решения: 1) разрешить его использование только внутри определения и, если возникает необходимость, создать слово с другими функциями, скажем ascii (на нижнем регистре), для режима интерпретации; 2) сделать его пригодным только для интерпретации: : ТЕСТ [ ASCII A ] LITERAL ;
Можно договориться и ввести другое слово: : [ASCII] ASCII [COMPILE] LITERAL ; IMMEDIATE
которое рекомендуется применять следующим образом: : ТЕСТ [ASCII] A ;