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

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

Я обучался программированию на языке PL/1. Это было формальное обучение, я должен был оцениваться на каждом этапе и продвигаться по служебной лестнице программиста-стажера, помощника программиста, младшего программиста, в конечном итоге достигая старшего программиста через несколько лет.

Оглядываясь назад, понимаю, что тогдашние мои наставники были одними из лучших разработчиков программного обеспечения, с которыми я когда-либо работал, но в те дни титула «разработчик программного обеспечения» еще не существовало.

Обучение включало в себя письменные и устные контакты, определение повестки дня совещаний и председательство на совещаниях, написание спецификаций, оценку алгоритмов и, конечно же, глубокое понимание языка PL/1, используемого на «мэйнфреймах» IBM.

В то время Си был академическим языком с очень небольшим присутствием в коммерческом мире, Паскаль был более распространен, чем Си, но в то время тремя основными языками были COBOL, Fortran и PL/1. У меня был выбор в колледже специализироваться на одном из этих трех, и после некоторых исследований в библиотеке, это не стало проблемой для такого технически склонного человека, как я, поскольку PL/1 был существенно более продвинутым, чем другие.

Вот некоторые не очень известные факты об этом языке:

  • До сравнительно недавнего времени оптимизирующий компилятор IBM PL/1 был самым сложным из существующих компиляторов.
  • PL/1 был первым языком высокого уровня, используемым для написания операционной системы (Multics).
  • PL/1 был первым языком, использующим /* */ для комментариев.
  • PL/1 был первым языком, который использовал термин «статический» для хранения переменных, не связанных со стеком.
  • Это был первый язык, который обрабатывал исключения на основе стековых фреймов (называемых «условиями», т.е. condition).
  • Это единственный язык программирования, в котором нет зарезервированных слов.
  • Это был первый язык, компилятор которого был написан на этом языке.
  • Это был первый язык, который использовал нотацию -> для указателей.

Как язык системного программирования он значительно превосходил Си, а написание компиляторов и операционных систем на языке PL/1 давало ряд преимуществ с точки зрения надежности, производительности и технического сопровождения.

Я написал почти полный компилятор PL/1 в Си для Windows NT (32-битный COFF) и до сих пор имею весь исходный код (реализация для Visual Studio 2005).

Способность парсера поддерживать требование «никаких зарезервированных слов», хотя и очень мощная, не слишком сложна, вот как это делается. На самом деле в языке существует только два вида операторов: операторы с ключевыми словами и операторы присваивания.

Оператором с ключевым словом может быть почти любое выражение языка, типа: call log_fault; или, например, do while (flag = FALSE); Оператор присваивания всегда имеет вид <ссылка> = <выражение>;

Таким образом, синтаксический анализатор просто решает, является ли оператор присваиванием или нет, если это так, то ключевые слова не имеют значения, а идентификаторы могут быть любыми. Вот почему PL/1 позволяет Вам кодировать, что-нибудь вроде:

if then then else=then; else then=if;

Грамматика очень мощная, и Вам не нужно «==» для сравнения, как в Си, достаточно только одного «=» для присвоения и сравнения.

Кстати, причина, по которой PL/1 поддерживает это, заключается не в том, чтобы позволить Вам писать сбивающий с толку код, а в том, чтобы позволить вводить новые ключевые слова в будущем, не нарушая существующий код.

Очень полезная статья о реализации компилятора PL/1 была написана Бобом Фрейбургхаузом в 1969 году, и вот ещё одна увлекательная статья, которая подробно рассказывает о том, как язык был выбран в качестве основы для Multics. Статья Боба была чрезвычайно полезна мне, когда я начал описывать дизайн и общий подход к моему собственному компилятору PL/1, любой, кто интересуется компиляторами, их реализацией и историей, должен ценить эти источники.



Автор: Hugh Gleaves, 23.11.2013.
Перевод: Д.Ю.Караваев. 27.07.2020

Опубликовано: 2020.07.27, последняя правка: 2020.07.27    20:34

Оцените

Отзывы

     2020/07/27 23:25, Австор сайта          # 

До сравнительно недавнего времени оптимизирующий компилятор IBM PL/1 был самым сложным из существующих компиляторов.

Мне кажется, компилятор Алгол-68 (если вести речь о языках 1960-70-х годов) был куда сложнее. Настолько сложнее, что первые его компиляторы появились аж лет 10 спустя после утверждения стандарта.

PL/1 был первым языком, который использовал термин «статический» для хранения переменных, не связанных со стеком.

Конечно, это преимущество. Но странно говорить о нём, когда в архитектуре IBM/360 (с которой начинался PL/1) концепция стека вообще не реализована.

Это был первый язык, компилятор которого был написан на этом языке.

