Страница произведения
Войти
Зарегистрироваться
Страница произведения

Еще одно такое-же типа дополнение к 4й главе


Автор:
Жанр:
Изобретательство
Опубликован:
17.03.2024 — 10.04.2024
Аннотация:
а на само деле результат очередной ревизии кода (самый конец до- и пере-писывается, а остальное - уже вряд ли)
Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава
 
 

значения" операторов. (Например счетчик строк, реально скопированных

оператором W %;.)

Второй: (А2) "строчный" аккумулятор — входной буфер оператора Ask. (Который

вишь вводит за раз целую строку, а использует её — постепенно.) Вокруг А2

постепенно сам собой нарос механизм работы с текстовыми строками. (См. далее.)

Существенно связанный с подсистемой ввода/вывода. Потому что считается что

тексты (как совокупность строк) слишком громоздки, и могут храниться только

снаружи, например в виде файлов.

Третий аккумулятор (условно "А3") — это та внутренняя переменная, куда

попадает указатель на файл, поучаствовавшей в последней по времени операции

ввода/вывода (в т.ч. и фиктивной) чтобы функция FTEll могла сообщить про него

какую-то информацию. И он нам тоже еще пригодится...


* * *

ЛОКАЛЬНЫЕ ПЕРЕМЕННЫЕ

В базовом Фокале, при обращении к подпрограмме с помощью спецфункции

FSBR можно передать только один параметр. Попадающий в переменную с именем &,

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

такой функции, предыдущее её значение безвозвратно терялось.

В данной реализации разрешается передавать подпрограмме произвольное

количество параметров. В том числе и при обращении к ней оператором Do.

А также при т.н. "структурном переходе" — порождении ситуации оператором

Quit (см. далее).

Эти (позиционные) параметры помещаются в настоящие локальные переменные,

доступные по именам & (или &0 или $ или $0), &1, &2, &3... (или $1, $2, $3...)

или как элементы одномерного массива &(...) включая и такие как &(-1), куда

обычно помещается количество переданных параметров.

Локальные переменные создаются не только при передаче параметров, но и так

же как и глобальные — при первом присваивании. Но в отличии от них, сперва

ищутся у подпрограмм с меньшей степенью вложенности. И обращение к

несуществующей локальной переменной ошибки не вызывает.


* * *

УСОВЕРШЕНСТВОВАНИЕ ОПЕРАТОРОВ

В операторе For:

— если шаг не указан, то он принимает значение +1 или -1 в зависимости от

того, больше конечное значение начального или меньше

— цикл завершается когда параметр цикла выйдет за конечное значение более чем

на пол шага. (Чтобы правильно работал и в случае когда шаг — не целый.)

— после окончания цикла его параметр, как и полагается, сохраняет то значение,

которые было на момент последней итерации.

— допускается форма из одного только ключевого слова: For;. Тогда остаток

строки выполняется ровно один раз, но как подпрограмма. (Это — в основном для

ограничения области действия структурного перехода — см.далее.)

В операторе If:

— допускается отсутствие не только последних, но и любого из адресов перехода

(при условии сохранения разделяющих их запятых) — в соответствующем случае

выполняется остаток строки

— допускается нулевой адрес перехода — в соответствующем случае выполнение

текущей строки просто завершается

— допускается отрицательный адрес перехода — он эквивалентен пропуску: в

соответствующем случае выполняется остаток строки.

Всё это — чтобы использовать оператор вообще без адресов. Например:

If (x) ,0; t "икс не равно нулю"!

If (x) 0, ,0; t "икс равно нулю "!

— из трёх адресов перехода вычисляется только один. Остальные — пропускаются.

Потому, что это может быть выражение общего вида, в том числе дающее побочные

эффекты.

Оператор Go

— с нулевым адресом передаёт управление на начало текущей строки — для

организации цикла без счетчика. Например:

...тело цикла...; If(Усл)0; G 0; Циклится пока Усл >= 0

Оператор Do

— кроме адреса перехода может содержать произвольное количество выражений.

Они все вычисляются и дают начальные значения локальных переменных &, &1, &2...

для вызываемой подпрограммы.

