|
Программирование >> Полиморфизм без виртуальных функций в с++
которому были неизвестны синтаксические конструкции, области действия и правила контроля типов С. Это явилось источником многих проблем как в определении, так и при использовании языка. Я твердо решил не сталкиваться больше с такими трудностями в пересмотренном я.зыке и его реализации. С-ы- и Cfront проектировались вместе. Определение языка и технология компиляции, несомненно, были связаны друг с другом, но ие так тривиально, как ду.мают некоторые. 3.3.2. Синтаксический анализ С++ в 1982 г., в начале планирования Cfront я хотел воспользоваться методом рекурсивного спуска, поскольку опыт написания таких синтаксических анализаторов у меня уже был. Они легко обеспечивают хорошую диагностику ошибок. Кроме того, мне импонировала идея иметь под рукой всю мощь универсального языка программирования, когда в синтаксическом анализаторе иеобходи.мо принимать те или иные решения. Но, будучи добросовестным молодым ученым, я спросил совета у экспертов. В то время в Центре исследований по вычислительной технике как раз работали Эл Ахо (Al Aho) и Стив Джонсон. Они-то, главным образом Стив, и убедили меня, что: □ вручную синтаксические анализаторы уже никто ие пишет; □ это пустая трата времени; □ при таком подходе неизбежно получится нечто непонятное, что даже сопровождать невозможно; □ применяемая в подобном анализаторе техника восстановления после ошибок несистематична, а значит, и ненадежна. Правильным приемо.м, по мнению вышеупомянутых специалистов, было бы использование LALR( 1 )-генератора синтаксических анализаторов, поэтому я принял на вооружение написанный Элом и Стиво.м YACC [Aho,1986]. Для большинства проектов такой выбор был бы идеальны.м. Это годилось бы почти для любого проекта, связанного с написание.м экспериментального языка с нуля. Но, оглядываясь назад, я понимаю, что именно для С++ этот выбор оказался роковой ошибкой. С++ был не экспериментальным языком, а почти совместимым надмножеством С, а в то время еще никому не удалось написать для С ЬАЬК(1)-гра.мматику. Такая грам.матика для ANSI С была построена Томом Пен-нелло (Тот Pennello) спустя примерно полтора года, то есть слишком поздно. Даже созданный Джонсоном РСС - лучший из всех тогдашних компиляторов С -был не совсем корректен в некоторых деталях, которые для синтаксического ана-ли.затора С++ являлись весьма существенными. В частности, в РСС неправильно обрабатывалисьлишниескобки, поэто.му int (х) ; не воспринималось как объявление X. Более того, из моих наблюдений следовало, что пользователи тяготеют к разным стратегиям разбора. Мое пристрастие к нисходящему разбору многократно проявлялось в форме написания конструкций, которые очень трудно ложатся на грамматику, поддерживаемую YACC. До сего дня Cfront построен на базе синтаксического анализатора YACC, определенным образом дополненного на уровне лексического разбора. С другой стороны, для С++ все же можно написать эффективный и достаточно изящный анализатор, использующий метод рекурсивного спуска. Так построены некоторые совре.менные компиляторы С++. 3.3.3. Проблемы компоновки Как уже говорилось выше, я решил обходиться традиционными компоновщиками со всеми их офаничениями. Однако одно офаничение оказалось совершенно нетерпимым и в то же время настолько глупым, что, будь у меня достаточно терпения, я поднял бы заинтересованных людей на борьбу с ним. Дело в том, что большинство тогдашних компоновщиков не позволяло использовать длинные внешние имена. Обычно число символов офаничивалось восемью, а K&R С гарантировал для внешних имен только шесть символов и один регистр. ANSI/ISO С также унаследовал это Офаничение. Принимая во внимание, что имя функции-члена включает имя класса и что при компоновке необходимо было каким-то образом отразить тип перегруженной функции (см. раздел 11.3.1), я понимал, что выбор у меня невелик. Рассмотрим примеры: void task::schedule() { /*...*/ } 4+8 символов void hashed::print() { /*...*/ ) 6+5 символов complex sqrt(complex); 4 символа плюс complex double sqrt(double); 4 символа плюс double Чтобы представить данные имена всего шестью символами верхнего регисфа, пришлось бы применить какую-то форму сжатия, а это усложнило бы написание инструментальных средств. Конечно, можно воспользоваться хэшированием, но тогда для разрешения конфликтов потребуется какая-нибудь рудиментарная база данных профаммы . Таким образом, первый способ крайне неприятен, а второй может стать источником серьезных проблем, поскольку в стандартной модели компоновки профамм на С и Fortran никакая база данных не предусмотрена. В связи со всем вышесказанным в 1982 г. я начал выступать в пользу доработки компоновщиков для поддержки длинных имен. Не знаю, мои ли усилия тому причиной, но современные компоновщики разрешают гораздо более длинные имена. В Cfront для реализации безопасного связывания применяются специальные алгоритмы кодирования типов. При этом 32 символа - это маловато, порой не хватает даже 256 (см. раздел 11.3.2). Временно - для архаичных компоновщиков - применялась система хэширования длинных идентификаторов, что было очень неудобно. 3.3.4. Версии Cfront Первые версии компиляторов С with Classes и С++ люди получали прямо от меня. Таким образом, возможность работать с С with Classes появилась у сотрудников десятков образовательных учреждений, таких как: Стэндфордский университет (декабрь 1981 г., первая поставка Срге), Калифорнийский университет в Беркли, университет штата Висконсин в Мэдисоне, Калифорнийский технологический институт, университет штата Северная Каролина в Чапел Хилл, Масса-чусетский технологический институт. Сиднейский университет, университет Кар-неги-Мэллон, университет штата Иллинойс в Урбана-Шампейн, Копенгагенский университет, Лаборатория Резерфорда (Оксфорд), IRCAM, INRIA Поставки компилятора отдельным образовательным учреждениям продолжались и после того, как был спроектирован и реализован С++. Таким образом компилятор получили следующие университеты: Калифорнийский (Беркли - август 1984 г., первая поставка Cfront), штата Вашингтон (Сент-Луис), Техасский (Остин), Копенгагенский и Нового Южного Уэльса. Было, конечно, множество неофициальных копий, поскольку студенты, как водится, не обращали внимания на бюрократические формальности. Уже тогда распространение версий на индивидуальной основе стало для меня обузой, а для университетского народа, желающего иметь С++, - причиной для раздражения. Поэтому мы с Брайаном Керниганом, начальником моего отдела, и Дейвом Каллманом, отвечавшим в AT&T за С++, решили организовать выпуск Cfront несколько иначе. Идея заключалась в том, чтобы избежать назначения цен, подписания контрактов, организации технической поддержки, рекламы, составления документации, отвечающей корпоративным стандартам и т.д. Вместо этого Cfront и некоторые библиотеки передавались университетам по цене носителей. Данную версию назвали Release Е ( Е - сокращение от Educational, образовательный). В январе 1985 г. Лаборатория Резерфорда и другие учреждения получили первые ленты. Версия Е заставила меня по-другому взглянуть на вещи. Фактически это было полное фиаско. Я ожидал быстрого роста интереса к С++ в университетах. Однако кривая роста нисколько не изменила своего характера (см. раздел 7.1), зато вместо новых пользователей мы получили поток жалоб от профессоров на то, что С++ не распространялся на коммерческой основе. Сколько раз я слышал такие слова: Да, я хочу работать с С++ и знаю, что могу получить Cfront бесплатно, но, увы, меня это не устраивает, так как мне необходима некая база, на основе которой я могу давать консультации, а мои студенты - использовать в индустриальных проектах . Вот ва.м и академическое стремление к чистому знанию. Стив Джонсон, тогдашний начальник отдела разработки С и С++, Дейв Каллман и я снова собрались и выработали план создания коммерческой версии 1.0. Однако практика предоставления компилятора С++ (с исходными текстами и библиотеками) образовательным учреждениям почти бесплатно , которая началась с версии Е, до сих пор жива. Версии С++ часто именуются по номерам версий Cfront. Версия 1.0 определена в книге Язык програ.м.мирования С++ [Stroustrup, 1986]. В версиях 1.1 (июнь 1986 г.) и 1.2 (февраль 1987 г.) в основном исправлялись ошибки, сюда были также добавлены указатели на члены и защищенные члены (см. раздел 13.9). В версии 2.0, вышедшей в июне 1989 г., компилятор подвергся существенной переработке. В нее же было включено множественное наследование (см. раздел 12.1). По общему признанию, это был большой шаг вперед с точки зрения функциональности и качества. В версии 2.1 (апрель 1990 г.) ошибки преимущественно исправили, и Cfront был (почти) приведен к определению, данному в книге The Annotated С++ Reference Manual [ARM] - см. раздел 5.3. В версии 3.0 (сентябрь 1991 г.) были добавлены шаблоны (см. главу 15) в соответствии с определением ARM. Вариант версии 3.0 с поддержкой исключений (см. главу 16) разработала и в конце 1992 г. выпустила на рынок компания Hewlett-Packard [Cameron, 1992].
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |