Редкая профессия - Евгений Зуев 6 стр.


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

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

У нас возникло ощущение, что, может быть, следует переправить бельгийцам то, что мы сделали за время после формальной сдачи. Наша (конечно же, несколько наивная) логика была такова: последняя принятая ими версия тестового пакета содержит ошибки. Теперь мы их исправили. Если мы оставим исправления при себе, то, продавая пакет с ошибками, фирма подмочит свою репутацию, что косвенно ударит и по нашему реноме. Мы несколько раз спорили друг с другом; наконец, решили не посылать сразу исправления, а сначала написать письмо с предложением: не хотите ли взять у нас новые версии компилятора и тестов? Тем самым, быть может, мы вынудим их раскрыть свои планы.

Ничего подобного не случилось. Ответ Вальтера был по-своему знаменателен. Он написал: "мы всегда готовы получить от вас новые версии".

Больше никаких контактов между нами не было. Все было кончено.

Любимое дитя

На душе было тяжело. Компилятор сдан, но его дальнейшая судьба абсолютно неизвестна. Если бельгийцы намереваются пустить его в дело, то первое, что они должны сделать, как и обещали,-- отдать на бета-тестирование. Полное молчание. Мы нисколько не боялись стороннего тестирования (уж сколько мы сами трепали его на всевозможных тестах!), наоборот, были бы несказанно рады, что у компилятора появляются какие-то перспективы. Но тогда, как бы ни был компилятор хорош, у пользователей обязательно должны были появляться проблемы, вопросы о непонятных ошибках и т.д… Никаких известий.

Словно послали учиться за границу единственного ребенка, а от него ни ответа ни привета.

Может быть, мы им так надоели, что они решили дальше работать с компилятором сами? Сомнительно. Несмотря на то что Вальтер в свое время продемонстрировал нам высокий уровень анализа нашего программного текста (даже ошибки у нас находил!), вряд ли, учитывая их непростое положение, они сейчас способны сами вести проект. Нет у них своих специалистов по Си++, а сформировать для поддержки бета-тестирования новую команду они просто не в состоянии. В любом случае, если бы они приняли определенное решение, рано или поздно они должны были объявить об этом публично. Однако их Web-страница наводила уныние, не меняясь уже больше года. Все это время на ней красовалось сообщение: "В конце года (какого? — авт.) у нас будет компилятор Си++"… Она и сейчас, когда прошло еще несколько месяцев, не изменилась ни в одном символе.

Единственное, что можно было еще предположить, — они продали исходный текст какой-нибудь третьей фирме. Тогда, конечно, мы уже никогда не узнаем, по чьим рукам пошел наш компилятор… Но и в это не очень верилось. Скорее всего, сейчас им просто не до компилятора.

Как бы вы поступили в подобном случае?

Долгое время мы просто переживали и… продолжали работать над компилятором. Как обычно, именно после официальной сдачи проекта обнаруживаются и исправляются ошибки из серии "непонятно, как раньше программа вообще работала", возникают новые плодотворные идеи и в течение нескольких дней воплощаются в программный текст. Появилась еще одна редакция предварительного стандарта, и те изменения, которые мы в ней увидели, были немедленно отражены в компиляторе. И в один прекрасный момент мы вдруг осознали, что:

* теперь компилятор соответствует самой последней редакции предварительного стандарта, а не версии годичной давности, как было зафиксировано в контракте;

* мы исправили несколько ошибок, выявленных уже после сдачи, и некоторые из этих ошибок были довольно серьезны;

* некоторые базовые алгоритмы были заметно улучшены в плане эффективности; компилятор заработал быстрее.

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

Но ведь мы не можем распространять от себя то, что формально нам не принадлежит! Следовательно, нужно сделать компилятор нашим. Из того, что рассказано выше, можно понять, что у нас давно чесались руки многое переделать. Теперь для этого возникли все условия. Часть пути уже пройдена, следует определить последующие шаги в этом направлении. Несколько дней мы провели в подробных обсуждениях. Мы не специалисты в юридических аспектах, относящихся к проблемам собственности, но нам было понятно, что изменения в компиляторе должны, с одной стороны, затрагивать если не все, то большинство его основных алгоритмов, и с другой — "внешний вид" программного текста также должен быть сильно модифицирован. Функциональность программы, естественно, останется (все компиляторы, по большому счету, делают одно и то же), но ее внутренности должны в значительной степени измениться. Это должен был быть новый компилятор.

