Что такое FOCAL?
FOCAL (FOrmula CALculator) — интерпретируемый язык программирования высокого уровня, разработанный в 1968 году компанией Digital Equipment Corporation (DEC) для мини-ЭВМ серии PDP. По замыслу создателей, он должен был стать простым и удобным средством для математических и инженерных расчётов, альтернативой более громоздкому FORTRAN.
Язык получился настолько лёгким в реализации, что его интерпретатор требовал всего 4–8 КБ оперативной памяти — по тем временам это был настоящий подвиг. Именно эта экономичность сделала FOCAL невероятно популярным в СССР, где его портировали на множество отечественных ЭВМ — от «СМ ЭВМ» до «Электроники-60» и машин на базе процессора К1801ВМ1, например БК 0010.
Интересный факт: в США FOCAL не прижился — ему предпочли более мощный BASIC. А вот в Советском Союзе он стал настоящим «народным языком» для научных лабораторий и заводских цехов.
Уровень языка: между ассемблером и C
По своей абстракции FOCAL стоит заметно выше машинного языка (ассемблера) и даже выше чистого C. Он оперирует переменными, функциями, циклами и условиями, скрывая от программиста регистры и управление памятью. При этом из-за интерпретируемого характера он работает медленнее компилируемых языков, но позволяет быстро тестировать алгоритмы.
Структура программы: нумерованные строки
Программа на FOCAL состоит из пронумерованных строк. Номер строки — это десятичное число, например 1.10. Целая часть обычно обозначает блок (логически связанную группу), а дробная — конкретную строку внутри блока.
Пример простейшей программы:
1.10 ASK X
1.11 TYPE !, X
Эта программа запрашивает у пользователя число X (строка 1.10), а затем выводит его на экран с переводом строки (строка 1.11). Символ ! — это управляющий код перевода строки.
Важное правило: строки внутри блока могут быть не подряд, например 1.10, 1.15, 1.20 — это допустимо. Интерпретатор выполняет их в порядке возрастания номеров.
Основные Операторы FOCAL
| Оператор | Синтаксис | Действие |
|---|---|---|
ASK | ASK X | Ввод числа с клавиатуры в переменную X |
TYPE | TYPE !, "текст", X | Вывод данных на экран. ! — перевод строки, # — возврат каретки, $ — вывод списка всех переменных |
SET | SET X = 5 | Присваивание значения переменной |
GO | GO 2.10 | Безусловный переход на указанную строку |
IF | IF X, 10.1, 20.2, 30.3 | Условный переход: первая метка — для X<0, вторая — для X=0, третья — для X>0 |
FOR | FOR X = 1, 1, 10 | Цикл по X от 1 до 10 с шагом 1. После окончания цикла управление переходит на строку, следующую за FOR |
DO | DO 5.10 | Вызов подпрограммы, начинающейся с указанной строки. Возврат — по оператору RETURN |
RETURN | RETURN | Возврат из подпрограммы, вызванной DO |
QUIT | QUIT | Завершение работы программы |
WRITE | WRITE 3 | Вывести на экран строку с номером 3 |
ERASE | ERASE 2, TEXT | Удалить строку 2 (или все строки с текстом, или все переменные) |
COMMENT | COMMENT Это комментарий | Комментарий |
MODIFY | MODIFY 4.10 | Перейти в режим редактирования строки 4.10 |
EXECUTE | EXECUTE FCHR(65) | Выполнить функцию без присваивания результата |
Математические функции
FOCAL предоставлял набор встроенных математических функций (все они начинались с буквы F):
FSIN(X),FCOS(X),FTAN(X)— тригонометрические (аргумент в радианах)FASIN(X),FACOS(X),FATAN(X)— обратные тригонометрическиеFLOG(X),FLOG10(X)— натуральный и десятичный логарифмыFEXP(X)— экспонентаFSGN(X)— знак: -1, 0, 1FITR(X)— целая частьFABS(X)— модульFSQT(X)— квадратный кореньFRAN()— случайное число (обычно от 0 до 1)FCLK()— количество тактов (часто используется для задержек)FCHR(n)— при n>0 печатает символ с кодом n, при n<0 ожидает ввод символа и возвращает его код
Как программировали условия без логических операторов?
Любопытная особенность: в классическом FOCAL не было операторов сравнения (>, <, =) в привычном виде. Вместо них использовался трёхпозиционный IF. Чтобы проверить, равно ли X нулю, писали:
IF X, 10.2, 10.1, 10.2
А чтобы проверить X > 0:
IF X, 10.1, 10.1, 10.2
Существовали готовые «шаблоны» для всех отношений:
| Условие | Конструкция IF |
|---|---|
| X = Y | IF X-Y, 10.2, 10.1, 10.2 |
| X ≠ Y | IF X-Y, 10.1, 10.2, 10.1 |
| X > Y | IF X-Y, 10.2, 10.2, 10.1 |
| X < Y | IF X-Y, 10.1, 10.2, 10.2 |
Неожиданный факт: Это не было упущением, а сознательным решением. Такой подход укладывался в 4-килобайтный интерпретатор и был очень эффективен по памяти.
Переменные и типы данных
В FOCAL существовал единственный тип данных — вещественное число двойной точности (диапазон примерно от 10⁻³⁸ до 10³⁸). Имена переменных — латинские буквы (иногда с цифрой, например A1). Отсутствие строкового типа компенсировалось функцией FCHR() и возможностью ввести строку как число — в этом случае в переменную попадал закодированный код, где каждая буква давала вклад, пропорциональный её номеру в алфавите.
Пример кодирования:
Если на запрос числа ввести «NO», то система посчитает:14*10¹ + 15*10⁰ = 155. Да, так тоже можно было программировать!
Пользовательские функции (хитрость с FSBR)
Функция FSBR(n, arg) позволяла эмулировать пользовательские функции. Номер строки n — это начало подпрограммы, которой присваивается специальная переменная &. После выполнения подпрограммы FSBR возвращает значение &.
Пример — вычисление котангенса:
1.10 ASK X
1.12 LET R = X * 3.14159 / 180
1.14 TYPE "ctg( ", X, " ) = ", FSBR(5, R)
1.16 QUIT
5.10 & = 1 / FTAN(&)
Коды ошибок
В советской версии ФОКАЛа сообщения об ошибках выглядели так:
| Код | Значение |
|---|---|
| 0 | Перезапуск системы |
| 1 | Неверный номер строки |
| 2 | Неизвестная функция или переменная |
| 3 | Непарные скобки |
| 4 | Неправильный оператор |
| 5 | Строка не существует |
| 6 | Строка не существует |
| 7 | Ошибка присваивания / цикла |
| 8 | Отсутствует оператор или отношение |
| 9 | Переполнение |
| 10 | Программа слишком длинна |
| 11 | Слишком много переменных |
| 12 | Слишком больше число |
| 13 | Ошибочный адрес |
| 14 | Деление на ноль |
| 15 | Слишком большая или маленькая экспонента |
| 16 | Слишком много символов во вводе |
| 17 | Квадратный корень из отрицательного числа |
| 18 | Переполнение |