Каким должен быть язык программирования? Анализ и критика Описание языка Компилятор
Отечественные разработки Cтатьи на компьютерные темы Компьютерный юмор Новости и прочее

Непрерывное компилирование

Вместо предисловия

            Вспомнил об ещё одной очень старой заметке, которую я писал ещё в 1995 году для журнала «Монитор» (но журнал к тому времени уже закрылся). Речь идет уже не о языке и трансляторе, а об IDE.

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

Собственно статья

            Так чем же занимается компьютер, когда Вы редактируете свою программу?

            Да, собственно, ничем. 99.99% времени уходит на ожидание нажатия клавиши (разумеется, если Ваш PC работает в обычном однозадачном режиме). А затем компьютер кинется компилировать сделанное Вами, и теперь уже Вы будете ждать его, ругая за медленное компилирование, что, честно говоря, несправедливо — он ждал Вас минуты, а Вы ждете лишь несколько секунд или десятки секунд.

            Вот если бы провести компиляцию, в то время как Вы размышляете над текстом программы, но, увы — в тот момент текст ещё не готов и трансляция его бессмысленна. Есть только один промежуток времени с момента как Вы нажали последнюю клавишу редактирования и до нажатия клавиши записи на диск, выхода из редактора и т.п., когда можно было бы попробовать провести компиляцию.

            Однако только Вы знаете, что это и была последняя редакция текста, а компьютер об этом узнать никак не может. Но поскольку он все равно ничего не делает между нажатиями клавиш — пусть считает каждую клавишу последней и непрерывно работает!

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

            Для проверки этой идеи был взят обычный текстовый редактор SideKick и компилятор с языка PL/1 (поскольку автор этой статьи занимается помимо всего прочего сопровождением этих программ и часто их меняет). Потребовалась также хорошая машина (486 DX2), так как компиляция проходит довольно долго и кроме этого, нужно было иметь нормальное ОЗУ (16М), что бы хранить там сам компилятор, стандартные файлы, вызываемые директивой INCLUDE и т.п. и не обращаться без конца к жесткому диску.

            Что же показал двухмесячный опыт работы в этом режиме? Эффект есть лишь в том случае, когда человек привыкает к такой работе и перестает обращать внимание на непрерывное компилирование. Индикация была специально сделана малозаметной и не отвлекающей — в верхнем правом углу экрана вместо псевдографического символа рамки появляется символ "К" — идет компиляция, "+" — компиляция прошла, ошибок не найдено, "-" — были ошибки.

            Если были ошибки — можно, нажав клавишу, вызвать окно с сообщением об ошибке на экран (как в обычной интегрированной среде).

            Удобно использовать индикатор при расстановке скобок и парных ключевых слов типа BEGIN — END. Редакторы интегрированных сред тоже оперативно обрабатывают текст программы — выделяют ключевые слова цветом, подсчитывают скобки и т.д., однако в более сложных случаях, например в файле, включаемым в данный текст с помощью оператора INCLUDE, уже есть такой идентификатор как и в Вашей программе, они не помогут сразу определить ошибку, что и понятно — ведь для этого в редактор потребуется встроить фактически полный компилятор!

            В данном же режиме работы это определяется легко и очень оперативно, синтаксические ошибки находятся компилятором быстро, практически мгновенно после каждого исправления. Это позволяет немного изменить сам стиль работы за компьютером. Раньше правильнее было вносить по одному исправлению в программу и затем проверять трансляцией, чтобы не запутаться в нескольких исправлениях и чтобы избежать влияния одних исправлений на другие. Теперь же все исправления вносятся в текст сразу, при этом лучше просто делать небольшую паузу после очередного логически законченного изменения и (скосив глаз) убедиться, что ошибок не возникло. Экономия времени и количества нажатых клавиш налицо. Однако и здесь есть один прокол: если между нажатиями клавиш компилятор успел таки довести трансляцию до конца или до первой ошибки, то компьютер опять ничего не делает и только ждет клавиши. Чем же теперь его занять, а?

            P.S. Вдогонку к заметке: в чем-то подобный подход реализован у нас и при вызове редактора связей. Он может автоматически вызываться после работы компилятора. Если компилируется не главный модуль, то вызывать редактор бессмысленно — он не знает где искать главный, да и главный может быть вообще ещё не готов. А вот если компилируется главный модуль, то может быть два случая: больше модулей уже не нужно (кроме указанных библиотек) или будут ещё какие-то модули. У нас в любом случае вызывается редактор, но если он не находит каких-то связей, то он на экран ничего не выдает и делает вид, что вообще не вызывался.

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

