Язык программирования FOCAL

Интерпретатор, который чуть не победил BASIC
18 минут6528

FOCAL – это интерактивный интерпретируемый язык программирования, основанный на JOSS, который использовался в основном на компьютерах серии PDP компании Digital Equipment Corporation (DEC). Название языка является аббревиатурой Formulating Online Calculations in Algebraic Language.

FOCAL очень похож на JOSS с точки зрения поддерживаемых команд и общего синтаксиса языка. Многие возможности JOSS, такие как диапазоны и пользовательские функции, удалены для упрощения анализатора. Некоторые операторы были переименованы так, чтобы они начинались с уникальной буквы. Это позволило писать программы, используя однобуквенные команды, сокращая таким образом потребности в памяти. Для компьютеров PDP-8, память которых часто ограничивалась несколькими килобайтами, это было важно. Поэтому FOCAL стал популярен на машинах DEC.

Подобно JOSS и поздним версиям BASIC, FOCAL на PDP-8 представлял собой законченную среду, включающую редактор строк, интерпретатор и процедуры ввода/вывода. Пакет назывался FOCAL-8, который также работал на PDP-5 и PDP-12. При портировании на PDP-11 полученный FOCAL-11 полагался на базовую операционную систему RT-11 для обеспечения работы с файлами. Определение языка обновлялось дважды, до FOCAL-69 и слегка измененного FOCAL-71. Существовала и версия для Intel 8080.

Исторически FOCAL известен как язык оригинальных версий ранних видеоигр Hamurabi и Lunar Lander. Позднее они были перенесены на BASIC, где стали более известными. FOCAL не был популярен за пределами платформы PDP и фактически исчез при переходе на VAX-11. На некоторое время он был возрожден в Советском Союзе, где клоны PDP-11 использовались как учебные и домашние компьютеры.

Немного истории

JOSS

JOSS был выпущен в мае 1963 года на несерийном компьютере JOHNNIAC в корпорации RAND. Потребности в вычислениях быстро росли, и машина, изначально построенная в 1953 году, быстро исчерпала свои возможности. JOHNNIAC «вышел на пенсию» в 1966 году, и JOSS был перенесён на недавно приобретенную PDP-6, первую «большую» машину DEC. Потребности в вычислениях продолжали расти, и к 1970 году систему использовали от 500 до 600 пользователей по всей стране. Появился ряд инноваций, например мобильные компьютерные терминалы, которые можно было переносить из комнаты в комнату и подключать для мгновенного доступа.

JOSS оказал серьезное влияние на компьютерную сферу. Он возник именно когда была представлена концепция time-sharing (разделения времени), появился существенный интерес к взаимодействию человека с вычислительной машиной и компьютеры стали использоваться более широко. В то время большинство операционных систем с разделением времени концентрировались на управлении учетными записями пользователей и файлами, оставляя пользователей без поддержки, когда дело доходило до программирования. JOSS же предоставил как эти функции, так и легко используемый язык программирования в одном пакете. А RAND представила эту систему множеству людей в компьютерной отрасли.

FOCAL

Варианты JOSS для других платформ стали появляться вскоре после выхода версии для PDP-6. FOCAL стал одним из этих многочисленных ответвлений.

Написанный Ричардом Мерриллом, FOCAL отказался от некоторых возможностей JOSS, чтобы работать в более ограниченном пространстве памяти PDP-8 и других 12-битных машин в линейке DEC. С этой целью было сделано серьезное изменение чтобы уменьшить количество временных данных, или «состояние», необходимое для анализа операторов. Одним из заметных результатов такого решения стало то, что условные выражения использовались теперь только для ветвлений, в отличие от JOSS, где условные выражения можно было применять в любом выражении.

Другим заметным изменением стала реорганизация ключевых слов с тем, чтобы каждое начиналось с уникальной буквы. Это упростило синтаксический анализатор, который читал только первую букву команды, а затем переходил к следующему пробелу. Список потенциальных команд содержал по одной букве для каждой. Напротив, JOSS должен был продолжать чтение, пока не прочтет целиком командное слово, а затем сравнивать его со списком, содержащим полные слова.