— некоторые из этих выражений могут быть пропущены — при наличии разделяющих

их запятых

— адрес перехода тоже может отсутствовать — при наличии отделяющей его от

следующих выражений запятой. Тогда никакая подпрограмма не вызывается, значения

попадают в локальные переменные текущей подпрограммы.

— НО: оператор Do (или Go) состоящий из одного только ключевого слова — для

запуска всей программы — исключение. Может быть в строке только единственным

(или последним, и даже ; после него не допускается), иначе вызывает ошибку.

Оператор Ret

— допускает одно выражение, вычисляющее возвращаемое значение подпрограммы.

Оно попадает в числовой аккумулятор (А1) и, возможно, возвращается с помощью

функции FSUbr. Ret Х; эквивалентно Хecut Х; Ret;

Функция FSUbr так же как и оператор Do

— допускает произвольное количество аргументов, а так же пропуск любых из них.

— первый аргумент, как и раньше — адрес для передачи управления подпрограмме,

остальные становятся начальными значениями её локальных переменных &, &1, &2...

— при пропуске первого аргумента (как и Do) никакой подпрограммы не вызывает;

сразу возвращает текущее содержимое аккумулятора А1. Остальные аргументы, если

есть, попадают в локальные переменные текущей подпрограммы.

Оператор Do и ф-я FSUbr передают управление точно, а Go и If — примерно.

Отсутствие строки с указанным номером в первом случае вызывает ошибку, а во

втором — передачу управления на следующую. (В пределах статуса выполнения!!!)

Операторы Set и Хecut

— допускают несколько выражений в операторе X и несколько присваиваний в

операторе Set — через запятую. Выпендрёж чистой воды.

Оператор Quit

— допускает один или несколько аргументов: первый — номер ошибки (ситуации),

остальные — параметры, которые будут переданы подпрограмме реакции на эту

ситуацию (см. ниже).

— допускается чтобы один из этих аргументов был текстовой константой. Это

сообщение о данной ошибке сидящему за терминалом человеку. Для оператора Quit

выполняющегося в "прямой" (нулевой) строке наличие такого аргумента блокирует

завершение работы интерпретатора. Примечание: в командном файле все строки

"прямые"...


* * *

Для операторов Write и Eraze в базовом Фокале понимавших только одно

ключевое слово Ales — "всё", добавлены дополнительные ключевые слова,

совпадающие с названиями операторов, результаты работы которых надо показать

или удалить. (Чтобы не спутать с ними выражение, начинающееся с имени

переменной, его всегда можно заключить в лишние скобки.)

— Open — список всех открытых файлов

— Set — список всех переменных

— Do — состояние операционного стека, включая локальные объекты

— Break — список ловушек на события

а так же

— Reg — содержимое регистров форматного механизма (см. далее)

— Tab — таблица табулостопов (в виде спецкомментария — см. далее.)

— Pul или Мешок — Write ничего не сообщает, а только помещает содержимое

строчного аккумулятора в пул (мешок) ранее введенных строк редактора командной

строки; Eraze делает его пустым.

Но "Set", "Do" и "Open" — только для Write, потому что переменные оператор

Eraze и раньше стирал без всяких ключевых слов, а содержимое стека возвратов

стереть нельзя впринципе. Файлов Eraze тоже закрывать не уполномочен...

(Только когда Eraze Ales; — сразу все, но кроме тех двух, на которые

направлены каналы ввода и вывода.)

Регистры форматного механизма E R; очищает, а вот аккумулятор А2 — нет.

(Как впрочем и А1 и А3 тоже не очищаются ничем.) Но он очищается автоматически

(если не запретить) при переключении канала ввода, и "вручную": Ask %

(см. далее).

Операторам Write и Eraze дополнительно поручено выдавать и соответственно

стирать не все переменные какие есть, а только некоторые. (Например элементы

одного массива.) Указанные текстовой константой в качестве аргумента:

Write "имя"; Eraze "имя";


* * *

СИТУАЦИИ И СОБЫТИЯ

При возникновении любой ошибки, базовый Фокал, будучи фактически

программируемым калькулятором, останавливал выполнение программы и передавал

