↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |
Я тут немножко причесал текущую версию и пытаюсь её выложить, а это — что-то типа описания к ней.
Дополнение к главе 4 книжки про Фокал.
(Как раз к той, где оный Фокал и описан. И которую теперь
можно и не читать, потому как здесь пересказывается всё заново...)
Надо же на чем-то остановиться?
Надо, ну хотя бы временно. Вот и давайте остановимся на умеренно стабильной версии 1Б.433 от 09.10.20, назовём её "базовая-2" и подробно опишем её свойства. В сравнении с "базовой-0" версией, за которую мы примем то, что описано в главе 4, к коей этот текст — дополнение.
Кратенько напомню что там было написано.
— что Фокал — строчно-ориентированный: читает очередную строку и либо кладёт в память (если она с номером) либо выполняет
— что номер строки — дробное число, и поэтому программа (то, что хранится в памяти) естественным образом разбита на подпрограммы — группы строк.
— что дробное число (в операторе что-то делающем со строками) указывает одну конкретную строку, а целое — всю группу. А всю программу — ключевое слово Ales.
— что программная строка состоит из операторов, каждый из которых выполняет одно элементарное (для данного языка) действие
— что если операторов в строке несколько они разделяются символом ';'
— что оператор обязательно начинается с ключевого слова (которое можно сокращать до первой буквы, потому что они нарошно подобраны на разные буквы алфавита). И может содержать что-то еще — от оператора зависит. Например выражение. Или еще одно ключевое слово. Или некий таинственный "формат"...
— что если выражений в операторе несколько — они разделяются символом ','
— что выражения описывают вычисления по формулам и состоят из операций и операндов. Ну и скобок — для красоты, удобства и для ради изменения порядка действий супротив "естественного". (Но скобки должны быть сбалансированы.)
— что работает Фокал с одним единственным типом данных — числами с плавающей запятой.
— что операции (коих ровно пять: '+' '-' '*' '/' '^') указывают арифметические действия над этими числами, а операнды указывают где их взять.
— что число можно непосредственно изобразить прямо в выражении в виде константы — самым обычным для всех алгоритмических языков способом — в виде последовательности циферок, возможно с десятичной точкой, отделяющей дробную часть от целой, а так же порядком после буквы 'E'
— что число можно взять из переменной, куда оно ранее было положено на хранение оператором Set (ну или For — он тоже "с присваиванием"). Каковая переменная обозначается "именем" — словом, начинающимся обязательно с буквы и состоящем из букв и цифр. (Впрочем в Фокале буква — всё что не цифра и не разделитель. В том числе ни для чего не используемые символы _:@#$&|~)
— что число может быть так же вычислено одной из встроенных функций. Каковые тоже обозначаются именами, но обязательно на букву 'F'. (А вот переменные на эту букву называть нельзя, увы.)
— что функции, возможно, надо передать аргументы — в скобочках после имени. Если несколько, то через запятую.
— что переменной тоже "причитаются" аргументы, вернее — индексы, один или два. (Или ни одного.) Это же массив получается! (Одно— или двух-мерный.)
— что функции — только встроенные, новую функцию (как в других языках) объявить невозможно. Но если очень хочется, то в качестве функции можно использовать подпрограмму — вызвав её с помощью спецфункции FSUbroutine. В том числе ей можно передать один аргумент (он присвоится спецпеременной '&') а по завершении она вернет результат, в качестве которого берётся значение последнего выражения, вычисленного перед возвратом из подпрограммы.
— что переменные (как в других языках) объявлять не надо, ни обычные ни с индексами — они заводятся в момент первого им чего ни будь присваивания. И занимают память до тех пор, пока все разом не будут уничтожены оператором Eraze
— что выражение произвольной сложности может быть использовано абсолютно везде, где по смыслу требуется число. (Кроме таинственной конструкции "формат") В том числе в операторах передачи управления, таких как Go, Do, If. (Получается "вычисляемый переход".) И даже когда ждет ввода оператор Ask. Он вводит не просто константу, а именно выражение, вычисляет его и кладёт результат в указанную в нём переменную. Можно сказать, что Ask — "левая часть" оператора присваивания Set.
— что операторы Set и Xecut просто вычисляют указанное в них выражение, но первый имеющий форму: Set переменная = выражение; кладёт результат выражения в переменную, а второй: Xecut выражение; этот результат просто теряет. Он предназначен для вызова функций с "побочным эффектом", возвращаемое значение которых — "не интересно".
— что оператор вывода Type выводит результат каждого из перечисленных в нём выражений например на терминал в удобочитаемом виде. А оператор ввода Ask делает всё наоборот — для каждой из указанных в нём переменных, вводит (например с того же самого терминала) и вычисляет одно выражение. А его результат помещает в эту переменную.
— что в обоих этих операторах допускаются так-же текстовые константы (в виде любых символов в кавычках), которые выводятся один к одному — в качестве комментариев к выводимым числам или приглашений ко вводу.
— что ранее упоминавшаяся таинственная конструкция "формат" указывает в операторе Type как ему выводить числа. Это либо одиночный символ '%' обозначающий "формат по умолчанию", либо '%' и два целых, разделенных точкой, указывающих ширину поля под число и количество выводимых цифр (т.е. точность).
— что оператор Operate указывает (с помощью второго ключевого слова) куда производить вывод и откуда ввод. И что при любой ошибке (в том числе — конец файла или другого носителя информации на устройстве, откуда идёт ввод) Фокал автоматически переключает ввод и вывод на терминал, после чего "ругается".
— что обычно операторы выполняются в "естественном" порядке — так как написаны в строке, а строки — в порядке ввода, или в порядке нумерации. Но есть операторы "передачи управления", меняющие этот естественный порядок. Оператор Goto — просто передаёт управление строке с указанным номером, остаток строки после него не выполняется никогда. Оператор Do передаёт управление подпрограмме — как бы "взаймы": когда подпрограмма завершится, управление получит следующий после него оператор. Условный оператор If тоже как и Go передаёт управление навсегда. If (условие) адрес1, адрес2, адрес3; Но в зависимости от того, меньше нуля значение "условия", равно или больше — по одному из трех адресов. Если последние из них отсутствуют, то в соответствующих случаях выполняется остаток строки.
— что подпрограммой может быть как отдельная строка так и вся группа — в зависимости от того дробное или целое число было в операторе Do.
— что возврат из подпрограммы происходит автоматически по достижению её конца, ну или при выполнении оператора Return.
— что оператор Quit останавливает выполнение всей программы независимо от глубины вложенности вызовов подпрограмм. (В то время как Ret завершает только последнюю.) А в "нулевой" ("прямой") строке (в отличии от "косвенных" — находящихся в памяти) оператор Quit завершает работу интерпретатора (позволяет выйти в операционную систему).
— что для многократного выполнения чего либо (например действий над каждым из элементов массива) используется оператор For переменная = нач_зн, кон_зн, шаг; который сначала (в качестве начального значения) присваивает указанной в нём переменной значение первого выражения в его заголовке. А потом каждый раз увеличивает его на "шаг" (или на единицу, если третьего выражения в заголовке нет) до тех пор, пока оно не станет больше конечного значения. И каждый раз выполняет остаток строки. Причем как подпрограмму.
— что для обслуживания (т.е. сохранения, исправления, удаления...) хранящихся в памяти программных строк используются такие же операторы, как и все остальные (а не какие-то специфические "команды" как в подобных интерпретаторах других языков). Оператор Write — как для вывода на терминал так и для сохранения на внешних носителях. Оператор Modify для редактирования и Eraze для удаления. А для загрузки ранее сохраненной программы какой либо специальный оператор не требуется: достаточно переключить на неё канал ввода, как программа автоматически будет читаться и загружаться. А если там встретятся ненумерованные строки — они выполняться в точности так же, как если бы они были введены с терминала. (Что и позволяет использовать Фокал для выполнения "командных" (они же "скриптовые") файлов.) А запуск программы на выполнение осуществляется любым оператором передачи управления — Go, Do и даже If.
— что оператор Load используется для подгрузки к интерпретатору спецфункций, отсутствовавших в базовой комплектации. (Которые после этого становятся "встроенными".)
— что для посимвольного ввода/вывода используется спецфункция FCHR, выводящая каждый из своих положительных аргументов, а встретив отрицательный (который должен быть последним или единственным) вводящая один байт и возвращающая число, равное его коду.
(* Надеюсь, Вы уже догадались, что заглавными я пишу обязательные буквы в именах функций и операторов, а вовсе не выказываю им повышенное уважение. *)
— что для отсчета временных интервалов используется спецфункция FCLK, возвращающая количество тиков таймера с момента прошлого своего вызова.
— что для обращения к управляющим регистрам внешних устройств (в т.ч. нестандартных, собственной разработки) используется спецфункция FX, а для их сброса (т.е. приведения в некоторое "исходное" состояние) — оператор Kill.
— что для назначения реакции на (одно?) внешнее событие используется оператор Break, указывающий какую подпрограмму в этом случае вызывать.
— что в базовый набор встроенных функций входили корень, экспонента, логарифм, прямые и обратные тригонометрические функции. А так же генератор псевдослучайных чисел — функция FRND, без аргумента выдающая очередное число, а с аргументом — настраивающая генератор. И кроме того функции FABs и FSGn для получения абсолютного значения и знака (-1,0,+1) числа; FITr и FMOd — его целой и дробной части.
— что для поддержки процесса отладки (неизбежного для любой программы, потому что в любой программе найдётся хотя бы одна ошибка (С)), реализована "трассировка" и "пошаговый режим". Трассировка включается (и выключается) символом '?' перед оператором, а пошаговый режим — двумя вопросительными знаками. При трассировке текст каждого выполняемого оператора выдаётся на терминал, а при пошаговом режиме интерпретатор еще и останавливается, ожидая команды пользователя: выполнить следующий оператор, остановить программу или продолжить без трассировки...
— что для написания комментариев (пояснений к программе) имеется оператор Comment, весь остаток строки после которого просто игнорируется.
— что все скобки ([{<>}]) эквивалентны, и все кавычки '"` — тоже. (Что чтобы в текстовой константе изобразить кавычку, константу нужно заключить в кавычки другого типа.)
— что операторы распознаются по первой букве, имена переменных — по двум, а имена функций по первым уникальным. А лишние символы просто игнорируются.
— что пробелы — для красоты, и их можно вставлять в любых количествах. Но после ключевого слова обычно требуется какой либо символ-разделитель, например пробел.
— что запятые (если это не список аргументов функции), тоже в принципе для красоты...
— что всего может быть до 99 групп и до 99 строк в каждой группе.
— что к одной и той же переменной можно обращаться как с одним так и с двумя индексами, что к тому-же зависит от реализации. (Впрочем обычно гарантируется, что X(0,0) и X(0) это одна и та же переменная X.)
— что таймер в машинах разных типов тикает по разному. А чтобы сделать (с помощью функции FX) с внешним устройством что-то осмысленное, надо знать про него почти всё, иначе будет ОЙ!
— и.т.д. и.т.п. — в зависимости от возможностей аппаратуры и фантазии разработчиков.
Ну в общем что Фокал это типичный калькулятор (правда программируемый): чуть что — сразу останавливается, ругается и передаёт управление пользователю.
Вот где-то примерно так. Ага.
Ну так чем-же наша "базовая-2" версия отличается от вышеописанной?
В "негативную" сторону тем, что подгрузка дополнительных функций (и занимающийся этим оператор Load) — не реализована. Сброс внешних устройств (оператором Kill) — тоже. (Впрочем, в используемой архитектуре это не предусмотрено.) Да и обращение к аппаратуре на физическом уровне (функцией FX) — тоже сделано в ограниченном объёме — только к портам ввода/вывода. А к пространству оперативной памяти — нет.
И, да: злонамеренно сохранены почти все ограничения базового Фокала. В т.ч. распознавание имени переменной только по двум символам и "табу" на букву 'Ф'.
А в "позитивную" — в принципе по четырем аспектам:
1. доработан ввод/вывод для взаимодействия с файловой системой
2. сделаны настоящие локальные переменные
3. реализована реакция не только на (внешние) "события" но и на (внутренние) "ситуации". (В т.ч. на ошибки времени выполнения.)
4. обнаружен "регистр-аккумулятор" под текстовую строку. И вокруг него реализован механизм работы со строками. Совсем не такой, как планировался для третьего Фокала.
5. ну и кое-что по-мелочи: введены удобства и красивости; додуманы и доопределены некоторые операторы и функции...
Вот с этого и начнем — с удобств и красивостей.
5.1 Первым делом, первым делом... пианину? Нет, оператор Help! Который бы выдавал справки по операторам и функциям. Заранее заготовленные в отдельном справочном файле. По первой букве указанного в нём ключевого слова.
Этот самый справочный файл — самый обыкновенный — текстовый. (Чтобы можно было читать и так. Хотя бы потому, что это и есть основная документация на данное ПО. Да и писать удобней.) Но разбит на "секции" с помощью комбинации символов <<Х>> обязательно находящейся в начале строки. (Где Х — первая буква соответствующего ключевого слова).
Сначала разделы были маленькие — чтобы убирались на один экран. Но потом они разрослись и понадобился встроенный просмотрщик. Чтобы за раз выдавал на экран не больше строк, чем его высота. И ожидал реакции пользователя. (ВК — еще одна строка, пробел — следующий экран. В точности как в UNIX`овском more.)
А так как выводом у нас занимается еще и Type — ему спецформат %% чтобы и его вывод управлялся этим просмотрщиком. А вывод оператора Write (когда он на терминал) идёт через просмотрщик всегда.
5.2 Далее. Главное из удобств, реально облегчающих жизнь пользователю — "экранный" редактор командной строки. С "карманом" под фрагмент строки и "пулом" (мешком) ранее уже введенных строк. А так же средством захвата в карман фрагмента с любого места экрана. (Подсмотрено в Дос-Навигаторе.)
Разумеется, эта штука автоматически используется всегда, когда ввод с терминала.
↓ Содержание ↓
↑ Свернуть ↑
| Следующая глава |