Первая версия FOCAL была выпущена в 1968 году для PDP-8. Обновленная версия вышла в следующем году, позднее её назвали FOCAL-69. Система в целом, независимо от версии, была известна как FOCAL-8, при портировании на другие машины 12-битной серии, включая PDP-5 и PDP-12. FOCAL был популярен, поскольку эффективно использовал память, которая в этих машинах обычно ограничивалась несколькими килобайтами. FOCAL-11 работал на PDP-11 под управлением операционной системы RT-11.

Корпорация Processor Technology также предложила версию 8k FOCAL, в комплекте с игрой Lunar Lander, для системы Altair 8800 на базе Intel 8080. Это предлагалось для копирования с ленты, в то время как исходный код предоставлялся бесплатно с другими покупками.

BASIC

В то время как FOCAL обретал популярность на машинах DEC, BASIC становился ещё более популярной альтернативой на других платформах. К концу 1960-х годов ряд компаний конкурировали с DEC, продавая аналогичные машины, работающие с BASIC версиями с разделением времени. Среди них следует отметить серию HP 2100 с ОС HP Time-Shared BASIC.

Дэвид Х. Ахл присоединился к группе DEC PDP-8 когда компания заинтересовалась продажей машины в образовательные учреждения. Из-за популярности BASIC на рынке образования, особенно с растущей библиотекой программ от Minnesota Educational Computing Consortium, Ахл обнаружил, что продать машины с FOCAL было трудно, несмотря на его преимущества. Как он отметил позже:

– Язык FOCAL DEC во многих аспектах был равен BASIC, а кое в чём был даже лучше, но имел один огромный недостаток: DEC не желал его лицензировать для других производителей компьютеров. FOCAL вел тяжелую борьбу против BASIC, который был доступен на GE, Honeywell, HP и других компьютерах.

Я думаю, что это привело к такой же ситуации, как Sony и Betamax. Sony говорит: «Betamax наш, и это лучший формат, чем VHS». Но потом JVC говорит: «У нас есть VHS и Toshiba. Эй, вы хотите их использовать? Хорошо, мы предоставим вам лицензию на это практически даром».

Ахл взял на себя задачу создать систему BASIC для PDP платформы, наняв компанию, которая, как он узнал позже, состояла из одного программиста в Бруклине, чтобы создать версию для 4 килобайтной PDP-8. DEC начала продавать версии PDP-8 с терминалами и BASIC в качестве линейки «EduSystem», причем более крупные системы этой серии имели расширенные версии BASIC, а в некоторых случаях ещё и FOCAL и FORTRAN. Некоторые EduSystem были созданы также на базе PDP-11.

Затем Ахл начал переносить программы с FOCAL на BASIC, в частности, The Sumer Game (которую он переименовал в Hamurabi), версию Lunar Lander и несколько небольших FOCAL демо-программ. Объединив свои версии с работами сторонних программистов, ему удалось собрать достаточно материала, чтобы DEC опубликовал101 BASIC Computer Games в 1973 году. Книга имела моментальный успех и в итоге выдержала три издания к 1975 году.

К середине 1970-х годов BASIC стал стандартной опцией всех машин DEC, а использование FOCAL прекратилось.

Возрождение в Советском Союзе

PDP-11 был клонирован в Советском Союзе в 1970-х годах для военных целей. В 1980-х годах были выпущены одночиповые версии, подобные LSI-11, которые дали начало серии домашних компьютеров, совместимых с PDP-11. Наиболее заметной среди нескольких моделей была серия Электроника BK, выпущенная в 1985 году. Они изначально поставлялись с FOCAL в ПЗУ-картридже, а картридж с BASIC был опциональным дополнением. Более поздние модели поставлялись с BASIC по умолчанию.

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

Следующее описание основано на FOCAL-69, как видно из справочного руководства по языку FOCAL-8.

Директивный и недирективный режимы

FOCAL следует модели JOSS для взаимодействия с пользователем с помощью командной строки. Это позволяет вводить команды, которые будут выполнены немедленно (директивный режим). Или добавлять к ним номер строки (недирективный режим). В этом случае они добавляются в программу, если номер уникальный, или заменяют уже существующую строку с таким же номером.

