Память Форта. Словари и контекстные словари
Теперь мы знаем, что Форт предоставляет вам большую власть над ЭВМ, чем большинство других языков. Целью данной главы и двух последующих является предоставление вам возможности еще большего контроля. Форт обеспечивает значительную гибкость там, где это возможно, за счет создания новых слов-описателей или, например, написания редактора. Но для использования всех преимуществ Форта, его мощи и максимальной гибкости вы должны иметь хорошее понимание внутреннего устройства языка. Вы должны понять, например, как Форт использует память ЭВМ, как устроен словарь и как он работает. Мы раскроем эти темы в данной главе. Вы должны также понять, как Форт интерпретирует входной поток информации, как он интерпретирует слова и как происходит исполнение слов. Это темы гл.15. Наконец, для достижения полного контроля над ЭВМ некоторые вещи должны выполняться на ассемблере. Мы обсуждаем Форт-ассемблер в гл.16.
Теперь вы уже сформировавшийся программист и можете писать сложные программы на Форте, но внутреннее устройство языка является для вас, вероятно, таинственным. Эти три главы раскроют тайну, фактически мы расскажем вам кое-что, что действительно необходимо знать, чтобы создать версию Форта. Существует несколько тем. такие как метакомпиляторы и целевые компиляторы, декомпиляторы и дисассемблеры, использование в операционных системах, связь с аппаратурой и различные пути реализации цепных программ ("шитых кодов"), которые мы не рассмотрим здесь, - это тема другой книги, Но когда вы закончите последние три главы, у вас будет все, что нужно практически для любых приложений языка.
Об использовании памяти в Форте
Мы немало написали о словаре, стеке, словах PAD, HERE, блочных буферах и других частях Форта безотносительно к их действительному положению в памяти. Хотя детальное знание распределения памяти в Форте не нужно для использования языка, полезно иметь карту памяти, чтобы сделать наглядным то, как организован Форт. Карта памяти (табл.14.1) является последовательным списком позиций в памяти и их функций.
Одни адреса показаны с их Форт-именами, в то время как другие отмечают границы областей, используемых для
Таблица 14.1. Типичная карта памяти (MMSFORTH)
Адрес Шестнадцатеричный Десятичный функция
0 0 BLOCK ; блочный буфер 1 402 1026 BLOCK ; блочный буфер 2 44Е 1102 TIB ; текстовый входной буфер Недокуметировано Различные системные величины и программы 804 2052 ' FORTH ; начало словаря: ядро программ в машинных кодах 9С4 2500 Словарь, исходные тексты не поставляются 2008 8200 ' HEX : Словарь, исходные тексты поставляются 1А38 19000 Словарь, Скомпилированные программы пользователя Разное HERE, DP @; верх словаря: место для приема данных от WORD Разное PAD ; временный буфер Свободная память (переменного размера) Разное SP@ или 'S: верх стека параметров 79E0 31200 S0 @ или S0: начало стека параметров Разное Верх стека возвратов Разное Начало стека возвратов Разное Начало дополнительного блочного буфера 7D00 32000 Конец дополнительного блочного буфера
Адреса памяти неточны, правильные значения смотрите в вашем руководстве по программированию.
других целей. Таблица 14.1 представляет собой карту распределения для конкретной реализации MMSFORTH; карта вашей системы будет другой. Она может отличаться только специфическими адресами или может быть фундаментально другой, но описание, использующее MMSFORTH в качестве примера, поможет вам понять функциональные элементы почти любого Форта.
Если карта памяти не поставлена вместе с документацией вашей версии Форта, вы можете подготовить ее сами на примере таблицы 14.1. Начните с пометки первой и последней ячеек памяти вашей ЭВМ вверху и внизу листа бумаги и, заполнив столько позиций, сколько вы сможете, используйте слова Форта, как в нашей модели, или их эквиваленты из вашего Форта. Вы можете выполнить некоторое исследование и изучить вашу документацию, и, если только вы не имеете версию Форта с очень необычной организацией (HS/FORTH, например), вы сможете все разрисовать.
Хотя карты памяти и отличаются, благодаря особенностям работы Форта должны быть и сходства.
Все версии Форта должны иметь блочные буферы, программы в машинных кодах, словарь, свободную память, а также стек параметров и стек возвратов; они составляют основу конструкции языка. Но стандарты определяют только способ поведения Форта, а не то, как это поведение реализуется. Таким образом реализации отличаются. Многозадачные и многопользовательские системы будут особенно различными, и мы не будем здесь их обсуждать. Несмотря на это, последующее обсуждение карты для MMSFORTH применимо к большинству других версий Форта, даже если конкретные адреса памяти и будут отличаться.
В MMSFORTH область младших адресов памяти содержит два блочных буфера, сразу за ними размещен текстовый входной буфер. Многие версии имеют блочные буферы в верхней части памяти. Эти адреса вы можете найти с помощью слов BLOCK и TIB. Вслед за входным буфером, но до словаря, лежит область системных величин и программ в машинных кодах, которые имеют отношение к функциям примитивов языка. Сюда относятся данные о числе и типах дисковых драйверов, значения по умолчанию и текущие значения системных переменных, таких как указатель стека возвратов, а также программы в машинных кодах, используемые всеми словами Форта. Значения переменных пользователя (такие как BASE, STATE и BLK) также запоминаются в массиве перед словарем, указания на их адреса обеспечиваются соответствующими словами. Это позволяет установить все переменные пользователя (например, при инициализации системы) простой засылкой таблицы в память.
Первым словом словаря является FORTH, которое представляет собой действительное имя контекстного словаря Форта (об этом подробнее в следующей главе). Словарь, конечно, включает в себя все слова Форта и их откомпилированные описания. Младшая часть словаря в MMSFORTH имеет предкомпилированную форму, загружается непосредственно с системного диска и не может быть легко изменена пользователем. Эта младшая часть состоит из описаний системных слов и собственных программ, что отличает MMSFORTH от других версий.
HEX - первое слово MMSFORTH, текст которого доступен для программиста. Тексты форт-описаний,начиная с HEX и далее, хранятся в виде блоков на диске и могут компилироваться по выбору или модифицироваться с целью получения версии MMSFORTH, отвечающей вашим собственным требованиям. Этот текст включает в себя расширение компилятора, ассемблер, программы управления печатающим устройствам, экранный редактор и многое другое. Когда первая часть этого "репертуара" блоков загружена, MMSFORTH становится согласованным со стандартом Форт-79. Некоторые версии Форта предоставляют текст почти всего словаря, для других это предоставляется за дополнительную плату. Некоторые используют мета компилятор для трансляции ядра словаря, а некоторые как MMSFORTH, рассматривают ядро словаря как собственность. Не важно, каков размер словаря, адрес первого доступного байта после словаря засылается в стек оператором HERE. HERE берет значение указателя словаря (переменная пользователя с именем DP в MMSFORTH и большинстве других версий, но ни в одном из стандартов она не упомянута) и заносит его в стек. Слово HERE можно описать как : HERE DP @ ;
В целях ускорения его можно описать в машинных кодах. Хотя мы часто обращаемся к HERE так, как если бы это была константа, которая засылает в стек адрес конца словаря, нужно помнить, что это в действительности слово, которое выдает значение переменной - пользователя. То есть вы не можете ее изменить, дав команду HERE !. Конечно, значение, выдаваемое HERE, изменяется по мере пополнения словаря при компиляции новых слов или в результате работы оператора FORGET, удаляющего слова из словаря. Действительно, : ALLOT DP + ! : является описанием, используемым в некоторых версиях Форта для изменения значения HERE.
Вспомним из гл.9, что память, начиная с HERE и далее, используется оператором WORD в качестве временного буфера или области для запоминания, а "плавающая" зона, отстоящая от HERE на фиксированное число байтов, является временным буфером, адрес которого сообщает PAD.
Слово PAD можно описать как : PAD HERE n + ; . где n- фиксированное число (по крайней мере 65 в большинстве версий Форта и по меньшей мере 85 в Форт-83). Как и в случае HERE, легко подумать о PAD как о константе, а не как о слове, которое вычисляет адрес. Как вы видели в предшествующих главах, PAD весьма полезен для временного запоминания данных, так как он никогда не может быть в конфликте со словарем. PAD не пригоден для длительного запоминания, потому что некоторые слова Форта используют его и из-за того, что он смещается при изменении размера словаря.
В большинстве версий Форта стек параметров размещается в области старших адресов памяти и в конце первых 64К байт (далее могут размещаться блочные буферы). Между PAD и стеком параметров - переменное число свободных ячеек памяти (сам временный буфер), это число зависит от нескольких факторов, включая размер памяти ЭВМ, от конфигурации Форта, размера словаря и числа кодов в стеке параметров. Свободная память может лежать в интервале от нескольких до многих тысяч байтов и может быть использована для системных процедур, таких как форматирование или создание копий содержимого диска. Главным образом область свободной памяти предназначена для использования словарем или стеком. Хотя словарь увеличивается от малых адресов к большим, стек параметров в действительности растет от своего начала в сторону меньших адресов. Это позволяет использовать свободную память как для словаря, так и для стека по необходимости. Вы можете понять, почему переполнение стека имеет катастрофические последствия. Переполненный стек может наложиться на PAD, HERE и на верхнюю часть словаря, разрушив его. Это может, вероятно, случиться при беззаботном описании слов, которые оставляют в стеке что-то при зацикливании. И конечно, размер словаря ограничен, так как нельзя двигать PAD дальше, чем на верх стека параметров.
Стеки
Как контролируется содержимое стека? С помощью указателя. Если мы произвольно установим начало стека по адресу 1000, мы сможем представить шесть байтов области стека как
Адрес Содержимое
995 х 996 х Указатель стека 997 2 LSB Верх стека (SP@ или 'S) 997 998 0 MSB 999 1 LSB 1000 0 MSB Начало стека (S0 или S0 @)
где каждый адрес содержит старший (MSB) или младший (LSB) байт числа. В этом случае стек содержит 1 и 2, а каждый символ "х" проставлен для неопределенного байта. Число 2 находится на верху стека, так как на адрес его младшего байта указывает указатель стека. Если мы положим в стек 3 с помощью 3 таблица измениться:
Адрес Содержимое
Указатель стека 995 3 LSB Верх стека (SP@ или 'S) 995 996 0 MSB 997 2 LSB 998 0 MSB 999 1 LSB 1000 0 MSB Начало стека (S0 или S0 @)
Два байта, представляющие число 3, занесены в ячейку с адресами 996 и 995, а указатель стека уменьшен на 2. Если вы теперь напечатаете DROP
результатом будет
Адрес Содержимое 995 3 996 0 Указатель стека 997 2 LSB Верх стека (SP@ или 'S) 997 998 0 MSB 999 1 LSB 1000 0 MSB Начало стека (S0 или S0 @)
Снова указатель стека просто увеличен на 2. Форт может стирать или не стирать 3, которая "удалена" из стека. Число 3 может остаться, так как любое новое число, положенное в стек, просто заместит его там. Стек по существу - массив с полуавтоматической укладкой и извлечением чисел. Если вы немного знакомы с тем, как работает процессор, мы можем сказать, что обычно указатель стека параметров совпадает с указателем стека процессора. Ото обсуждается подробнее в гл.16.) Большинство версий Форта имеет нестандартные слова, позволяющие вам найти адреса начала и верха стека. Наиболее часто адрес начала стека хранится в переменной пользователя, так что SO @ заносит в стек этот адрес (MMSFORTH делает это), хотя в некоторых версиях SO само засылает в стек этот адрес, т.е. @ не нужно. Адрес верхней ячейки стека засылается в стек оператором SP@ (засылка указателя стека - Stack Pointer Fetch), хотя некоторые модификации Форта используют слово 'S (MMSFORTH использует SP@). Таким образом, если стек содержит
3 9 99 тогда S0 @ 2 - @ . S0 @ 4 - @ . S0 @ 6 - @ .
отобразит на экране 3 6 99 в то время как SP@ @ . SP@ 2+ @ . SP@ 4 + @ . выдаст на экран 99 6 3
С помощью этих слов можно описать другие полезные слова. Например: : DEPTH ( nl п2, - nl n2..,nn) SP@ SO @ SWAP - 2 / ;
Мы попросим вас описать некоторые другие слова в качестве упражнений. Как вы знаете, с целью экономии времени Форт не контролирует переполнение стека, так что только внимательное программирование предотвращает разрушение словаря ниже стека. Извлечение кодов из пустого стека намного более вероятно, так как довольно легко напечатать лишнюю точку с клавиатуры или неправильно оценить число аргументов, необходимых слову Форта. В такой ситуации указатель стека имеет значение больше, чем нижний адрес стека, т.е. если SP@ выдает число большее, чем SO @. Фактически все варианты Форта проверяют, не случилось ли такое событие при переходе к пультовому режиму и при многих операциях вывода. Обычно, если зарегистрировано извлечение кода из пустого стека, выдается сообщение об ошибке, а указатель стека устанавливается в начальное положение. Но возможно и разрушение системы без сообщения об ошибке. Например, если стек пуст, следующая программа сделает это: : BOMBIT 500 0 DO DROP LOOP ;
Слово BOMBIT почти наверняка разрушит Форт, и потребуется перегрузка ЭВМ. Форт возлагает больше ответственности за ошибки на программиста. Это одна из причин, почему Форт обладает высоким быстродействием. Потребовалось бы очень много времени, чтобы контролировать переполнение стека каждый раз, когда изменяется его указатель. Хотя в MMSFORTH входной текстовый буфер размещен за блочным буфером в области младших адресов, в некоторых вариантах Форта он помещен выше стека параметров. Во всяком случае, стек возвратов, который обсуждается в гл.8, обычно находится сразу за входным буфером или стеком параметров. Вы видели, что >R, R> и R@ позволяют использовать стек возвратов для запоминания значений из стека параметров и что стек возвратов используется для запоминания индексов цикла, но это не его главная функция.
Стек возвратов используется для записи адресов так, что Форт знает, куда вернуться, когда выполнение слова завершилось. Это описано в деталях в разделе об исполнении слов Форта в гл.15. Область между стеком возвратов и верхней границей памяти может использоваться для различных целей в разных версиях. В MMSFORTH эта область может быть зарезервирована для дополнительных блочных буферов, которые расширяют число буферов, размещенных ниже словаря, но это, конечно, соответственно сокращает количество свободной памяти. Организация памяти, которую мы описывали до сих пор, является типичной для ЭВМ, которые могут непосредственно адресоваться до 64К байт. Но 16-битовые ЭВМ, так же как IBM PC, могут работать с 1М байтом памяти и более, в то время как числа одинарной длины не могут описать адрес более 65535. Существуют различные пути решения проблемы, чтобы работать с большими массивами памяти в Форте. Может быть, простейшим и наиболее общим является предоставление основной части Форта младших 64К байт (для программ редко требуется больше памяти) и использование адресов двойной длины для адресации к данным, лежащим выше. Например, MMSFORTH использует организацию памяти, которую мы описали, но имеет слова для извлечения, запоминания, пересылки, резервирования и прочего использования памяти с адресами более 64К. Очень часто в этой области памяти организуется псевдодиск. MMSFORTH использует сходную схему, но предусматривает возможность воспользоваться метакомпилятором для другого Форта в области старших сегментов памяти и работать с ним в дальнейшем как с совершенно независимым языком (это делается, когда подготовлена новая версия Форта). В тех случаях, когда программа со словарем больше, чем позволяет адресоваться 16-разрядное слово, могут использоваться оверлеи, когда части словаря замещаются с диска, по мере необходимости (за счет потери быстродействия). По крайней мере, одна версия Форта, PC/FORTH+, программно использует 32-разрядные, а не 16-битовые числа как для стека, так и для адресуемой памяти (хотя и за счет места и скорости).
Таким образом, память может адресоваться через обычные коды и, хотя карта памяти организована так же, как было описано, программа может работать со всей доступной памятью. Может быть, наиболее сложное использование памяти большей емкости реализовано в HS/FORTH, где применены различные сегменты для различных частей описаний слов, для различных контекстных словарей и для стеков, буферов и т.д. Таким образом, дополнительная память используется многими компонентами Форта, в то время как 16- разрядные числа могут использоваться так же, как в Форте, в пространстве, ограниченном 64К байтами. Различные схемы использования памяти в 16-разрядных ЭВМ является темой для другой книги. Лучший путь понять, что где лежит, - это пропечатать на терминале большой кусок памяти. Мы предлагаем вам сделать это в упражнениях следующего раздела этой главы. Даже если ваш Форт имеет оператор DUMP, вы можете найти следующее описание полезным, так как оно выдает как ASCII, так и цифровое представление байтов. : DUMP ( начальный адрес, число строк --) CR BASE @ >R HEX ( спасение BASE, выбор шестнадцатеричной системы) 16 * OVER + SWAP ( вычисление индексов цикла) DO I 0 TYPE 2 SPACES ( печать номера строки) 16 0 DO ( Начало цикла по байтам) I 4 MOD 0= IF SPACE THEN ( группируем байты по 4) I J + C@ ( получаем байт) 0 TYPE SPACE ( печать байта) LOOP ( цикл для 16 байтов) CR 7 SPACES ( новая строка) 16 0 DO ( начало цикла для символов) I 4 MOD 0= IF SPACE THEN ( группируем символы по 4) I J + C@ DUP ( извлечение байта) 31 > OVER 127 < AND ( печатный ascii-символ?) IF EMIT 2 SPACES ( если так. печатаем символ) ELSE DROP 3 SPACES ( если нет. удаляем байт) THEN ( конец ветвления) LOOP CR ( цикл для 16 байтов) 16 +LOOP ( шаг в 16 байтов на каждой строке) R> BASE ! ; ( восстановление BASE пo завершении)
Слово DUMP предполагает, что в стеке лежит начальный адрес и число 16- байтовых строк, которые вы хотите отобразить. При выводе строки из 16 байтов пропечатывается шестнадцатеричный начальный адрес, за которым следует сами байты.
В следующей строке представляются ASCII- символы для печатных байтов, отображенных в предшествующей строке. Выводимые символы во многих случаях бессмысленны, но могут помочь вам найти откомпилированный текст или имена слов Форта (если они записаны в незакодированном виде).
Вы можете захотеть пропечатать часть или весь ваш словарь с помощью печатающего устройства (что потребует много страниц). Многие вещи, которые кажутся абстрактными и труднозапоминаемыми, становятся ясными, когда у вас есть четкая запись, в которую можно заглянуть. Это может быть непрактично, если ваш Форт запоминает слова в нетипичном формате (например, различные части слов записаны в разных сегментах памяти). Если вы действительно пропечатали вашу систему, будет полезным использовать цветные фломастеры для выделения каждого класса слов. Как можно найти и идентифицировать слова, будет ясно из следующего раздела.
Упражнения
1. Переведите ЭВМ в шестнадцатеричную систему счисления и введите числа 0, 10. FF, F00 и FFFF в стек. Что вы ожидаете получить, выдав команду SP@ I DUMP? Используйте DUMP, чтобы проверить ваш ответ. 2. Дайте ответ для упражнения 1 в случае чисел двойной длины 0. 10., FF., FFFF. и FFFFFFFF.. 3. Как вы можете определить, какое самое длинное число может быть интерпретировано при вводе с пульта в вашем Форте? Куда кладет Форт слово, которое компилируется? 4. Опишите С, и , (запятая), не используя ALLOT. 5. Если свободная память в вашем Форте лежит между PAD и верхом стека параметров, опишите слово.MEM, которое выдает на дисплей величину емкости этой памяти. 6. Опишите PICK как NEWPICK. используя SP@ или 'S в зависимости от того, что приемлемо в вашей системе. 7. Опишите NEW.S используя S0. He используйте ROLL. 8. Опишите ZERO-STACK, которое заполняет стек нулями, не меняя указателя стека. Не используйте DO-LOOP, примените FILL.
Как слова Форта записаны в словаре?
Ключом к пониманию того, как работает Форт и почему он легко расширяем, является структура слов Форта и то, как они записываются в словаре. (Помните, что существует много способов сделать это и что мы описываем наиболее общий из них с целью пояснения.) Термины Форта "слово" и "словарь" действительно весьма близки к их исходному смыслу, так как (как и в русском языке) слова Форта определены через другие слова, которые, сгруппированные вместе, образуют словарь.
Аналогия на этом не кончается: слова Форта могут быть организованы в контекстные словари и одно и то же слово может даже быть использовано в нескольких разных контекстах. Давайте рассмотрим один элемент словаря. Если мы введем: : BASE? BASE @ DUP DECIMAL . BASE ! ; почти все версии Форта скомпилируют его в словарь в формате, содержащем поле имени и поле связи (в совокупности называемые заголовком), а также поле программы и поле параметров (называемые телом слова). Заголовок используется при поиске в словаре, в то время как тело управляет тем, что слово должно делать. Четыре поля могут быть представлены в виде:
Заголовок Тело (поле имени)(поле связи) (поле программы)(поле параметров)
Адресам первого байта имени, ячейки связи, программы и поля параметров слова часто присваиваются сокращения NFA, LFA, CFA и PFA. Так, если BASE? было скомпилировано, начиная с шестнадцатеричного адреса 7000, его представление в словаре может быть описано как
Заголовок Тело Поле ИМЕНИ СВЯЗИ ПРОГРАММЫ ПАРАМЕТРОВ Длина 4 байта 2 байт 2 байта (варьируется) Адрес NFA=7000 LFA=7004 CFA=7006 PFA=7008
К несчастью, терминология Форта стала неоднозначной и путаной при использовании терминов NFA, CFA, LFA и PFA. Они часто используются не только как адреса первого байта поля, но и как содержимое поле. Так как все поля, кроме поля имени, содержат адреса (например, поле связи содержит адрес или указатель, используемый при просмотре словаря), это сильно все путает. Мы используем эти термины для обозначения только адресов полей и советуем вам поступать так же. Мы будем ссылаться на содержимое поля связи, например, называя его именно так или, может быть, как адрес или указатель, лежащий в поле связи. (Некоторые считают, что следует использовать сокращения ANF, ACF, ALF и APF, чтобы избежать путаницы. Мы же чувствуем, что, введя больше терминов, можно в действительности внести еще больший разнобой.) Давайте посмотрим, что из себя представляет каждое поле и что оно делает. Поле имени содержит имя слова, оно служит для того, чтобы было можно найти слово Форта в словаре, например, позволяя Форту исполнить слово, имя которого было введено с последующим нажатием клавиши "возврат каретки".
Имя (такое как "BASE?") кодируется каким-то способом (в зависимости от версии), прежде чем быть запомненным. Мы скоро увидим подробнее, как кодируются имена. Следующая часть элемента словаря - поле связи содержит просто указатель на другое слово, уже описанное в словаре. Этот адрес используется, чтобы направить поиск на слово, описанное перед этим, обычно на его NFA. Слово, на которое указано, может лежать непосредственно перед данным словом или заметно раньше, в зависимости от структуры связи в конкретной версии. Полезность поля станет яснее, когда мы позднее в этой главе обсудим контекстные словари. Поле программы содержит указатель на программу в машинных кодах, которая исполняется при использовании слова. Эта программа в машинных кодах определяет, wrn делает слово и к какому типу оно относится. Все слова определенного типа (описания, начинающиеся с двоеточия, константы, переменные и т.д.) имеют один и тот же адрес в своем поле программы. Таким образом, константа (созданная оператором CONSTANT) имеет адрес в ее поле программы, указывающий на программу в машинных кодах, которая копирует в стек число из его поля параметров. Эта программа для каждого типа слов называется исполнительной. Адрес поля программы всех описаний, начинающихся с двоеточия, указывает на исполнительную программу, которая управляет выполнением слова в соответствии со списком адресов, хранящихся в поле параметров. Исполнение слов типа : и других слов рассмотрено подробнее в гл. 15. (Действительно использование поля программы, которое мы описали, представляет собой то, что называется косвенно цепной программой. Существуют другие возможности, но они используются нечасто.) Длина поля параметров слова варьируется значительно в соответствии с типом слова и способом его описания. Она может в диапазоне от одного байта (как в словах, описанных CCONSTANT) до многих тысяч байт (скажем, в массивах). Конкретное содержание поля параметров зависит от типа слова. Например, поле параметров константы, переменной и массива содержит последовательность байтов, или данные, в то время как строка-константа будет иметь в поле параметров счетную строку. (Адрес, выдаваемый любым словом, созданным с помощью CREATE, равен PFA этого слова.) Поле параметров слова типа двоеточие содержит адреса, обычно CFA слов, используемых в описании слова.
Если мы выделим CFA слов, используемых при описании BASE?, скобками ({...}), содержимое поля параметров BASE можно будет представить как
Поле параметров {BASE} {@} {DUP} {DECIMAL} {.} {BASE} {!} {EXIT}
В последней ячейке поля параметров любого описания типа двоеточие лежит адрес слова, названного EXIT, которое кладется туда оператором ; (точка с запятой). Слово EXIT необходимо, чтобы за вершить исполнение слова и передать управление слову, из которого произошло обращение. (Это исчерпывающе объяснено в гл.15.)
Как запоминаются имена?
Простейший способ запомнить имя слова BASE? в словаре заключается в том, чтобы записать число букв в слове, после чего занести буквы в ASCII представлении, т.е. оформить как счетную строку. Если записано имя полностью, тогда имеется возможность получить полный список слов в словаре. Это делается посредством слов WORDS, VLIST или CATALOG, в зависимости от версии. Данное преимущество компенсируется потерями в памяти и увеличением времени, необходимого для поиска слова. Форт-79 и Форт-83 специфицируют только то, что различные слова должны иметь до 31 символа и быть уникально закодированы и узнаваемы. Как это сделать, оставлено на усмотрение разработчику языка. Общим нестандартным методом является запоминание числа символов в исходном имени, за которым следуют только первые три символа имени.
В некоторых версиях пользователь может определить максимальное число запоминаемых символов, изменяя величину системной переменной с именем WIDTH, прежде чем компилировать текст программы. Опасность укорочения исходного имени до заданного числа символов заключается в том, что длинные имена с равным числом символов могут оказаться не уникальными. Таким образом, BASE? и BASE! следует переименовать на ?BASE и !BASE для того, чтобы они были различимыми. MMSFORTH использует необычную схему. Он кодирует (хэширует) слова так, чтобы вставить как можно больше информации в четыре байта поля имени. Таким образом, никакого дополнительного места в словаре не используется, так как имена укорочены, но вероятность неуникальности имени сведена к минимуму.
Это в принципе соответствует регламентации стандартов, но не буквально. Преимуществом является экономия места и сокращение времени поиска. К недостаткам относится невозможность декодирования имен слов и, как следствие, недоступность списка слов в словаре. Аналогичный метод кодирования имен вы можете применить и в вашем Форте. Так как только 5 битов первого байта поля имени необходимо для кодирования максимального числа символов (31), три остальных бита байта длины используются для других целей. В MMSFORTH (и некоторых других версиях Форта) первый бит поля имени равен 1 для слов немедленного исполнения (например, если оно исполняется даже при компиляции слова типа двоеточие подобно.( ). В Форте, где запоминается все имя, старший бит первого и последнего символов (включая байт длины) устанавливаются в единичное состояние, для того чтобы отметить начало и конец имени. (Так как все символы - имени ASCII, их старшие биты равны 0.) Эта информация может быть использована нестандартным словом TRAVERSE (см. стр.195). Другие свободные биты могут быть равны 0 или 1 в зависимости от того, откомпилировано ли слово без ошибок или допустимо ли, чтобы оно было найдено в словаре при поиске. Бит, который используется для того, чтобы слово могло быть найдено, называется бит-метка, для переключения этого бита используется нестандартное слово SMUDGE. Имеет смысл упомянуть еще раз, что, хотя структура словаря, которую мы описали, является наиболее распространенной, она не является единственно используемой. Могут применяться другие варианты для языка в целом или только для отдельных слов. Например, можно компилировать слова с более чем одним полем программы, как это сделано в слове QUAN MMSFORTH, которое использует три поля программы. Каждое CFA содержит указатель на исполняемую программу, который придает словам QUAN три различных образа поведения, когда они используются с IS, AT и сами по себе. Слово F-83 Лаксена и Перри компилирует номер блока, откуда извлечена программа, в заголовок слова, так что оператор VIEW может сообщить, в каком блоке лежит описание данного слова.
Возможны и более радикальные варианты. Функциональные элементы слов Форта (имя, ячейка связи, поля программы и параметров) могут храниться даже в различных частях или сегментах памяти, как в HSFORTH и (немного иначе) в MacFORTH.
Нахождение частей слов
Вы уже знаете наиболее часто используемые слова Форта, предназначенные для поиска адресов других слов в словаре ' (апостроф), ['] и FIND, которые находят CFA или PFA в зависимости от того, используете вы Форт-79 или Форт-83. И вы так же знаете о слове >BODY в Форт-83, которое находит PFA для данного CFA, лежащего в стеке. Слово FIND в Форт-83 имеет совершенно другой смысл по отношению к Форт-79. В стандарте 83 слово FIND предполагает наличие в стеке адреса счетной строки. Затем FIND ищет эту строку в словаре и, если находит, заносит в стек CFA и 1 или -1 на верх стека. Если слово в описании типа двоеточие помечено как слово "немедленного исполнения", в стек заносится 1, если же оно работает только в режиме исполнения - то -1. Если строка в словаре не найдена, в стек заносится адрес исходной строки, а на верх стека - 0. В Форт-83 слово FIND может использоваться не только подобно ' с EXECUTE, но решение может быть принято в зависимости от того, является ли слово оператором немедленного исполнения и найдено ли слово вообще. В действительности FIND используется главным образом для внутренней работы языка при компиляции, а не для целей программирования. Многие версии снабжены дополнительными словами для вычисления адресов различных полей, выдавая PFA или NFA в стек. Их работа пояснена ниже:
NFA "n-f-a" (PFA - NFA) LFA "l-f-a" (PFA - LFA) CFA "c-f-a" (PFA - CFA) PFA "p-f-a" (NFA - PFA)
NFA использует нестандартное слово TRAVERSE, которое просматривает поле имени произвольной длины из конца в конец (в любом направлении), находя начальный или конечный байт, это позволяет работать с именем любой длины. Хотя Форт-79 и Форт-83 категорически запрещают изменение содержимого скомпилированных слов в стандартной программе, экспериментальный стандарт Форт-83 признает полезность нахождения адресов полей слова.
Предлагаются следующие слова:
>BODY "to-body" (CFA - PFA) (стандарт Форт-83) >NAME "to-name" (CFA - NFA) (к полю имени) >LINK "to-link" (CFA - LPA) (к полю связи) B0DY> "from-body" (PFA - CFA) (от PFA) NAME? "from-name" (NFA - CFA) (от NFA) LINK> "from-link" (LFA - CFA) (от LFA) N>LINK "name-to-link" (NFA - LFA) (от имени к LPA) L>NAME "link-to-name" (LFA - NFA) (от LFA к имени)
Если эти или аналогичные слова отсутствуют в вашем Форте, вы можете сами описать их. Например, используя структуру словаря, которую мы описали, с именами длиной в четыре байта, будет довольно просто составить их описание: : >BODY ( cfa - pfa) 2 + ; или : L>NAME ( lfa - nfa) 4 - ; Мы попросим вас попытаться описать такие слова в качестве упражнения.
Упражнения
1. Предположим, что версия форта имеет поле имени длиной 4 байта, поле связи и поле программы по 2 байта. Опишите остальные предлагаемые Форт-83 слова, приведенные выше ( >NAME, >LINK и т.д.). 2. Запишите положение слово HERE, введите описание BASE?, которое мы использовали, пропечатайте эту часть словаря с помощью DUMP, для того чтобы посмотреть, можете ли вы идентифицировать его имя. поля связи, программы и параметров, а также их содержимое. Используйте ' (Форт-79) или ' >BODY (Форт-83) с BASE? и выполните команду DUMP для полученного адреса. 3. Опишите по крайней мере пять слов в форме : 1DUMMY ;, : 2DUMMY ; и т.д. и пропечатайте посредством DUMP каждый из этих элементов словаря, чтобы посмотреть, куда в предшествующем слове указывает содержимое поля связи. Указывает ли каждое поле связи на предшествующее слово или какое-либо другое? 4. Найдите адрес исполняемой программы для слов типа двоеточие. Зная этот адрес, опишите слово COLONWORDS, которое воспринимает два адреса со стека и находит CFA всех слов типа двоеточие, которые лежат между указанными адресами.
Контекстные словари
Концепция контекстных словарей расширяет буквально смысл метафоры, примененной в отношении определений слова и словаря.
Контекстный словарь не используется в смысле "ее разговорный словарь велик", это не означает просто набор слов. Пожалуй, фразы "словарь джаза", "медицинский словарь" или "инженерный словарь" ближе по смыслу, вкладываемому Форт(1). В Форте контекстный словарь - это совокупность родственных слов, которые ищутся как целое, т.е. он представляет собой секцию базового словаря. Другим подходом к этому могут быть контекстные словари - это наборы слов, описания которых в словаре связаны друг с другом. Контекстные словари Форта предоставляют вам контроль за тем, как производится поиск слов в словаре- Все программы, которые мы составили до сих пор, использовали только один контекстный словарь - словарь FORTH, начинающийся словом с именем FORTH. He удивительно, что первичный контекстный словарь имеет имя FORTH, часто поставляются два других контекстных словаря (называемые EDITOR и ASSEMBLER). Первый содержит слова, используемые для редактирования текстов программ, а второй включает слова для компиляции программ, написанных на ассемблере (см.гл.16). Когда введено одно из слов EDITOR или ASSEMBLER, слова, принадлежащие к этому контекстному словарю, просматриваются первыми вне зависимости от того, когда они описаны или когда загружен словарь. Поиск в пределах любого контекстного словаря производится сверху вниз, т.е. начиная со слов, описанных только что, в направлении слов, загруженных раньше. Когда поиск в специализированном контекстном словаре завершен, он продолжается в словаре FORTH (снова сверху вниз). FORTH является словарем по умолчанию и всегда просматривается вне зависимости от того, какой словарь или комбинация словарей просматривались первыми, С другой стороны, если исполнено слово FORTH, тогда просматривается только контекстный словарь FORTH, а слова из других словарей игнорируются.
Легко понять, что просмотр словаря не может происходить непосредственно от слова HERE до слова FORTH, скорее, он следует структуре логического дерева, где контекстный словарь FORTH
1 В русском языке трудно подобрать отличные друг от друга слова для DICTIONARY и VOCABULARY. Последнее переведено - контекстный словарь. - Прим. перев.
является стволом, а другие контекстные словари - ветвями, ведущими к стволу. Эта структура позволяет вам просмотреть или добавить любой контекстный словарь вне зависимости от того, где он размещен в словаре. Предположим,что вы определили слово, использующее мнемонику ассемблера со словом CODE (о программировании на Форт-ассемблере см.гл.16). Одним из действий CODE будет то, что контекстный словарь ASSEMBLER просматривается первым, так что мнемоника ассемблера, которая компилирует машинные коды, будет находиться в словаре прежде, чем распознаются любые другие слова с тем же именем. Это не только несколько ускоряет компиляцию программы на ассемблере, но имеет важное следствие, позволяющее словам с идентичными именами иметь разные функции в различных контекстных словарях. Какое "значение" имеет слово, когда определены несколько слов с одним и тем же именем, зависит от того, какое из них будет найдено первым; а это задается порядком, в котором просматриваются контекстные словари. Имеется несколько способов введения контекстных словарей, и фактически внутренние детали в различных реализациях могут варьироваться значительно. Все контекстные словари в конце концов связаны со словарем FORTH, но они могут быть связаны также друг с другом. Контекстные словари пользователя могут быть связаны непосредственно со стволом FORTH или образовывать цепочку веточка-ветка-ствол, согласно которой и происходит поиск. Порядок просмотра для простой структуры будет выглядеть так:
(1) Контекстный словарь -> : (2) Контекстный словарь -> : -> (4) Контекстный словарь FORTH (3) Контекстный словарь -> :
где числами (1) - (4) помечены альтернативы начальных точек просмотра словаря. Этот метод связи словарей встречается в некоторых реализациях Форта, но более сложные методы позволяют контекстным словарям образовывать цепи, как показано ниже: (1) Контекстный -->: словарь :-> (3) Контекстный --->: (2) Контекстный -->: :->(5) Контекстный словарь словарь FORTH (4) Контекстный словарь------------------> : где снова просмотр может начинаться в одной из точек, помеченных цифрами (1) - (5), но если первым просматривается контекстный словарь (1), то следующим перед FORTH будет словарь (3).
Эта иерархия возможных путей поиска является гибкой, но потенциально не однозначной. Хорошей идеей является максимальное упрощение использования словарей, что обеспечит простоту чтения и отладки вашей программы.
Контекстный словарь создается словом-описателем VOCABULARY (name) и, когда (name) исполнено, поиск будет начат именно с этого словаря. Адрес контекстного словаря, который должен просматриваться первым, хранится в переменной пользователя CONTEXT, названной так в соответствии с ее функцией (как, например, в предложении "класс в образовательном контексте означает...но в контексте спортивной квалификации смысл его...)(1). Любое число слов с идентичными именами могут быть доступны, если все они определены в разных контекстных словарях. Конечно, если одно и то же имя присутствует в одном и том же контексте словаре, использоваться сможет лишь то, которое найдено первым.
Если вы хотите добавить описание в словарь с именем (name), напишите (name) DEFINITIONS где слово DEFINITIONS имеет описание ; DEFINITIONS CONTEXT @ CURRENT ! ; и где CURRENT является еще одной переменной пользователя, которая указывает на контекстный словарь, который только что подключен к основному. Вы, вероятно, будете не так часто непосредственно пользоваться словами CONTEXT или CURRENT, в то время как VOCABULARY и DEFINITIONS являются более удобочитаемыми и обеспечивают работу с контекстными словарями. (CONTEXT и CURRENT включены в Форт-79, но удалены из базового набора слов Форт-83 предположительно из-за того, что они редко, если вообще когда-либо, используются программистами.)
Следует еще раз подчеркнуть, что последовательность, в которой слова обнаруживаются при поиске в контекстном словаре, определяется не их расположением в словаре, а лишь содержанием по лей связи. Слова контекстного словаря ASSEMBLER, например, будут связаны с другими ассемблерными словами вплоть до самого последнего (т.е. слова ASSEMBLER). Это последнее слово будет связано с последним описанным словом из контекстного словаря FORTH.
Порядок просмотра словаря
1 В оригинале не класс, a school в значениях школа и косяк рыбы.- Прим. перев.
задается при компиляции слова. Когда с помощью слова VOCABULARY создан новый контекстный словарь (пусть он имеет имя STATISTICS), в поле параметров слова STATISTICS зарезервировано место для адреса слова, описанного в контекстном словаре STATISTICS последним. Каждый раз, когда добавляется новое слово, адрес предшествующего заносится в поле связи слова, а адрес нового слова укладывается в STATISTICS для использования при описании следующих слов. Когда просмотр достигает конца контекстного словаря, начинается просмотр сверху вниз словаря (FORTH или какого-то другого), в котором был описан предшествующий.
Мы описали два способа работы с контекстными словарями (связь только с FORTH или друг с другом и с FORTH), и в обоих случаях мы предполагаем, что в словаре существует только один ПУТЬ ПОИСКА. Пути поиска - это пути от конца словаря к его началу согласно указателям в ячейках связи слов, входящих в контекстный словарь. Используя более чем один путь поиска, можно заметно сократить время компиляции исходного текста программы. Заметьте, то, что мы называем путем поиска, другие называют "нитью". Мы избегаем слова "нить" в этом контексте, чтобы не путать путь поиска с цепочкой программ в машинных кодах, которая работает при исполнении скомпилированных слов и также называется "нитью" ("thread").
MMSFORTH предоставляет пример того, как можно использовать несколько путей поиска. Мы видели, что MMSFORTH запоминает слова в словаре, используя закодированные имена, чтобы различать слова со сходными именами. Если длина хэш-кода задана (0 - 31 в MMSFORTH), он может быть использован для управления поиском в словаре. В этом случае каждое имя контекстного словаря (например, ASSEMBLER или FORTH) вместо того, чтобы иметь один указатель на слово, описанное последним, имеет 32 таких указателя, по одному на каждый путь поиска. Когда слово компилируется, его хэш-код определяет, с каким из путей просмотра контекстного словаря его связать и где будет запомнен его адрес (в качестве будущего объекта связи для последующих слов того же маршрута поиска).
Когда слово ищется, его имя снова кодируется (формируется тот же хэшкод) и определяется маршрут поиска, где оно должно быть найдено. Таким образом, только 1/32 словаря должна быть просмотрена, чтобы найти слово, что значительно ускоряет компиляцию, так как поиск - процесс времяемкий. Если слово связано с маршрутом поиска на фазе компиляции, то, конечно, оно может быть найдено позднее на том же самом пути поиска. Этот метод требует большего по размеру описания слова и так же зависит от способа хэш-кодирования, который определяет номера маршрутов, которые (в среднем) распределяются равномерно. Правильное использование большого числа маршрутов просмотра всегда ускоряет поиск в словаре, независимо от того, используются ли контекстные словари.
Вы помните, что слово FORGET служит для удаления слов из словаря. Ниже показано, как оно работает. Формат обращения FORGET (name) если (name) отсутствует в текущем словаре, будет дано сообщение об ошибке. Слово FORGET устанавливает верхнюю границу словаря (указанную словом HERE и содержащуюся в переменной пользователя DP) равной первому байту слова (name) (т.е. его NFA), эффективно удаляя все слова и контекстные словари, описанные позднее. Может показаться, что FORGET не обращает внимания на контекстные словари и просто укорачивает словарь до имени (name), но FORGET делает намного больше. Все маршруты просмотра во всех затронутых словарях должны быть поправлены FORGET так, чтобы последующий поиск начинался с самого последнего оставшегося слова в контекстном словаре, из которого были удалены слова. Очевидно, что делается много больше, чем просто изменяется значение переменной DP. В некоторых, версиях слово FORGET, прежде чем что-либо делать, проверяет адрес, хранящийся в переменной пользователя FENCE, чтобы убедиться, что FENCE содержит адрес меньше, чем слово, которое следует забыть. Переменная FENCE, которая может быть задана как HERE FENCE ! защищает все, что лежит в словаре ниже адреса, который в нее записан, от случайного стирания.
Хотя стандарты и не требуют наличия FENCE, эта переменная удобна для предотвращения потенциально катастрофических ошибок. Хотя мы описали большинство наиболее употребляемых структур словарей, могут использоваться и другие структуры. Применение контекстных словарей в Форте находится в процессе изменения (как и некоторые другие части языка). Существует несколько хороших способов определить выборочный поиск в секции словаря, каждый со своими преимуществами и недостатками. Например, Форт-83 имеет экспериментальное предложение разрешить управление порядком поиска путем декларации, а не во время компиляции. Манипулирование контекстными словарями в основном весьма просто; это делается тремя словами: VOCABULARY, DEFINITIONS и FORGET, а так же именами индивидуальных контекстных словарей. В заключение: 1. VOCABULARY (имя) создает контекстный словарь с именем (имя). 2. (имя) делает (имя) контекстным словарем (т.е. поиск начнется с него). 3. (имя) DEFINITIONS делает (имя) текущим словарем, в который добавляются новые описания. 4. FORGET (имя) удаляет (имя) и все слова, описанные после (имя), если (имя) принадлежит к текущему словарю.
Главные ограничения контекстных словарей связаны с тем, что они могут приводить к путанице (в особенности когда связаны друг с другом) и к тому, что порядок поиска не может быть изменен, если исходный текст откомпилирован. Большинство программистов старается как можно меньше использовать контекстные словари, но, как мы увидим в следующем разделе, даже с учетом перечисленных ограничений словари могут быть вполне полезными.
Упражнения
1. Ваш Форт, вероятно, имеет слово (называемое иногда VLIST, CATALOG или WORDS) для выдачи списка слов в контекстном словаре. Как вы можете просмотреть слова всех контекстных словарей в вашем Форте? Как вы думаете указанные выше операторы находят слова, которые отображают? 2. Опишите новый контекстный словарь с именем A-VOC. Опишите четыре слова в словаре A-VOC, чтобы печатать некоторые фразы, и присвойте имена с префиксом А-, последнее слово должно иметь имя A-LAST. 3.Отпечатайте список слов в A-VOC, которые вы описали.
Сделайте FORTH контекстным словарем и повторите выдачу, Что получилось? 4. Попытайтесь выполнить A-LAST при контекстном словаре FORTH. Что получилось? Сделайте контекстным A-VOC и попытайтесь исполнить A-LAST снова. 5. Сделайте A-VOC контекстным словарем, опишите другой словарь B- VOC и добавьте несколько новых описаний, завершающихся словом B- LAST. Теперь посмотрите, можете ли вы исполнить A-LAST, находясь в B-VOC. Что говорит вам это о структуре контекстных словарей в вашем Форте? 6. Опишите еще одно слово с именем A-LAST в контекстном словаре B-VOC (используя B-VOC DEFINITIONS, чтобы быть уверенным, что вы пользуетесь нужным контекстным словарем). Как вы можете воспользоваться обеими версиями A-LAST?
Использование контекстных словарей
Существует несколько причин использования различных контекстных словарей, а не только FORTH. Во-первых, вы можете описать набор слов с идентичными именами, но с различными функциями, так что они не будут мешать друг другу. Это весьма удобно при написании Форт-ассемблера, так как вы можете описать слова, управляющие программой, для ассемблера, используя те же имена, что и в Форте, даже если их функции совершенно различны, т. е. при наличии отдельного контекстного словаря ASSEMBLER слова IP, ELSE, THEN и т.д. могут без каких-либо неопределенностей сосуществовать в общем словаре, имея те же имена, что и слова FORTH. Это позволяет сделать программирование на Форт-ассемблере во многом идентичным программированию на Форте. При использовании в определенных контекстных словарях слова, имеющие одинаковые имена, могут выполнять различную работу.
Другой причиной использования контекстного словаря является ускорение компиляции. Это становится особенно важным, если ваша программа настолько велика, что вы вынуждены использовать оверлеи различных блоков для различных функций в верхней области очень большого словаря. Каждый раз, когда загружается набор блоков, вы можете сэкономить на времени компиляции, используя отдельный контекстный словарь для каждой функции.
С точки зрения приоритета поиска здесь создается эффект помещения каждой функции "в верхней части словаря". Это существенно менее важно для Форта, который при компиляции использует много маршрутов поиска. Заметим, что исполнение не ускорится, так как оно не включает в себя поисков в словаре (за исключением нахождения первого слова, чтобы начать исполнение программы).
Еще одним преимуществом нескольких контекстных словарей является то, что не все слова в конкретном словаре должны быть описаны сразу. Вы можете использовать (имя) DEFINITIONS поочередно в различных местах программы, чтобы описать порядок обхода родственных слов (объединив их в одном контекстном словаре). Это может быть удобно для последующего расширения набора команд в словаре.
Но чрезмерное увлечение контекстными словарями может привести к вредным привычкам просто потому, что добавление слов в словарь когда попало не представляется разумным. Намного лучше держать контекстный словарь в одном месте (непрерывный массив блоков), так чтобы с ним можно было работать как с единым логическим блоком. Вашу программу будет легче читать и поддерживать.
Вот пример удобного использования контекстного словаря при создании процедуры "help", которая переопределяет слова Форта в словаре с именем HELPS. Новые операторы могут отобразить краткое описание функций слов словаря Форта. Это может показаться теперь тривиальным, но представьте, что вы имели бы это, когда мы только начали изучать Форт.
Сначала создадим словарь HELPS: VOCABULARY HELPS HELPS DEFINITIONS Теперь введем несколько слов в словарь "HELPS": : DUP ." = stack (n - n n) " CR ; : DROP ." = stack (n - ) " CR ; и т.д. Когда вы кончили, опишите слово HELP, которое используется следующим образом: HELP (name) . что выдает описание, содержащееся в слове (name). Для того чтобы слово HELP было найдено в любом случае, оно должно быть описано, как слово словаря FORTH. Таким образом, его описание должно начинаться с FORTH DEFINITIONS HELP могло бы быть описано как : HELP [COMPILE] HELPS FIND EXECUTE [COMPILE] FORTH ;
Слово HELP делает HELPS контекстным словарем для того, чтобы найти ваши полезные описания. Слово FIND находит (имя) и исполняет его, а затем делает контекстным словарем FORTH. Слово [COMPILE] необходимо, если ваши контекстные словари являются словами немедленного исполнения (для дальнейшего обсуждения см. гл.15). Кроме того, пользователи Форт-83 должны использовать ' вместо FIND. Это описание опасно: в такой системе может произойти катастрофа, если HELP будет использовано с (имя), которое не было описано в контекстном словаре "HELPS". Несколько лучше описание HELP, приведенное ниже: : HELP [COMPILE] HELPS FIND ?DUP IF [ FIND HELPS ] LITERAL OVER U< ( IF ['] HELPS OVER U< ) (Форт-83) IF EXECUTE ELSE DROP . " not in HELP list." THEN ELSE ." not found." THEN [COMPILE] FORTH ;
Когда исполняется HELP (name), HELPS делается контекстным словарем, так что новые описания будут найдены раньше, чем слова FORTH с тем же именем получат шанс быть исполненным. Слово FIND выдает CFA (имя) или 0, если поиск не имел успеха. Если (name) найдено, контролируется его CFA, для того чтобы выяснить, было ли (name) описано позже. чем HELPS (функция [ FIND HELPS ] LITERAL будет прояснена в гл.15); если это так, слово из словаря HELPS исполняется, если же нет, имеется две возможности: или (name) не описано в словаре HELPS, или оно нигде не найдено, включая словарь FORTH. При реализации этих вариантов выдаются соответствующие сообщения. В конце концов FORTH делается контекстным словарем, так чтобы вы после выполнения HELP не остались в словаре HELPS. Этот пример должен показать вам, как отдельные контекстные словари могут выполнять работу просто и понятно там, где другие методы трудноприменимы.
Упражнения
1. Опишите HELP так, чтобы вы возвращались в контекстный словарь, из которого произошло обращение (а не всегда в FORTH). 2. Опишите контекстный словарь "HELPS", который печатает описание слов из блоков на диске, а не из словаря, лежащего в памяти.
Ограничьте каждое описание 32 или 64 символами (так чтобы 32 или 16 описаний помещалось в одном блоке). Каждое слово из HELPS должно использовать BLOCK для загрузки блока, где лежит нужный текст, вычислять адрес начала текста и отображать его. Для формирования слов из набора HELPS, которые вам нужны, используйте слово-описатель HELPER (сосредоточьте ваши усилия вначале на первом блоке).
Выводы
В первой части главы мы обсудили организацию памяти и словаря Форта без практических примеров применения. Вы. возможно, почувствовали, что материал, предложенный там. имел главным образом академический интерес. Но только благодаря пониманию организации памяти и структуры слов Форта вы сможете вполне контролировать работу системы. В гл.15 мы обсудим, как работает интерпретация, компиляция и осуществляется выполнение программ. Вы убедитесь, что все, что вы узнали об организации памяти и структуре словаря, весьма существенно.