Читатель простит некоторую сдержанность при описании этих аспектов работы. Скажу только, что в новой версии мы умудрились изменить даже стиль программирования, не говоря уже о более простых вещах. Что же касается переработки алгоритмов, то, помимо уже описанных выше изменений, мы оптимизировали формальное описание синтаксиса входного языка, сделав разбор выражений примерно на 20-25% быстрее, доработали механизм шаблонов, включив в него массу нововведений, появившихся за последнее время, реализовали новую схему работы с именами (см. главку "Как отремонтировать подгнивший дом") и усовершенствовали как компиляцию исключений, так и алгоритмы времени выполнения, связанные с обработкой исключительных ситуаций. Сделано еще много заметных изменений, и эта работа продолжается.

Мы перенесли компилятор на персоналки и заставили его работать в среде Windows’95 (правда, без формирования объектного кода — генератора для платформы Intel у нас пока нет).

Наконец, мы решили проблему с форматом промежуточного представления, которое порождает компилятор. Это очень интересная история. Читайте дальше.

Confidential

Наша система — не традиционный компилятор, порождающий объектный код, а так называемый компилятор переднего плана (front-end compiler), который в качестве результата своей работы формирует образ исходной программы на некотором промежуточном языке. Далее этот образ обрабатывается отдельной компонентой — генератором кода (back-end). Это обычная схема, давно принятая в многоязыковых системах программирования. Так как промежуточное представление выбирается единым для всех входных языков, то в системе достаточно единственного генератора кода, что исключает затраты на реализацию генератора для каждого отдельного компилятора. Кроме того, можно разработать несколько генераторов кода с единого внутреннего представления для различных аппаратных платформ, получив тем самым многоплатформную систему программирования. По этой схеме организована система gcc, похожим образом устроены и продукты семейства TopSpeed и десятки других.

Промежуточное представление, которое использовали бельгийцы в своих компиляторах (это, по существу, специальный язык, который можно назвать обобщенным ассемблером), было разработано довольно давно, выглядело несколько архаично, но для него было сделано несколько работающих генераторов для платформ Intel, Motorola, Sparc и менее известных процессоров. Спарковский генератор они и передали нам для использования совместно с создаваемым компилятором, специально оговорив недопустимость его копирования. На документации по промежуточному языку красовались жирные штампы "Confidential". Это вызывало уважение и некоторый трепет. Перед нами как бы приоткрыли дверь в святая святых компании — поделились своим ноу-хау.

Когда произошло все то, о чем было написано выше, и мы начали интенсивно переделывать и дорабатывать компилятор, стремясь сделать его полностью "нашим", перед нами, словно чугунный рельс,-- ни обойти, ни сдвинуть — все время стояло это безальтернативное, как хлопок двери, слово,-- "Confidential". В самом деле, пусть мы переписали компилятор, пусть его исходный текст сильно изменился, но он, тем не менее, порождает код, формат которого является чужой собственностью,-- как мы можем считать такой компилятор своим? Придумать собственное промежуточное представление или адаптировать, например, внутренний код gcc — он, как и весь проект GNU, имеет статус freeware — конечно, можно, но сколько времени это займет? А соответствующая переделка компилятора сравнима с созданием нового.

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

Был краткий период моральной усталости от отладочной гонки, которая выглядела бесконечной (последние пять процентов ошибочных тестов поддавались с невероятным трудом и требовали все новых правок). Мы задумались о будущем и начали прикидывать, как могла бы выглядеть совсем новая версия компилятора. Мы начали интенсивно искать в Интернете все, что так или иначе касалось компиляции, генерации кода и языка Си++. Как ни странно, больше всего информации оказалось о методах генерации. И вот в один прекрасный день Саша натолкнулся на работу Джонсона[3] о реализации одного из первых компиляторов Си — проекте Portable C, относящегося к концу 70-х годов. Это была статья в каком-то древнем формате с подробным описанием проектных решений и описывающая, в частности, подход к генерации кода. Мы не глядя распечатали ее и ахнули: в ней были расписаны основные коды бельгийского внутреннего представления, который мы помнили наизусть! Два дня ушло на лихорадочный поиск и запросы во все стороны, где можно найти исходники Portable C. Нашлись, родимые, рядышком, у какого-то коллекционера в Финляндии! И что же? Похожие названия команд, те же кодировки и почти те же самые заголовочные файлы, что и у бельгийцев!

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

