Д.Н.Кузнецов, А.E.Недоря
Термин "турбо-компилятор", или просто "турбина", прочно
вошел в лексикон программистов. Своим происхождением он обязан
первой широко доступной системе подобного класса TURBO PASCAL
фирмы Borland. Турбо-компилятор представляет собой
интегрированную систему, поддерживающую основной цикл
разработки программного обеспечения (ПО) -
редактирование-компиляция-запуск. Он включает в себя редактор
текста программ, быстрый компилятор, способный компилировать
программы по схеме "память -> память", и подсистему
отладочного запуска скомпилированных программ. Объединение
трех этих функций в рамках одной системы позволяет получить
новые возможности:
1) Переход от редактирования к компиляции сводится к
нажатию нескольких клавиш в редакторе. После завершения
компиляции система переходит опять в состояние редактирования.
Нет необходимости запускать редактор и компилятор средствами
ОС, не надо выходить из редактора для запуска компилятора и
снова входить в редактор для продолжения редактирования.
Запуск скомпилированной программы также происходит без выхода
из редактора.
2) По ошибке при компиляции редактор позиционируется в
место ошибки, исключая необходимость запоминать ошибки,
выданные компилятором, и искать их позиции в тексте.
3) Турбо-компилятор может существенно сократить обращение
к внешним устройствам, и соответственно, увеличить скорость
компиляции. Нет необходимости читать файл исходного текста (он
в памяти редактора), нет необходимости записывать файл
листинга. Более того, турбо-компилятор может не писать файл
кода и файлы с информацией для отладчика при каждой
компиляции, а записывать их по требованию пользователя.
Особенно важна эта особенность турбо-компилятора для модульных
языков. Так, Модула-2 компилятор существенную часть времени
своей работы занимается чтением симфайлов [1].
Турбо-компилятор может прочесть симфайлы и преобразовать их во
внутреннее представление при первой компиляции, а в дальнейшем
использовать их уже во внутреннем представлении.
Турбо-компилятор может предоставлять также разнообразные
дополнительные возможности: символьную отладку с выходом в
исходный текст при ошибках исполнения, поддержку использования
и создание библиотек и т.д..
Естественно, турбо-компилятор требует значительно больших
ресурсов (например, оперативной памяти), чем при традиционном
подходе, но этот недостаток окупается увеличением скорости и
удобства работы. Очевидна необходимость турбо-компилятора для
автоматизированного рабочего места профессионального
программиста, что соответствует подходу, принятому для
семейства процессоров КРОНОС [2]. Перед разработкой
турбо-компилятора с языка Модула-2 мы рассматривали два пути:
- разработка с нуля;
- интеграция уже существующих компонент ОС Excelsior
(редактор ex, компилятор m2 и оболочка системы shell).
Был выбран второй путь, как менее трудоемкий. Для
реализации турбо-компилятора были разработаны следующие модули
(подробнее см. Приложение 2):
- библиотека для запуска Модула-2 компилятора (mcPublic);
- встроенный в редактор shell с возможностями,
аналогичными оболочке системы (exShell, exExec);
- модуль, обеспечивающий запуск компилятора в редакторе и
обработку ошибок компиляции (exComp);
- головной модуль турбо-компилятора (e2).
Взаимосвязь редактирующих и компилирующих компонент
системы приведена в Приложении 1.
В текущей (первой) версии турбо-компилятор не использует
возможностей оптимизации обращений к внешним устройствам. Так,
файл кода всегда пишется на диск, а симфайлы читаются при
каждой компиляции заново. В настоящее время идет реализация
авторами нового компилятора с расширенной Модулы-2 (mx), и при
реализации его турбо-версии эти возможности будут реализованы.
Кроме традиционных для турбо-компилятора возможностей,
которые описаны выше, наш компилятор поддерживает возможность
создания и исполнения так называемых фильтров. Фильтр - это
утилита, запускаемая в редакторе и имеющая доступ к образу
редактируемого файла в памяти. Она может по номеру строки
текста получить строку, изменить содержимое строки, вставить
или удалить группы строк и т.д.. Фильтром является любая
утилита, использующая библиотеку ScreenMgr (см. Приложение 3).
В Приложении 3 приведены примеры фильтров: фильтр, который
преобразует в помеченном диапазоне строк все маленькие буквы в
большие, и фильтр подсчета частоты использования слов в
тексте.
Наличие фильтров позволяет динамически добавлять
дополнительные возможности в редактор, причем добавлять их
могут не только разработчики, но и пользователи редактора.
Простота написания фильтров определяется простым интерфейсом
модуля ScreenMgr. В состав фильтров могут входить форматеры,
перекодировщики, компиляторы, утилиты печати для конкретных
печатающих устройств и т.д..
Модуль ScreenMgr можно рассматривать как прообраз
стандарта исполняющей системы, то есть некоторой среды, в
которой работают все утилиты, причем это может быть редактор,
обычная оболочка системы или система управления окнами.
Разработка такого стандарта приведет к независимости утилит от
программно-аппаратной обстановки, в которой они работают.
Концепция "бурной" (turbo) работы по разработке ПО
является новой, элегантной альтернативой громоздким,
устаревшим решениям пошаговой, диалоговой, частичной
компиляции. При достижении скоростей компиляции порядка
нескольких тысяч строк в минуту (Turbo Pascal-IV 20 тыс./мин
на IBM PC AT [I80286, 10Mhz], Modula-2 6 тыс./мин на
КРОНОС-2.6 [3Mhz]) цикл редактирование-компиляция-запуск для
типичного модуля размером 300-700 строк укладывается в
считанные секунды. Объединение концепции "TURBO" с модульным
принципом разработки ПО (как это сделано в Excelsior-II, Turbo
Pascal-IV) дает программисту принципиально новые возможности в
разработке программ. Качественно меняется сам стиль разработки
и использования программного обеспечения. Традиционные
текстовые редакторы и последовательные компиляторы (типа
внешняя память -> внешняя память) даже в самых развитых
"диалоговых системах" являются, по сути, всего лишь частичной
автоматизацей процесса
"программа_на_бланке" ->
"колода_перфокарт" ->
"трансляция" ->
"загрузочный_модуль" ->
"редактирование связей" ->
"исполнение программы" ...
Турбо-системы стали первым реальным шагом на пути создания
"миров", в которых должен обитать создатель ПО. Естественно,
именно в понятиях и терминах таких миров должно происходить
дооснащение программиста необходимыми средствами, такими, как
базы знаний о программах, системы синтеза программ и др..
Предложенный механизм "фильтров" - еще один шаг по этому пути.
ЛИТЕРАТУРА
1. Кузнецов Д.Н., Недоря А.Е. Симфайлы как интерфейс
операционной системы //Информатика. Технологические
аспекты. - Новосибирск, 1987 с.68-75.
2. Кузнецов Д.Н. и др. КРОНОС - автоматизированное место
профессионального программиста //Методы трансляции и
конструирования программ. - Новосибирск (в печати).
ПРИЛОЖЕНИЕ 1
Связь компонент редактора и компилятора:
ex e2 m2 mc
\ / \ | /
\ / \ | /
\ / exComp | /
\ / \ | /
\ / \ | /
exMain, exShell mcPublic
| | |
| exExec |
V V
редактор Modula-2
текстов компилятор
exMain -- Библиотека редактирования.
exShell -- Шелл (оболочка) редактора.
exExec -- Запуск задач в редакторе.
mcPublic -- Библиотека запуска компилятора.
ex -- Головной модуль текстового редактора
(без возможности компиляции).
m2 -- Головной модуль компилятора.
mс -- Головной модуль компилятора с возможностью
масовой компиляции
(mc *.m - компиляция всех модулей рабочей директории).
e2 -- Турбо-компилятор.
Объем дополнительно разработанного ПО для реализации
турбо-компилятора:
+----------------+---------------+
| Имя модуля | Число строк |
| | в реализации |
+----------------+---------------+
| mcPublic | 42 |
| exComp | 164 |
| exShell | 186 |
| exExec | 218 |
+----------------+---------------+
| Итого: | 610 |
+----------------+---------------+
ПРИЛОЖЕНИЕ 2
DEFINITION MODULE mcPublic; (* Ned 20-Oct-87. (c) KRONOS *)
FROM SYSTEM IMPORT WORD;
TYPE
GETLINE = PROCEDURE (VAR ARRAY OF CHAR);
PRINT = PROCEDURE (ARRAY OF CHAR, SEQ WORD);
ERROR = PROCEDURE (INTEGER,INTEGER, ARRAY OF CHAR, SEQ WORD);
PRAGMA = ['a'..'z'];
TYPE
INFO = RECORD
name : ARRAY [0..79] OF CHAR; -- имя модуля
lines : INTEGER; -- число строк
errors: INTEGER; -- число ошибок
time : INTEGER; -- время процессора
iotime: INTEGER; -- время ввода/вывода
codes : INTEGER; -- размер кода
END;
PROCEDURE enterCompiler(cpu: INTEGER);
(* Инициализация компилятора. Компилятор будет порождать
код для процессора с номером -cpu-.
*)
PROCEDURE compile(print,info: PRINT;
error: ERROR;
getline: GETLINE;
maxer: INTEGER;
VAR res: INFO);
(* Запуск компилятора. Компилятор использует процедуры
print,info - для сообщений компилятора;
error - для сообщений об ошибках;
getline - для чтения очередной строки исходного текста.
maxer - максимальное число ошибок.
res - информация о результатах компиляция.
*)
PROCEDURE pragma(p: PRAGMA; onoff: BOOLEAN);
(* Определение опции компилятора. *)
PROCEDURE exitCompiler;
(* Завершение компиляции. *)
END mcPublic.
DEFINITION MODULE exShell; (* Leo 30-Apr-88. (c) KRONOS *)
PROCEDURE Interpret(cmd: ARRAY OF CHAR; refresh: BOOLEAN);
(* Исполняет команду cmd.
refresh - надо ли перерисовывать экран после исполнения
команды.
*)
END exShell.
DEFINITION MODULE exExec; (* Andy & Ned 17-Apr-88. (c) KRONOS *)
PROCEDURE call(line: ARRAY OF CHAR; refresh: BOOLEAN);
(* Исполнение задачи.
line - строка с именем задачи и параметрами.
refresh - надо ли перерисовывать экран после исполнения
команды.
*)
END exExec.
ПРИЛОЖЕНИЕ 3
ПРИМЕРЫ ФИЛЬТРОВ
DEFINITION MODULE ScreenMgr; (* Ned 03-May-88. (c) KRONOS *)
FROM SYSTEM IMPORT WORD;
PROCEDURE curl(): INTEGER;
(* Возвращает номер текущуй строки. *)
PROCEDURE jump(line: INTEGER);
(* Прыжок на строку с номером line *)
PROCEDURE get(VAR s: ARRAY OF CHAR; VAR sz: INTEGER);
(* Взять текущую строку. *)
PROCEDURE size(): INTEGER;
(* Размер текущей строки. *)
PROCEDURE put(VAL s: ARRAY OF CHAR; sz: INTEGER);
(* Записать текущую строку. *)
PROCEDURE delete(n: INTEGER);
(* Удалить n строк начиная с текущей. *)
PROCEDURE insert(n: INTEGER);
(* Вставить n строк перед текущей. *)
PROCEDURE refresh;
(* Перерисовать экран. *)
PROCEDURE message(wait: BOOLEAN; VAL form: ARRAY OF CHAR; SEQ args: WORD);
(* Вывести сообщение. *)
TYPE FRAME = RECORD undef: BOOLEAN;
l0,c0,l1,c1: INTEGER;
END;
PROCEDURE frame(VAR f: FRAME);
(* Определить границы области.
Диапазон строк l0..l1, диапазон столбцов c0..c1.
*)
END ScreenMgr.
1. Фильтр, преобразующий в помеченном диапазоне строк все
маленькие буквы в большие
MODULE cap; (* Ned 02-Jun-88. (c) KRONOS *)
FROM ScreenMgr IMPORT FRAME, jump, frame, get, put, refresh
, message;
FROM Misc IMPORT Capital;
PROCEDURE capital(VAR s: ARRAY OF CHAR; size: INTEGER);
VAR i: INTEGER;
BEGIN
FOR i:=0 TO size-1 DO s[i]:=Capital(s[i]) END;
END capital;
VAR f: FRAME;
line: ARRAY [0..255] OF CHAR;
no : INTEGER;
size: INTEGER;
BEGIN
frame(f); -- получаю границы области
IF f.undef THEN -- если область не определена
message(TRUE,"НЕ УСТАНОВЛЕНН МАРКЕР НАЧАЛА И/ИЛИ КОНЦА");
HALT
END;
no:=f.l0;
WHILE no<=f.l1 DO -- для всех выделенных строк
jump(no); -- выбрал строку с номером no
get(line,size); -- взял строку
capital(line,size); -- преобразование строки
put(line,size); -- запись строки
INC(no);
END;
refresh; -- перерисовка экрана
END cap.
2. Фильтр подсчета частоты использования слов
MODULE words; (* Ned 02-Jun-88. (c) KRONOS *)
FROM ScreenMgr IMPORT jump, get, refresh, message, last;
FROM Strings IMPORT Str2, GetWord, Len;
FROM StdIO IMPORT ShowAndWait, print, Home, Clear;
CONST N=1024;
TYPE Word=ARRAY [0..31] OF CHAR;
VAR
line: ARRAY [0..255] OF CHAR;
no : INTEGER;
size: INTEGER;
VAR words: INTEGER;
word: ARRAY [0..N-1] OF Word;
count: ARRAY [0..N-1] OF INTEGER;
PROCEDURE scan;
VAR i: INTEGER; w: Word;
BEGIN Str2(line);
GetWord(line,w);
WHILE Len(w)#0 DO
i:=0;
WHILE (i<words) & (word[i]#w) DO INC(i) END;
IF i>=words THEN
IF words<HIGH(word) THEN
word[words]:=w; count[words]:=1;
INC(words);
END;
ELSE
INC(count[i]);
END;
GetWord(line,w);
END;
END scan;
PROCEDURE sort;
VAR i,j: INTEGER; w: Word; done: BOOLEAN;
BEGIN
REPEAT done:=TRUE;
FOR i:=0 TO words-2 DO
IF count[i]>count[i+1] THEN done:=FALSE;
w:=word [i]; word [i]:=word [i+1]; word [i+1]:=w;
j:=count[i]; count[i]:=count[i+1]; count[i+1]:=j;
END;
END;
UNTIL done;
END sort;
BEGIN Home;
words:=0;
FOR no:=0 TO last() DO
jump(no); get(line,size); scan;
END;
sort; Home; Clear;
FOR no:=0 TO words-1 DO
print("%-32.32s %3d\n",word[no],count[no]);
IF no MOD 24 = 23 THEN
ShowAndWait("НАЖМИТЕ ЛЮБУЮ КНОПКУ ДЛЯ ПРОДОЛЖЕНИЯ");
Home; Clear;
END;
END;
ShowAndWait("НАЖМИТЕ ЛЮБУЮ КНОПКУ");
END words.
ФАКСИМИЛЕ ПОСЛЕДНИХ ЭКРАНОВ ПОСЛЕ РАБОТЫ words
НАД ТЕКСТОМ ЭТОЙ СТАТЬИ
как 3
реализации 3
возможности 3
это 3
фильтров 3
турбо-компилятор 4
Турбо-компилятор 4
не 4
компилятора 4
файл 4
В 4
на 4
строк 4
редактор 5
компилятор 5
их 5
турбо-компилятора 5
-> 5
по 6
к 6
компиляции 6
может 6
с 6
при 7
НАЖМИТЕ ЛЮБУЮ КНОПКУ ДЛЯ ПРОДОЛЖЕНИЯ
системы 8
для 10
- 12
и 24
в 28
НАЖМИТЕ ЛЮБУЮ КНОПКУ