управление человеку, сидящему за терминалом. В настоящей версии на этот

случай реализован "механизм ситуаций".

Ситуация, возникшая в результате ошибки или искусственно созданная

оператором Quit, начинает "распространяться". И если никакой реакции на неё

небыло предусмотрено, то, как и раньше, останавливает работу программы с

выдачей сообщения об ошибке. И переключением каналов ввода и вывода на

терминал и клавиатуру. Передавая тем самым управление человеку за терминалом.

Но любая из подпрограмм может поставить на данную ситуацию "ловушку". Если

ситуация так и не возникла, то это не окажет никакого влияния на ход выполнения

программы: когда подпрограмма завершится, ловушка будет просто удалена так же,

как и принадлежащие этой подпрограмме локальные переменные. А вот если и когда

возникшая где-то во вложенных подпрограммах ситуация дораспространяется до

этого места — ловушка сработает, будет выполнена предусмотренная в ней реакция

(в том числе "нулевая") и столь предусмотрительная подпрограмма завершится

нормально, как будто никаких ошибок небыло. Это и есть "структурный переход".

Позволяющий, в частности, досрочно выйти из цикла. Или даже нескольких

вложенных. Например нам нужно найти в матрице a() элемент a(i,j) значение

которого больше или равно k. Полезный результат — вот как раз индексы i и j,

которые здесь параметры циклов.

5.4 B 17; F i=1,N1; F j=1,N2; I(a(i,j)-k) 0; Q 17

Да, параметры циклов можно было сохранить во вспомогательных переменных и

установить равными конечным значениям N1 и N2. Но вот так — изящнее.

Номер ситуации 17 здесь выбран "от балды", главное: ошибок с таким номером

заведомо нет.

Обратим внимание: строкой 5.4 выполнение подпрограммы в группе 5 и

закончится. Потому что срабатывание ловушки ведёт к выходу из ближайшей

подпрограммы. Если нам надо, чтобы после 5.4 выполнялись так же строки 5.5,

5.6, 5.7... можно ограничить распространение ситуации одной только текущей

строкой — следующим образом:

5.4 F; B 17; F i=1,N1; F j=1,N2; I(a(i,j)-k) 0; Q 17; C см. оператор For

Ошибки (ситуации), так же как и номера программных строк, объединяются в

группы, чтобы можно было поставить ловушку как на всю группу ошибок сразу, так

и на конкретную. Группы ошибок:

0 — действия человека за терминалом (например 0.3 — нажата Ctrl/C)

1 — синтаксические ошибки (например 1.4 — дисбаланс скобок)

2 — арифметические ошибки (например 2.1 — деление на ноль)

3 — ошибки ввода/вывода (например 3.2 — конец файла)

4 — прочие ошибки (например 4.3 — нет переменной)

5 — недостаток ресурсов (например 5.1 — не хватает оперативной памяти)


* * *

Реакцию на внешние по отношению к программе события тоже устанавливает

оператор Break. События отличаются от ситуаций тем, что их номера -

отрицательные, ловушки на них — глобальные, и реакция не может быть "нулевой":

если указана нулевая реакция — отслеживание данного события отменяется.

Фокал — интерпретатор медленный, поэтому внешние события именно что

"отслеживаются": с каждым из них связан счетчик, при возникновении события он

наращивается. А когда запускается подпрограмма реакции — передаётся ей в

качестве одного из аргументов и обнуляется.

Реакция на событие (аналог прерываний) запускается "вне очереди" между

выполнением операторов основной программы. Тоже как подпрограмма. И на время

её работы реакция на другие события запрещается. (А вот если она сама вызовет

подпрограмму — там уже можно.)

Следует иметь в виду, что некоторые операторы могут выполняться очень

долго. Например включающие ожидание ввода с терминала. В том числе когда

"интерфейсная" часть интерпретатора ожидает ввода очередной командной строки.

Реакция в это время, разумеется, запущена быть не может, но события -

отслеживаются.

События искусственно порождаются оператором Kill. Первые 256 из них это

реальные машинные прерывания. (Поэтому: обращаться осторожно!) События с

