Фокал
FOCAL |
- Тип исполнения:
- интерпретатор
- Типизация:
- один тип — вещественный
- Дата появления:
- 1959
- Диалекты:
- FOCAL-69 («классический»), FOCAL 1971, FOCAL 11, FOCAL-81
- Реализации:
- музейный FOCAL-81 для POSIX-систем
FOCAL (аббр. FOrmula CALculator) — универсальныйинтерпретируемый язык программирования высокого уровня, ориентированный на решение вычислительных задач в режиме диалога с пользователем. (Для сравнения FORTRAN — FOrmula TRANslator.)
Происхождение[править | править код]
Фокал, так же как Фортран или Бейсик — язык первого поколения: типы данных — только встроенные (один единственный — вещественные числа); для управления порядком действий используются только метки и переходы к ним (условный, безусловный, к подпрограмме); из структур данных — только массив. И оператор цикла для его обхода. Время появления таких языков: с середины пятидесятых годов прошлого века до середины шестидесятых, когда начали распространяться идеи структурного программирования. Фокал разработан как дополнение к Фортрану — для более оперативного решения относительно простых задач вычислительного характера в режиме непосредственного диалога пользователя с машиной посредством подключенного к ней телетайпа. То есть он был призван играть роль «программируемого калькулятора», которых тогда, разумеется, ещё не было. Язык имеет предельно простой синтаксис, крайне лаконичен, легко реализуется, нетребователен к ресурсам целевой машины. Последние два обстоятельства послужили причиной переноса его в конце шестидесятых годов на появившиеся тогда мини-ЭВМ (в частности на 12-и разрядную PDP-8 с ОЗУ 4К слов, автор Ричард Мерилл) что ошибочно считается датой появления языка. На мини-ЭВМ, как правило не имевших внешних запоминающих устройств, интерпретатор Фокала сам обеспечивал всё необходимое программное окружение и не нуждался в операционной системе. (Впрочем, так же как и реализованные для них версии Бейсика.)
В нашей стране Фокал эксплуатировался на аналоге PDP-8 — мини-ЭВМ Электроника-100 и аналогах PDP-11 от супермини-ЭВМ Э-79 до настольного компьютера ДВК-1/2/3 и бытового БК-0010. В последнем интерпретатор Фокала был зашит в ПЗУ (в поздних моделях БК — доступнен на картридже). Были также доступны расширения Фокала для этих машин, написанные различными энтузиастами. Расширения содержали разнообразные дополнительные команды и функции для работы с графикой, звуком, запуска двоичных программ, обработки строк и пр.
Существенно расширенная версия Фокал использовалась в качестве включающего языка в ДИАСП — Диалоговой Системе Проектирования — специализированной САПР, предназначенной для целей микроэлектроники.
В 1990-е годы энтузиастами была предпринята попытка переноса Фокала на IBM PC (Turbo Focal), но она не вышла из стадии бета-версии, которая распространялась по каналам BBS.
Сравнительное описание[править | править код]
Фокал просто обречен на сравнение с Бейсиком — эти два языка похожи очень во многом: имеют сходное строение и синтаксис; эксплуатировались на одних и тех же машинах; использовались для решения одного и того же круга задач; имели примерно одинаковые возможности и сходные ограничения… Но Фокал это подручный инструмент для специалистов, а Бейсик — средство для обучения начинающих. Фокал ориентирован на экономию ресурсов — как машины так и пользователя, а Бейсик — на интуитивную понятность с опорой на «естественный» язык. Фокал может быть реализован только чистой интерпретацией, а Бейсик (в исходном виде — упрощенное подмножество Фортрана) изначально был ориентирован на компиляцию. Причем с перфокарт, о чем говорят сохранившиеся и в диалоговых версиях перфокарточные рудименты — операторы DATA и READ.
На каждом из этапов развития вычислительной техники реализации Фокала при сходных возможностях были в разы компактные и производительнее аналогичных реализаций Бейсика. А сам язык отличался значительно большей «диалоговостью». Но не смотря на это, Бейсик всегда был значительно популярней Фокала. Видимо вследствии того, что программированию обучали именно с помощью Бейсика. Хотя, как показала практика, ни тот ни другой язык для обучения программированию решительно не годится (особенно с азов), так как первый алгоритмический язык (так же как и первый в жизни разговорный язык) становится родным — формирует стиль мышления человека по своему образу и подобию, и исправить потом его очень трудно. Тем не менее даже после появления Паскаля (и других нацеленных на обучение языков, например придуманного академиком Ершовым безымянного «алгоритмического языка», известного так-же как «Ершол») долгое время продолжалось обучение программированияю начиная с Бейсика.
С началом «бума персональных ЭВМ» круг людей, обученных по-бейсиковски резко расширился. По их настоятельным требованиям в их любимый (а часто и единственный) язык были включены разнообразные средства и концепции, позаимствованные из других языков. (В том числе плохо совместимые как с исходной концепцией языка, так и между собою.) Начиная с концепции типов данных и средств работы со строками. А рыхлая структура языка позволила это сделать. В результате чего из маленького и простого, хотя и несколько аляповатого языка, Бейсик превратился в громоздкого труднообозримого монстра, но живёт и здравствует и по сей день. Фокал напротив активно сопротивлялся бездумному включению в него средств, не соответствующих духу и структуре языка. Но в результате перестал удовлетворять современным требованиям; постепенно выпал из сферы общественного внимания и в настоящий момент поддерживается исключительно энтузиастами. В частности, попытка сделать турбо-версию Фокала оказалась неудачной не по техническим, а чисто по идеологическим причинам: интегрированная турбо-среда не делала и без того предельно диалоговый язык более удобным, а напротив вызывала когнитивный диссонанс с простым и строгим дизайном языка. Это выглядело примерно так же, как если-бы к слесарной ножовке по металлу приделать рукоятку, обитую пурпурным бархатом и украшенную висюльками ювелирной работы.
Грамматика Фокала и Бейсика аналогичны.
В исходном виде оба языка строчно-ориентированные. То есть диалог с оператором (или ввод программы) производится построчно. Если в начале строки присутствует номер — строка помещается в память, если нет — выполняется сразу. Сохраненные в памяти строки упорядочиваются по номерам и составляют собственно программу. Обслуживание программы (запуск её на выполнение, сохранение на машинном носителе или загрузка с него, а так же удаление или распечатка на терминале) в Фокале производится операторами самого языка, а не внешними по отношению к языку средствами, как в Бейсике (командами операционной системы — в пакетных версиях; специальными командами, действующими только в «нулевой» строке — в диалоговых версиях; через систему меню или с помощью «горячих клавишей» в турбо-версиях). Поэтому в частности любая (полноценная) реализация Фокала (начиная с самых ранних) позволяет писать самоподгружающиеся (а при наличии файловой системы и самомодифицирующиеся) программы, а для Бейсика подобное, как правило, исключено.
Номера строк как в Фокале, так и в Бейсике играют так же роль меток для операторов передачи управления. Но в Бейсике номер строки — целое число, в результате чего программа имеет вид безструктурного массива строк; а в Фокале это вещественное число. В результате чего программа получается структурированной — распадается на группы строк, каждая из которых — «естественная подпрограмма». (Целая часть — номер группы, дробная — номер конкретной строки в ней.) Поэтому с одной стороны синтаксис работающих со строками операторов (и обслуживающих программу Write, Modify, Erase и операторов передачи управления Go, Do, If) получается предельно простым: дробное число в них указывает конкретную строку, целое — целую группу, а вся программа, как правило, указывается ключевым словом Ales (что значит «всё»). А с другой — «сам бог велел» использовать группу (а так же отдельную строку, тоже являющуюся «естественной подпрограммой») для размещения подпрограммы, выполняющей одно законченное сложное действие.
Три структурные единицы программного текста (вся программа, группа строк, отдельная строка) при передаче им управления как подпрограмме (оператором DO или функцией FSUbr — см. далее) возвращают управление по достижении их конца автоматически. То есть даже в том случае, если там нету оператора возврата Ret. Это свойство используется, в том числе, при отладке программ: не требуется какой-то специальный отладчик с точками останова, пошаговым режимом, средствами слежения за значениями переменных и т. п. — вполне достаточно штатных средств. Достаточно вызывать строчки по одной (в том числе с использованием трассировки) и смотреть, что они делают.
В турбо-версиях Бейсика, имеющих встроенный редактор, пропала необходимость указывать обслуживающим программу командам части программы, и от обязательной нумерации строк отказались. А в качестве меток разрешили использовать как числа, так и имена. В Фокале отказ от нумерации строк невозможен: на них держится сама структура программы. А так же механизм вычисляемых переходов: в любом месте, где по смыслу требуется число, может быть использовано выражение произвольной сложности (в том числе даже, когда ввода числа ожидает оператор ввода Ask). В операторах перехода, разумеется, тоже. В большинстве реализаций Бейсика подобное не допускается — метки могут быть только константами.
В обоих языках программная строка состоит из «операторов», каждый из которых выполняет одно законченное элементарное действие. Оператор обязательно начинается с ключевого слова, и может содержать что-то ещё. В Фокале, в отличии от Бейсика, все ключевые слова подобраны на разные буквы алфавита и могут сокращаться до одной буквы (остальные всё равно игнорируются).
Основные операторы Фокала[править | править код]
оператор | описание | аналог в Бейсике |
Comment | комментарий (текст следом за командой игнорируется) | REM |
Set | присваивание значения переменной (или элементу массива) | LET |
eXecute | выполнить — вычисление выражения без присваивания результата | |
Ask | ввод | INPUT |
Type | вывод | |
Oper | переключение ввода/вывода между внешними устройствами | |
Go | безусловный переход | GOTO RUN (команда) |
If | условный переход | IF … ELSE |
Do | переход к подпрограмме | GOSUB RUN (команда) |
Ret | возврат из подпрограммы | RETURN |
For | цикл | FOR … NEXT |
Quit | останов программы или выход из интерпретатора | STOP соответствует частично |
Write | вывод или сохранение программы | LIST SAVE(команды) |
Erase | удаление строк программы | DELETE (команда) |
В программной строке может быть как один так и несколько операторов — столько, сколько поместится. Но в Бейсике помещается максимум два-три оператора, а в Фокале — пять-десять. В частности за счет того, что в фокаловских операторах нет лишних «шумовых» слов, предназначенных сделать их похожими на фразы «естественного» языка. В Фокале операторы разделяются символом ;, а в Бейсике — чем попало: в некоторых версиях символом :, а в некоторых \ (символ ; был задействован в операторе PRINT обозначать переход на следующую строку и разделять операторы оказалось нечем).
Выражения как в Фокале так и в Бейсике строятся из числовых констант, переменных, обращений к функциям, знаков операций и скобок, изменяющих естественный порядок их выполнения. Операций в Фокале ровно пять: + - * / ^ — сложение, вычитание, умножение, деление и возведение в степень. В Бейсике изначально было то-же самое, разве что возведение в степень обозначалось **, но в поздних версиях была введена концепция типов данных и количество операций резко возросло.
Имена переменных в Фокале, как и во всех языках, состоят из букв и цифр и начинаются обязательно с буквы. (Впрочем буквой в Фокале считается всё, что не цифра и не разделитель.) Переменная заводится «в явочном порядке» — в момент первого присваивания ей чего-либо — и существует до тех пор, пока все переменные разом не будут уничтожены с помощью оператора Erase. Наряду с переменными можно также использовать одно- и двухмерные массивы. Их элементы заводятся так же, как и простые переменные в момент первого присваивания (так как на самом деле это «переменные с индексами»). Это неэффективно, зато удобно. К тому же, сам собою отпадает вопрос о границах массива. (Для сравнения — в Бейсике массив должен быть предварительно объявлен оператором DIM; нумерация его элементов — с единицы, а не с нуля — уступка «обывательскому» сознанию.) Но в качестве побочного эффекта имеет место возможность обращаться к одной и той же переменной с разным количеством индексов, к тому же зависящая от реализации. Впрочем как правило гарантируется, что Х(0,0), Х(0) и Х — это одна и та же переменная.
Функции в Фокале только встроенные — возможности вводить новые функции с произвольными именами нет. Точнее говоря, нет возможности присваивать произвольные имена подпрограммам. Вызвать подпрограмму не как процедуру (оператором Do) а как функцию — из середины выражения — с передачей параметра (только одного) и возвратом результата — с помощью спецфункции FSBr. (В Бейсике изначально было то же самое. Разве что, такая подпрограмма объявлялась заранее и могла быть только одна.)
Имена всех встроенных функций, так же как и ключевые слова, распознаются по первым уникальным буквам. Но во-первых в отличие от ключевых слов, специально подобранных на разные буквы алфавита — по нескольким; а во-вторых все они (для упрощения распознавания) обязательно начинаются на букву F. А вот переменные на эту букву заводить нельзя, увы.
Набор встроенных функций как правило включает:
FSIn FCOS FTAn | - тригонометричесские |
FASin FACos FATan | - обратные тригонометричесские |
FSQrt FExp FLOg | - корень, Е в степени Х, логарифм |
FRnd | - генератор случайных чисел |
FABs FItr FMOd FSGn | - модуль, целая и дробная часть числа, знак |
FSBr | - вызов подпрограммы как функции |
FX | - обращение к внешним устройствам |
FCHr FCLk | - посимвольный ввод/вывод, таймер |
А так же другие функции — исходя из возможностей аппаратуры и фантазии разработчиков. Например:
FTMp | - дата/время |
FMAx FMIn | - минимум и максимум |
FBip FK FM | - управление звуком, курсором, мышью |
FT FL | - рисование точки, линии… |
В Фокале, в отличие от Бейсика, соблюдается принцип «ортогональности», заключающийся в том, что любое имеющееся средство (или концепция) применимо везде. В частности выражение произвольной сложности допустимо везде, где по смыслу требуется число. В том числе, в операторах передачи управления. (Получается т. н. «вычисляемый переход» — средство, аналогичное, например оператору, switch языка Си.) И даже в том случае, когда ввода числа с внешнего устройства (например, с терминала) ожидает оператор Ask.
Поэтому же в Фокале нету операций сравнения. В условном операторе значение выражения сравнивается с нулём, и чтобы сравнить два числа, приходиться вычитать одно из другого, что не очень удобно и ненаглядно. Но, во-первых, подавляющее большинство кодировок не предоставляет возможности обозначить все такие операции одним символом, как требуют принципы языка; а во-вторых, пришлось бы, либо ограничить применение этих операций только условным оператором (как в Бейсике), либо они тянут за собой логический тип данных и операции с ним. И это при том, что вещественное число само по себе — логическое значение трёхзначной (с нейтральным элементом, который можно и не использовать) или вообще нечеткой логики. В качестве инверсии можно использовать смену знака, а в роли операций И и ИЛИ — функции FMAx и FMIn.
Примеры программ[править | править код]
Стандартный пример Hello World
C Программа выводит на экран тестовую строку
1.1 T "Hello World !" !;Q
В операторах ввода/вывода Ask
и Type
допускаются текстовые константы — текст, заключенный в кавычки любого типа. А так же восклицательный знак, обозначающий переход на следующую строку. Они выводятся в качестве приглашения к вводу или пояснений к выводимым числам.
Решение квадратного уравнения вида .
1.1 T " Решаем квадратное уравнение вида: A*X^2 + B*X + C = 0 "!
1.2 T "Введите коэффициенты A B C"!
1.3 A " A=",A, " B=",B, " C=",C
1.4 S D=B*B-4*A*C; Т "дискриминант D=",D," "; I (D)1.9,1.8
1.5 T !,"Корни уравнения: X1=", (-B+FSQRT(D))/(2*A) !
1.6 T " X2=", (-B-FSQRT(D))/(2*A) !
1.7 T "Всё"! ; Q
1.8 T " - нулевой"! "Поэтому корень только один: " (-B)/(2*A) ! ; G 1.7
1.9 T " - отрицательный"!"Поэтому у этого уравнения корней нет"!; Q
Условный оператор If
вычисляет значение выражения и производит передачу управления по одной из трех меток — для случаев если значение этого выражения меньше, равно и больше нуля соответственно. Последние метки могут отсутствовать — тогда выполняется остаток строки.
Шуточная программа
1.1 A " Который час? ",N; F i=1,N,1;T "ку-ку"!
Циклический оператор For
содержит переменную — «параметр цикла» и три выражения (вычисляемые до начала цикла) — начальное значение параметра цикла, конечное значение и шаг. (Шаг может отсутствовать, тогда он буде 1 или −1 в зависимости от того что больше — конечное значение или начальное.)
Тело цикла — остаток строки. Если тело цикла в одну строку не помещается — его вполне можно разместить в отдельной группе (для того они собственно и нужны), а после оператора цикла — передача ей управления с помощью оператора Do
. Тело цикла — естественная подпрограмма: если передать оттуда управление оператором Go
другой строке — то по достижении её конца, управление опять вернется заголовку цикла для произведения следующей итерации. За то досрочно выйти таким методом из цикла (как это делается в других языках) — невозможно. Для досрочного выхода из цикла необходимо присвоить его параметру значение больше конечного.
Развитие языка[править | править код]
Сохраняя за Фокалом роль "программируемого калькулятора", развитие языка возможно по трем аспектам: * использование комплексных и гиперкомплексных чисел. Изменения грамматики: операция унарный плюс будет обозначать комплексное сопряжение, и возможно добавятся функции FRE и FIM для выделения реальной и мнимой части числа. Мнимая единица в константе будет указываться вместо Е, предшествующей показателю степени. Например: 1.2e3 + 4.5i6; или даже 1+2i. Для гиперкомплексных чисел в соответствующей позиции - следующие после i буквы алфавита. * визуализация результатов вычислений. Средство построения графиков. Добавляется оператор Vizual в котором второе ключевое слово указывает графический примитив. И в дополнение к нему - функция FVIZ для получения а так же установки параметров визуализации (включение графического режима, размеры экрана, глубина цвета и.т.п.). Графическими примитивами оператора Vizual являются вовсе не "точка", "линия", "полигон", "закраска"... в экранных координатах - как показала практика, они слишком примитивны. Поэтому они реализуются двумя функциями "расстровой графики" FT и FL, введенными еще в версии Фокала для бытового компьютера БК-00-10. Примитивы оператора Vizual (в том числе с теми же названиями) отрисовываются в абстрактных координатах. Которые получаются путем размещения на экране точки начала координат и опорных точек координатных осей. К каждой из которых привязывается значение параметра, откладываемого по этой оси. (Два значения: для опорной точки оси и точки начала координат, хотя последнее по-умолчанию - ноль.) Рисование одновременно нескольких графиков (предположительно - разными цветами) достигается с помощью примитива "коллекция точек". (Например строим графики А Б Ц, точки для них вычисляем в порядке: а1 б1 ц1, а2 б2 ц2, а3 б3... и.т.д. Переключить цвет перед отрисовкой точки - не проблема, проблема соединить линией текущую точку с предыдущей именно для своего графика.) Точки, относящиеся к ненулевой коллекции, сохраняются в памяти и при необходимости могуть быть отрисованы повторно например в других осях координат. * взаимодействие с файловой системой и общее совершенствование языка. Для открытия, закрытия и позиционирования файлов доопределяется оператор Operate: каждый открытый им файл теперь обозначается в нём "псевдонимом" - вторым ключевым словом. (Ключевые слова, ранее обозначавшие устройства, при этом сохраняются.) Для получения позиции в файле добавляется функция FTEll. Ей же (с аргументом в виде текстовой константы) поручается поиск файлов в текущем каталоге. В оператор Write добавляется второе ключевое слово Oper - для получения списка уже открытых файлов в форме пригодной для обратного ввода. Добавляются так же ключевые слова Set и Do для отображения результатов деятельности этих операторов. (Списка переменных и состояния стека вызовов подпрограмм.) Для программной реакции на ошибки (а так же внешние по отношению к Фокалу события) вводится оператор Break. Причем реакция на ошибки получается локальная в поставившей эту "ловушку" подпрограмме, а реакция на внешние события - глобальной. При возникновении события она отрабатывается между операторами выполняющейся программы. Для искусственного порождения собыния вводится оператор Kill (ранее использовавшийся для сброса в исходное состояние внешних устройств, что в современных архитектурах - нецелесообразно). "Событием" считается сигнал в UNIX`е и его клонах и прерывание - если под ДОС`ом. Для искусственного порождения ошибки ("ситуации") доопределяется оператор Quit, который впрочем и ранее генерировал неперехватываемую ситуацию с номером -1, останавливающую выполнение программы. (Комбинация ловушки на ситуацию и её искусственного порождения известно как "структурный переход". И позволяет например преждевременно выйти из одного или нескольких вложенных циклов в случае, если цель их работы уже достигнута. В базовом Фокале это можно было сделать только установкой параметра цикла больше его конечного значения.) Соответственно в оператор Write добавляется второе ключевое слово Break для отображения уже установленных реакций на внешние события. Ловушки на ситуации отображаются вторым ключевым словом Do в составе стэка вызовов подпрограмм. Здесь же отображаются локальные переменные: функции FSUBr разрешено иметь не один, а произвольное количество дополнительных параметров. Доступ к ним в вызванной этой функцией подпрограмме по именам: & &1 &2... и т.п. Или как к элементам одномерного массива &[0] &[1]... (но и &[-1] &[-2]...). Соответствующим образом доопределен так же оператор Do. Кроме того локальные переменные могут быть использованы для передачи параметров в подпрогамму реакции на событие или ситуацию. Кроме того для удобства использования в "нулевой" (ненумерованной) строке доопределяются некоторые операторы. Например If таким образом, чтобы в нем можно было выполнить остаток строки, пропустив не только последнюю, но и любую из трех меток. А так же чтобы можно было не выполнять, а перейти к следующей строке, независимо от её номера. Например: If(X)0,,0;Type "X равно нулю"!
Для взаимодействия с файловой системой, для самомодификации программы, а так же для многих других целей (например для облегчения написания на Фокале скриптовых файлов) очень желательно иметь средства манипулирования со стороками. Есть два пути дополнить ими язык: * полиморфизм. Ввести второй тип данных - "строку" и доопределить все пять имеющихся в языке операций. Например следующим образом:
+строка | -> число | - длина строки |
- строка | -> строка | - инверсия строки |
строка + строка | -> строка | - сцепление строк ("конкатенация") |
строка - строка | -> число | - сравнение строк (позиция вхождения одной в другую) |
строка * число | -> строка | - размножение строки |
число * строка | -> строка | - --//-- |
строка / число | -> строка | - разрезание строки |
число / строка | -> строка | - --//-- |
строка ^ строка | -> строка | - поиск общей подстроки ("полукорреляция") |
строка * спец_строка | -> строка | - замена символов, перекодировка |
строка / шаблон | -> строка | - сопоставление с регулярным выражением |
остальные комбинации типов вызывают ошибку |
Здесь "шаблон" это строка специального вида, содержащая регулярное выражение. В котором некоторые символы изображают сами себя, а некоторые - служебные: с их помощью изображаются конструкции, сопоставляющиеся не с одним единственным символом, а с целым их классом (например: "буква", "цифра", "открывающая скобка") или с состоящей из символов конструкцией (например: "слово", "имя", "выражение"...). А "спец_строка" это последовательность пар таких шаблонов. Операция / просто ищет в левом операнде фрагмент, который бы сопоставился с её правым операндом. А операция * сканирует строку и если с фрагментом, начинающимся с текущего места, сопоставится один из "первых" шаблонов правого операнда, то в результирующую строку попадает парный к нему. А если нет - текущий символ переносится как есть. (Основная проблема: сделать такой "второй" (генерирующий) шаблон общего вида, чтобы он генерировал фрагмент строки по образчику, сопоставившемуся с "первым" (анализирующим), причем без ограничения общности т.е. даже в том случае если они неконгруентны.) Ввести третий "пустой" тип данных, значение которого - результат пустого выражения, пропущенного параметра при обращении к функции, а так же начальное значение неинициализированной переменной. Оно вызывает ошибку при лююой операции с ним кроме: пусто-пусто всегда дающей в результате -1. (Заметим, что вычитание числа из самого себя всегда даёт ноль, а строки из самой себя - всегда +1.) Доопределить все (или по крайней мере некоторые) операторы для корректной работы со значениями вышеуказанных типов. Далее можно вводить еще какие-то типы данных, например указатели на внешние или внутренние объекты (включая переменные) с автоматическим их использованием некоторым образом... Предполагается, что всё это будет "Фокал-3", считая "классический" вариант - "первым Фокалом". Потому, что он за прошедшие много десятков лет, так и остался собою, стойко сопротивляясь любым противоречащим его духу изменениям.
* аккумуляторность. Использование внутренних ресурсов Фокала: оказывается что в нём изначально имелся и числовой регистр-аккумулятор и строчный. В первый попадает результат вычисления любого выражения. (Кроме может быть выражений, вычисляющих номер строки в операторах передачи управления.) Для того чтобы функция FSUBr могла "вернуть" его в то место, откуда вызвана. А вот второй - это входной буфер оператора Ask. Дело в том, что Фокал - строчно ориентированный. За один раз читает целую строку и потом использует её до тех пор, пока она не кончится. В частности оператор Ask для каждой очередной переменной из списка ввода вводит одно число (или выражение, сразу же и вычисляя его), но таких чисел в строке может быть несколько. Средство посимвольного ввода/вывода функция FCHr берет символы из канала ввода только в том случае если этот буфер пуст. А если нет - то из него. (По другому - очень уж некрасиво получается.) Соответственно, с одной стороны требуется средство принудительного опустошения этого буфера (например: Ask %), а с другой - немножко доопределив FCHr получаем средства работы с его содержимым - не только чтения но записи туда символов, а так же произвольного перемещения "маркера" - указателя, делящего буфер на "уже использованную часть" и "еще нет". Остаётся найти возможность ввода туда произвольной строки и её вывода. Для ввода используется сам же оператор Ask с пустым списком ввода, а для вывода - доопределенный оператор Write ("с фоорматом"). В результате получается "первая очередь" средсств обработки строк. (Если считать "нулевой" то, что было в Фокале изначально: функция FCHr для поштучного ввода/вывода символов и возможность их хранения в переменных в виде чисел.) Вторая очередь (реализованая в версии 6 Фокала-1Б) дополнительно включает развитые форматные выражения в Write %... и доопределение оператора Modify чтобы можно было перемещать программные строки между группами, а за одно и между ними и аккумулятором, а так же прилагающимися к нему "регистрами" форматного механизма. Третья очередь предполагает реализацию регулярных выражений, а так же набора встроенных форматов, например для преобразования текстов из одной кодировки в другую. Основа форматного механизма - доопределение оператора Write для того чтобы с его помощью можно было бы (в дополнение к прочим его обязанностям) еще и просматривать файлы. Точнее копировать указанное число строк из канала ввода в канал вывода. Через строчный аккумулятор, разумеется. Возможно, с некоторым преобразованием, вот как раз указанным форматом - конструкцией, начинающеся с символа %. Даже без каких либо преобразований, оператор уже полезен: например в демонстрационно-обучающих программах, выдающих на экран обширные тексты и выполняющихся непосредственно из файла, где всё это хранится. Или чтобы выдать находящуюся в аккумуляторе строку. Встроенные форматные преобразования предполагается указывать буквами. А прочими значками обозначать операции. Основных операций всего две: это * вставить и / удалить. Обе нуждаются в правом операнде (а левый - то место строки в аккумуляторе, куда указывает "маркер" - уже упоминавшийся указатель границы между "уже использованной" частью строки и "еще нет".) Правый операнд для * это то, что надо вставить - в простейшем случае строчная константа в виде любых символов в кавычках. А правый операнд для / это число символов, которые надо удалить. В простейшем случае числовая константа - одна или несколько цифр. Отдельно, не будучи чьими-то аргументами, они сами являются операциями - предписывают перемещение маркера и поиск фрагмента строки. Направление перемещения или поиска указывается префиксами - и +. А на случай неудачи (или напротив удачи) имеются постфиксы \ и & выполняющие в соответствующих случаях следующую за ними операцию. (А в несоответствующих - её пропускающие.) Если их нет, то при первой же неудаче выполнение форматного выражения сразу прекращается. Если одной операции мало, их можно сгруппировать круглыми скобками. Префикс повторения @ предусмотрен на случай, если например слово, подлжежащее обнаружению и замене может встретиться в строчке несколько раз. Чтобы запоминать позиции в строке и длины фрагментов, можно задействовать фокаловские переменные со специфическими именами, начинающимися на #, а чтобы сами фрагменты - несколько прилагающихся к форматному механизму строчных "регистров". Чтобы посмотреть, что в них хранится (а за одно и в аккумуляторе) оператору Write добавлено второе ключевое слово Reg. Фигурные скобки используются когда требуется значение фокаловского выражения, а вот квадратные и угловые зарезервированы для третьей очереди.
Литература и публикации[править | править код]
- В. А. Абрамов, А. В. Стрижков, А. Р. Федоров; «Диалоговый язык ФОКАЛ». М. «Высшая школа», 1991. Серия «Программное обеспечение МикроЭВМ», книга 4. ISBN 5-06-001785-0
- Г. И. Фролов, Г. А. Куправа, Ю. Г. Чаиров и др.; Под редакцией Л. Н. Преснухина; «Программирование на языке ФОКАЛ». М. Изд-МИЭТа, 1984
- А. Н. Писаревский, Л. Г. Осетинский, М. Г. Осетинский; «ФОКАЛ — диалоговый язык для миниЭВМ». Л. «Машиностроение». Ленинградское отделение. 1985
Ссылки[править | править код]
- The Retrocomputing Museum — интерпретатор FOCAL-81 для POSIX систем.
- Эмулятор различных ЭВМ, на котором можно запускать Фокал
- DEC’s FOCAL 1969 Promotional Booklet(англ.)
- Focal-81 в исходниках
- Фокал снаружи и внутри
- описание "продвинутой" версии 6 Фокала-1Б и ссылка для её скачивания