Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Таунсенд Проектирование и программная реализац...doc
Скачиваний:
15
Добавлен:
12.11.2019
Размер:
4.53 Mб
Скачать

Variable имя_переменной

где. имя переменной следует за словом VARIABLE. При выполне- нии этого слова в памяти резервируется область (объемом обычно в 16 бит) для хранения значения переменной с указанным именем. При обращении к переменной исполняющая процедура возвращает

115

в качестве результата адрес зарезервированной области, который затем может быть использован для считывания или записи. В Фор- те эти операции обозначаются соответственно символами @ (про- износится "разыменовать") и ! (произносится "присвоить").

Аналогично константы определяются с помощью слова CON- STANT. Их значения относятся к классу "только для считывания" и задаются в виде

значение CONSTANT имя

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

ПЕРЕДАЧА ДАННЫХ ЧЕРЕЗ СТЕК

Константы и переменные при их инициировании возвращают в качестве результата соответственно числа и адреса областей. Но куда при этом записывается результат? В языке Форт имеется стек данных (или стек параметров), через который слова пересылают друг другу данные. Сам по себе стек - довольно распространенная структура данных. Он широко используется в программных систе- мах фирмы Хьюлетт-Паккард. Данные можно "втолкнуть" в стек, а затем "вытолкнуть" из него, соблюдая определенный порядок: последним вошел, первым вышел. Например, если в стек данных Форт-системы втолкнуть числа 1, 2, 3, а затем произвести три выталкивания, то извлеченные из стека числа будут находиться в таком порядке: 3, 2, 1. Для того чтобы убедиться в этом на пра- ктике, выполните слово-команду, которое выталкивает число, на- ходящееся на вершине стека, для чисел натурального ряда. Тогда после ввода с дисплея чисел

1 2 3 ...

вы получите их обратно в следующем порядке: ... 3 2 1 ok

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

116

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

( п ==> )

где п - число, а отсутствие символа справа от стрелки означает, что вершина стека пуста (число оттуда удалено). Введенная форма записи может быть также проиллюстрирована на примере слова + , выполняющего сложение двух чисел nl и п2, которые находятся на вершине стека. Результатом является число пЗ, помещаемое на стек:

( п1 п2 ==> пЗ )

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

ИЕРАРХИЧЕСКАЯ ДЕКОМПОЗИЦИЯ И РАЗБИЕНИЕ НА МОДУЛИ

Необходимость помнить последовательность состояний стека представляется малопривлекательной для программиста. С одной стороны, Форт позволяет.увидеть, что происходит в программе на уровне ее ассемблерной реализации, но с другой стороны, прог- раммирование не в содержательных терминах, а в трудно интер- претируемых кодах, близких к машинным, может показаться чрез- вычайно сложным. Этот недостаток Форта в значительной степени компенсируется наличием средств для определения новых слов, позволяющих освободиться от необходимости программировать в кодах путем создания высокоуровневых команд требуемой проб- лемной ориентации, и тем самым перейти к решению задачи на более высоком уровне абстракции. Однако операции низкого уров- ня хотя и неявно, но все же будут присутствовать в программах, реализующих ваш алгоритм. Языки, в которых вместо стека ис- пользуются локальные переменные, конечно, свободны от такого недостатка, но в свою очередь не позволяют программисту вносить коррективы в машинную версию программы. В Форте же, напро- тив, существует возможность опуститься на самый низкий уровень выполнения программы, для чего и предназначено слово CODE. Иными словами, команды уровня реализации в языке Форт явля- ются доступными для программиста. (Локальные переменные то- же могут применяться в Форте, но здесь они не рассматриваются). Явно задавая команды, выполняющие операции над стеком, вы мо-

117

У ровень машинной реализации (ядро) системы)

У ровень управления периферийными уст- ройствами

У ровень интерпретатора

Уровень компилятора

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

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