номерами от 1000 — внутренние. Например 1003 — нажатие комбинации кнопок

Ctrl/C, а 1004 — окончание звукового фрагмента. Имеется так же возможность

заказать события с помощью функций FViz и FCLk — на действия с мышкой в

пределах указанной области и на истечение временного интервала (или с

указанным периодом).

Так как некоторые из прерываний — обращения к ДОС`у и БИОС`у,

предполагающие передачу параметров (через регистры процессора), то в операторе

Kill допускается произвольное количество дополнительных параметров. Первые из

которых раскладываются по регистрам, а потом помещаются в локальные переменные.

(В А1 — признак "успешности".)

При отсутствии первого аргумента (при условии сохранения разделяющих

аргументы запятых) оператор Kill ничего не делает, а только раскладывает

остальные аргументы по локальным переменным текущей подпрограммы.


* * *

ТАБУЛОСТОПЫ — существующее с незапамятных времён средство для облегчения

печати таблиц, или каких либо данных в виде аккуратных колонок. У пишущих

машинок это были выдвигающиеся железочки, помечавшие начала полей, а кнопка

ТАБ перемещала каретку до следующей такой позиции.

Фокал имитирует этот механизм, поддерживая таблицу табулостопов. Установить

(и считать) которые можно как ф-ей FViz, так и с помощью спецкомментария:

: : : : : : : ;

Здесь каждое очередное двоеточие отмечает начало поля, а завершаться

такая строка должна либо символом ! указывающим позицию автопереноса, либо

символом ; указывающим на продолжение "стандартным" способом — через каждые

восемь (или указанное всё той же FViz) число позиций.

Табулостопы автоматически используются оператором Write и могут быть

использованы так же операторами Ask и Type: двоеточие в их списке ввода/вывода

указывает на переход к позиции очередного табулостопа.

Развитие идеи табулостопов предполагает сопоставить каждому такому полю

сначала порядковый номер (чтобы заполнять или читать поля в произвольном

порядке), а потом и имя плюс тип, что даст возможность например обращаться к

полям записи из реляционной базы данных (типа .dbf). Но потребует двойной

буферизации: такая запись должна быть считана из файла и/или записана туда

только сразу и целиком. (Что известно как "транзакция".)


* * *

Минимальные средства работы с символами, а значит и с составленными из них

текстовыми строками были в Фокале всегда: ф-я FCHR преобразует символы в числа

(и обратно), с которыми дальше можно делать что угодно, в т.ч. хранить в

обычных переменных и элементах массивов... Да, кое что с отдельными строками и

Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава



Иные расы и виды существ 11 списков
Ангелы (Произведений: 91)
Оборотни (Произведений: 181)
Орки, гоблины, гномы, назгулы, тролли (Произведений: 41)
Эльфы, эльфы-полукровки, дроу (Произведений: 230)
Привидения, призраки, полтергейсты, духи (Произведений: 74)
Боги, полубоги, божественные сущности (Произведений: 165)
Вампиры (Произведений: 241)
Демоны (Произведений: 265)
Драконы (Произведений: 164)
Особенная раса, вид (созданные автором) (Произведений: 122)
Редкие расы (но не авторские) (Произведений: 107)
Профессии, занятия, стили жизни 8 списков
Внутренний мир человека. Мысли и жизнь 4 списка
Миры фэнтези и фантастики: каноны, апокрифы, смешение жанров 7 списков
О взаимоотношениях 7 списков
Герои 13 списков
Земля 6 списков
Альтернативная история (Произведений: 213)
Аномальные зоны (Произведений: 73)
Городские истории (Произведений: 306)
Исторические фантазии (Произведений: 98)
Постапокалиптика (Произведений: 104)
Стилизации и этнические мотивы (Произведений: 130)
Попадалово 5 списков
Противостояние 9 списков
О чувствах 3 списка
Следующее поколение 4 списка
Детское фэнтези (Произведений: 39)
Для самых маленьких (Произведений: 34)
О животных (Произведений: 48)
Поучительные сказки, притчи (Произведений: 82)
Закрыть
Закрыть
Закрыть
↑ Вверх