INTERCAL

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 20:14, 1 июня 2016.
INTERCAL
Парадигма эзотерический
Спроектировано Дон Вудс, Джеймс М. Лайон
Первый   появившийся 1972
Лицензия GNU General Public licence
Портал: http://www.catb.org/~esr/intercal/
Влияние
Befunge, Brainfuck, Malbolge, Unlambda, LOLCODE
Дон Вудс в 2010
Джеймс Лайон в 2005

INTERCAL (абр. The Compiler Language With No Pronounceable Acronym - Компилируемый Язык С Непроизносимым Акронимом) - эзотерический язык программирования, созданный в 1972 году Дон Вудсом и Джеймсом Лионом в качестве шутки-пародии на языки программирования того времени. Несмотря на всю экзотичность, INTERCAL является полным по Тьюрингу, то есть, на нём можно вычислить всё, что и на «нормальном» языке программирования.

История

Язык стандартизован в основном его первой реализацией, INTERCAL-72, на совместимость с которой ориентируются последующие реализации. Большинство реализаций привносят в язык что-то свое, будь это альтернативный формат ввода-вывода или элементы квантовых вычислений. Особенности оригинальной реализации (например, случайные ошибки или стилистику сообщений об ошибках) тщательно сохраняются и переносятся в новые реализации.

Особенности

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

DO :1 <- #0¢#256

Любой разумный программист сказал бы, что это абсурд. INTERCAL имеет много других особенностей, сделанных специально, чтобы сделать написание программ еще более неудобным для программиста: он использует такие выражения, как "READ OUT", "IGNORE", "FORGET", выражение "PLEASE". Последнее должно встречаться в программе достаточно часто, чтобы компилятор не посчитал автора излишне грубым, но не слишком часто, чтобы не быть излишне вежливым.

Несмотря на преднамеренную тупость и нелепость синтаксиса, INTERCAL полон по Тьюрингу: он может решить любую задачу, которую может решить универсальная машина Тьюринга. Хотя делает он это ужасно медленно. Так, программа вычисляющая все простые числа от 1 до 65536 работала 17 часов, в то время как программа, написанная на С, выполнила задачу за 0.5 секунды.

Справочное руководство

Современные эзотерические языки концентрируют свою необычность в самой сути языка, а их руководства ограничиваются сухими фактологическими описаниями команд и особенностей. В случае INTERCAL авторы пошли другим путем: в описании языка программирования "The INTERCAL Programming Language Reference Manual" наполнен эпиграфами из «Алисы в Стране Чудес» и ехидными комментариями, сказанными совершенно серьезным тоном. Кроме того, специально для этого языка авторы разработали систему эвфемизмов для использующихся служебных символов: ' — искра, " — кроличьи ушки, . — пятно, : — двойное пятно, , — хвост, ; — гибрид, $ — большие деньги, ~ — загогулина и т.д. (полный список прилагается к руководству)1.

От авторов

  • INTERCAL — очень простой для изучения язык, и можно было бы предположить, что он будет хорош для инициации программистов-новичков. На самом деле он скорее подтолкнет программиста к поиску другой работы.
  • В INTERCAL есть 5 операторов — 2 бинарных и 3 унарных. Впрочем, в некотором смысле все операторы бинарны, поскольку все они оперируют с двоичным представлением аргументов, но эта игра слов уводит нас в сторону от изложения.
  • Приоритет операторов определяется следующим образом: (остаток страницы целенаправленно оставлен пустым — не забывайте, что создатели INTERCAL ставили своей целью отсутствие приоритетов).
  • Каждой команде программы можно задать вероятность, с которой она будет выполняться при запуске программы. Кроме того, существуют команды, которые блокируют выполнение последующих команд определенного типа или изменения переменных.
  • Числа выводятся в римской записи, а вводятся словами по одной цифре на любом языке, который поддерживает компилятор. Ввод-вывод символов реализован по-разному в разных компиляторах, и в любом случае слишком ужасен, чтобы описывать его здесь.

Сообщения об ошибках

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

  • E252 «Я забыл, что я собирался сказать» — ошибка переполнения памяти при операциях ввода-вывода
  • E182 «Кажется, тебе очень нравится эта метка» — ошибка использования одной и той же метки несколько раз.
  • E405 «Программа отвергнута из соображений психического здоровья» сигнализирует об использовании команд многопоточности или вычислений с откатами без соответствующей опции компилятора
  • E017 «Что, я правда должен с этим разобраться?» — об использовании констант неправильного диапазона,
  • E127 «Говорить „абракадабра“ без волшебной палочки совершенно бесполезно» — о том, что стандартная библиотека не подключена.

Некоторые ошибки вообще не имеют аналогов в других языках:

  • E079 «Программист недостаточно вежлив» и E099 «Программист слишком вежлив» относятся к количеству идентификаторов команды PLEASE в программе (никакой другой смысловой нагрузки идентификатор PLEASE не несет)
  • E774 «Случайный баг компилятора» полностью соответствует своему названию — возникает случайно и при повторной компиляции обычно пропадает
  • E995 «Что, я правда должен был это реализовать?» возникает при попытке выполнить код, который еще не написан (только не спрашивайте, как это можно сделать!)

Синтаксис