Модульность значительно упрощает поиск ошибок в програм- мах (т.е. процесс их отладки), поскольку в этом случае программа разбивается на несколько автономных модулей, которые могут тес- тироваться параллельно. Декомпозиция программы приводит к об- разованию модулей различного уровня абстрактности, причем при движении вниз от уровня к уровню сложность модулей уменьшает- ся. Множество уровней абстракции образует иерархию. На самом нижнем уровне Форта находится его ядро - небольшой набор прог- рамм, написанных в машинном коде, с помощью которых строятся все слова более высоких уровней. Затем на основе стандартных слов, которые и определяют язык Форт, строятся слова, отража- ющие специфику конкретного приложения. Тем самым осуществ- ляется переход с нижнего уровня, где слова реализованы в машин- ном коде, на более высокий уровень. Все множество слов Форта можно разбить на несколько уровней абстракции. Характеристики слов, относящихся к каждому из них, приведены на рис. 6.1.

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

ВЫПОЛНЕНИЕ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ

Как вы видели, в Форте аргументы передаются через стек, и и "." выполняют действия над элементами стека. 16- битовое представление целого числа является стандартным для

У ровень приложений языка

Скомпилированные слова Форта, хранящиеся в словаре системы. Предназначены для программиро- вания прикладных задач пользователя

Слова, предназначенные для создания новых слов (определяющие слова), их компиляции и записи в словарь

Слова, поддерживающие процесс интерпретации программ, введенных с клавиатуры или считанных с диска

Слова, реализующие доступ к устройствам ввода-вывода:

клавиатуре и дисплею

  • дисководам

Слова, написанные в машинном коде, которые управляют выполнением основных операций виртуальной Форт-машины. Сюда входят:

  • слова периода выполнения (т.е. реализующие процедуры) для опреде- ляющих и компилирующих слов

  • внутренний (адресный) интер- претатор

Р ис. 6.1. Уровни слов Форта

реализаций Форта, ориентированных на 8-разрядный компьютер; однако в компьютере с 32-разрядным процессором область памяти для хранения числа (так называемая ячейка) занимает 32 бита. Несмотря на то что при реализации Форта всегда ориентируются на некоторый постоянный размер ячейки, сама по себе ее величина не влияет на определения базовых функций языка. Какой бы ни была величина ячейки памяти, именно она определяет количество

118

разрядов, отводимых для хранения чисел одинарной точности, и машинных адресов.

Уровень машинной реализации

! 2+ CMOVE> MOD

2- COUNT NEGATE

*/ 2/ D+ NOT

*/MOD < D< OR

+ = DEPTH OVER

+ ! > DNEGATE PICK

>R DROP R>,

/ ?DUP DEXECUTE R@

/MOD @ EXIT ROLL

0< ABS FILL ROT

0= AND I SWAP

0> C! J U<

1+ C@ MAX UM*

1- CMOVE MIN UM/MOD

XOR

Уровень управления периферийными устройствами

BLOCK KEY BUFFER SAVE-BUFFER

CR SPACE EMIT SPACES

EXPECT TYPE FLUSH UPDATE

Уровень интерпретатора

# <# FIND PAD

#> >BODY FORGET QUIT

#S >IN FORTH SIGN

#TIB ABORT FORTH-83 SPAN

BASE HERE TIB