Автор: Д.Ю.Караваев. 1995 г.

Опубликовано: 2018.08.26, последняя правка: 2019.01.28    20:39

ОценитеОценки посетителей
   ██████████████ 3 (33.3%)
   ██████████████ 3 (33.3%)
   █████ 1 (11.1%)
   ██████████ 2 (22.2%)

Отзывы

✅  2018/09/20 19:36, Автор сайта          #0 

Чем занять компьютер? Ответ очевиден: пусть он для Вас майнит биткоины. А будет Ваш компилятор с IDE стоять на тысячах компьютеров да на Вас добывать криптокопеечку — глядишь — и на работу ходить не надо. Знай себе только работай над компилятором с IDE, чтоб биткоины не иссякали :) С Вас причитается за идею :)

✅  2018/11/03 22:43, rst256          #1 

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

В идеале вообще надо ещё и через парсер сразу код прогонять и держать всегда актуальное АСТ в памяти IDE. Тогда при редактировании исходного текста программы достаточно будет обработать только те узлы АСТ, исходный текст которых был изменен. И если анализ не выявил ошибок в коде, то запускать компиляцию измененной функции или её части.

✅  2022/06/09 22:33, void          #2 

Любопытно. Читал в Википедии про "Atari Assembler Editor" — картридж с ассемблером и монитором для CPU 6502. Эта же компания разработала ранее Atari BASIC, вот и этот "Assembler Editor" содержал редактор + токенайзер + компилятор/интерпретатор в духе этого Бейсика (например, у этого ассемблера были номера строк, простенький макроязык, монитор и отладчик для редактирования/запуска). Изначально этот "Assembler Editor" получился чуть ли не самой медленной реализацией ассемблера 6502 из имеющихся на тот момент (как и их реализация Бейсика). Затем он был доработан: следующие версии EASMD, MAC/65, BUG/65 развивала другая фирма (от тех же основателей), "Optimized Systems Software", язык Action! (упрощённый Алгол вроде Cowgol).

MAC/65, в свою очередь, был одним из самых быстрых ассемблеров для Atari (под 6502) — получилось действительно Optimized. Почему? Работал инкрементальный парсер/токенайзер (аналогично бейсиковскому).

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

А вообще, чем сложнее язык — тем больше в нём сложных высокоуровневых структурных выражений, в смысле first class objects этого языка. Поэтому по идее нужно что-то вроде структурного редактора и инкрементально парсить последнее охватывающее правки структурное выражение, охватывающее последнее изменённое, его AST/CST/макросы.

Например, авторы Plan9 изобрели текстовый редактор sam и написали статью про структурные regexp-ы. Sam — это редактор с командным языком вроде ed, только визуальный, а не командно-строчный. У него есть область по умолчанию, которая редактируется и к которой применяются команды.

Ещё например, наподобие редактора vim есть kakoune. В kakoune есть multiple cursors, multiple selection. Идея в том, что в "визуальном", но модальном vim есть нормальный командный режим, и режим вставки. Командный режим в Vim можно понимать как Verb-Object, то есть:
сначала указывается что делать, потом с чем.

Командный нормальный режим + режим вставки в vim сами по себе не вполне логичны. В kakoune предлагают:

1) большую ортогональность, то есть разделение труда между командным и режимом вставки,

2) более логичный язык, то есть: командный режим в kakoune можно понимать как Object-Verb, то есть сначала указывается с чем делать, потом что,

