]]> ]]>
Править | Обсудить | История

BCPL

Дата создания:
1967
Создан под влиянием:
Повлиял на:
Парадигма:
Типизация:
Принятые расширения файлов:
.b
Реализации и версии (свернуть все | развернуть все):
Язык программирования

BCPL (аббр. Basic/Bootstrap CPL) — бестиповый структурный язык программирования, разработанный Мартином Ричардсом (Martin Richards) в 1966 году (первая реализация создана им же в 1967).

Язык был создан на основе CPL путем удаления из него элементов, усложняющих компиляцию, а именно: типизации переменных и набора синтаксических структур, определяющих блоки с различными правилами видимости переменных. Кроме того, синтаксис языка значительно упрощен и добавлена возможность раздельной компиляции сегментов программы.

BCPL разрабатывался как компактный язык для системного программирования и написания компиляторов, в частности, на нем должен был быть написан компилятор CPL (отсюда вариант названия Bootstrap CPL). В итоге первый компилятор, переписанный на BCPL же, занимал около 1000 строк и требовал менее 20 кБ памяти для запуска.

В свое время язык использовался достаточно широко: к 1979 году существовали компиляторы для как минимум 25 архитектур, на нем даже писали операционные системы (TRIPOS и AmigaDOS). Он оказал значительное влияние на B, который, в свою очередь, стал прародителем C. Именно из BCPL создатели этих языков позаимствовали идею предоставления программисту свободы, не ограниченной возможностями языка. В настоящее время язык не используется в практических целях; существует только одна реализация языка, созданная Мартином Ричардсом и предназначенная для Cintpos (варианта TRIPOS).

Для BCPL был впервые придуман и реализован ряд возможностей, ставших характерными для более современных языков. В частности, именно в нем были впервые использованы фигурные скобки { } для выделения блоков и // для выделения комментариев до конца строки. Считается, что именно на BCPL была написана первая программа “Hello, World!”. Для обеспечения переносимости языка и программ, написанных на нем, между разными архитектурами, была изобретена виртуальная машина. Компилятор состоял из двух частей: фронт-энда, который разбирал код программы и генерировал по нему O-CODE (объектный код), и бэк-энда, который интерпретировал объектный код или транслировал его в машинно-зависимый. Для переноса языка на новую архитектуру было достаточно переписать бэк-энд, а он занимал около 1/5 общего объема компилятора.

Единственный тип данных в языке — целое число, обычно 16-битное, позднее 32-битное. При этом применяется контекстная типизация — переменные трактуются как числа, символы, указатели, битовые паттерны или логические значения в зависимости от того, какие операторы к ним применяются. Проверки того, может ли конкретная операция применяться к конкретному значению переменной, не проводятся — за этим должен следить программист. Некоторые реализации добавляли в язык числа с плавающей точкой и специальные операторы для их обработки.

Единственная структура данных языка — массив (последовательность ячеек). Используя ячейки массива в качестве указателей на другие переменные/массивы, можно строить более сложные структуры.

Структура блоков и управляющих команд BCPL близка к использующейся в CPL. Блок может использоваться вместо команды или вместо выражения; во втором случае перед блоком добавляется слово VALOF, а результат его выполнения задается словом RESULTIS внутри блока. В любом блоке могут присутствовать объявления локальных переменных и процедур. Позднее язык был расширен возможностью определения сопрограмм, что сделало системное программирование еще более удобным.

Имена процедур, если рассматривать их как значения, являются указателями на соответствующие фрагменты кода. Они могут храниться в переменных, передаваться в функции/процедуры как аргументы и т.д. Возможны переходы между процедурами при помощи псевдофункций level() и longjmp(). Принципы работы с процедурами позднее были заимствованы для C.

Набор библиотек языка предельно лаконичен: они содержат только базовые функции ввода-вывода данных и динамического распределения памяти.

Элементы синтаксиса:

Комментарий до конца строки //
Регистрозависимость да
Присваивание значения переменной <varname> := <value>, <varname> : <value>
Объявление переменной с присваиванием значения let varname = value
Группировка выражений ( ... )
Блок { ... } или $( ... $)
Равенство =
Неравенство ~= neqv
Определение функции f(para1, para2, ...) = valof $( ... $) или let f(para1, para2, ...) be $( ... $)
Вызов функции f(a,b,...f) или f[a,b,...]
Если - то if <condition> do <trueBlock>
Если - то - иначе test <condition> then <trueBlock> or <falseBlock>; <condition> -> <trueBlock>, <falseBlock>
Цикл с предусловием while <condition> do <loopBody>
Цикл с постусловием <loopBody> repeatuntil <condition>
Цикл for - next для диапазона целых чисел с инкрементом на 1 for i = 1 to 10 do <loopBody>

Примеры:

Hello, World!:

Пример для версий 64-bit BCPL Cintcode System (1 Nov 2006)

*n служит для печати символа перевода строки

GET "libhdr"

LET start() = VALOF
$( writes("Hello, World!*n")
   RESULTIS 0
$)

Факториал:

Пример для версий 64-bit BCPL Cintcode System (1 Nov 2006)

Используется рекурсивное определение факториала.

*n служит для печати символа перевода строки.

Вычисление факториала 15 и более вызывает арифметическое переполнение. В результате вывод программы имеет следующий вид:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 18000
16! = 000

GET "libhdr"

LET start() = VALOF
{ FOR i = 0 TO 16 DO writef("%n! = %n*n", i, factorial(i))
  RESULTIS 0
}

AND factorial(n) = n=0 -> 1, n*factorial(n-1)

Числа Фибоначчи:

Пример для версий 64-bit BCPL Cintcode System (1 Nov 2006)

Используется рекурсивный метод вычисления чисел Фибоначчи.

GET "libhdr"

LET start() = VALOF
{ FOR i = 0 TO 15 DO writef("%n, ", fibonacci(i))
  writef("...*n")
  RESULTIS 0
}

AND fibonacci(n) = n<2 -> 1, fibonacci(n-1)+fibonacci(n-2)

Факториал:

Пример для версий bcplkit UNIX v7

Используется рекурсивное вычисление факториала. Числа больше 13! вызывают переполнение.

Вывод:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184

GET "LIBHDR"

LET START() = VALOF 
$(1
	FOR I = 1 TO 16 DO
    	WRITEF("%N! = %I4*N", I, FACT(I))
    RESULTIS 0
$)1

AND FACT(N) = N = 0 -> 1, N * FACT(N - 1)

Комментарии

]]>

blog comments powered by Disqus

]]>

Работа программистам