АЛГОЛ 68 (сокращение от Algorithmic Language 1968 ) — это императивный язык программирования , который был задуман как преемник языка программирования АЛГОЛ 60 , разработанный с целью гораздо более широкой сферы применения и более строго определенного синтаксиса и семантики.
Сложность определения языка, которое занимает несколько сотен страниц, заполненных нестандартной терминологией, затруднила реализацию компилятора , и было сказано, что у него «нет реализаций и нет пользователей». Это было правдой лишь отчасти; АЛГОЛ 68 действительно нашел применение на нескольких нишевых рынках, особенно в Соединенном Королевстве , где он был популярен на машинах International Computers Limited (ICL), а также в учебных целях. За пределами этих областей использование было относительно ограниченным.
Тем не менее, вклад АЛГОЛа 68 в область информатики был глубоким, обширным и устойчивым, хотя многие из этих вкладов были публично отмечены только тогда, когда они вновь появились в впоследствии разработанных языках программирования. Многие языки были разработаны специально в ответ на воспринимаемую сложность языка, наиболее заметным из которых был Pascal , или представляли собой повторные реализации для конкретных ролей, как Ada .
Многие языки 1970-х годов создавались именно по АЛГОЛу 68, отбирая некоторые функции и отказываясь от других, которые считались слишком сложными или выходящими за рамки определенных функций. Среди них — язык C , на который непосредственное влияние оказал АЛГОЛ 68, особенно его строгая типизация и структуры. Большинство современных языков, по крайней мере, часть своего синтаксиса восходят к C или Pascal и, таким образом, прямо или косвенно к ALGOL 68.
Возможности ALGOL 68 включают синтаксис на основе выражений, объявленные пользователем типы и структуры/объединения тегов, эталонную модель переменных и ссылочных параметров, нарезку строк, массивов и матриц, а также параллелизм.
АЛГОЛ 68 был разработан Рабочей группой 2.1 IFIP Международной федерации обработки информации (IFIP) по алгоритмическим языкам и исчислениям. 20 декабря 1968 года этот язык был официально принят группой, а затем одобрен для публикации Генеральной Ассамблеей ИФИП.
Алгол 68 был определен с использованием формализма , двухуровневой формальной грамматики , изобретенной Адрианом ван Вейнгаарденом . Грамматики Ван Вейнгаардена используют контекстно-свободную грамматику для создания бесконечного набора продуктов, которые распознают конкретную программу ALGOL 68; в частности, они способны выражать требования, которые во многих других технических стандартах языков программирования называются семантикой и должны быть выражены в склонной к неоднозначности прозе естественного языка, а затем реализованы в компиляторах в виде специального кода, прикрепленного к синтаксическому анализатору формального языка. .
АЛГОЛ 68 был первым (и, возможно, одним из последних) основных языков, для которого было дано полное формальное определение до его реализации.
ЦДХ Костер [8]
Основные цели и принципы проектирования АЛГОЛА 68:
Алгол 68 подвергался критике, особенно со стороны некоторых членов его комитета по проектированию, таких как К. А. Хоар и Эдсгер Дейкстра , за то, что он отказался от простоты АЛГОЛа 60 , стал средством реализации сложных или слишком общих идей и мало что сделал для облегчения задачи автора компилятора . проще, в отличие от нарочито простых современников (и конкурентов), таких как C , S-algol и Pascal .
В 1970 году АЛГОЛ 68-R стал первым работающим компилятором АЛГОЛА 68.
В версии 1973 года некоторые функции, такие как процедуры , гоммы [13] и формальные границы , были опущены. [14] См. формулировку непересмотренного отчета.r0
Хотя европейские оборонные ведомства (в Великобритании — Королевское учреждение сигналов и радиолокации (RSRE)) продвигали использование АЛГОЛА 68 из-за его ожидаемых преимуществ в области безопасности, американская сторона альянса НАТО решила разработать другой проект — язык Ada , сделав его использование обязательным. по оборонным контрактам США.
АЛГОЛ 68 также имел заметное влияние в Советском Союзе , подробности о котором можно найти в статье Андрея Терехова 2014 года: «АЛГОЛ 68 и его влияние на СССР и российское программирование», [15] и «Алгол 68 и его влияние». по программированию в СССР и России». [16]
Стив Борн , входивший в комитет по пересмотру ALGOL 68, перенес некоторые его идеи в свою оболочку Bourne (и, таким образом, в потомки оболочек Unix , такие как Bash ) и в C (и, следовательно, в потомки, такие как C++ ).
Полную историю проекта можно найти в книге CH Lindsey «История Алгола 68» . [17] [18]
Полное описание языка см. в «Программировании на ALGOL 68 Made Easy» [19] доктора Сиан Маунтбаттена или в «Изучение ALGOL 68 Genie» [20] Марселя ван дер Веера, которое включает пересмотренный отчет.
АЛГОЛ 68, как следует из названия, является продолжением языка АЛГОЛ , который был впервые формализован в 1960 году. В том же году Международная федерация обработки информации (IFIP) сформировала и основала Рабочую группу по АЛГОЛу, или WG2.1. Эта группа выпустила обновленную спецификацию АЛГОЛ 60 в Риме в апреле 1962 года. На последующем собрании в марте 1964 года было решено, что группа должна начать работу над двумя последующими стандартами, АЛГОЛ X , которые будут переопределением языка. с некоторыми дополнениями и АЛГОЛ Y , который имел бы возможность модифицировать свои собственные программы в стиле языка LISP . [21]
Первое собрание группы ALGOL X состоялось в Принстонском университете в мае 1965 года. В отчете о собрании отмечались две широко поддерживаемые темы: введение строгой типизации и интерес к концепциям Эйлера о «деревьях» или «списках» для работы с коллекциями. [22]
На второй встрече в октябре во Франции были представлены три официальных предложения: АЛГОЛ W Никлауса Вирта вместе с комментариями о структурах записей КАР (Тони) Хоара , аналогичный язык Герхарда Зегмюллера и статья Адриана ван Вейнгаардена о « Ортогональная конструкция и описание формального языка». Последний, написанный почти неразборчивой «W-грамматикой», оказался решающим сдвигом в эволюции языка. Встреча завершилась соглашением о том, что ван Вейнгаарден перепишет представление Вирта/Хора, используя свою W-грамматику. [22]
Эта, казалось бы, простая задача в конечном итоге оказалась сложнее, чем ожидалось, и последующую встречу пришлось отложить на шесть месяцев. Когда он собрался в апреле 1966 года в Кутвейке , проект ван Вейнгаардена остался незавершенным, и Вирт и Хоар представили версию, использующую более традиционные описания. Было общепринято, что их статья представляет собой «правильный язык в неправильном формализме». [23] По мере изучения этих подходов стало ясно, что существует разница в описании параметров, которые будут иметь реальные последствия, и хотя Вирт и Хоар протестовали против того, что дальнейшие задержки могут стать бесконечными, комитет решил дождаться ван Версия Вейнгаардена. Затем Вирт реализовал свое нынешнее определение как АЛГОЛ В. [24]
На следующей встрече в Варшаве в октябре 1966 года [25] был представлен первоначальный отчет Подкомитета ввода-вывода, который встречался в Национальной лаборатории Ок-Ридж и Университете Иллинойса, но еще не добился большого прогресса. Два предложения предыдущей встречи были снова рассмотрены, и на этот раз возникла новая дискуссия об использовании указателей ; АЛГОЛ W использовал их только для ссылки на записи, тогда как версия ван Вейнгаардена могла указывать на любой объект. Чтобы добавить путаницы, Джон Маккарти представил новое предложение по перегрузке операторов и возможности связывать вместе и /или конструкции, а Клаус Самельсон хотел разрешить анонимные функции . В результате возникшей путаницы возникла дискуссия о прекращении всех усилий. [24] Неразбериха продолжалась и на протяжении, как предполагалось, встречи по Алголу Y в Зандворте в мае 1967 года. [22]
Проект отчета был наконец опубликован в феврале 1968 года. Он был встречен «шоком, ужасом и несогласием» [22] в основном из-за сотен страниц нечитаемой грамматики и странной терминологии. Чарльз Х. Линдси попытался выяснить, какой «язык спрятан внутри него», [26] этот процесс занял шесть человеко-недель усилий. Получившаяся в результате статья «АЛГОЛ 68 с меньшим количеством разрывов» получила широкое распространение. На более широком совещании по обработке информации в Цюрихе в мае 1968 года участники жаловались, что им навязывали эту формулировку и что ИФИП был «настоящим злодеем в этой необоснованной ситуации», поскольку встречи были в основном закрытыми и не было формального механизма обратной связи. В то время Вирт и Питер Наур официально покинули свои авторские позиции в WG2.1. [26]
Следующее заседание WG2.1 состоялось в Тиррении в июне 1968 года. Предполагалось, что оно будет обсуждать выпуск компиляторов и другие вопросы, но вместо этого перешло к обсуждению языка. Ван Вейнгаарден в ответ заявил (или пригрозил), что опубликует только еще одну версию отчета. К этому моменту Наур, Хоар и Вирт отказались от участия в проекте, а еще несколько человек угрожали сделать это. [27] Последовало еще несколько встреч: в Норт-Бервике в августе 1968 года и в Мюнхене в декабре, в результате которых в январе 1969 года был опубликован официальный отчет, но также закончились написанием спорного отчета меньшинства. Наконец, в Банфе, Альберта , в сентябре 1969 года проект в целом был признан завершенным, и обсуждение в основном касалось исправлений и значительно расширенного введения к отчету. [28]
Усилия заняли пять лет, сожгли многие величайшие имена в области компьютерных наук и в нескольких случаях зашли в тупик из-за проблем как в определении, так и в группе в целом. Почти сразу же Хоар опубликовал «Критику Алгола 68» [29] , на которую широко ссылаются во многих работах. Вирт продолжил разработку концепции ALGOL W и выпустил ее под названием Pascal в 1970 году.
Первая реализация стандарта, основанная на проекте отчета конца 1968 года, была представлена Королевским радарным учреждением в Великобритании под названием АЛГОЛ 68-R в июле 1970 года. Однако это было подмножество полного языка, и Барри Майу , последний редактор Report, пошутил: «Это вопрос морали. У нас есть Библия, а вы грешите!» [30] Тем не менее, эта версия стала очень популярной на машинах ICL и стала широко используемым языком в военном программировании, особенно в Великобритании. [31]
Среди изменений в 68-R было требование объявлять все переменные перед их первым использованием. Это имело значительное преимущество, заключающееся в том, что компилятор мог работать в один проход, поскольку место для переменных в записи активации выделялось до ее использования. Однако это изменение также имело побочный эффект: требовалось объявлять PROC дважды: один раз как объявление типов, а затем снова как тело кода. Еще одним изменением было исключение предполагаемого режима VOID , выражения, которое не возвращает значения (называемого оператором на других языках) и требующего добавления слова VOID там, где оно предполагалось. Кроме того, в 68-R исключены явные команды параллельной обработки на основе PAR . [30]
Первая полная реализация языка была представлена в 1974 году CDC Нидерланды для серии мэйнфреймов Control Data . Это использовалось ограниченно, в основном при обучении в Германии и Нидерландах. [31]
Версия, похожая на 68-R, была представлена Университетом Карнеги-Меллона в 1976 году как 68S и снова представляла собой однопроходный компилятор, основанный на различных упрощениях оригинала и предназначенный для использования на небольших машинах, таких как DEC PDP-11 . Его тоже использовали в основном в учебных целях. [31]
Версия для мэйнфреймов IBM не стала доступна до 1978 года, когда она была выпущена Кембриджским университетом . Это было «почти завершено». Линдси выпустила версию для небольших машин, включая IBM PC , в 1984 году. [31]
Известны три реализации Algol 68 с открытым исходным кодом: [32]
«Ван Вейнгаарден однажды охарактеризовал четырех авторов, несколько иронично, как: Костер: транспьютер, Пек: синтаксис, Майу: исполнитель, Ван Вейнгаарден: партийный идеолог». – Костер.
1968: 20 декабря 1968 года «Заключительный отчет» (MR 101) был принят Рабочей группой, а затем одобрен Генеральной Ассамблеей ИФИП ЮНЕСКО для публикации. Переводы стандарта были сделаны на русский , немецкий , французский и болгарский , а затем на японский и китайский языки . [46] Стандарт также был доступен на языке Брайля .
1984: ТК 97 рассмотрел Алгол 68 для стандартизации как «Новый рабочий элемент» TC97/N1642 [2][3]. Западная Германия, Бельгия, Нидерланды, СССР и Чехословакия были готовы участвовать в подготовке стандарта, но СССР и Чехословакия «не были подходящими членами правильных комитетов ISO» [4], и стандартизация ISO в Algol 68 застопорилась. [5]
1988: Впоследствии АЛГОЛ 68 стал одним из стандартов ГОСТ в России.
Стандартный язык содержит около шестидесяти зарезервированных слов, обычно выделенных жирным шрифтом, а некоторые имеют эквиваленты «кратких символов»:
MODE , OP , PRIO , PROC , FLEX , HEAP , LOC , LONG , REF , SHORT , BITS , BOOL , BYTES , CHAR , COMPL , INT , REAL , SEMA , STRING , VOID , CHANNEL , FILE , FORMAT , STRUCT , UNION , AT "@", ЛИБО r0 , IS ":=:", ISNT IS NOT r0 ":/=:" ":≠:", OF "→" r0 , TRUE , FALSE , EMPTY , NIL "○", SKIP " ~", CO "¢", COMMENT "¢", PR , PRAGMAT , CASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC "( ~ | ~ |: ~ | ~ | ~ )", FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ OD , IF ~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI "( ~ | ~ |: ~ | ~ | ~ )", PAR BEGIN ~ END "( ~ )", GO TO , GOTO , EXIT " □" р0 .
Основная языковая конструкция — это единица . Единицей может быть формула , вложенное предложение , обычный текст или одна из нескольких технически необходимых конструкций (присваивание, переход, пропуск, ничто). Технический термин «прилагаемое предложение» объединяет некоторые конструкции, заключающие в скобки, известные как «блок » , «оператор do », «оператор переключения» в других современных языках. При использовании ключевых слов обычно для завершения вложения используется обратная последовательность символов вводного ключевого слова, например ( IF ~ THEN ~ ELSE ~ FI , CASE ~ IN ~ OUT ~ ESAC , FOR ~ WHILE ~ DO ~ OD ). Этот синтаксис защищенной команды был повторно использован Стивеном Борном в общей оболочке Unix Bourne . Выражение может также давать множественное значение , которое создается из других значений с помощью вспомогательного предложения . Эта конструкция выглядит как пакет параметров вызова процедуры.
Базовыми типами данных ( mode
на языке Алгола 68 они называются s) являются real
, int
, compl
( комплексное число ) , bool
, и . Например:char
bits
bytes
ИНТ n = 2; CO n имеет фиксированное значение 2. CO INT m := 3; CO m — это вновь созданная локальная переменная , значение которой изначально установлено равным 3. CO CO Это сокращение от ref int m = loc int := 3; CO REAL авогадро = 6,0221415⏨23; CO число Авогадро CO long long real long long pi = 3,14159 26535 89793 23846 26433 83279 50288 41971 69399 37510; COMPL квадратный корень из минус единицы = 0 ⊥ 1;
Однако объявление REAL x;
— это всего лишь синтаксический сахар для . То есть на самом деле это постоянный идентификатор ссылки на вновь созданную локальную переменную REAL .REF REAL x = LOC REAL;
x
Кроме того, вместо определения обоих float
и double
, или int
и long
и и short
т. д., АЛГОЛ 68 предоставляет модификаторы , так что текущее общее значение вместо этого double
будет записываться , например, как LONG REAL или LONG LONG REAL . Константы прелюдии и max real
предназначены min long int
для адаптации программ к различным реализациям.
Все переменные должны быть объявлены, но объявление не должно предшествовать первому использованию.
примитив-объявитель: INT , REAL , COMPL , COMPLEX G , BOOL , CHAR , STRING , BITS , BYTES , FORMAT , FILE , PIPE G , CHANNEL , SEMA .
Сложные типы можно создавать из более простых с помощью различных конструкторов типов:
Некоторые примеры см. в разделе «Сравнение АЛГОЛа 68 и C++» .
Другие символы объявления включают: FLEX , HEAP , LOC , REF , LONG , SHORT , EVENT S.
Имя режима (типа) можно объявить с помощью объявления MODE , которое похоже на TYPEDEF в C/C++ и TYPE в Паскале:
ИНТ макс=99; MODE newmode = [0:9][0:max] STRUCT ( LONG REAL a, b, c, SHORT INT i, j, k, REF REAL r );
Это похоже на следующий код C:
const int max = 99 ; typedef struct { double a , b , c ; короткий я , j , k ; плавать * р ; } новый режим [ 9 + 1 ] [ макс + 1 ];
В АЛГОЛе 68 слева от символа равенства появляется только индикация режима NEWMODE , и, что особенно важно, конструкция создается и может быть прочитана слева направо, независимо от приоритетов. Кроме того, нижняя граница массивов Algol 68 по умолчанию равна единице, но может быть любым целым числом от -max int до max int .
Объявления режима позволяют типам быть рекурсивными : определяться прямо или косвенно в терминах самих себя. На это распространяются некоторые ограничения – например, эти заявления являются незаконными:
MODE A = REF A MODE A = STRUCT ( A a, B b) MODE A = PROC ( A a) A
пока они действительны:
РЕЖИМ A = СТРУКТУРА ( REF A a, B b) MODE A = PROC ( REF A a) REF A
Принуждение порождает принуждение из принуждения в соответствии с тремя критериями: априорный способ принуждения до применения какого-либо принуждения, апостериорный способ принуждения, требуемый после этих принуждений, и синтаксическая позиция или «вид» принуждения . . Принуждения могут быть каскадными.
Шесть возможных принуждений называются депроцедурой , разыменованием , объединением , расширением , гребли и аннулированием . Каждое приведение, за исключением объединения , предписывает соответствующее динамическое воздействие на связанные значения. Следовательно, многие примитивные действия могут быть запрограммированы неявно посредством принуждения.
Сила контекста – разрешенные приведения:
В АЛГОЛе 68 имеется иерархия контекстов, определяющая тип приведения, доступный в конкретной точке программы. Эти контексты:
Более подробную информацию о первичных, вторичных, третичных и четвертичных типах см. в разделе «Приоритет операторов».
Прагматы — это директивы программы, обычно подсказки компилятору; в новых языках они называются «прагмы» (без «т»). например
Куча PRAGMAT =32 Куча PRAGMAT PR =32 PR
Комментарии можно вставлять разными способами:
¢ Оригинальный способ добавить свои 2 цента в программу ¢ КОММЕНТАРИЙ «жирный» комментарий КОММЕНТАРИЙ CO Стиль i комментарий CO# Комментарий к стилю ii #£ Это комментарий в виде решётки/решетки для британской клавиатуры £
Обычно в АЛГОЛе 68 комментарии не могут быть вложенными. Это ограничение можно обойти, используя различные разделители комментариев (например, использовать хэш только для временного удаления кода).
АЛГОЛ 68 является языком программирования, ориентированным на выражения , значение, возвращаемое оператором присваивания , является ссылкой на пункт назначения. Таким образом, следующий действительный код АЛГОЛА 68:
НАСТОЯЩАЯ половина пи, одно пи; одно пи := 2 * (половина пи := 2 * дуга tan(1))
Это понятие присутствует, среди прочего, в C и Perl . Обратите внимание, что, как и в более ранних языках, таких как Algol 60 и FORTRAN , в идентификаторах разрешены пробелы, так что half pi
это один идентификатор (таким образом можно избежать подчеркивания , верблюжьего регистра и всех проблем с строчными буквами ).
В качестве другого примера, чтобы выразить математическую идею суммы от i =1 до n, достаточно f(i)
следующего целочисленного выражения Алгола 68:
( INT sum:= 0; FOR i TO n DO sum +:= f(i) OD ; sum)
Обратите внимание, что, будучи целочисленным выражением, первый блок кода может использоваться в любом контексте, где может использоваться целочисленное значение . Блок кода возвращает значение последнего вычисленного выражения; эта идея присутствует в Лиспе , среди других языков.
Все составные операторы завершаются характерными закрывающими скобками:
IF условие THEN операторы [ ELSE операторы] FI «краткая» форма: (условие | утверждения | утверждения )
IF условие1 THEN операторы ELIF условие2 THEN операторы [ ELSE операторы ] FI «краткая» форма: (условие1 | операторы |: условие2 | операторы | операторы )
Эта схема не только позволяет избежать проблемы с висячим else , но также позволяет избежать использования BEGIN
and END
во встроенных последовательностях операторов .
CASE переключатель IN операторы, операторы,... [ OUT операторы ] ESAC «краткая» форма: (переключатель | утверждения, утверждения,... | утверждения )
CASE switch1 IN операторы, операторы,... OUSE switch2 IN операторы, операторы,... [ OUT операторы ] ESAC "краткая" форма оператора CASE : ( switch1 | операторы, операторы,... |: switch2 | операторы, операторы ,... | высказывания )
Пример предложения выбора с краткими символами:
PROC дней в месяце = ( INT год, месяц) INT : (месяц| 31, (год÷×4=0 ∧ год÷×100≠0 ∨ год÷×400=0 | 29 | 28 ), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
Пример предложения выбора, выделенного жирным шрифтом:
PROC дней в месяце = ( INT год, месяц) INT : CASE месяц IN 31, ЕСЛИ год MOD 4 EQ 0 И год MOD 100 NE 0 ИЛИ год MOD 400 EQ 0 THEN 29 ELSE 28 FI , 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ЭСАК ;
Пример предложения выбора, сочетающего жирные и краткие символы:
PROC дней в месяце = ( INT год, месяц) INT : CASE месяц IN¢янв.¢ 31,¢Фев¢ (год MOD 4 = 0 И год MOD 100 ≠ 0 ИЛИ год MOD 400 = 0 | 29 | 28 ),¢Мар¢ 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ¢ по декабрь ¢ ЭСАК ;
Algol68 позволял использовать переключатель либо типа INT , либо (единственно) UNION . Последнее позволяет применять строгую типизацию к переменным UNION . см., например, объединение ниже.
[ Индекс FOR ] [ FROM first ] [ BY инкремент ] [ TO Last ] [ WHILE условие ] Операторы DO OD Минимальная форма «предложения цикла» следующая: Операторы DO OD
Это считалось «универсальным» циклом , полный синтаксис:
ДЛЯ i ОТ 1 ОТ -22 ДО -333 ПОКА i×i≠4444 DO ~ OD
У конструкции есть несколько необычных аспектов:
INT сумма sq:=0; ДЛЯ Я ПОКА print(("Пока:",i,newline)); сумма кв≠70↑2ДЕЛАТЬ сумма sq+:=i↑2ОД
Последующие «расширения» стандарта Algol68 позволили заменить синтаксический элемент TO на UPTO и DOWNTO для достижения небольшой оптимизации. Те же компиляторы также включили:
Дополнительные примеры можно найти в примерах кода ниже.
АЛГОЛ 68 поддерживает массивы любого числа измерений и позволяет разрезать целые или частичные строки или столбцы.
РЕЖИМ ВЕКТОР = [1:3] РЕАЛЬНЫЙ ; # векторное объявление MODE (typedef) # MODE MATRIX = [1:3,1:3] REAL ; # объявление матрицы MODE (typedef) # VECTOR v1 := (1,2,3); # переменная массива изначально (1,2,3) # [] REAL v2 = (4,5,6); # константный массив, тип эквивалентен VECTOR , границы подразумеваются # OP + = ( VECTOR a,b) VECTOR : # определение бинарного OP erator # ( VECTOR out; FOR i FROM ⌊a TO ⌈a DO out[i] := a [i]+b[i] OD ;выход); МАТРИЦА m := (v1, v2, v1+v2); печать ((m[,2:])); # фрагмент 2-го и 3-го столбцов #
Матрицы можно разрезать любым способом, например:
ССЫЛОЧНЫЙ ВЕКТОР строка = m[2,]; # определяем REF (указатель) на вторую строку # REF VECTOR col = m[,2]; # определяем REF (указатель) на второй столбец #
АЛГОЛ 68 поддерживает структуры нескольких полей ( STRUCT ) и объединенные режимы . Ссылочные переменные могут указывать на любой MODE , включая срезы массива и поля структуры.
В качестве примера всего этого приведем традиционное объявление связанного списка:
MODE NODE = UNION ( VOID , REAL , INT , COMPL , STRING ), LIST = STRUCT ( NODE val, REF LIST next);
Пример использования UNION CASE NODE :
Объявления процедур ( PROC ) требуют указания типа как для параметров, так и для результата ( VOID , если нет):
PROC max of real = ( REAL a, b) REAL : IF a > b THEN a ELSE b FI ;
или, используя «краткую» форму условного оператора:
PROC max of real = ( REAL a, b) REAL : (a>b | a | b);
Возвращаемое значение a proc
— это значение последнего выражения, вычисленного в процедуре. Ссылки на процедуры ( ref proc ) также разрешены. Параметры вызова по ссылке предоставляются путем указания ссылок (например, ref real
) в формальном списке аргументов. В следующем примере определяется процедура, которая применяет функцию (указанную как параметр) к каждому элементу массива:
PROC apply = ( REF [] REAL a, PROC ( REAL ) REAL f): FOR i FROM LWB a TO UPB a DO a[i] := f(a[i]) OD
Такая простота кода была недостижима в предшественнике АЛГОЛА 68, АЛГОЛЕ 60 .
Программист может определять новые операторы , причем как те, так и заранее определенные операторы могут быть перегружены , а их приоритеты могут быть изменены программистом. В следующем примере определяется оператор MAX
как с диадической, так и с монадической версиями (сканирование элементов массива).
ПРИО МАКС = 9; OP MAX = ( INT a,b) INT : ( a>b | a | b ); OP MAX = ( REAL a,b) REAL : ( a>b | a | b ); OP MAX = ( COMPL a,b) COMPL : ( ABS a > ABS b | a | b ); OP MAX = ([] REAL a) REAL : ( REAL out := a[ LWB a]; FOR i FROM LWB a + 1 TO UPB a DO ( a[i]>out | out:=a[i]) OD ; вне)
Технически это не операторы, а скорее считаются «единицами, связанными с именами».
Конкретные детали:
Технически это не операторы, а скорее считаются «единицами, связанными с именами».
Примечание. Кватернарии включают имена SKIP и ~.
":=:" (альтернативно " IS ") проверяет, равны ли два указателя; ":/=:" (альтернативно " ISNT ") проверяет, не равны ли они.
Зачем нужны :=: и :/=:: попробуйте сравнить два значения указателя, например следующие переменные, объявленные как указатели на целое число:
REF INT ip, jp
Теперь рассмотрим, как определить, указывают ли эти два на одно и то же место или один из них указывает на NIL . Следующее выражение
ip = jp
разыменует оба указателя до значений типа INT и сравнит их, поскольку оператор "=" определен для INT , но не REF INT . Недопустимо определять "=" для операндов типа REF INT и INT одновременно, поскольку тогда вызовы становятся неоднозначными из-за неявных приведений, которые могут быть применены: если операнды оставить как REF INT и эту версию оператор звонил? Или их следует разыменовать в дальнейшем на INT и вместо этого использовать эту версию? Поэтому следующее выражение никогда не может быть признано законным:
ip = NIL
Отсюда необходимость в отдельных конструкциях, не подпадающих под действие обычных правил приведения операндов к операторам. Но есть одна загвоздка. Следующие выражения:
ip :=: jp
ip :=: NIL
будучи законным, он, вероятно, не сделает того, чего можно было бы ожидать. Они всегда будут возвращать FALSE , поскольку сравниваются фактические адреса переменных ip
и jp
, а не то, на что они указывают . Чтобы добиться нужного эффекта, пришлось бы написать
ip :=: REF INT(jp)
ip :=: REF INT(NIL)
Большинство «специальных» символов Алгола (⊂, ≡, ␣, ×, ÷, ≤, ≥, ≠, ¬, ⊃, ≡, ∨, ∧, →, ↓, ↑, ⌊, ⌈, ⎩, ⎧, ⊥, ⏨, ¢, ○ и □) можно найти на клавиатуре IBM 2741 со вставленной печатающей головкой APL «мяч для гольфа»; они стали доступны в середине 1960-х годов, когда разрабатывался Алгол 68. Эти символы также являются частью стандарта Unicode , и большинство из них доступны в нескольких популярных шрифтах .
Транспут — это термин, используемый для обозначения средств ввода и вывода Алгола 68. Он включает в себя заранее определенные процедуры для неформатированной, форматированной и двоичной передачи. Файлы и другие устройства передачи обрабатываются согласованным и машинонезависимым образом. В следующем примере выводится неформатированный вывод на стандартное устройство вывода :
print ((новая страница, «Название», новая строка, «Значение i равно», i, "и x[i] есть ", x[i], новая строка))
Обратите внимание на предопределенные процедуры newpage
, newline
передаваемые в качестве аргументов.
Транспутация состоит из КНИГ , КАНАЛОВ и ФАЙЛОВ :
match
.establish, create, open, associate, lock, close, scratch
.char number, line number, page number
.space
, backspace
, newline
, newpage
.get good line, get good page, get good book
, иPROC set=(REF FILE f, INT page,line,char)VOID:
on logical file end, on physical file end, on page end, on line end, on format end, on value error, on char error
.«Форматированная передача» в передаче ALGOL 68 имеет свой собственный синтаксис и шаблоны (функции), при этом FORMAT встроен между двумя символами $. [49]
Примеры:
printf (($2l"Сумма:"x, g(0)$, m + n)); ¢ печатается так же, как: ¢ print ((новая строка, новая строка, «Сумма равна:», пробел, целое (m + n, 0))
АЛГОЛ 68 поддерживает программирование параллельной обработки. С помощью ключевого слова PAR вспомогательное предложение преобразуется в параллельное предложение , где синхронизация действий контролируется с помощью семафоров . В A68G параллельные действия отображаются в потоки, если они доступны в операционной системе хоста . В A68S была реализована другая парадигма параллельной обработки (см. ниже).
PROC eat = VOID : ( muffins-:=1; print(("Ням!", новая строка))), говорить = VOID : (words-:=1; print(("Як...",новая строка))); INT кексы:= 4, слова:= 8; Устье SEMA = УРОВЕНЬ 1; PAR НАЧИНАЕТСЯ , ПОКА кексы > 0 ДЕЛАТЬ ВНИЗ рта; есть; ВВЕРХ рот ОД , В то время как слова > 0 ДЕЛАТЬ ВНИЗ рот; говорить; ВВЕРХ рот OD КОНЕЦ
Этот пример программы реализует «Решето Эратосфена» для поиска всех простых чисел меньше 100. NIL — это аналог нулевого указателя в АЛГОЛе 68 в других языках. Обозначение x OF y обращается к элементу x структуры STRUCT y .
НАЧАЛО # Сито простых чисел Алгол-68, функциональный стиль # Ошибка PROC = ( STRING s) VOID : (print(( новая строка, "ошибка: ", s, новая строка)); ПЕРЕЙТИ к остановке); PROC от одного до = ( INT n) СПИСОК : ( PROC f = ( INT m,n) LIST : (m>n | NIL | cons(m, f(m+1,n))); f(1,n)); СПИСОК РЕЖИМОВ = ОПОРНЫЙ УЗЕЛ ; MODE NODE = STRUCT ( INT h, LIST t); PROC cons = ( INT n, LIST l) LIST : HEAP NODE := (n,l); PROC hd = ( LIST l) INT : ( l IS NIL | error("hd NIL "); SKIP | h OF l); PROC tl = ( LIST l) LIST : ( l IS NIL | error("tl NIL "); SKIP | t OF l); PROC show = ( LIST l) VOID : ( l ISNT NIL | print((" ",whole(hd(l),0))); show(tl(l))); PROC фильтр = ( PROC ( INT ) BOOL p, LIST l) LIST : IF l IS NIL THEN NIL ELIF p(hd(l)) THEN cons(hd(l), filter(p,tl(l))) ELSE filter (p, tl(l)) FI ; PROC sieve = ( LIST l) LIST : IF l IS NIL THEN NIL ELSE PROC not Multiple = ( INT n) BOOL : n MOD hd(l) ~= 0; cons(hd(l), сито( фильтр( не кратный, tl(l) ))) ФИ ; Простые числа PROC = ( INT n) LIST : sieve(tl(one to(n))); показать(простые числа(100))КОНЕЦ
Примечание. Компьютеры советской эпохи Эльбрус-1 (Эльбрус-1) и Эльбрус-2 были созданы с использованием языка высокого уровня Эль-76 (АЛ-76), а не традиционной сборки. Эль-76 похож на Алгол-68. Основное отличие — типы динамической привязки в Эль-76, поддерживаемые на аппаратном уровне. Эль-76 используется для приложений, управления заданиями, системного программирования. [53]
И АЛГОЛ 68C , и АЛГОЛ 68-R написаны на АЛГОЛ 68, что фактически делает АЛГОЛ 68 самостоятельным приложением. Другие приложения включают в себя:
Особенностью АЛГОЛА 68, унаследованной от традиции АЛГОЛА , являются его различные представления. Существует язык представления , используемый для описания алгоритмов в печатных работах, строгий язык (строго определенный в Отчете) и официальный справочный язык , предназначенный для использования во входных данных компилятора. В примерах присутствуют слова, набранные ЖИРНЫМ шрифтом, это СТРОГО язык. Зарезервированные слова АЛГОЛа 68 фактически находятся в другом пространстве имен , чем идентификаторы, и в идентификаторах разрешены пробелы, поэтому следующий фрагмент является допустимым:
INT реальный int = 3 ;
Программист, который пишет исполняемый код, не всегда имеет возможность использовать ЖИРНЫЙ шрифт или подчеркивание в коде, поскольку это может зависеть от аппаратного обеспечения и культурных особенностей. Были разработаны различные методы обозначения этих идентификаторов. Это называется стропинг- режимом . Например, все или некоторые из следующих представлений могут быть доступными программными представлениями :
INT реальное int = 3; # СТРОГО язык #'INT'A REAL INT = 3; # ЦИТАТА обрезает стиль #.INT РЕАЛЬНОЕ INT = 3; # Стиль обрезки POINT # INT реальное int = 3; # ВЕРХНИЙ стиль обрезки # интервал a_real_int = 3; # Стиль ограничения RES, разрешено 61 зарезервированное слово #
Все реализации должны распознавать как минимум POINT, UPPER и RES внутри разделов PRAGMAT. Из них ограничение POINT и UPPER довольно распространено, тогда как ограничение RES противоречит спецификации (поскольку в нем нет зарезервированных слов). ЦИТАТА (кавычка с одинарным апострофом) была первоначальной рекомендацией, тогда как кавычки с совпадающим апострофом, распространенные в АЛГОЛе 60, не часто используются в АЛГОЛе 68. [56]
Следующие символы были рекомендованы для переносимости и названы «достойными символами» в Отчете о стандартном аппаратном представлении Алгола 68, заархивированном 2 января 2014 г. на Wayback Machine :
Это отражало проблему 1960-х годов, когда некоторое оборудование не поддерживало ни строчные буквы, ни некоторые другие символы, отличные от ASCII , действительно, в отчете 1973 года было написано: «Четыре достойных символа — «|», «_», «[ «и «]» — часто кодируются по-разному, даже на установках, номинально использующих один и тот же набор символов».
АЛГОЛ 68 позволяет каждому естественному языку определять свой собственный набор ключевых слов Алгол-68. В результате программисты могут писать программы, используя ключевые слова своего родного языка. Ниже приведен пример простой процедуры расчета «на следующий день», код на двух языках: английском и немецком. [ нужна цитата ]
# Дата следующего дня - английский вариант # MODE DATE = STRUCT ( INT день, STRING месяц, INT год); PROC следующего дня = ( ДАТА x) ДАТА : ЕСЛИ день x < длина месяца (месяц x , год x ) THEN (день x + 1, месяц x , год x ) ELIF месяц x = " Декабрь" THEN (1, "Январь", год x + 1) ELSE (1, последующий месяц (месяц x ), год x ) FI ;
# Nachfolgetag - Deutsche Variante # MENGE DATUM = TUPEL ( тег GANZ , WORT monat, GANZ jahr); FUNKTION naechster tag nach = ( DATUM x) DATUM : WENN tag VON x < monatslaenge(monat VON x, jahr VON x) DANN (tag VON x + 1, monat VON x, jahr VON x) WENNABER monat VON x = "Декабрь" ДАНН (1, "Январь", яр VON x + 1) ANSONSTEN (1, nachfolgemonat(monat VON x), jahr VON x) ENDEWENN ;
Русский/советский пример: на английском языке оператор случая Algol68 читается CASE ~ IN ~ OUT ~ ESAC , на кириллице это читается выб ~ в ~ либо ~ быв .
Из-за своей технической сложности АЛГОЛ 68 нуждается в роге изобилия методов, позволяющих отрицать существование чего-либо:
ПРОПУСК , "~" или "?" C – неопределенное значение, всегда синтаксически допустимое, EMPTY – единственное значение, допустимое для VOID , необходимое для выбора VOID в UNION , VOID – синтаксически как MODE , но не одно, NIL или «○» – имя, ничего не обозначающее, неопределенный эталонный режим,() или конкретно [1:0] INT — вакуум — это пустой массив (здесь конкретно MODE [] INT ). undefined – процедура отчетов по стандартам, вызывающая исключение в системе времени выполнения.ℵ — используется в отчете о стандартах для предотвращения самоанализа определенных типов. например, SEMA
другие примеры ℵ см. ниже.
Термин NIL IS var всегда оценивается как TRUE для любой переменной (но см. выше правильное использование IS :/=:), тогда как неизвестно, какое значение оценивается сравнением x < SKIP для любого целого числа x .
АЛГОЛ 68 намеренно оставляет неопределенным то, что происходит в случае целочисленного переполнения , представление целочисленных битов и степень числовой точности для чисел с плавающей запятой. Напротив, язык Java подвергался критике за чрезмерную спецификацию последнего.
Оба официальных отчета включали некоторые расширенные функции, которые не были частью стандартного языка. Они были отмечены знаком ℵ и считались фактически частными. Примеры включают «≮» и «≯» для шаблонов, OUTTYPE / INTYPE для грубого набора текста , а также операторы STRAIGHTOUT и STRAIGHTIN для «выпрямления» вложенных массивов и структур.
Выдержка из отчета 1973 года:
§10.3.2.2. Режимы транспортировкиа) MODE ℵ SIMPLOUT = UNION (≮ℒ INT ≯, ≮ℒ REAL ≯, ≮ℒ COMPL ≯, BOOL , ≮ℒ bits≯, CHAR , [ ] CHAR );б) MODE ℵ OUTTYPE = ¢ фактический – объявитель, указывающий объединенный режим из достаточного набора режимов, ни один из которых не является «пустым» или не содержит «гибких», «ссылка на», «процедуру» или «объединение» ¢;в) MODE ℵ SIMPLIN = UNION (≮ REF ℒ INT ≯, ≮ REF ℒ REAL ≯, ≮ REF ℒ COMPL ≯, REF BOOL , ≮ REF ℒ BITS ≯, REF CHAR , REF [ ] CHAR , REF STRING );г) РЕЖИМ ℵ ТИП = ¢ ... ¢; §10.3.2.3. Выпрямлениеa) OP ℵ STRAIGHTOUT = ( OUTTYPE x) [ ] SIMPLOUT : ¢ результат «выпрямления» 'x' ¢;б) OP ℵ STRAIGHTIN = ( INTYPE x) [ ] SIMPLIN : ¢ результат выпрямления 'x' ¢;
Если не указано иное (с надстрочным индексом ), вышеописанный текст используется в «Пересмотренном отчете (r1) ».
Исходный язык (согласно «Итоговому отчету» r0 ) отличается синтаксисом приведения режима и имеет функцию обработки , то есть принудительного приведения значения термина в процедуру, которая оценивает этот термин. Целью процедуры было бы сделать вычисления ленивыми . Наиболее полезным применением могла бы быть сокращенная оценка логических операторов. В:
OP ANDF = ( BOOL a, PROC BOOL b) BOOL :(a | b | FALSE ); OP ORF = ( BOOL a, PROC BOOL b) BOOL :(a | TRUE | b);
b оценивается только в том случае, если a истинно.
Как определено в АЛГОЛе 68, это не работало должным образом, например в коде:
IF FALSE ANDF CO proc bool: CO ( print («Не должно выполняться»); TRUE ) THEN ...
вопреки наивным ожиданиям программистов, печать будет выполнена, поскольку обработано только значение разработанного вложенного предложения после ANDF . Текстовая вставка закомментированного PROC BOOL : заставляет его работать.
Некоторые реализации эмулируют ожидаемое поведение для этого особого случая путем расширения языка.
Перед доработкой программист мог решить, что аргументы процедуры будут оцениваться последовательно, а не побочно, используя точки с запятой вместо запятых ( гомм ).
Например в:
PROC- тест = ( REAL a; REAL b) :......тест (х ПЛЮС 1, х);
Первый аргумент проверки гарантированно будет оценен раньше второго, но как обычно:
PROC- тест = ( REAL a, b):......тест (х ПЛЮС 1, х);
тогда компилятор мог оценивать аргументы в любом порядке.
После пересмотра отчета были предложены некоторые расширения формулировок для расширения сферы применения:
ENVIRON
и USING
из АЛГОЛа 68C [59]На данный момент в Algol 68 Genie реализована лишь частичная параметризация.
Язык S3 , который использовался для написания операционной системы ICL VME и многих других системных программ в серии ICL 2900 , был прямым производным от Algol 68. Однако в нем были опущены многие из более сложных функций и заменены базовые режимы набором типов данных, которые напрямую связаны с аппаратной архитектурой серии 2900.
АЛГОЛ 68R (R) от RRE был первой реализацией подмножества АЛГОЛ 68, работающей на ICL 1900 . В исходном языке основными ограничениями подмножества были определение перед использованием и отсутствие параллельной обработки. Этот компилятор был популярен в университетах Великобритании в 1970-х годах, где многие студенты -компьютерщики изучали АЛГОЛ 68 как свой первый язык программирования; компилятор был известен хорошими сообщениями об ошибках.
ALGOL 68RS (RS) от RSRE представлял собой портативную систему компилятора, написанную на ALGOL 68RS (загруженную из ALGOL 68R) и реализованную на различных системах, включая ICL 2900 / Series 39 , Multics и DEC VAX/VMS . Язык был основан на пересмотренном отчете, но с ограничениями подмножества, аналогичными ALGOL 68R. Этот компилятор сохранился в виде компилятора Algol68-to-C.
В АЛГОЛе 68S (S) от Университета Карнеги-Меллона возможности параллельной обработки были улучшены за счет добавления ортогонального расширения eventing . Любое объявление переменной, содержащее ключевое слово EVENT , делало присвоения этой переменной допускающими параллельное вычисление, т. е. правая часть превращалась в процедуру, которая перемещалась в один из процессоров многопроцессорной системы C.mmp . Доступ к таким переменным задерживался после завершения задания.
Cambridge ALGOL 68C (C) был портативным компилятором, реализовавшим подмножество ALGOL 68, ограничивающее определения операторов и опускающее сборку мусора, гибкие строки и форматированную передачу.
Algol 68 Genie (G) М. ван дер Веера — это реализация ALGOL 68 для современных компьютеров и операционных систем.
«Несмотря на благие намерения, программист может нарушить переносимость, непреднамеренно применив локальное расширение. Чтобы защититься от этого, каждая реализация должна предоставить прагматическую опцию PORTCHECK. Пока эта опция действует, компилятор печатает сообщение для каждой конструкции, которую он распознает как нарушая некоторые ограничения переносимости». [67]
{{cite book}}
: |journal=
игнорируется ( помощь ){{cite web}}
: CS1 maint: архивная копия в заголовке ( ссылка ){{cite web}}
: CS1 maint: архивная копия в заголовке ( ссылка )