Не будем гадать о том, почему фирма взяла за основу своего промежуточного представления формат Джонсона. Для своего времени это было естественное и, наверное, правильное решение, и, конечно, их нельзя упрекнуть в некорректности — статья известна всем, она до сих пор входит в комплект документации по "Seventh Edition release of the UNIX operating system" компании Bell Telephone Laboratories, а исходные тексты Portable C общедоступны.

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

Это сладкое слово — свобода!

Надо бы зарегистрировать его в РАПО…

Заключение. Полетит?

К настоящему времени (конец 1997 года) мы далеко ушли от версии, сданной бельгийцам в конце прошлого года. Теперь компилятор соответствует последней, декабрьской версии Предварительного Стандарта и успешно проходит примерно 98% всех тестов. Заметно быстрее работает синтаксический разбор, почти полностью реализованы шаблоны. Наконец, теперь он перенесен на платформу Intel (в виде консольного приложения для Windows’95), а в конце года должен заработать наш собственный генератор кода для Win32.

Мы подготовили эскизный проект совершенно новой версии компилятора, надеемся, свободного от проектных ошибок, которые уже невозможно выковырять из теперешней версии и в котором заложены очень заманчивые решения (и, конечно, новые ошибки!).

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

Знакомые ребята из одной московской фирмы, разрабатывающей программно-аппаратные комплексы на основе микроконтроллеров, некоторое время назад написали компилятор ANSI Си для одного семейства однокристальных микроконтроллеров. Их история оказалась несколько похожей на нашу, что может говорить о типичности явления. Они делали компилятор по заказу известной американской фирмы, в контракте с которой был пункт об оплате всей работы после проведения тестирования. Сроки тестирования никак не оговаривались, а проводить его должны были сами заказчики. Через год компилятор был полностью готов (вместе с библиотеками, отладчиком, макроассемблером, программным эмулятором процессора и средой разработки!), однако, к этому времени ситуация изменилась: американцы, видимо, потеряли интерес к разработке и… просто не стали проводить тестирование! Придраться было не к чему, буква контракта нарушена не была. В результате фирма осталась без денег, правда, с компилятором, который теперь стал, естественно, их собственностью.

Но… нет худа без добра. Теперь они распространяют его сами и продают до шести комплектов в месяц. У нас, в России, продается компилятор, разработанный в России же, и покупают его наши пользователи! Как хотите, а это здорово.

Однако их опыт не слишком подходит нам. Ниша, образуемая системным программным обеспечением для микроконтроллеров, в гораздо меньшей степени насыщена такими инструментами, как компиляторы языков высокого уровня. Поэтому у ребят остаются неплохие шансы выйти и на мировой рынок, который, конечно, существенно шире. Что же касается инструментов общего назначения, то здесь конкуренция очень жесткая. Примеры превосходных систем программирования на Си++ для любых платформ известны всем. Что из того, что наш компилятор лучше соответствует стандарту? Зато он не интегрирован с редактором, с отладчиком, у него нет "Менеджера Проектов" и других полезных штучек. Даже несмотря на наличие собственного генератора кода он, по существу, остается полуфабрикатом, пригодным для включения в какую-нибудь интегрированную среду, в которой есть все, что надо, но по недосмотру не оказалось компилятора. Сами мы такую среду не напишем — мало сил, не та квалификация, и вряд ли у нас это получится профессионально (каждый должен заниматься своим делом). Кому нужен такой продукт?

Правда, не все так уж плохо. Весь последний год мы работали по контракту с небольшой, но серьезной российской фирмой, создающей заказные программно-аппаратные комплексы и спроектировавшей собственный (sic!) специализированный процессор (опытные экземпляры вот-вот появятся; еще один пример того, что не все занимаются проталкиванием импортных решений!). Мы принимали участие в разработке системного ПО для этого процессора и адаптировали для него свой компилятор. Что получится из этого проекта, пока не известно. Многое зависит от того, как код, сгенерированный нашим компилятором, заработает на реальном "камне", а не на эмуляторе, и от того, сможет ли фирма заинтересовать этой разработкой потенциальных заказчиков. Однако факт остается фактом: наш компилятор получил (пусть даже очень небольшое) признание, оказался востребован.

Однако принципиально ситуация не изменилась. Возможное использование компилятора в одном проекте, к тому же еще не доведенном до конца, никак нельзя назвать успехом. Вопрос "летает — не летает?" по-прежнему остается без ответа и по-прежнему мучает нас.

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

Назад Дальше