Ввод (WRITE IN) и вывод (READ OUT) не используют обычные форматы. В INTERCAL-72 инструкция WRITE IN принимает числа, записанные в виде английских слов-названий цифр (например SIX FIVE FIVE THREE FIVE), а READ OUT печатает в формате римских цифр. Более современные версии имеют собственные форматы.

Комментарии получаются, если в строке встречается идентификатор NOT или N'T. Такие строки будут игнорированы компилятором.

Структуры данных

INTERCAL-72 имел всего 4 типа данных: 16-битное целое (записывается с использованием . так же "пятно"), 32-битное целое (: "двойное пятно"), массив 16-битных целых (, "хвост"), и массив 32-битных целых (; он же "гибрид").

Программисту доступно 65535 переменных любого типа, от 1 до 65535. Причем каждая из этих переменных имеет собственный стек, над которым доступны операции push и pop (STASHed и RETRIEVEd, в терминологии INTERCAL), что сильно увеличивает возможную сложность структур данных. Массивы могут быть многомерными. Так же можно использовать целые константы от 0 до 65535 (записываются с помощью #)

Операторы

В INTERCAL-72 всего 5 операторов.

INTERCAL operators
Operator INTERCAL-72 characters
INTERLEAVE / MINGLE c backspace /
SELECT ~
AND &
OR V
XOR V backspace -

В противоположность большинству других языков, операторы AND, OR, и XOR - унарные, которые работают с последовательностью битов собственных аргументов; самый значительный бит (имеющий наибольший вес) результата получается путем применения оператора к самому значительному и самому незначительному биту входного аргумента, второй по значимости бит результата - оператор, примененный к 1 и 2 по значимости битам, третий по значимости бит - результат применения оператора к 2 и 3 по значимости битам аргумента и так далее. Оператор помещается между типом переменной или константы и ее номером, или просто внутри группирующих знаков.

SELECT и INTERLEAVE - инфиксные бинарные операторы; SELECT берет биты первого оператора, которые соответствуют "1" битам второго операнда и удаляет биты, которые соответствуют "0". Например, 51 (110011 в двоичном) SELECT 21 (10101) = 5 (101 в двоичном);

MINGLE чередует биты своего первого и второго операнда (в таком порядке, что самый младший бит второго операнда - самый младший бит результата)

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

Управляющие структуры

В INTERCAL инструкции всегда начинаются с специального идентификатора: в INTERCAL-72 это может быть DO, PLEASE и PLEASE DO, каждая из которых делает одно и то же (но использование одной и той же конструкции много раз подряд может вызвать ошибку компиляции), или в инвертированной форме, если добавить в конец идентификатора NOT или N'T

В начале строки может быть записана необязательная строка в виде целого числа в круглых скобках - метка. В конце выражения можно записать строку в виде %50, которая означает вероятность выполнения команды. (изначально 100%)

В INTERCAL-72, основные инструкции управления - это NEXT, RESUME, и FORGET.

DO (N) NEXT переход на строку N и занесение следующей строки, которая не была выполнена, в стек.

DO FORGET expression удаляет вхождения expression из головы стека.

DO RESUME expression удаляет вхождения expression из стека вызовов и переходит на самую недавно помещенную в стек строку.

CLC-INTERCAL и новейшие версии C-INTERCAL так же поддерживают COME FROM (DO COME FROM expression) и NEXT FROM, который делает то же самое, но еще и сохраняет адрес возврата.

Так же, повлиять на ход выполнения программы можно с помощью инструкций IGNORE и REMEMBER примененные к переменным (которые заставляют компилятор игнорировать команды присвоения значений переменной), а так же ABSTAIN и REINSTATE, заставляющие пропускать строки кода.

Примеры

Традиционная программа "Hello, world!" демонстрирует, как сильно INTERCAL отличается от обычных языков программирования. В Си это бы выглядело так:

#include <stdio.h>

int main(void) {
    printf("Hello, world!\n");
    return 0; // _exit(0);
}

Аналогичная программа на INTERCAL более длинная и запутанная:

DO ,1 <- #13
PLEASE DO ,1 SUB #1 <- #238
DO ,1 SUB #2 <- #108
DO ,1 SUB #3 <- #112
DO ,1 SUB #4 <- #0
DO ,1 SUB #5 <- #64
DO ,1 SUB #6 <- #194
DO ,1 SUB #7 <- #48
PLEASE DO ,1 SUB #8 <- #22
DO ,1 SUB #9 <- #248
DO ,1 SUB #10 <- #168
DO ,1 SUB #11 <- #24
DO ,1 SUB #12 <- #16
DO ,1 SUB #13 <- #162
PLEASE READ OUT ,1
PLEASE GIVE UP

Программа, инкрементирующая переменную .1:

(2000)	PLEASE DO STASH .1 + .2 + .3
	DO .2 <- #1
	DO (2001) NEXT
(2001)	PLEASE FORGET #1
	DO .3 <- "?!1~#1'$#1"~#3
	DO (2002) NEXT
	PLEASE DO .2 <- !2$#1'~'#65535$#1'
	DO .1 <- .1~#65534
	DO (2001) NEXT
(2002)	PLEASE DO (2003) NEXT
	DO RETRIEVE .1
	DO .3 <- .1
	PLEASE DO .1 <- '?.2$.3'~'#0$#65535'
	DO RETRIEVE .2 + .3
	DO RESUME #2
(2003)	DO RESUME .3

Ссылки