Такой метод работы аналогичен «непосредственному режиму» BASIC и «программному режиму». Что отличается от JOSS, в котором все команды, как программные, так и прямые, были сохранены и загружены как часть рабочей области пользователя. Это позволяло JOSS иметь команды без номеров строк, которые использовались для определений форм и других задач. У FOCAL такой возможности не было, поэтому инструкции, которые нужно было загрузить и сохранить, стали опциями для других команд режима программы, таких как Type.

Операторы программы

Каждая строка в программе FOCAL должна начинаться с номера строки. Как и в JOSS, номера строк – это числа с фиксированной запятой, состоящие из двух двузначных чисел, разделенных точкой. В FOCAL-8 номера строк варьируются от 1.01 до 31.99. При распечатке командой WRITE добавляются ведущие нули, так что все номера строк будут содержать пять символов, включая точку, например строка 1.10 будет напечатана как 01.10. Операторы, обращающиеся к этим строкам, не нуждаются в ведущих нулях, например, GOTO 1.10.

Число слева от точки называется «номером группы». Группы обеспечивают определённый уровень организации кода, которого не хватает в таких языках, как Fortran или BASIC. Основное их применение в том, чтобы использовать группу в качестве подпрограммы, которую можно вызывать с помощью DO. Например, DO 5 обеспечит переход к подпрограмме, записанной в группе 5. Редактор также использовал их во время редактирования, например, можно было написать WRITE 2, чтобы показать список строк в группе 2, или ERASE 4, чтобы удалить все строки в группе 4.

Каждая строка должна начинаться с ключевого слова команды, следующего за номером строки. Не существует «команды по умолчанию», как в BASIC с его необязательным LET. Несколько операторов могут быть помещены в одну строку, разделённые точкой с запятой. Обычно это поведение ничем не отличается от того, если бы операторы были в отдельных строках, за исключением ситуации с циклом FOR.

Команды

ASK. Команда ASK (сокращённо A) берет список строк и переменных, выводит строки на экран и сохраняет введенные пользователем данные в переменных. Эквивалентна команде INPUT в BASIC.

01.01 ASK "NAME", N
01.02 ASK "COORDINATES", X, Y
01.03 ASK "A1",A1,"OMEGA",W,"T0",T0,"DAMPING FACTOR",DAMPINGFACTOR

Если пользователь вводит не число, а текст, система преобразует начальный символ в число с «A» = 1, «B» = 2 и т.д.

COMMENT. Команда COMMENT (сокращённо C) создаёт комментарий. Эквивалентна REM в BASIC.

01.01 COMMENT: THE SUMER GAME, BY RICHARD MERRILL

DO. Команда DO (сокращённо D) создаёт ветвь для выполнения подпрограммы. Это эквивалент BASIC команды GOSUB. На подпрограмму ссылается либо номер группы, либо номер строки. Если указан номер строки, эта строка выполняется и затем происходит возврат к оператору после DO. Если номер строки не указан, выполнение начинается с первой строки группы и продолжается, пока не будет достигнут конец группы или не встретится RETURN. RETURN требуется только для раннего возврата, в конце группы он не нужен.

01.15 DO 7.24
01.16 DO 8

FOR. Команда FOR (сокращённо F) реализует цикл for. Когда заданы три аргумента, первый – это начальное значение переменной цикла, второй – приращение, а третье – это конечное значение цикла. Если указаны два значения, первое – это начальное значение, а второе – конечное значение, а приращение устанавливается равным 1.

В отличие от других частей языка, где несколько операторов в строке независимы, FOR всегда выполняет операторы, следующие за ним в строке, до того, как будет выполнено завершение, а затем переходит к следующей строке. Таким образом, циклы должны быть в одной строке или вызывать подпрограмму с DO. Эквивалента BASIC команды NEXT нет.

01.01 FOR X=1,10; TYPE X,!
01.02 FOR X=0,10,100; DO 2

Простой цикл for:

