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

Фокал - часть 3 (пишется)


Автор:
Опубликован:
24.05.2026 — 04.07.2026
Читателей:
1
Аннотация:
Типа продолжение к "Фокал снаружи и внутри"
Предыдущая глава  
↓ Содержание ↓
  Следующая глава
 
 

начинает "распространятся" — последовательно прекращая выполнение вложенных

вызовов подпрограмм. И дораспространявшись до интерпретатора, вызывает с его

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

подходящую ловушку — она срабатывает; запускается подпрограмма реакции, которая

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

нормально завершается — возвращает управление в точку вызова.

Искусственно порождать ситуации поручено оператору Quit (а события — Kill).

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

Brek 7; For i=1,N; For j=-M,M; For k=0,L; If(FSBr(ххх, i,j,k))0; Quit 7,""

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

переданные ей i j k её вполне устраивают, так и. Это и есть "структурный

переход". Ситуация 7 выбрана "от балды" (лишь бы не совпадала с уже имеющимися:

теми, которые ошибки). Дололнительные числовые аргументы в Quit передаются

подпрограмме реакции, но она в этом примере — "нулевая". А вот текстовый -

интерпретатору, чтобы он, если что, знал что сказать. А в нулевой строке (как

в данном случае) указывает — что мол еще поработаем, что это не команда на

завершение работы интерпретатора.

Если вышеприведённый пример в одну строку, таки строка подпрограммы, то

следующие после неё строки не будут выполнены: ведь тут же случилась СИТУАЦИЯ,

но реакция на оную (хотя и нулевая) героически устранила последствия. После

чего подпрограмма НОРМАЛЬНО завершается, а не... (Типа: не устрани она — ой что

было бы!) Ага-ага. Но если нам надо чтобы выполнились и следующие строки, надо

засунуть всё это в персональную подпрограмму, сделав телом оператора For из

одного только этого ключевого слова. Вот пусть это она "нормально завершается".

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

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

пристойно работает только в текстовых режимах) — чтобы трассировочная

информация попадала туда и не на основной экран и не портила изображение;

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

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

значения переменных или заглянуть в основной хелп...

А вот перенаправление трассировочной информации в отдельный файл — тот,

который указывается в командной строке вторым и открывается под псевдонимом Б,

так и не сделано: уж больно как-то оно всё неизящно получается...

— Табулостопы и спецкомментарий из одних двоеточий, типа: : : : !

где двоеточиями отмечаются их позиции. Спецкомментарий становится "спец" только

если завершается ! (восклицательным знаком) или ; (точкой с запятой),

указывающими на конец строки или же её продолжение. Иначе, как и любой

комментарий, игнорируется. (Раньше двоеточие тоже числилось буковкой на ряду со

всякими # @ $ | ~ но поручив ему табуляцию, пришлось назначить

его разделителем.)

Вобще-то табулостопы понадобились оператору Write со вторым ключевым

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

переменных, имеющихся на настоящий момент в памяти. Вместе с их значениями,

разумеется. Этих переменных может быть как две-три, так и десятки, сотни и

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

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

Надо чтобы в виде таблички, желательно стройными рядами и колоннами... Ну так

на то и табуляция!

Секретарши испокон веку печатали на пишущих машинках всяческие таблички.

И у них там эти самые "табулостопы" — такие выдвигающиеся железочки,

отмечающие начало очередной колонки. А клавиша ТАБ передвигала каретку к

следующему. Но в эпоху алфавитно-цифровых дисплеев их тупо расставили в каждую

восьмую позицию... А я сперва сделал чтобы можно было устанавливать какой хочу

шаг табуляции, а потом и оные табулостопы индивидуально. И свалил всё это на

FVIz. Получилось универсально, но таки сложновато и ненаглядно. А наглядно — в

виде вот такого спецкомментария. Он же выдаётся по Write Tab; а Eraze Tab;

приводит систему с состояние по-умолчанию.

И теперь вот думаю: а ведь запись в базе данных, ну например типа .dbf,

она ведь вот так же выглядит? Правда, там у полей есть имена, и их границы

пересекать не полагается... А что мешает и мне так сделать? И можно будет

заполнять поля оной записи в произвольном порядке, типа: Type :имя, значение;

Правда, для этого понадобится еще и буферизация вывода...


* * *

Подсистема ввода/вывода Фокала (ну наконец-то мы до неё добрались!)

устроена очень просто: есть один канал ввода и один канал вывода. Канал вывода

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

