Парадигмы программирования

Машинно ориентированное программирование


Рассматривается два подхода к машинно независимому эффективному программированию. Язык Forth - пример организации вычислений над стеком. Можно рассматривать как язык-ядро с возможностью практически неограниченного проблемно-ориентированного расширения. Язык Little - пример традиционной организации вычислений над структурированными битовыми строками. Основные конструкции аналогичны фортрановским, но с учетом современных решений, упрощающих реализацию компилятора. Оба языка допускают порождение эффективного кода "хорошо" написанных программ [[3],[32]].

Появление в 70-х годах микропроцессорных средств с малым объемом памяти и сравнительно невысоким быстродействием вызвало очевидные трудности в применении привычных языков высокого уровня. Не удивительно, что поиск подходящих средств программирования сменил приоритеты в оценке свойств языков и систем программирования. На передний план вышли машинно-ориентированные языки-оболочки, поддерживающие достижение эффективности и компактности программ при достаточном уровне абстрагирования от конкретики процессоров, сравнимом с абстрагированием в языках высокого уровня. Особо ярким явлением в эти годы стал язык Forth, сохранивший многочисленных приверженцев и в наши дни, когда пресс технических характеристик изрядно помягчал [[6]]. Little приведен как пример альтернативного подходе к решению проблемы машинно ориентированного программирования.

Наиболее убедительное применение Forth получил как средство разработки специализированных систем, создаваемых по методике раскрутки, начиная с тщательно минимизированного ядра с рядом последовательных шагов расширения в рамках единой оболочки. Сам язык устроен по такому же принципу, так что такая технология пошагового программирования впитывается при изучении идей и средств системы программирования на базе Forth-а. Кроме общеизвестных примеров про системы управления астрономическими телескопами и лазерами, следует упомянуть IBMCAD - аналог системы инженерного AutoCAD и систему автоматизации издательского дела МРАМОР.
Для последней именно на Форте была создана предельно компактная операционная система объемом около 4 килобайт. Форт был успешно применен при реализации языка PostScript, до сих пор используется при разработке видеоигр и систем начальной загрузки ОС, чувствительных к скорости срабатывания. При значительном внешнем несходстве Форт обладает концептуальным родством с языком Лисп, что побудило в 80-е годы к разработке языка ФоЛи, объединяющего достоинства обоих языков.

Программирование на Форте требует вдумчивости и аккуратности. Достижимость лаконичных форм дается ценой нестандартных индивидуальных решений, мало приспособленных к передаче программ в чужие руки. Лозунги "Программируйте все сами!" и "Не бойтесь все переписывать заново!" правильно отражают подход к программированию на Форте. Успех достигается явным максимализмом в тщательной отладке и способностью видеть задачу программирования в развитии.

Язык Форт предложен Чарльзом Маури в 1968 году. К середине 70-х Форт стал третьим по популярности после Бейсика и Паскаля, завоевавшим свои позиции при освоении микропроцессоных средств. По технике программирования Форт весьма похож на макроассемблер, только вместо системы команд над машинными словами в нем используется система операций на стеком.

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

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



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

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

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

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

Традиционно отмечаемые недостатки Форта:

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


Активный популяризатор Форта Мур отметил: "Форт не уравнитель, а усилитель!"

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

Имеются константы TRUE и FALSE, символизирующие логические значения.



Заключение в кавычки "строка" означает вариант со счетчиком и ограничитель - 0

Состояние системы программирования можно исследовать на уровне системных переменных. Различается состояние компиляции (создание кода программы) и интерпретации (непосредственное исполнение программы). Если STATE = 0, то система ведет исполнение программы.

Системная переменная BASE задает систему счисления.

Исполнение программы организовано как диалог над стеком. Каждая команда знает, что взять из стека и во что преобразовать:

DROP (X --)1) = сбросить из стека DUP (X -- X X) = скопировать вверх NIP (X1 X2 -- X2) = сбростиь предпоследний OVER (X1 X2 -- X1 X2 X1) = предпоследний наверх PICK (XN ... X0 N -- XN ... X0 XN) = выборка из середины стека ROLL (XN ... X0 N -- XN-1 ... X0 XN) = перестановка на заданную глубину ROT (X1 X2 X3 -- X2 X3 X1) = перестановка трех верхних элементов SWAP (X1 X2 -- X2 X1) = обмен местами TUCK (X1 X2 -- X2 X1 X2) = копирование под вершину DEPTH (-- N) = глубина ?DUP (X -- X X\=0) = ? истина

Кроме обычных арифметических операций имеются эффективно реализуемые:

1+ 1- 2+ 2- 2/ половина

Слово стека занимает 16 разрядов, но имеются операции над двойными словами - в 32 разряда:

2drop 2dup 2over 2rot 2swap



Есть вариант умножения чисел без потери точности - результат пишется в двойное слово:

UM* (a,b cc)

Система программирования использует при работе ряд стеков:

R - стек возвратов C - стек компиляции F - стек чисел S - стек словарей

Имеются операции, работающие с адресами и памятью:

@ (adr -- x) чтение - разыменование ! (x adr --) запись

ALLOCATE выделить память FREE освободить память RESIZE заменить размер IOR код завершения операции

ALLOT (N -- адр) резервирование памяти в словах HERE (-- А) адрес слова , компиляция со стека UNUSED (-- N) остаток памяти

Операции заполнения памяти предусматривают следующие вариции кодов росписи:

FILL char ERASE 0 BLANC пробел

