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

       

Целевая компиляция и модель форт-системы


Решая задачу на языке Форт, программист расширяет исходный набор слов-команд форт-системы, добавляя к нему новые определения. Его конечной целью является определение некоторого «главного» слова, исполнение которого и решает поставленную задачу. Главное слово можно запустить на счет через текстовый интерпретатор форт-системы, если ввести имя слова в качестве очередной форт-команды. Во время исполнения этого слова используются ранее введенные определения вспомогательных слов и (прямо или косвенно) ряд слов исходной форт-системы.

Во многих форт-системах предусмотрена возможность сохранения текущего состояния словаря во внешней памяти в качестве двоичного форт-модуля. Это позволяет при последующих обращениях к данной задаче сразу начинать счет, запуская на исполнение ее главное слово. При таком подходе естественно возникает задача минимизации используемых средств и построения конечного программного продукта, уже не зависящего от форт-системы. Такую задачу позволяет решать пакет целевой компиляции, который является ценным инструментальным средством при создании прикладного программного обеспечения на языке Форт.

Целевая компиляция позволяет создавать единый независимый рабочий модуль исходя из комплекса взаимосвязанных определений на языке Форт. Составной частью этого комплекса является запись определений всех стандартных слов, которая образует модель форт-системы и над которой «надстраиваются» определения данной задачи. В тексте модели обычно выделяется запускающая часть, которая обеспечивает инициирование работы и переход к исполнению главного слова в данном комплексе определений. Если в реализации есть пакет целевой компиляции, его часто используют для раскрутки самой форт-системы исходя из некоторой ее начальной версии. В этом случае главным является приводившееся выше слово ФОРТ-СИСТЕМА, которое выполняет бесконечный цикл по вводу входного потока с терминала и его текстовой интерпретации.

Входной текст для целевой компиляции помимо собственно текста на языке Форт содержит еще ряд слов-директив, позволяющих выполнять компиляцию за один проход по тексту.
Эти директивы включают, в частности, средства предописания слов для того, чтобы некоторые слова можно было использовать раньше их определения (например, чтобы в запускающей части, с которой обычно начинается входной текст, указать имя главного слова, которое будет определено только в конце). Важной возможностью является управление построением целевой словарной статьи: некоторые или даже все статьи можно создать без заголовка, значительно сократив за счет этого размер рабочего модуля. Кроме того, язык директив обычно содержит средства для диагностики, распечатки карты создаваемого модуля, построения таблицы перекрестных ссылок, сбора и распечатки статистической информации об использовании тех или иных слов.

Пакет целевой компиляции представляет собой отдельно загружаемый пакет, написанный на языке Форт. В начале работы он резервирует область памяти для целевого адресного пространства, в которой строит двоичный код конечного программного продукта по мере обработки входного текста. После завершения целевой компиляции построенный модуль может быть выгружен во внешнюю память для дальнейшего использования в качестве независимого модуля в соответствии с заложенными в него соглашениями о связях.

В состав пакета целевой компиляции входят целевой ассемблер и целевой компилятор. Целевой ассемблер отличается от обычного встроенного ассемблера форт-системы только тем, что строит машинный код не в инструментальном адресном пространстве от текущей вершины словаря, которая задается словом HERE (здесь), а в целевом. Указатель в целевом адресном пространстве обычно обозначается словом THERE (там) внутри самого пакета, который пользуется обоими этими указателями. Для того чтобы получить целевой ассемблер из исходного инструментального, как правило, достаточно оттранслировать его в контексте других определений компилирующих слов (, , C, , ALLOT и т.д.), которые выполняют те же действия, но в целевом адресном пространстве, а не в инструментальном.

Задача целевого компилятора состоит в построении высокоуровневого шитого кода в целевом адресном пространстве, причем все ссылки на статьи, включая и ссылки на все стандартные форт-слова, должны также относиться к этому пространству.


Для решения этой задачи обычно поступают следующим образом. В списке слов целевой компиляции переопределяют все стандартные определяющие слова (:, CONSTANT, VARIABLE, CODE и т.д.) таким образом, чтобы они строили две статьи: одну стандартным образом, но в целевом адресном пространстве, а другую — специальным образом — в инструментальном. Исполнение инструментальной статьи компилирует ссылку, соответствующую целевой статье данного слова, как очередной элемент шитого кода на вершину целевого словаря. Обрабатывая стандартным текстовым интерпретатором высокоуровневое определение в контексте таких инструментальных определений, мы получаем в целевом пространстве соответствующий шитый код. Аналогичным образом должны быть переопределены и все слова с признаком немедленного исполнения, реализующие структуры управления и выполняющие какую-либо компиляцию во время обработки определений (IF, THEN, ; и т.д.). Эти слова в отличие от их стандартных прототипов должны компилировать статьи и переходы для целевого адресного пространства, а не инструментального. Совокупность перечисленных определений и образует целевой компилятор.

При построении конечного программного продукта путем целевой компиляции возможно существенное уменьшение его размера. Кроме уже упоминавшегося исключения из словарных статей ненужных заголовков целевая компиляция позволяет вести учет всех используемых данной задачей слов и автоматически собрать для нее специальное ядро поддержки, состоящее только из тех слов, которые в ней действительно используются. При этом возможна еще большая оптимизация за счет непосредственной подстановки определений в место их вызова для тех слов, которые оказались использованными только один раз. Некоторые пакеты целевой компиляции дают возможность довести такую подстановку до уровня машинного кода, при этом высокоуровневые определения рассматриваются как своеобразные макроопределения. После выполнения такой макрогенерации результирующий машинный код уже не требует адресного интерпретатора и представляет собой линейную последовательность непосредственно исполняемых машинных команд.



Именно этот прием был применен, например, при создании известного пакета машинной графики ГРАФОРТ для персонального компьютера фирмы ИБМ и компьютеров фирмы «Эппл» (Apple, США). Сравнительно большой объем получившегося машинного кода компенсировался чрезвычайно высоким быстродействием, недостижимым для традиционных языков программирования. В то же время совершенно очевидно, что разработать и отладить программу такого объема на языке ассемблера вручную практически невозможно.

Описанный подход к целевой компиляции применим и в том случае, когда целевая ЭВМ, для которой строится конечный программный продукт, отличается по своей архитектуре и системе команд от инструментальной. В этом случае изменения касаются только целевого ассемблера и определений в машинном коде, которые должны отвечать системе команд целевой ЭВМ. Такое использование целевой компиляции в качестве инструментального кросс-средства все чаще имеет место при создании программного обеспечения встроенных микропроцессоров и специализированных микропроцессорных устройств на их основе.


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