переключен оператором Operate куда-то еще. А канал ввода соответственно

по-умолчанию подключен к клавиатуре.

Из канала ввода читает функция FCHr — побайтно, оператор Ask — построчно,

и интерфейсная часть интерпретатора (тоже построчно), когда ей нужна

очередная командная строка.

Обратим внимание: интерфейсная часть интерпретатора читает командные

строки из канала ввода, не интересуясь — к чему именно он подключен. Что и

даёт возможность как загрузить ранее сохранённую программу (просто переключив

на неё канал ввода — будет вводиться сама собою, пока не кончится...), так и

выполнять командные ("скриптовые") файлы — в точности так же. Отличаются

только тем, что тут все строки — "прямые", а там — косвенные. То есть ничем:

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

её сразу же и запустит, так и командному файлу по мере необходимости

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

Бейсику было доступно хоть что-то подобное.)

Кстати, при запуске интерпретатора, первый аргумент в командной строке

это имя файла, который сразу же открывается (под псевдонимом "А") и на него

переключается канал ввода...

В канал вывода пишут все, кому не лень: и та же самая функция FCHr — тоже

побайтно; и операторы Type, Write, Help; и сам интерпретатор — сообщения об

ошибках; и даже функция FTMp. (Прямо не канал, а проходной двор!)

Но за то, в отличии, например, от Бейсика, где и для вывода программы

"на посмотреть" пользователю, и для сохранения её где-то на внешнем носителе

используются разные команды — LIST и SAVE, каждая со своим собственным

заковыристым и неочевидным синтаксисом, то в Фокале всё это делает один и тот

же оператор Write, синтаксис которого предельно прост. Но конечно для

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

а потом обратно. А если это файл, то перед этим надо его открыть, а после -

закрыть. Но это-то как раз очевидно, хотя и громоздко. Ну так для облегчения

жизни (самому себе) при попытке выйти из интерпретатора нажав ESC, выдаётся

уже готовая командная строка для сохранения программы в файле "sav.f". (Но

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

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

какой файл открывать, попытается открыть вот этот — тоже под псевдонимом А.)

Список вывода оператора Type содержит не только выражения, значения

которых и надо преобразовать в удобочитаемый вид, и таинственную конструкцию

формат, начинающуюся с символа % (процент), указывающую как именно это делать,

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

к выводимым числам. Это любые символы в кавычках, ! (восклицательный

знак), предписывающий учинить конец строки, а теперь еще и : (двоеточие),

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

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

три: " ' `

Аналогично, список ввода оператора Ask тоже может включать текстовые

константы, призванные служить "приглашениями" ко вводу очередного числа. Ну а

коли это приглашения, то я сделал что выводятся они только и исключительно на

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

случае когда канал ввода направлен на клавиатуру.

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

просмотрщик (для Write и Help — автоматически, а для Type — "вручную", с

помощью "спецформата" в виде пары символов %), а при построчном вводе -

редактор командной строки. А когда он не задействован — ввод попадает в

односимвольный буфер клавиатуры — специально для FCHr. А еще у экрана есть

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

нарисовано. (Всё это в ведении функции FKursor.)

Но этого может и не быть — терминал может, как в древние времена,

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

Файл, впрочем, штука тоже по-своему особенная: от клавиатуры или какой

либо линии связи отличается тем, что имеет "текущую позицию". И вообще может

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

одну из которых "обозревает" головка чтения/записи. Которая при любой операции

автоматически сдвигается на следующую. Но может быть принудительно установлена

куда нам вздумается. Это логично поручить тому, кто и оперирует с файлами

(оператору Operate, разумеется), но вот сообщить текущую позицию он не сможет,

для этого нужна функция. Ввёл, и по аналогии с Си-шной назвал FTEll. (Надо было

FOper называть! Хотя еще не вечер...) И это была вторая важная вещь, которой и

характерна "часть первая". (Потому что всё остальное — удобства и красивости.)

А позицию в каком из уже открытых файлов? Решил, что в том, который

участвовал в последней по времени операции ввода или вывода.

Намотаем на ус: где-то там, в недрах Фокала специально для FTEll завелась

скрытая переменная, куда попадает объект любой операции ввода/вывода так же,

как в аккумулятор А1 попадает значение (почти) любого вычисленного Фокалом

выражения. Забегая вперёд, скажем, что это и есть аккумулятор А3.

Оперирует каналами ввода и вывода оператор Operate ключевое_слово;

где вот это второе ключевое слово и указывает на одно из подключенных к ЭВМ

устройств ввода-вывода, или (сейчас) еще и на файл. И тогда называется

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

пока он открыт. Как известно, чтобы добраться до содержимого ящика, сундука,

шкафа, потрфеля... ну и файла, разумеется — их сперва надо открыть, а

попользовавшись, закрыть обратно. Файлов одновременно можно открыть штук

несколько. (Но не очень много: таблица открытых файлов не резиновая).

Некоторые ключевые слова испокон веку закреплены за устройствами и

использовать их под псевдонимы нежелательно. К терминалу (Tty) и клавиатуре с

принтером (Kbd, Lpt) добавились еще I, O, E — стандартный ввод, вывод и вывод

ошибок, которые, по традиции UNIX`а открыты у любой программы уже в момент её

запуска. (И обычно указывают на те же самые клавиатуру и терминал. Но запросто

могут оказаться куда-то перенаправлены...) И плюс к ним ко всем еще и

C — стандартный компорт, который ДОС тоже почему-то предоставляет каждому

запущенному процессу, нимало не интересуясь, нужен он ему или нет.

Файлы открываются (и закрываются): Ope "имя_файла" (позиция) Псевдоним;

(закрываются если имя файла — пустое). Позиция (число в скобках) при открытии

не обязательна, но если есть — файл будет открыт с неё, а не с начала. Только

позиция без имени файла — вот это самое позиционирование. В том числе и

фиктивное (если в скобках пусто) — для последующего обращения к FTEll.

В отличии от всех других ключевых слов, в псевдониме не все "лишние"

буквы игнорируются: некоторые указывают как именно открыть файл (и/или какие

каналы переключать): R W A (последняя — тоже на запись, но в конец) и тип

файла: B — бинарный, T — текстовый.

Если буферизация вывода еще только-только намечается, то на ввод есть два

буфера — у оператора Ask и у самого интерпретатора: они оба читают за раз сразу

целую строку, а вот используют её — постепенно. Интерпретатор выполняет по

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

выражению...

Так, еще раз, и помедленнее: оператор Ask, встретив в своём списке ввода

очередную переменную, ВЫЧИСЛЯЕТ полученное из канала ввода ВЫРАЖЕНИЕ, а не

просто берет оттуда число и преобразует во внутреннее представление, как во

всех других языках! Где еще подобное видано?! Фокал — калькулятор, однако...

Но вернемся к нашим баранам.

Входной буфер интерпретатора позволяет в пределах одной "прямой" строки

выделывать с каналом ввода всякие фокусы — это никак не влияет на её выполнение

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

("скриптового") файла. Ведь там, например для обращения к подпрограмме, надо

перемотать файл на её начало, где-то сохранив при этом адрес возврата. Если с

местоположением подпрограммы — большой вопрос (но пусть мы его откуда-то знаем

и уже храним в переменной П1), то с адресом возврата всё просто: текущая строка

уже целиком в буфере; указатель чтения/записи — на начале следующей, которой и

надо будет вернуть упраление. Поэтому, считая, что командный файл у нас — под

псевдонимом А, делаем так: Op () A; Set Ав=Ftell(); Op (П1) A

А возврат из такой подпрограммы: . . . . . . . . . . Op (Ав) A

И всё.

А вот с буфером оператора Ask явно что-то не так...

Забегая вперёд, скажем, что эта штука, предназначенная для временного

хранения текстовой строки — искомый аккумулятор А2, позволяющий Фокалу работать

со строчками. (Вот только делать с ним мы ничего пока не умеем.)


* * *

И с этого места у нас начинается ЧАСТЬ ВТОРАЯ нашего повествования


* * *

Не будем тянуть кота за хвост, а сразу возьмём быка за рога: желаем

работать с текстовыми строками. Но сами тексты — слишком громоздкие. Пусть

так и лежат снаружи в виде текстовых файлов...

(Впринципе мы и раньше могли вводить и выводить тексты посимвольно — с

помощью спецфункции FCHr, а хранить — в массиве в виде последовательности

чисел. Да, стрельба из пушек по воробьям, но на безрыбье и рак — рыба...)

Одно из применений — самомодификация. Вот например: мы никак не можем

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

1234567 ... 141516
Предыдущая глава  
↓ Содержание ↓
  Следующая глава



Иные расы и виды существ 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)
Закрыть
Закрыть
Закрыть
↑ Вверх