01.10 ASK "HOW MUCH MONEY DO YOU WANT TO BORROW ?",PRINCIPAL
01.20 ASK "FOR HOW MANY YEARS ?",TERM
01.30 FOR RATE=4.0,.5,10; DO 2.0
01.40 QUIT
02.10 SET INTEREST=PRINCIPAL*(RATE/100)*TERM
02.20 TYPE "RATE",RATE,"   ","INTEREST",INTEREST,!

GOTO. Команда GOTO (сокращённо G) переводит выполнение программы на указанный номер строки. Он идентичен одноименной команде в BASIC. В отличие от GO, используемой из командной строки, которая запускает программы, эквивалент RUN в BASIC.

01.05 GOTO 1.01
02.90 TYPE !!,"TRY AGAIN.",!!!!!; GOTO 1.1

IF. Команда IF (сокращённо I) обеспечивает ветвление по условию, основанному на знаке выражения. После этого выражения команда IF может содержать список от одного до трех номеров строк. Если результат выражения меньше нуля, выполнение переходит к первому номеру; если равен нулю, на второй номер; если больше нуля, номер третьей строки. В языке отсутствуют относительные операторы, такие как «больше чем», «равно» или «меньше». Для ветвления по условию IF X>5, нужно проверить результат выражения X-5.

02.20 IF (25-25) 2.4,2.3,2.4
03.01 IF (X) 3.1,3.02,3.1

IF может быть в сокращенной форме, если поставить точку с запятой (или конец строки) после номера первой строки. Например:

02.20 IF (X)1.8; TYPE "Q"
02.30 IF (X)1.8,2.50
02.40 TYPE "P"

В этом случае проверка в 2.20 заставит программу перейти на строку 1.8, если значение X отрицательное, в противном случае она продолжится и выведет «Q» на консоли. В строке 2.30 произойдет переход к 1.8 или 2.5, если значение будет отрицательным или нулевым, а в противном случае выведет «P» в консоли.

QUIT. Команда QUIT (сокращённо Q) останавливает программу и возвращает управление среде редактирования. Эквивалентно END или STOP в BASIC.

01.10 FOR X=-10,1,10;TYPE X
01.20 QUIT

RETURN. Команда RETURN (сокращённо R) выполняет возврат из подпрограммы к месту её вызова. Использование RETURN является необязательным в последней строке, подпрограмма в любом случае возвращается из последней строки в группе. Ниже приведен пример подпрограммы для преобразования ответа YES/NO в значение.

22.78 COMMENT: 'YES OR NO' SUBROUTINE
22.80 ASK "ANSWER YES OR NO ?",AN
22.82 IF (AN-YES)22.84,22.86
22.84 IF (AN-NO)22.8,22.88,22.8
22.86 SET X=2;RETURN
22.88 SET X=1;RETURN

SET. Команда SET (сокращённо S) присваивает результат выражения указанной переменной. Эквивалентна команде LET в BASIC.

01.30 SET PI=3.14156
01.60 SET INTEREST=PRINCIPAL*(RATE/100)*TERM

TYPE. Команда TYPE (сокращённо T) обеспечивает вывод одного или нескольких элементов, разделенных запятыми. Эквивалентна PRINT в BASIC.

Элементы могут быть переменными, строками символов, заключенными в двойные кавычки, или различными управляющими символами. Управляющие символы включают в себя ! для вывода возврата каретки и перевода строки, # только для возврата каретки и : для символа табуляции. Управляющие символы могут быть записаны вместе, например, !!! выведет три CR/LF без необходимости разделять их запятыми.