3) более логичные переходы между структурными выделениями. То есть, есть например весь текст — всё выделение. выделили например блок (подвыделение этого всего текста), в нём поискали регексп. выделились все подходящие вхождения (подвыделение этого блока), их сразу одной командой заменили на замену.

Вот пример полезности "multiple selections", "multiple cursors".

В целом, идея про инкрементальный парсинг, непрерывный lint/макроподстановки/компиляцию/сборку, линковку — интересная. И для языков где явно можно выделить локально изменённые структурные выражения, последнее исправленное, макросы, охватывающее — такой структурный редактор даже может отрабатывать быстро. А для простых языков вроде ассемблера, алгола Action!, высокоуровневого ассемблера вроде HLA с CTFE макросами, ну или вот PL/1 (без особо навороченных макросов вроде IBM'овского PL/1, где препроцессором можно было строчку вручную сгенерировать и подать к компиляции, реализовав свой DSL, например REXX PARSE выражения через препроцессор) — сам транслятор может быть достаточно скорострельный, например, на mmap файлах в рамдиск.

HLA v3, ADK: "скорость трансляции составляет порядка несколько тысяч строк в секунду, на современном компьютере". Например, по тестам отсюда http://www.plantation-productions.com/Webster/RollYourOwn/index.html из файла BM.zip:

1) генерируем тесты bm.exe,
2) ассемблируем сгенерированный hlaBM.hla:
 
bash$ time hla -s hlaBM.hla # to asm source only

real 0m3,517s
user 0m0,015s
sys 0m0,000s

bash$ time hla.exe -c hlaBM.hla #compile and assemble to object file only

real 0m7,102s
user 0m0,000s
sys 0m0,015s

bash$ time hla.exe hlaBM.hla #compile, assemble and link to exe

real 0m8,740s
user 0m0,015s
sys 0m0,000s

bash$ lines=$(wc -l hlaBM.hla)
bash$ echo $lines
642967 hlaBM.hla

bash$ bc
lines=624967
lines/8.740 # total to exe
71506
lines/7.102 # compile and assemble to obj file only
87998
lines/3.517 # compile to asm source only
177698
То есть даже для такого вот достаточно "высокоуровневого ассемблера" как HLA, с довольно развитым макроязыком CTFE Compile-time Function Execution, Compile-time metaprogramming language — например, объектная система и аналог STL сделаны полностью на этом макроязыке — скорость компиляции этого ассемблера, по бенчмаркам составляет порядка 180 тысяч строк в секунду (либо падает до 88..71 если заодно делать и ассемблирование и линковку). Это ещё если не использовать рамдиск, например.

Вы действительно успеете набрать 180 тысяч строк в секунду (даже "заснув на клавише Энтер" — не получится)?

Вывод: скорость компиляции для большинства нормальных языков программирования (например: HLA, ассемблер, Форт, Алгол cowgol Action!, Go или Hare, V или Vx, ну или вот PL/1, например) — ну только не С++, с бустом, шаблонами и STL, разумеется

1) достаточно быстра для большинства применений,
2) вы всё равно её не заметите,
3) большую часть времени вы всё равно проводите, тупо пялясь в монитор и думая, какую же следующую строчку написать дальше,
4) пытаясь разобраться со структурой уже существующего плохо документированного в смысле намерений кода.

Кроме, разумеется, клинических случаев вроде кода на шаблонах С++, который компилируется по полчаса, переливая из пустого в порожнее.

Добавить свой отзыв

Написать автору можно на электронную почту
mail(аt)compiler.su

Авторизация

Регистрация

Выслать пароль

Карта сайта


Содержание

Каким должен быть язык программирования?

Анализ и критика

Описание языка

Компилятор

Отечественные разработки

Cтатьи на компьютерные темы

●  О превращении кибернетики в шаманство

●  Про лебедей, раков и щук

●  О замысле и воплощении

●  О русском ассемблере

●  Арифметика синтаксиса-3

●  Концепция владения в Rust на примерах

●●  Концепция владения в Rust на примерах, часть 2