( BLK HOLD U.

-TRAILING CONVERT LOAD WORD

DECIMAL .( DEFINITION

Уровень компилятора

+LOOP , ." :

; DO LOOP VOCABULARY

ABORT" DOES> REPEAT WHILE

ALLOT ELSE STATE [

BEGIN IF THEN [ ' ]

COMPILE IMMEDIATE UNTIL [ COMPILE ]

CONSTANT LEAVE VARIABLE ]

CREATE LITERAL

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

Форт включает в себя четыре основных арифметических опе- рации и несколько их вариаций. Операция вычитания имеет вид:

- (n1 n2 ==> пЗ)

Вычитание n2 из nl и занесение результата nЗ на стек.

Умножение и деление представляются так:

* (п1 п2 ==> nЗ)

Умножение nl на n2 и занесение результата nЗ в стек.

/ ( п2 ==> пЗ)

Деление nl на п2 и занесение результата пЗ в стек.

Если нужно получить остаток от деления, то выполняется следую- щая операция:

/MOD (n1 n2 ==> r q ) Деление nl на n2 с получением

остатка г и частного q.

Быстрое умножение или деление на 2 позволяют осуществить такие команды:

2* (n1 ==>п2)

Значением n2 является nl, умноженное на 2.

2/ (n1 ==> n2) Значением п2 является nl, деленное на 2.

Результат не округляется - последние цифры просто отбрасы- ваются.

Часто также применяются слова, которые увеличивают или уменьшают число на единицу или на два:

1+ (n1 ==>n2)

Увеличение nl на единицу.

2+ (n1 ==> n2)

Увеличение nl на два.

1- (n1 ==> n2)

Уменьшение nl на единицу.

Рис. 6.2. Слова, предусмотренные стандартом Форт-83

120

121

2- (n1 ==> n2) Уменьшение n1 на два.

Например, в результате деления 60 на 10 и уменьшения частного на единицу, т.е. выполнения слов

60 10 / 1 -

получим число 5. Поскольку в качестве чисел в Форте ис- пользуются целые со знаком, имеется слово для получения значения с противоположным знаком:

NEGATE (n1 ==> n2) Результатом является n2 = -nl.

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

где 14 - шестнадцатиричное представление десятичного числа 20. Число, записанное в шестнадцатиричной системе счисления, поме- чается предшествующим знаком доллара ($). Например, число 20 в шестнадцатиричной системе счисления будет выглядеть как $14.

МАНИПУЛИРОВАНИЕ ЭЛЕМЕНТАМИ СТЕКА

Если вы начнете составлять пограмму на Форте, то очень ско- ро почувствуете, что вам требуются слова, позволяющие произво- дить различные действия с элементами стека. Представьте, напри- мер, что при делении 60 на 11 вам понадобилось сохранить оста- ток, а не частное. Слово /MOD засылает остаток в стек вторым элементом, а брать из стека можно только верхний элемент. Для удаления с вершины стека частного и перемещения туда остатка в Форте имеется слово DROP:

MIN (n1 n2 ==> nЗ)

Значением пЗ является наименьшее из чисел nl и п2.

DROP (n1 ==> )

Удаление верхнего элемента стека.

МАХ (n1 n2 ==> nЗ)

Значением пЗ является наибольшее из чисел nl и п2.

Здесь по умолчанию принято, что числа nl и п2 имеют знак. Для получения абсолютного значения числа служит слово:

ABS (n1 ==> n2)

DUP (n1 ==> n1 n1)

Значением п2 является |nl| - абсолютное значение числа nl.

2DUP (n1 n2 ==>n1 n2 n1 n2)

Форт располагает и другими словами, выполняющими ариф- метические операции, но и перечисленных здесь вполне достаточно для понимания программ, приведенных далее в книге.

На уровне машинной реализации арифметические операции Форта выполняются над числами в двоичном представлении (с ос- нованием 2), однако имеется возможность вводить и выводить чис- ла, представленные в других системах счисления, отличных от двоичной и десятичной. Основание (или модуль) для представле- ния числа задается значением системной переменной BASE. Если ее значение равно 10 (что имеет место при инициализации Форт- системы), то арифметические операции выполняются в десятичной системе счисления. Для изменения основания на 16, т.е. перехода в шестнадцатиричную систему счисления , предусмотрено слово HEX, а для обратного перехода в десятичную систему - слово DECIMAL. Например, перевод числа 20 из десятичной системы в шестнадцатиричную записывается так:

20 HEX . 14

Удалить с вершины стека два элемента можно с помощью слова

2DROP (n1 n2 ==> )

Удаление двух верхних элементов стека.

Иногда требуется скопировать верхний элемент стека. Это позволяет сделать слово:

Создание дубля верхнего элемента стека.

Дублирование двух верхних элементов стека выполняется словом:

Создание дублей двух верхних элементов стека.

Обратите внимание, что слово 2DROP приводит именно к такому результату, а не к (nl => nl nl nl), т.е. эта команда дублирует два элемента стека,а не записывает один элемент дважды.

Иногда может потребоваться создать копию второго элемента стека и поместить его на вершину. Это можно сделать с помощью слова:

OVER (n1 n2 ==> n1 n2 n1 )

Создание копии второго элемента и помещение его на вершину стека.

122

123

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

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

SWAP (n1 n2 ==> n2 n1 )

Меняет местами два верхних элемента стека.

Теперь покажем, как с помощью введенных слов манипулиро- вания элементами стека получить доступ к остатку от деления, выполненного словом /MOD. Если полученный остаток уже нахо- дится на вершине стека, то для его снятия нужно обратиться к слову DROP, а затем переместить остаток на вершину словом SWAP, т.е. нужно выполнить такую последовательность команд: