FOCAL (аббревиатура от Formulating On-line Calculations in Algebraic Language [ 1] или FORmula CALculator [2] ) — это интерактивный интерпретируемый язык программирования, основанный на JOSS и в основном используемый на машинах серии PDP компании Digital Equipment Corporation (DEC) .
JOSS был разработан как простой язык, позволяющий непрограммистам легко писать программы. FOCAL очень похож на JOSS по командам, которые он поддерживает, и общему синтаксису языка. Он отличается тем, что многие из расширенных функций JOSS, такие как диапазоны и определяемые пользователем функции, были удалены для упрощения синтаксического анализатора . Некоторые зарезервированные слова (ключевые слова) были переименованы так, чтобы все они начинались с уникальной первой буквы. Это позволяет пользователям вводить программы, используя односимвольные операторы, что еще больше снижает потребность в памяти. Это было важным соображением на PDP-8 , который часто ограничивался несколькими килобайтами (КБ).
Подобно 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, где стали гораздо более известны. [3] FOCAL не был популярен за пределами платформы PDP и в значительной степени исчез во время перехода на VAX-11 . Он имел сильное возрождение в Советском Союзе , где клоны PDP-11 использовались в качестве учебных и домашних компьютеров ( серия BK ).
JOSS был выпущен в мае 1963 года на единственном компьютере JOHNNIAC в RAND Corporation . В RAND использование быстро росло, и машина, изначально построенная в 1953 году, быстро исчерпала свои возможности. JOHNNIAC был выведен из эксплуатации в 1966 году, а JOSS был повторно реализован на недавно купленной PDP-6 , первой «большой» машине Digital Equipment Corporation (DEC). Использование продолжало расти, и к 1970 году система использовалась 500-600 пользователями по всей стране и породила несколько инноваций, таких как мобильные компьютерные терминалы , которые можно было перевозить из комнаты в комнату и подключать для быстрого доступа. [4]
JOSS был очень влиятельным. Он появился как раз тогда, когда вводилось разделение времени . Существовал значительный интерес к взаимодействию человека и машины, и компьютеры стали использоваться все шире. В то время как большинство операционных систем с разделением времени той эпохи концентрировались на управлении учетными записями пользователей и файлами, предоставляя пользователям возможность самостоятельно программировать, JOSS предоставлял редактирование файлов и язык программирования в одном пакете. RAND показал систему параду людей в отрасли. [4]
PDP-6 был первым мэйнфреймом DEC , и JOSS в полной мере использовал его мощность и емкость памяти. Программисты DEC интересовались JOSS, но большинство их машин не обладали мощностью, необходимой для его запуска. Написанный Ричардом Мерриллом , FOCAL удалил функции из JOSS по мере необходимости, чтобы иметь возможность работать в гораздо более ограниченном пространстве памяти PDP-8 и других 12-битных машин в линейке DEC. Чтобы добиться этого, было внесено серьезное изменение для уменьшения объема временных данных, или состояния , необходимого для разбора операторов. Одним из заметных последствий этого решения было то, что условные операторы можно было использовать только для ветвей , в отличие от JOSS, где условные операторы можно было применять к любому оператору.
Другим заметным изменением было перераспределение ключевых слов так, чтобы каждое начиналось с уникальной буквы. Это упростило синтаксический анализатор , которому нужно было прочитать только первую букву команды в строке кода, а затем можно было перейти к следующему пробельному символу . Затем он сравнивал это с внутренним списком возможных ключевых слов, который представлял собой один символ на запись. Напротив, JOSS должен был продолжать чтение, пока не прочитает все командное слово, а затем сравнить его со списком, содержащим полные слова. Это изменение не только экономило память в синтаксическом анализаторе, пользователи также могли экономить память, вводя только эту букву, уменьшая размер исходного кода .
Первая версия FOCAL была выпущена в 1968 году для PDP-8 . Обновленная версия вышла в следующем году, позже она стала известна как FOCAL-69. Система в целом, независимо от версии, была известна как FOCAL-8, когда она была перенесена на другие машины в 12-битной серии, включая PDP-5 и PDP-12 . Она была популярна, поскольку была очень эффективна в использовании памяти, которая часто была строго ограничена на этих машинах несколькими килобайтами (КБ). Похожая FOCAL-11 работала на PDP-11 под RT-11 .
Processor Technology также предлагала версию 8k FOCAL, в комплекте с Lunar Lander, для системы Altair 8800 на базе Intel 8080. Она была предоставлена за плату за копирование ленты, в то время как исходный код предоставлялся бесплатно при других покупках. [5]
В то время как FOCAL становился популярным на машинах DEC, BASIC становился все более популярной альтернативой на других платформах. К концу 1960-х годов несколько компаний вторглись в оплот мини-компьютеров DEC , продавая похожие машины, работающие на версиях BASIC с разделением времени. Среди них выделялась серия HP 2100 , работающая на HP Time-Shared BASIC . [6]
Дэвид Х. Аль недавно присоединился к группе PDP-8 компании DEC, как раз когда компания заинтересовалась продажей машины в образовательные учреждения. Из-за популярности BASIC на рынке образования, особенно с растущей библиотекой программ BASIC от Minnesota Educational Computing Consortium , Аль обнаружил, что продавать машину с FOCAL было сложно, несмотря на ее преимущества. [6] Как он позже заметил:
Язык FOCAL от DEC был равен BASIC во многих аспектах и даже лучше в некоторых, но у него был один огромный недостаток: DEC не хотела лицензировать его другим производителям компьютеров. FOCAL вела тяжелую борьбу с BASIC, который был доступен на GE, Honeywell, HP и других компьютерах.
Я думаю, что это закончилось ситуацией, подобной той, что была у Sony и Betamax. Sony заявила: «Betamax — наш, и это лучший формат, чем VHS», что так и было. Но затем JVC заявила: «У нас есть VHS и Toshiba. Эй, вы хотите его использовать? Отлично, мы лицензируем его для вас почти даром». [6]
Аль взял на себя задачу создания системы BASIC для этой платформы, наняв компанию, как он позже узнал, одного программиста в Бруклине, чтобы создать версию для 4 kWord PDP-8. DEC начала продавать упакованные версии PDP-8 с терминалами и BASIC как линейку «EduSystem», причем более крупные системы в этой серии имели расширенные версии BASIC, а в некоторых случаях также FOCAL и FORTRAN . Также были созданы некоторые EduSystems на основе PDP-11. [7]
Затем Аль начал портировать программы с FOCAL на BASIC, в частности, The Sumer Game (которую он переименовал в Hamurabi ), версию Lunar Lander и множество небольших демоверсий FOCAL. Объединяя свои порты с предложениями от внешних программистов, он сумел собрать достаточно материала, чтобы DEC опубликовала 101 BASIC Computer Games в 1973 году. Книга сразу же стала успешной и в конечном итоге выдержала три издания до 1975 года. [8] [6]
К середине 1970-х годов BASIC стал стандартной функцией всех машин DEC, а использование FOCAL прекратилось. [8]
PDP-11 был клонирован в Советском Союзе в 1970-х годах для военных целей. В 1980-х годах были произведены однокристальные вариации, похожие на LSI-11 , которые дали начало серии совместимых с PDP-11 домашних компьютеров . Наиболее заметной среди нескольких моделей была серия Electronika BK , выпущенная в 1985 году. Они изначально поставлялись с FOCAL на картридже ROM , [9] в то время как картридж BASIC был дополнительным дополнением. Более поздние модели поставляли BASIC по умолчанию. [10]
Следующее описание основано на FOCAL-69, как показано в справочном руководстве по языку FOCAL-8. [11]
FOCAL следовал модели JOSS для взаимодействия через интерфейс командной строки . Это позволяло пользователям вводить команды в «прямом режиме», которые выполнялись немедленно, или предварять их номером строки, в этом случае они добавлялись в программу, если были уникальными, или переопределяли существующий код, если тот же номер использовался ранее. [12]
Метод работы похож на « непосредственный режим » BASIC против «программного режима». Он контрастирует с JOSS, в котором все команды, как программные, так и прямые, сохранялись и загружались как часть рабочего пространства пользователя. Это позволяло JOSS иметь команды без номеров строк, которые они использовали для Form
определений и других задач. FOCAL не обладал этой возможностью, поэтому те инструкции, которые требовалось загрузить и сохранить, становились опциями других команд программного режима, таких как Type
. [12]
Каждая строка в программе FOCAL должна начинаться с номера строки. Как и в JOSS, номера строк представляют собой числа с фиксированной точкой, состоящие из двух двузначных целых чисел, разделенных точкой. В FOCAL-8 допустимые номера строк находятся в диапазоне от 1,01 до 31,99. При распечатке с использованием WRITE
, эквивалента BASIC в FOCAL LIST
, будут добавлены начальные нули; 1,10 будет напечатано как 01.10
. Это делает все номера строк пятизначными при выводе, так что все номера строк выровнены. Операторы, ссылающиеся на эти строки, не нуждаются в начальных нулях, например, GOTO 1.10
. [13]
Число слева от точки известно как «номер группы». Группы обеспечивают определенный уровень организации кода, которого не хватает в таких языках, как Fortran или BASIC. Основное их применение заключалось в использовании группы в качестве подпрограммы , которая может быть вызвана с помощью DO
, например, DO 5
для перехода к подпрограмме, написанной в группе 5. Редактор также использовал их во время редактирования, например, можно было WRITE 2
создать листинг кода в группе 2 или ERASE 4
удалить все строки в группе 4. [13]
Каждая строка должна начинаться с ключевого слова команды, следующего за номером строки. [13] Не существует понятия «команда по умолчанию», как в BASIC с его необязательным LET
оператором. Несколько операторов могут быть размещены на одной строке, разделенные точкой с запятой. Обычно поведение не отличается от того, если бы операторы были на отдельных строках, за исключением цикла FOR. [14]
Команда ASK
(сокращенно A) возьмет список строк и переменных, выведет строки на экран и сохранит пользовательский ввод в переменных. [15] Эквивалентно BASIC INPUT
.
01.01 СПРОСИТЕ "ИМЯ", ИМЯ01.02 ЗАДАТЬ "КООРДИНАТЫ", X, Y01.03 СПРОСИТЕ "A1",A1,"OMEGA",W,"T0",T0,"КОЭФФИЦИЕНТ ЗАТУХАНИЯ",КОЭФФИЦИЕНТ ЗАТУХАНИЯ
Если пользователь не вводит число, а вводит текст, система преобразует исходный символ в число, где «A»=1, «B»=2 и т. д.
Команда COMMENT
(сокращение C) создает примечание. [16] Эквивалентно BASIC's REM
. В оригинальном руководстве CONTINUE
в качестве синонима COMMENT указывается, что он используется для обозначения пустых строк, но это не имеет внутреннего различия. [17]
01.01 КОММЕНТАРИЙ: ИГРА «ЛЕТО» РИЧАРДА МЕРРИЛА
Команда DO
(сокращенно D) разветвляет выполнение на подпрограмму. Это эквивалентно BASIC GOSUB
. Подпрограмма ссылается либо по номеру группы, либо по номеру строки. Если указан номер строки, эта единственная строка выполняется, а затем возвращается к оператору после DO
. Если номер строки не указан, выполнение начинается с первой строки блока и продолжается до тех пор, пока не будет достигнут конец блока или не RETURN
встретится . RETURN
требуется только для раннего возврата из группы, в конце группы он не нужен. [18]
01.15 ДО 7.2401.16 ДО 8
Команда FOR
(сокращенно F) реализует цикл for . Если указаны три аргумента, первый — начальное значение переменной цикла, второй — приращение, а третье — конечное значение цикла. Если указаны только два значения, первое — начальное значение, второе — конечное значение, а приращение устанавливается равным 1. Это шаблон из циклов FORTRANDO
, в отличие от BASIC, FOR
где приращение — последнее значение, если оно есть.
В отличие от других частей языка, где несколько операторов в строке независимы, FOR
всегда запускает операторы, которые следуют за ним в строке, до того, как будет достигнуто завершение, а затем переходит к следующей строке. Таким образом, циклы должны быть на одной строке или, в качестве альтернативы, вызывать подпрограмму с помощью DO
. Эквивалент BASIC's NEXT
. [14]
01.01 ДЛЯ X=1,10; ТИП X,!01.02 ДЛЯ X=0,10,100; ДО 2
Пример цикла FOR:
01.10 СПРОСИТЕ «СКОЛЬКО ДЕНЕГ ВЫ ХОТИТЕ ЗАНЯТЬ?», ДИРЕКТОР01.20 СПРОСИТЕ "НА СКОЛЬКО ЛЕТ?",ТЕРМИН01.30 ДЛЯ СТАВКИ=4.0,.5,10;ДО 2.001.40 ВЫХОД02.10 УСТАНОВИТЬ ПРОЦЕНТ=ОСНОВНАЯ СУММА*(СТАВКА/100)*СРОК02.20 ВВЕДИТЕ "СТАВКА",СТАВКА," ","ИНТЕРЕСЫ",ИНТЕРЕСЫ,!
Команда GOTO
(сокращенно G) переходит к выполнению программы на указанный номер строки. [18] Она идентична одноименному оператору в BASIC. В FOCAL GOTO
также используется для начала выполнения, как и в BASIC RUN
, но в этом случае документация ссылается на нее как на GO
вместо , GOTO
несмотря на то, что базовая команда та же самая.
01.05 ПЕРЕЙТИ К 1.0102.90 НАПИШИТЕ !!,"ПОВТОРИТЕ ПОПРОБУЙТЕ.",!!!!!;ПЕРЕЙДИТЕ К 1.1
Команда IF
(сокращение I) обеспечивает условный переход на основе знака выражения. После числового выражения команда IF может принимать от одного до трех номеров строк. Если выражение меньше нуля, выполнение переходит к первому номеру строки; если равно нулю, то к второму номеру строки; если больше нуля, то к третьему номеру строки. В языке отсутствовали относительные операторы, такие как больше, равно или меньше. Для перехода, если X > 5, нужно сравнить X - 5. [19]
02.20 IF (25-25) 2.4,2.3,2.403.01 ЕСЛИ (Х) 3.1,3.02,3.1
IF можно сократить, поставив точку с запятой (или конец строки) после номера первой строки. Например:
02.20 ЕСЛИ (X)1.8; ТИП "Q"02.30 ЕСЛИ (Х)1.8,2.5002.40 ТИП "П"
В этом случае тест в 2.20 заставит программу перейти к строке 1.8, если тест отрицательный, в противном случае она продолжит и наберет "Q" на консоли. Строка 2.30 перейдет к 1.8 или 2.5, если значение отрицательное или нулевое, а в противном случае продолжит набирать "P" на консоли. [19]
Команда QUIT
(сокращенно Q) завершает выполнение программы и возвращает управление среде редактирования. [16] Эквивалентно BASIC STOP
или END
.
01.10 ДЛЯ X=-10,1,10;ТИП X01.20 ВЫХОД
Команда RETURN
(сокращение R) разветвляет выполнение подпрограммы обратно в вызывающее место. [16] Использование RETURN
необязательно в последней строке подпрограммы, подпрограмма в любом случае возвращается в последнюю строку в группе. Ниже приведен пример подпрограммы для преобразования подсказки «да/нет» в значение. [1]
22.78 КОММЕНТАРИЙ: ПОДПРОГРАММА «ДА ИЛИ НЕТ»22.80 СПРОСИТЕ "ОТВЕТ ДА ИЛИ НЕТ?", AN22.82 ЕСЛИ (AN-0ДА)22.84,22.8622.84 ЕСЛИ (АН-0НО)22.8,22.88,22.822.86 УСТАНОВИТЬ X=2;ВОЗВРАТ22.88 УСТАНОВИТЬ X=1;ВОЗВРАТ
Команда SET
(сокращенно S) присваивает результаты выражения указанной переменной. [20] Эквивалентно BASIC-команде LET
.
01.30 УСТАНОВИТЬ ПИ=3,1415601.60 УСТАНОВИТЬ ПРОЦЕНТ=ОСНОВНАЯ СУММА*(СТАВКА/100)*СРОК
Команда TYPE
(сокращенно T) обеспечивает вывод одного или нескольких элементов, разделенных запятыми. [21] Эквивалентно BASIC PRINT
.
Элементы могут быть переменными, литеральными строками, заключенными в двойные кавычки, или различными управляющими символами. Управляющие символы включают !
для вывода возврата каретки и перевода строки, #
для возврата каретки в одиночку и :
для символа табуляции. Управляющие символы могут быть связаны вместе, например, !!!
выведет три CR/LF без необходимости разделять их запятыми. [15]
ТИП [ЧИСЛА, E1, "ТЕКСТ", !, #, :, $ ИЛИ %] ...ВЫВОД01.10 НАПИШИТЕ «ПРИВЕТ, СИМПАТИЧНО ВЫГЛЯДИШЬ. СКОЛЬКО ДЕНЕГ ХОЧЕШЬ ЗАНЯТЬ?»,!01.50 НАПИШИТЕ "ИНТЕРЕС",ИНТЕРЕС,!01.80 ВВЕДИТЕ "ПРОЦЕНТЫ ЗА", СРОК, "ЛЕТ",!,"СОСТАВЛЯЕТ", ПРОЦЕНТЫ, "ДОЛЛАРОВ.",!!01.90 НАПИШИТЕ "НЬЮ-ЙОРК",!,"ВАШИНГТОН",!,"АТЛАНТА",!,"ДАЛЛАС",!02.10 ТИП "X",X," ","X^2",X^2," ","КОРЕНЬ",FSQT(X)03.20 ТИП ".",#02.20 ТИП!!!!!
TYPE
также включен необязательный спецификатор формата, указанный с помощью формата %x.yz
, где x — количество цифр слева от десятичной точки, а yz — количество цифр справа от точки. Формат по умолчанию был %8.4
, что означает максимум восемь цифр и четыре справа от точки. [22] Так, например:
НАБОР А=67823ТИП %6.01,А= 67823.0ТИП %5,А= 67823ТИП %8.03,А= 67823.000ТИП %,А= 6.7823E4
Обратите внимание на дополнительные начальные пробелы в некоторых примерах, заполняющие полную определенную ширину. Использование только % приводило к печати вывода в "формате с плавающей точкой" с использованием E. [23]
Специальный управляющий символ был, $
который вызвал вывод таблицы всех определенных переменных и их значений. Будут напечатаны только первые две буквы имени, дополненные нулем, если необходимо. Элементы массивов печатаются на отдельных строках, а переменные с одним элементом будут индексированы (00). Например: [24]
ТИП $А0(00)=67823
Имена переменных могут начинаться с любой буквы, кроме F (F зарезервирована для функций), и могут содержать любую последовательность букв и цифр. Однако значимыми являются только первые два символа. Например, следующий пример кода из FOCAL: A New Conversational Language [25] ссылается на ту же переменную, что и DESTINATION, а затем на DES. Внутренне обе ссылки ссылаются на переменную, обозначенную DE:
01.80 СПРОСИТЬ НАЗНАЧЕНИЕ02.30 IF (DES-14) 2.4,3.1,2.4
Любая переменная может рассматриваться как массив, допускающий индексы от -2048 до 2047.[2]
FOCAL содержал пять математических операторов: [26]
^
для экспонент – экспонента преобразуется в 12-битное целое число*
для умножения/
для разделения+
для добавления-
для вычитанияОдной из особенностей версии FOCAL 1968 года было то, что операторы имели независимый приоритет, как в порядке выше. Хотя это, безусловно, относится к возведению в степень, умножению и делению, в руководстве FOCAL 1968 года есть некоторая двусмысленность относительно сложения и вычитания. В частности, приведены примеры, демонстрирующие приоритет операторов для умножения и деления, но примеры, демонстрирующие приоритет операторов для сложения и вычитания, отсутствуют. Тем не менее, буквальное толкование руководства FOCAL 1968 года предполагает, что формула SET T=2-3+1
будет вычисляться в порядке 2-(3+1) и, таким образом, даст -2. Это сильно отличалось от большинства языков, где + и - имели равный приоритет и оценивались бы (2-3)+1, давая 0. [26] Это может привести к тонким ошибкам при конвертации исходного кода FOCAL в другие системы.
Однако + и - имеют одинаковый приоритет в FOCAL-69 и FOCAL-71, поэтому SET T=2-3+1
, как и ожидалось, выдает 0.
FOCAL был необычен тем, что математические выражения могли использовать (), [] и <> взаимозаменяемо в сопоставленных парах для установления приоритета. [26] Например, следующее выражение является допустимым:
01.30 НАБОР А=<10*[5+1]*(1+5)>
Все они имеют одинаковый уровень приоритета и читаются слева направо, когда находятся на одном уровне, поэтому этот оператор будет оценен [], затем (), затем <>, чтобы получить 360. [26]
Язык содержал следующие встроенные функции: [27]
FABS()
– Абсолютное значениеFATN()
– АрктангенсFCOS()
– Косинус аргумента в радианахFEXP()
– Естественная основа силы аргументаFITR()
– Целая часть аргументаFLOG()
– Наперианское бревноFRAN()
– Случайное числоFSGN()
– Знак аргумента; FSGN(0)=1 в FOCAL-69, но FSGN(0)=0 в FOCAL-71 и более поздних версияхFSIN()
– Синус угла, заданного в радианахFSQT()
– Квадратный кореньFOCAL-71 добавил две новые функции для ввода односимвольных значений, похожие на ASK, но возвращающие значения ASCII.
FIN
останавливается, пока пользователь не введет символ, а затем возвращает код ASCIIFOUT
выводит значение ASCII в виде символа на консоль или в файлFOCAL также включал несколько специальных функций: [28]
FADC
считывает значение из аналого-цифровых преобразователей PDP-8, используя номер канала в качестве параметраFDIS
участки в заданном месте YFDXS
участки в заданном месте XFOCAL используется GOTO
в редакторе для запуска программы. Однако, общепринятым правилом было сократить это до GO
. Это эквивалент RUN
в BASIC. GOTO
также может использоваться в редакторе для запуска выполнения с указанной строки.
Новые строки вводятся в программу, просто начиная команду с номера строки. Команды редактирования были ERASE
(аббревиатура E), [26] MODIFY
(аббревиатура M), [29] и WRITE
(аббревиатура W): [15]
ERASE
– обнулить все переменные; иногда это используется в программах для их сбросаERASE line number
– удалить оператор в указанной строкеERASE group number
– удалить все утверждения в указанной группеERASE ALL
– удалить всю программуMODIFY line number
– разрешить редактирование указанной строкиWRITE line number
– отобразить выписку в указанной строкеWRITE group number
– отобразить все утверждения в указанной группеWRITE ALL
– отобразить указанную программуКоманда файла была ОТКРЫТА (сокращенно 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-8FOCAL-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) и в большей степени полагалась на эту операционную систему для обработки и редактирования файлов.
Одним из изменений в новой версии стал 10-значный математический пакет для дополнительной точности. FSGN
Теперь функция возвращала ноль, если входное выражение оценивалось как ноль. Раньше это возвращало единицу. FRAN
Теперь использовался лучший алгоритм, который производил более случайно распределенные числа. Также была добавлена новая функция FIN
, которая принимала строку и возвращала ее значение ASCII (похоже на BASIC ASC
), а FOUT
также принимала число и возвращала строку с этим символом ASCII ( CHR
).
Поскольку все эти опции занимали ограниченный объем памяти, при запуске FOCAL,1971 открывался диалог, в котором пользователю предлагалось указать, какие функции он хотел бы использовать.
FOCAL, по сути, является очищенной версией JOSS с изменениями, делающими синтаксис более кратким и более простым для анализа. Почти все команды FOCAL имеют однозначное соответствие с JOSS и отличаются только деталями. Наиболее очевидным изменением на первый взгляд является то, что JOSS нечувствителен к регистру и выводит ключевые слова в смешанном регистре, тогда как FOCAL выводит только в верхнем регистре. Кроме того, операторы JOSS заканчиваются точкой, что делает их похожими на письменные операторы, тогда как FOCAL не имеет обязательного завершения строки.
Одно из главных отличий заключается в том, что JOSS включал полный набор операций сравнения и систему булевой логики , которая работала внутри if
и for
конструкций. Кроме того, ветви и циклы могли применяться к любому оператору, в отличие от FOCAL, где единственная операция, которую они могли выполнять, была эквивалентна goto. Например, в JOSS можно было:
1.10 Тип A, если X>10. 1.20 Введите i для i=1(1)10.
Первая строка опционально печатает A на основе значения X, а вторая печатает числа от 1 до 10. Напротив, в FOCAL отсутствовала возможность сравнивать значения, и циклы применялись путем перехода к следующей строке после их завершения. Эквивалентный код в FOCAL будет следующим:
1.10 ЕСЛИ (X-10),,1.301.20 ТИП А!1.30 ДЛЯ I=1,1,10;ТИП I,!
Реализация JOSS упрощает построение общих конструкций и более точно соответствует намерениям программиста, за счет усложнения среды выполнения. Например, JOSS допускает гибкое описание диапазонов в циклах, например, 1,2,3,10(5)50,75,78. Эта гибкость имеет свою цену; в FOCAL начало, конец и шаг могут быть записаны в пользовательской структуре в памяти и легко обновляться по мере выполнения цикла, тогда как JOSS требует переоценки выражения, которое может быть, но часто не является, более сложным.
Чтобы сделать код в FOCAL более кратким, изменения были относительно незначительными. Например, JOSS' Do part 20.
становится немного меньшим FOCAL DO 20
, а Do step 20.1
становится DO 20.1
. Ключевые слова команд также были сокращены, где это было возможно, поэтому JOSS' Demand
становится FOCAL's ASK
, как для того, чтобы сделать его короче, так и для того, чтобы буква D могла быть использована уникально для DO
.
Для упрощения синтаксического анализатора некоторые конструкции JOSS были удалены. Например, JOSS мог выполнять множественные назначения с , Set S=P, P=Q, Q=S.
в то время как в FOCAL это должно было быть сделано отдельными операторами, SET S=P; SET P=Q; SET Q=S
. Аналогично, JOSS' Form
, используемый для форматирования вывода, был объединен в FOCAL TYPE
с %
.
Сравнения между FOCAL и BASIC были неизбежны, поскольку оба языка были распространены на мини-компьютерах одной эпохи, и оба языка имеют много общего в синтаксисе и структуре. В большинстве случаев происходит прямое преобразование кода FOCAL в BASIC и обратно. Например, чтобы попросить пользователя ввести значение, в FOCAL нужно:
СПРОСИТЕ "Сколько вам лет?",ВОЗРАСТ
в то время как в BASIC эквивалентом является:
ВВОД "Сколько вам лет?" , ВОЗРАСТ
За исключением нескольких особенностей, отсутствующих в одном или другом языке, и некоторых сравнительно незначительных различий в синтаксисе, эти два языка очень похожи.
Одним из заметных исключений является IF
в BASIC, который позволял помещать любой оператор после THEN
, что делало его более похожим на управляющие структуры JOSS. BASIC изменил порядок кода по сравнению с JOSS, поместив условное выражение в начало строки, а не в конец; в BASIC используется , IF this THEN that
тогда как в JOSS используется that IF this
. FOCAL IF
больше походил на вычисляемый goto BASIC , , но допускал любое количество строк в качестве целей, в отличие от только трех для отрицательного, нулевого и положительного значений, как в FOCAL.ON X GOTO 10,20,30
ON...GOTO
Другое важное различие между ними заключается в том, что в FOCAL отсутствовала встроенная поддержка строк как элементов данных, которые можно было бы назначать переменным. Как и в ранних версиях BASIC или FORTRAN до добавления строк (в F77), это ограничение обычно обходили с помощью использования литеральных строк в командах ввода и вывода. Только при манипулировании отдельными строками или символами в них это становилось существенной проблемой.
Поскольку строковые переменные не поддерживались, ввод строки использовал кладж , который преобразовывал любые символы, введенные пользователем, в их числовые значения. Например, если кто-то ввел их HELLOв оператор ввода, FOCAL преобразовал бы H в "8", числовое значение "H" в шестибитных кодах символов PDP-8 ("H" - восьмая буква). Затем он интерпретировал бы "E" как начало экспоненты, а затем попытался бы вычислить "8" в степени "LLO", что заняло бы несколько секунд процессорного времени и дало бы значение 0,76593020E+103, что не было бы полезным ответом. Тем не менее, задавая вопросы, на которые можно было бы ответить с помощью однобуквенных ответов, например "Вам нужны инструкции, Y или N?", программисты могли бы проверить результат на соответствие известным значениям символов, чтобы получить нечто похожее на ввод символов.
Добавление нуля к строке приведет к ее приведению к числовому виду, поэтому программы могут проверять определенные многосимвольные строки с помощью операторов IF, например, I (A-0BROWN) 1.00,2.00,1.00
которые будут переходить к 2.00, если A = "BROWN" или 1.00 в противном случае. Однако программа выдаст ошибку переполнения, если пользователь введет текст с неудачно размещенными символами 'E'. Например, можно проверить "BROWN" или "RED", но не "GREEN" или "YELLOW".
Реализация FOCAL PDP-8 использовала представление с плавающей точкой , которое представляло числа в виде четырех 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, которые добавили много функций, включая улучшенный ввод-вывод файлов массового хранения и даже виртуальную переменную память.
В середине 1970-х годов DELTA была более сложной версией FOCAL. Номера строк программы были от 00 до 99 "частей" и от 000000 до 999999 "шагов", выполняемых в алфавитно-цифровом порядке. DELTA имела несколько специализированных команд для осциллографа Tektronix 4010/14.
В России он нашел применение лишь в начале 1990-х годов в серийных домашних компьютерах серии «Электроника БК» .
Microsoft продавала версию FOCAL на бумажной ленте. [30] По словам Рэймонда Чена, мастер-лента утеряна, и FOCAL больше не доступен.
Оригинальный Lunar Lander является прекрасным примером для изучения кода FOCAL, поскольку он использует большинство функций языка. Этот код взят из оригинала, найденного на странице Lunar Lander Джима Сторера. [31]
01.04 T «УПРАВЛЕНИЕ ВЫЗОВОМ ЛУННОГО МОДУЛЯ. НЕОБХОДИМО РУЧНОЕ УПРАВЛЕНИЕ»!01.06 T «ВЫ МОЖЕТЕ СБРОСИТЬ РАСХОД ТОПЛИВА K КАЖДЫЕ 10 СЕКУНД НА 0 ИЛИ ЛЮБОЕ ЗНАЧЕНИЕ»!01.08 T «ОТ 8 ДО 200 ФУНТОВ/СЕКУНДУ. У ВАС 16000 ФУНТОВ ТОПЛИВА. ОЦЕНКА»!01.11 Т "ВРЕМЯ СВОБОДНОГО ПАДЕНИЯ - 120 СЕКУНД. ВЕС КАПСУЛЫ - 32500 ФУНТОВ"!01.20 T "ПЕРВАЯ ПРОВЕРКА РАДАРОМ ПРИБЛИЖАЕТСЯ"!!!;E01.30 T "НАЧАТЬ ПРОЦЕДУРУ ПОСАДКИ"!"ВРЕМЯ,СЕКУНДЫ ВЫСОТА,"01.40 T "СКОРОСТЬ В МИЛЬ+ФУТАХ, ТОПЛИВО В МИЛЬ/Ч, РАСХОД ТОПЛИВА В ФУНТАХ"!01.50 SA=120;SV=1;SM=32500;SN=16500;SG=.001;SZ=1.802.10 Т " ",%3,Л," ",ФИТР(А)," ",%4,5280*(А-ФИТР(А))02.20 T %6.02," ",3600*В," ",%6.01,MN," K=";AK;ST=1002.70 Т %7.02;I (200-К)2.72;I (8-К)3.1,3.1;I (К)2.72,3.102.72 T "НЕВОЗМОЖНО";FX=1,51;T "."02.73 Т "К=";АК;Г 2.703.10 Я (МН-.001)4.1;Я (Т-.001)2.1;СС=Т03.40 Я ((Н+С*К)-М)3.5,3.5;СС=(МН)/К03.50 Д 9;И (И)7.1,7.1;И (В)3.8,3.8;И (Ю)8.103.80 Д 6;Г 3.104.10 Т "ТОПЛИВО КОНЧИЛОСЬ НА", Л, "СЕК"!04.40 СС=(FSQT(V*V+2*A*G)-V)/G;СВ=V+G*S;СЛ=Л+С05.10 Т "НА ЛУНЕ В",Л,"СЕК"!;SW=3600*V05.20 T "СКОРОСТЬ УДАРА",W,"МИЛЬ/Ч"!,"ОСТАЛОСЬ ТОПЛИВА:"МН," ФУНТ"!05.40 Я (1-З)5.5,5.5;Т "ИДЕАЛЬНАЯ ПОСАДКА !-(УДАЧА)"!;Г 5.905.50 Я (10-З)5.6,5.6;Т "ХОРОШАЯ ПОСАДКА-(МОГЛО БЫТЬ ЛУЧШЕ)"!;Г 5.905.60 Я (22-З)5.7,5.7;П "ПОЗДРАВЛЯЮ С НЕУДАЧНОЙ ПОСАДКОЙ"!;Г 5.905.70 I (40-W)5.81,5.81;T "УЩЕРБ КОРАБЛЮ. УДАЧИ"!;G 5.905.81 I (60-W)5.82,5.82;T "АВАРИЙНАЯ ПОСАДКА - У ВАС 5 ЧАСОВ КИСЛОРОДА"!;G 5.905.82 T "ИЗВИНИТЕ, НО ВЫЖИВШИХ НЕ БЫЛО - ВЫ ВСЕ ОБЛАДИЛИ!"!"IN "05.83 T "ФАКТ, ВЫ ВЗРЫВИЛИ НОВЫЙ ЛУННЫЙ КРАТЕР",W*.277777," FT.DEEP."05.90 T !!!!"ПОПЫТАТЬ ЕЩЕ РАЗ?"!05.92 A "(ОТВЕТ ДА ИЛИ НЕТ)"P;I (P-0НЕТ)5.94,5.9805.94 Я (П-0ДА)5.92,1.2,5.92 05.98 T "КОНТРОЛЬ ВНЕ"!!!;Q06.10 SL=L+S;ST=TS;SM=MS*K;SA=I;SV=J07.10 Я (С-.005)5.1;СС=2*А/(V+FSQT(V*V+2*А*(ГЗ*К/М)))07.30 Д 9;Д 6;Г 7.108.10 SW=(1-M*G/(Z*K))/2;SS=M*V/(Z*K*(W+FSQT(W*W+V/Z)))+.05;D 908.30 Я (И)7.1,7.1;Д 6;Я (-Й)3.1,3.1;Я (В)3.1,3.1,8.109.10 SQ=S*K/M;SJ=V+G*S+Z*(-QQ^2/2-Q^3/3-Q^4/4-Q^5/5)09.40 СИ=АГ*С*С/2-В*С+З*С*(Q/2+Q^2/6+Q^3/12+Q^4/20+Q^5/30)
Программа четко разделена на множество подпрограмм. Это было почти универсально в программах FOCAL (и JOSS), поскольку схема нумерации строк делала такие конструкции простыми в использовании. Эта программа использует девять подпрограмм. Первая, группа 1, просто выводит инструкции с помощью оператора T
ype и устанавливает начальные значения для запуска. Масса топлива не записывается напрямую, вместо этого она использует текущую M
заднюю и пустую массу, N
, поэтому оставшееся топливо равно M-N
и у посадочного модуля заканчивается топливо, когда M-N
равно 0. Также обратите внимание на E
rase в конце строки 01.20, которая сбрасывает все значения переменных.
Основной игровой цикл управляется группой 2. Поскольку код «проваливается» через группу 1 в группу 2 во время первого запуска, начальные значения выводятся в первых двух строках. Ближе к концу строки 02.20 пользователю предлагается A
ввести скорость сгорания как K
, а затем таймер цикла сбрасывается с помощью S T=10
. Строка 02.70 проверяет ввод пользователя по нескольким возможностям, если он больше 200 или меньше 8, он печатает «НЕВОЗМОЖНО" и ряд точек, а затем возвращается к циклу, чтобы попросить пользователя повторить попытку. Если значение находится между этими значениями, он переходит к группе 3. Обратите внимание, что IF
здесь очевидны ограниченные возможности команды FOCAL, в BASIC это можно было бы сократить до одногоIF K>200 OR K<8 THEN...
Группа 3 сначала проверяет, закончилось ли топливо, и переходит к группе 4, если это так. Затем она проверяет, T
истек ли 10-секундный период в, и, если да, возвращается к циклу, чтобы снова все распечатать, что имеет побочный эффект сброса T и S до 10. Строка 03.40 проверяет, уменьшит ли количество топлива, сожженного за этот период, массу транспортного средства в целом, сверх пустого веса, N. Если нет, она движется дальше, если да, то вместо этого устанавливает таймер цикла на количество времени, в течение которого сгорит оставшееся топливо, таким образом завершая цикл раньше времени. В любом случае она вызывает группу 9 для обновления скорости и положения. Затем она проходит по группам 7, 8 и 9, пока значение I не сойдется.S*K
S*K-M
Когда 10-секундный таймер заканчивается или достигает конца из-за проверки топлива в строке 03.10 или проверки высоты в 07.10. В последнем случае он перейдет к группе 4 и провалится в группу 5, или перейдет непосредственно в группу 5. Группа 5 вводит результаты конца игры, а затем спрашивает пользователя, хочет ли он попробовать еще раз. Если да, он переходит к 01.20, чтобы очистить все значения и снова напечатать заголовки, если нет, то проваливается к 05.98 и Q
uits.