●●  Концепция владения в Rust на примерах, часть 3

●  Суть побочных эффектов в чисто функциональных языках

●  О неулучшаемой архитектуре процессоров

●  Двадцать тысяч строк кода, которые потрясут мир?

●  Почему владение/заимствование в Rust такое сложное?

●  Масштабируемые архитектуры программ

●  О создании языков

●●  Джоэл Спольски о функциональном программировании

●  Почему Хаскелл так мало используется в отрасли?

●  Программирование исчезнет. Будет дрессировка нейронных сетей

●  О глупости «программирования на естественном языке»

●  Десятка худших фич C#

●  Бесплатный софт в мышеловке

●  Исповедь правового нигилиста

●  ЕС ЭВМ — это измена, трусость и обман?

●  Русской операционной системой должна стать ReactOS

●  Почему обречён язык Форт

●  Программирование без программистов — это медицина без врачей

●  Электроника без электронщиков

●  Программисты-профессионалы и программирующие инженеры

●  Статьи Дмитрия Караваева

●●  Идеальный транслятор

●●  В защиту PL/1

●●  К вопросу о совершенствовании языка программирования

●●  Опыт самостоятельного развития средства программирования в РКК «Энергия»

●●  О реализации метода оптимизации при компиляции

●●  О реализации метода распределения регистров при компиляции

●●  О распределении памяти при выполнении теста Кнута

●●  Опыты со стеком или «чемпионат по выполнению теста Кнута»

●●  О размещении переменных в стеке

●●  Сколько проходов должно быть у транслятора?

●●  Чтение лексем

●●  Экстракоды при синтезе программ

●●  Об исключенных командах или за что «списали» инструкцию INTO?

●●  Типы в инженерных задачах

●●  Непрерывное компилирование

●●  Об одной реализации специализированных операторов ввода-вывода

●●  Особенности реализации структурной обработки исключений в Win64

●●  О русском языке в программировании

●●  Формула расчета точности для умножения

●●  Права доступа к переменным

●●  Заметки о выходе из функции без значения и зеркальности get и put

●●  Модификация исполняемого кода как способ реализации массивов с изменяемыми границами

●●  Ошибка при отсутствии выполняемых действий

●●  О PL/1 и почему в нём не зарезервированы ключевые слова

●●  Не поминайте всуе PL/1

●●  Скорость в попугаях

●●  Крах операции «Инкогнито»

●●  Предопределённый результат

●●  Поддержка профилирования кода программы на низком уровне

●●  К вопросу о парадигмах

●  Следующие 7000 языков программирования

●●  Что нового с 1966 года?

●●  Наблюдаемая эволюция языка программирования

●●  Ряд важных языков в 2017 году

●●  Слоны в комнате

●●  Следующие 7000 языков программирования: заключение

Компьютерный юмор

Новости и прочее




Последние отзывы

2024/12/07 20:54 ••• Клихальт
Переключатель

2024/12/06 18:44 ••• Анкнав
Русский язык и программирование

2024/12/01 00:00 ••• alextretyak
Продолжение цикла и выход из него

2024/11/29 23:08 ••• Вежливый Лис
О русском ассемблере

2024/11/26 23:53 ••• Бурановский дедушка
ЕС ЭВМ — это измена, трусость и обман?

2024/11/25 18:31 ••• Деньги на WWWетер
Ресурсы, посвящённые созданию языков программирования и компиляторов

2024/11/12 20:24 ••• Вежливый Лис
Правила языка: строки, комментарии

2024/11/12 13:10 ••• Вежливый Лис
Новости и прочее

2024/11/12 00:32 ••• Автор сайта
Оценка надёжности функции с несколькими реализациями

2024/11/06 02:50 ••• Иван
Энтузиасты-разработчики компиляторов и их проекты

2024/11/05 23:51 ••• Борис К.
Изменение приоритетов операций

2024/11/05 23:38 ••• Борис К.
Шестнадцатиричные и двоичные константы

2024/11/01 12:11 ••• ИванАс
Русской операционной системой должна стать ReactOS