TYPE [NUMBERS, E1, "TEXT", !, #, :, $ OR %] ...OUTPUT
01.10 TYPE "HI THERE, GOOD LOOKING. HOW MUCH MONEY DO YOU WANT TO BORROW?",!
01.50 TYPE "INTEREST",INTEREST,!
01.80 TYPE "THE INTEREST FOR",TERM," YEARS",!,"IS",INTEREST," DOLLARS.",!!
01.90 TYPE "NEW YORK",!,"WASHINGTON",!,"ATLANTA",!,"DALLAS",!
02.10 TYPE "X",X,"   ","X^2",X^2,"   ","SQRT",FSQT(X)
03.20 TYPE ".",#
02.20 TYPE !!!!!

TYPE также может иметь необязательный спецификатор формата, указанный в виде %x.yz, где x – это число цифр до точки, а yz – это число цифр справа от точки. Формат по умолчанию %8.4, что означает максимум восемь цифр до и четыре справа от точки. Например:

SET A=67823
TYPE %6.01,A
=  67823.0
TYPE %5,A
= 67823
TYPE %8.03,A
=    67823.000
TYPE %,A
= 6.7823E4

Обратите внимание на дополнительные начальные пробелы в некоторых примерах. Использование только % привело к выводу в «формате с плавающей запятой» с использованием E.

Специальным управляющим символом был $, который вызывает вывод таблицы всех определенных переменных и их значений. Будут напечатаны только первые две буквы имени, дополненные нулями, если необходимо. Элементы массивов печатаются в отдельных строках, а переменным, в которых только один элемент, будет присвоен индекс (00). Например:

TYPE $
A0(00)=67823

Переменные

Имена переменных могут начинаться с любой буквы, кроме F (F зарезервирована для функций) и могут содержать любую последовательность букв и цифр. Тем не менее, только первые два символа имеют значение. Например, следующий пример кода из FOCAL в A New Conversational Language ссылается на ту же переменную, что и DESTINATION, а затем DES. Внутри обе ссылки относятся к значению, обозначенному DE:

01.80 ASK DESTINATION
02.30 IF (DES-14) 2.4,3.1,2.4

Любая переменная может рассматриваться как массив, что позволяет использовать индексы от -2048 до 2047.

Математика

FOCAL-69 содержит только пять математических операций:

  1. ^ для возведения в степень – показатель степени преобразуется в 12-разрядное целое число
  2. * для умножения
  3. / для деления
  4. + для дополнения
  5. - для вычитания

Любопытно, что все операторы FOCAL имеют независимый приоритет, как в указанном выше порядке. Это означает, что формула SET T=2-3+1, будет рассчитана в порядке 2-(3+1) и, следовательно, даст -2. Это сильно отличается от большинства языков, где + и - имеют одинаковый приоритет и оцениваются (2-3) +1 что в результате даёт 0. Это может вызвать незначительные ошибки при переносе исходного кода FOCAL на другие языки.

FOCAL необычен в том смысле, что математические выражения могут использовать (), [] и <> взаимозаменяемо в согласованных парах, чтобы установить приоритет. Например, допустимо следующее:

01.30 SET A=<10*[5+1]*(1+5)>

Все скобки имеют одинаковый уровень приоритета и читаются слева направо, когда находятся на одном уровне, поэтому сначала будет вычислен результат в [], затем (), затем <>, в результате получим число 360.

FOCAL содержит следующие встроенные функции:

  • FABS() – абсолютное значение
  • FATN() – арктангенс
  • FCOS() – косинус от аргумента в радианах
  • FEXP() – возвращает число e, возведенное в указанную степень
  • FITR() – целая часть аргумента
  • FLOG() – натуральный логарифм
  • FRAN() – случайное число
  • FSGN() – знак аргумента; FSGN(0)=1 в FOCAL-69, но FSGN(0)=0 в FOCAL-71, как и в более поздних версиях
  • FSIN() – синус от аргумента в радианах
  • FSQT() – квадратный корень

Другие функции

FOCAL также содержит ряд специальных функций:

  • FDIS берёт два значения и рисует точку на экране графического терминала
  • FADC читает значение из пронумерованного аналогового входа и возвращает целочисленное значение

Команды окружения

Запуск программ

FOCAL использовал GOTO в редакторе для запуска программы. Тем не менее, на практике это было сокращено до GO. Это эквивалент команды RUN в BASIC. GOTO можно также использовать в редакторе для запуска программы с указанной строки.

Команды редактирования

Новые строки добавляются в программу, просто когда команда начинается с номера строки. Команды редактирования: ERASE (сокращённо E), MODIFY (сокращённо M) и WRITE (сокращённо W).

  • ERASE – удаляет все переменные. Это может быть в начале программы
  • ERASE <номер строки> – удаляет строку с заданным номером
  • ERASE <номер группы> – удаляет все строки в заданной группе
  • ERASE ALL – удаляет всю программу
  • MODIFY <номер строки> – позволяет редактировать указанную строку
  • WRITE <номер строки> – отображает строку с заданным номером
  • WRITE <номер группы> – отображает все строки заданной группы
  • WRITE ALL – отображает всю программу

Файловые команды

Работу с файлами обеспечивает команда OPEN (сокращённо O):

  • OPEN INPUT [device:][file][,ECHO] – подготовка к чтению с начала файла
  • OPEN OUTPUT [device:][file][,ECHO] – подготовка к записи с начала файла
  • OPEN RESTORE INPUT[,ECHO] – возобновить ввод
  • OPEN RESTORE OUTPUT[,ECHO] – возобновить вывод
  • OUTPUT CLOSE – вывести буфер и закройте файл

Библиотечные команды

FOCAL включает возможность управлять коллекциями программ FOCAL в виде библиотеки кодов. Программы могут вызывать другие программы по цепочке, используя LIBRARY CALL, или вызывать одну подпрограмму в другой программе, используя LIBRARY GOSUB. Имена программ могут быть длиной шесть символов. Команда LIBRARY (сокращенно L) имеет следующие подкоманды:

  • LIBRARY DELETE [device:]<program name> – удалить программу
  • LIBRARY LIST [device:][file name] – список программ
  • LIBRARY RUN [device:]<program name>; [line number] – связать программы, возможно, выполнение по указанному номеру строки
  • LIBRARY SAVE [device:]<program name> – сохранить программу
  • LIBRARY EXIT – возврат в программу мониторинга PDP-8

FOCAL-71 добавил:

  • LIBRARY CALL [device:]<program name> – загрузить программу
  • LIBRARY GOSUB [device:]<program name> [group number] – вызвать подпрограмму из внешней программы

Коды ошибок

Поскольку интерпретатору не хватало места в памяти для хранения сообщений об ошибках или даже таблицы номеров ошибок, FOCAL использовал обходной путь, сообщая адрес кода, обнаружившего ошибку, как число с фиксированной точкой. Например, если была обнаружена ошибка деления на ноль, появляется сообщение 28.73@01.10, где 28.73 представляет проверку кода для этой ошибки на странице 28 памяти плюс смещение 73 слова, а 01.10 – номер строки, в которой произошла ошибка. Страницы в PDP-8 имели размер 128 байт, поэтому этот адрес преобразуется в местоположение 3657.

Различия между версиями

DEC выпустила три версии FOCAL для серии PDP-8, оригинальную, известную просто как FOCAL, и две обновленные версии, FOCAL, 1969 и FOCAL, 1971. FOCAL 1969 был в значительной степени идентичен оригиналу, но FOCAL, 1971 был главным обновлением, которое добавило обработку файлов, новые математические функции и множество других изменений. В отличие от первых двух версий, которые были автономными системами, FOCAL 1971 года был основан на новой OS/8 (тогда еще называемой PS/8) и больше полагался на эту операционную систему для обработки и редактирования файлов.

FOCAL, 1971

Одним из изменений в новой версии стал 10 значный пакет математических функций для дополнительной точности. Функция FSGN стала возвращать ноль, если входное выражение равно нулю. Предыдущая версия возвращала 1. FRAN стал использовать лучший алгоритм, который производил больше случайно распределенных чисел. Были также добавлены новые функции FIN, которая принимает строку и возвращает ее значение ASCII (сродни ASC BASIC) и FOUT, которая принимает число и возвращает строку с этим символом ASCII (подобно CHR в BASIC).

Поскольку все эти дополнения использовали ограниченную память, при старте FOCAL 1971 выводит диалог, с вопросом пользователю: какие функции он хотел бы использовать.

Сравнение с JOSS

FOCAL – это, по большому счету, очищенная версия JOSS с изменениями, делающими синтаксис более понятным и более простым для анализа. Почти все команды FOCAL имеют непосредственное соответствие в JOSS и отличаются только деталями. Некоторые особенности JOSS отсутствуют в FOCAL.

Одно из главных отличий состоит в том, что JOSS включает в себя полный набор операций сравнения и систему логики, которая работает в конструкциях if и for. Кроме того, if и циклы могут применяться к любому выражению, в отличие от FOCAL, где единственная операция, которую можно было выполнить, была эквивалентна goto. Например, в JOSS можно было бы:

1.10 Type A if X>10.
1.20 Type i for i=1(1)10.

Где опционально будет выведено значение A в зависимости от условия, а затем выведены числа от 1 до 10. В отличие от этого, в FOCAL нет возможности сравнивать значения, и циклы используются для перехода к следующей строке после их завершения. Эквивалентный код FOCAL будет выглядеть так:

1.10 IF (X-10) ,,1.30
1.20 TYPE A,!
1.30 FOR I=1,1,10;TYPE I,!

Реализация JOSS облегчает создание общих конструкций и более точно соответствует намерениям программиста за счет усложнения среды выполнения. Например, JOSS допускает гибкое описание диапазонов в циклах, например, 1,2,3,10 (5) 50,75,78. Эта гибкость имеет цену; в FOCAL начало, остановка и шаг могут быть записаны в пользовательской структуре в памяти и легко обновляться по мере выполнения цикла. Напротив, система JOSS требует указателя на то, что может быть, но часто не является, более сложным выражением, которое нужно обойти с помощью более сложного кода синтаксического анализа.

С точки зрения того, чтобы сделать код более кратким, изменения были относительно незначительными. Например, Do part 20. в JOSS становится немного меньше в FOCAL – DO 20, а Do step 20.1 становится DO 20.1. Командные ключевые слова были также сокращены, где это возможно, поэтому Demand в JOSS становится ASK в FOCAL, чтобы сделать его и короче, и позволить уникально использовать букву D для DO. Период, необходимый для указания конца строки в JOSS, был удален.

Чтобы упростить анализатор, некоторые опции в FOCAL были удалены. Например, JOSS может выполнять несколько присвоений с помощью Set S=P, P=Q, Q=S, в то время как в FOCAL это должны были быть отдельные команды, SET S=P; SET P=Q; SET Q=S. Аналогично, Form в JOSS, используемая для форматирования вывода, объединён в FOCAL в TYPE %.

Сравнение с BASIC

Сравнения FOCAL c BASIC неизбежно, поскольку оба языка были распространены на мини-компьютерах той эпохи, и эти два языка имеют много общего с точки зрения синтаксиса и структуры. В большинстве случаев происходит прямое преобразование кода FOCAL в и из BASIC. Например, чтобы попросить пользователя ввести значение в FOCAL можно так:

ASK "What is your age?",AGE

эквивалент в BASIC:

INPUT "What is your age?",AGE

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

Заметным исключением является IF в BASIC, который позволяет размещать любое выражение после THEN, делая его более похожим на структуры управления JOSS. BASIC изменил порядок кода по сравнению с JOSS, поместив условное выражение в начале строки, а не в конце; в BASIC каждый использует IF this THEN that, в отличие от that IF this JOSS. Преимущество BASIC в том, что среда выполнения может немедленно прервать чтение остальной части оператора, если выражение не соответствует действительности. Напротив, IF FOCAL больше походит на вычисленное goto BASIC, ON X GOTO 10,20,30, но ON ... GOTO допускал любое количество строк в качестве целей, в отличие от только трех для отрицательных, нулевых и положительных, как в JOSS и FOCAL.

Другое важное различие между состоит том, что у FOCAL отсутствует встроенная поддержка строк как данных, которые можно присваивать переменным. Как и в ранних версиях BASIC или FORTRAN до добавления строк (в F77), этого ограничения обычно избегали используя строки символов в командах ввода и вывода. Только когда потребовалось манипулировать строками или символами внутри них, это стало серьёзной проблемой.

Поскольку строковые переменные не поддерживаются, при вводе строки используется метод, который преобразует любые символы, введенные пользователем, в их числовое значение. Например, если ввести «HELLO», FOCAL преобразует H в «8», числовое значение «H» в шестибитовых кодах PDP-8 («H» - восьмая буква), затем интерпретирует «E» как начальную экспоненту, а затем попытается вычислить «8» в степени «LLO», что займет несколько секунд процессорного времени и приведет к значению 0,76593020E + 103, что не будет особо полезным ответом. Тем не менее, задавая вопросы, на которые можно было бы ответить, используя однобуквенные ответы, такие как «Нужны ли вам инструкции, Y или N», программисты могли проверить результат по известным значениям символов, чтобы получить то, что выглядело как ввод символов.

В реализации FOCAL PDP-8 использовалось представление с плавающей запятой, которое хранило числа в виде четырех 12-битных слов, всего 48 бит, с 36 битами мантиссы и 12 экспоненты. Это позволило получить значительно более высокую точность и значительно более широкий диапазон значений, чем большинство современных интерпретаторов, что делало FOCAL разумным выбором для серьезной работы с числами. Эта высокая точность и хороший выбор для стандартного десятичного форматирования вывода означали, что проблемы двоично-десятичного округлением не беспокоили начинающих пользователей. Для сравнения, Microsoft BASIC первоначально использовал 32-битный формат, более поздние версии расширили его до 40-бит. У большинства BASIC были проблемы с округлением, что приводило к крошечным ненулевым остаткам в простых выражениях.

Общепринято, что FOCAL более эффективно использовал ресурсы, чем сопоставимые системы BASIC. На типичной машине того времени, часто с 6–24 килобайтами памяти на магнитных сердечниках, FOCAL мог выполнять более крупные и сложные задачи программирования, чем BASIC.

Версии и ответвления

Корпорация Coca-Cola использовала индивидуальную версию FOCAL под названием COKE.

FOCAL был позднее реализован на PDP-7, PDP-9, PDP-10, PDP-11, PDP-12, PDP-5 и LINC-8.

Руководство FOCAL показало, как добавлять команды в анализатор FOCAL, поэтому многие сайты добавили специальные команды для работы с пользовательским оборудованием.

Группа Digital Equipment Computer Users' Society собрала много патчей и улучшений для FOCAL. Там присутствовали основные улучшенные ответвления FOCAL, такие как FOCAL-W, которые добавили множество функций, в том числе улучшенный ввод-вывод файлов и даже работу с виртуальной памятью.

В России FOCAL появился в начале 1990-х годов в серийных домашних компьютерах серии Электроника BK.

Пример кода

В качестве примера можно рассмотреть реализацию игры “Угадай число”. В строке 1.30 генерируется случайное число. В строке 2.10 пользователь вводит свой вариант. Если угадать удалось, происходит переход на строку 6.10, где выводится сообщение о победе. Если не удалось – выводится подсказка и запрос числа повторяется. Количество попыток ограничено тремя.

1.10 COMMENT GUESS THE NUMBER 0..9 IN 3 ATTEMPTS
1.20 SET C=1
1.30 SET N=FITR(FRAN(1)*10)
2.10 ASK "GUESS THE NUMBER 0..9",G
2.20 IF (G-N) 3.3,6.1
3.10 TYPE "YOUR NUMBER IS GREATER",!
3.20 GOTO 4.1
3.30 TYPE "YOUR NUMBER IS LESS",!
4.10 SET C=C+1
4.20 IF (C-3) 2.1,2.1
5.10 TYPE "YOU LOSE... IT WAS ",%1.0,N,!
5.20 QUIT
6.10 TYPE "YOU WON! COOL!",!
6.20 QUIT

Подведём итог

В Советском Союзе FOCAL сыграл менее заметную роль, нежели в Америке, поскольку появился значительно позже пика своей популярности, которая пришлась на конец 60-х годов. Тем не менее этот интерпретатор может представлять интерес для всех, кто интересуется историей развития языков программирования.

Реализация такого простого интерпретатора может стать интересным вызовом для программиста. Версию FOCAL, разработанную на Java, вы можете найти в моём git репозитории.

программированиеисторияfocal
Нашли ошибку в тексте? Напишите нам.
Спасибо,
что читаете наш блог!