Возможно пересылка блоков памяти:

CMOVE CMOVE> MOVE

Арифметические операции:

+ - * / (n1 n2 -- n3)



*/ (n1 n2 n3 -- n4) n1 * n2/n3 "рабочая лошадка", эффективно выполняющая часто встречающееся сочетание операций.

* OVER - SWAP DUP *

Пример 4.1. Программа для подсчета по формуле (x,y,z -> x**2 + y * z - x)

Новые слова можно вводить в форме:

: имя опр;:SQ DUP (-- A,B,B) * SWAP (B**2, A) DOP * (B**2, A**2) +; (B**2 + A**2)

Пример 4.2. Введение нового слова SQ для подсчета суммы квадратов (A,B -> A**2 + B**2)

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

Средства размещения слов в словарь:

IMMIDIATE (--) немедленное исполнение в любом состоянии FORGET убрать из словаря

Обозначение систем счисления:

DECIMAL HEX LITERAL

Моделирование переменных и констант:

VARIABLE имя - переменная в словарь знач имя ! - присвоить = запись в переменную имя @ (a -- x) - чтение в стек из переменной знач CONSTANT имя (X --) - создание константы по стеку имя (-- x) - конст стек знач VALUE имя (X --) - переименование

Богато представлена логика и операции сравнения:

and or xor not < = > <> :<= :>= :<> 0< 0= 0>

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

усл IF часть-то THEN усл IF часть-то ELSE часть-иначе THEN

зн-0 CASE зн-1 OF ветвь1 ENDOF --- ---

[ветвь-иначе] ENDCASE

Моделирование циклов:

кон-зн нач-зн DO тело-цикла LOOP кон-зн нач-зн DO тело-цикла шаг +LOOP ?DO - м.б. ни разу

I - текущее значение счетчика J - внешний цикл

UNLOOP сброс счетчика LEAVE выход из цикла

... BEGIN ... AGAIN бесконечный цикл ... усл WHILE ... REPEAT ... !ложь______! ... BEGIN ... усл UNTIL !ист________!

Манипулирование стеками:

n STACK s новый стек S размера N ws PUSH запись в стек S POP перенос в стек данных s POP s ST@ скопировать s ST! сброс стека

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


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

CODE ... ENDCODE

KEY ввод с клавиатуры KEY? есть ли символ? ACCERT [=EXPECT ] ввод строки PARSE адр слова в буфере и его длина

При работе со словарем, рассматриваемым как список слов, можно применять отношение порядка:

ORDER - в порядке поиска

Имеются средства работы с событиями, исключениями (0 - успех) и прерываниями:

CATCH - THROW

Можно создавать метаопределения:

CREATE DOED>

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

В отличие от языка Forth предложенный Дж.Шварцем машинно независимый машинно ориентированный язык программирования Little включает средства обработки битовых строк в привычную языковую схему языка Фортран. Сохраняется обычная система подготовки и понимания программ, меняются лишь операции по обработке данных и набор встроенных типов данных. Данные - это битовые строки произвольной длины, а операции обеспечивают манипулирование битовыми строками как на уровне отдельных подстрок и битов, так и на уровне крупных, совместно используемых блоков и структур данных. [[32]]

X = 23 .f. 1,10, a (2) = 44 /* в поле с 1 по 10-й разряд записать 44 */ .ch. 5, text = 'A' /* в 5-й символ текста записать 'A' */

Листинг 4.1. Примеры операторов присваивания в языке Little

subr START; /* Разбор оператора присваивания языка Little */ size SYM (48); call SCAN (SYM); /* Чтение первого символа */ call ASSIGN; return; end;

subr ASSIGN; /* Разбор оператора присваивания, первый символ которого уже прочитан процедурой SYM */

if TC(SYM).EQ. TC ( '.' ) go to ASS; if TC(SYM).EQ. TC (NAME) go to NAME1; ERROR;

/ASS/ call SCAN (SYM); /* левая часть*/ IF TC (SYM).ne. TC (PREF) ERROR; call SCAN (SYM);

IF TC (SYM).ne.


TC ( '.' ) ERROR; call SCAN (SYM); call SCAN (PREF); /* f, s, e, ch */ /* выделение поля из левой части */ call SCAN (SYM);

IF TC (SYM).ne. TC (NAME) ERROR; go to NAME1;

/NAME1/ call SCAN (SYM); if TC(SYM).EQ. TC ( '=' ) go to NAME2; if TC(SYM).EQ. TC ( '(' ) go to RI-PAR; ERROR;

/RI-PAR/ call SCAN (SYM); IF TC (SYM).ne. TC (EXPR) ERROR; call SCAN (SYM); IF TC (SYM).ne. TC ( ')' ) ERROR; Call SCAN (SYM); IF TC (SYM).ne. TC ( '=' ) ERROR; go to NAME2;

/NAME2/ call SCAN (SYM); IF TC (SYM).ne. TC (NAME) ERROR; return;

/NO/ end;

Листинг 4.2. Программа синтаксического анализа операторов присваивания написанная на языке Little.

Средства машинно ориентированного программирования обычно доступны в системах программирования для языков высокого уровня в виде операций или команд, образующих линейные участки. Язык Little не получил особого распространения, хотя был успешно применен для эффективной реализации языка сверх высокого уровня Setl. Принятые в нем решения представляют интерес как эксперимент по разработке многоуровневых систем программирования.

  1)

  Круглыми скобками выделена схема изменения стека

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