Это вовсе не так. Впервые раскрутка компилятора была применена для языков ассемблера. Первым компилятором с применением техники раскрутки для языка высокого уровня был компилятор для Neliac — диалекта языка Алгол-58. Уж поверьте мне хотя бы потому, что 80% текста этой статьи в Википедии — мои.

Вам не нужно «==» для сравнения, как в Си, достаточно только одного «=» для присвоения и сравнения.

Целую статью посвятил этому: Операции присвоения и проверки на равенство. Возможно ли одинаковое обозначение?. Что бы ответил автор статьи, если дал ему такое задание на засыпку: переопределить операции присвоения и проверки на равенство, использующих одинаковое обозначение?

На самом деле в языке существует только два вида операторов: операторы с ключевыми словами и операторы присваивания.

Спорное утверждение, при том я PL/1 основательно забыл.
 f(g(h(x)));    /* нет ни ключевых слов, ни присваивания */
Или правильно так?
 CALL f(g(h(x)));

Оператором с ключевым словом может быть почти любое выражение языка, типа: call log_fault; или, например, do while (flag = FALSE);
Оператор присваивания всегда имеет вид

<ссылка> = <выражение>;

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

Я понимаю, что в PL/1 свои порядки. И со своим уставом в чужой монастырь не лезут. Но возьмём такой пример, когда if в одном случае является идентификатором переменной, а в другом — ключевым словом.
 if = (if A; B else C) /* если A истинно, то переменной if присвоить значение B;
иначе переменной if присвоить значение C */
Есть подозрение, что грамматика современных распространённых языков вызовет трудности у анализатора. Хотя у Дмитрия Юрьевича есть практический опыт преодоления неоднозначностей в своём компиляторе :) Наверное, будет уместным спросить самого Дмитрия Юрьевича: как ключевые слова отличить от обычных идентификаторов и насколько эти приёмы применимы к другим языкам?

     2020/07/30 11:04, kt          # 

Я думаю, преувеличения «первый» вместо «один из первых» и т.п. происходят от того, что в 60-70 была очень слабая связь между разработчиками. Многие были просто не в курсе, что происходит в разных фирмах.
Про ключевые слова я писал давно, ещё в статье «Да здравствует ПЛ!».
Структура языка такова, что все должно начинаться с ключевых слов. Кроме метки и присваивания. Поэтому предварительный просмотр пытается дойти до двоеточия или равенства вне скобок. Т.е. найти метку или присваивание. Иначе — это ключевое слово.
Все получается довольно изящно и просто. И я выкинул необходимость слова CALL и тоже ничего не сломалось. Правда, при ошибках, вместо «неописанный идентификатор» теперь идет сообщение «неописанная процедура». Но на этом и все.
При этом выражения типа
if = (if A; B else C);
в языке были изначально недопустимы.
Интересно, что другой автор в статье «В защиту PL/1» считает эту философию ошибочной и называет незарезервированные слова «бородавками языка».
Т.е. он не понимает, что цель была — добавление новых ключевых слов без изменения уже созданного ПО. Пример — я легко добавил русские ключевые слова и старое ПО не нужно было менять.
Я не считаю это ошибкой и бывали случаи, когда забывал, что есть такое ключевое слово и использовал его как идентификатор. Все нормально проходило. Но сейчас в ряде случаев, компилятор все-таки предупредит, что какая-нибудь GAMMA есть как встроенная функция языка. При этом код сгенерируется для GAMMA-идентификатора.
На всякий случай для разрешения подобных случаев имеется атрибут BUILTIN

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

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

Авторизация

Регистрация

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

Карта сайта


Содержание

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

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

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

Компилятор

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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




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

2020/09/29 12:03 ••• kt
Синтаксический сахар

2020/09/20 21:24 ••• Неслучайный читатель
Философия языка

2020/08/04 23:42 ••• Автор сайта
Короткие комментарии

2020/07/30 11:04 ••• kt
О PL/1 и почему в нём не зарезервированы ключевые слова

2020/07/29 10:00 ••• Тимофей
Энтузиасты-разработчики компиляторов и их проекты

2020/06/21 15:05 ••• рст256
Русский язык и программирование

2020/06/08 21:53 ••• kt
Поддержка профилирования кода программы на низком уровне

2020/05/02 20:59 ••• Denis Juriev aka D.V.J.
В защиту PL/1

2020/03/28 17:28 ••• Comdiv
Программирование без программистов — это медицина без врачей

2020/02/05 19:59 ••• Александр Коновалов aka Маздайщик
Обработка ошибок

2020/01/25 12:55 ••• kt
Тест. Какой Вы программист?

2019/12/18 11:34 ••• Noname
Программирование исчезнет. Будет дрессировка нейронных сетей