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

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


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

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

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

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

жизни (самому себе) при попытке выйти из интерпретатора нажав 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, а хранить — в массиве в виде последовательности

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

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

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

Open текстовой константой! С числами — полный ажур: везде, где по смыслу нужно

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

А тут?!... Кого — как, а меня такое положение дел совершенно не устраивает!...

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

сможет сама соорудить себе какой хошь оператор, в том числе вписав там в

кавычки всё что ей вздумается...

Делаем так: открываем файл (да, с фиксированным именем, но сразу и на

запись и на чтение); формируем в нём необходмую нам командную строку, или даже

несколько; перематываем этот файл в начало; переключаем на него канал ввода и

останавливаем программу! Тогда интерфейсная часть интерпретатора прочитает и

выполнит (или сохранит в памяти) то, что мы вот только что написали. Главное:

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

Этот механизм был в Фокале всегда, изначально. Файлов для него подходящих

небыло... Да, имя файла тоже было не нужно. Однако, это не единственная

константа... Да и самомодификация — это само по себе круто: эффектно,

эффективно, смертельно опасно! Даже при предельно простой фокаловской

грамматике...

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

механизмом ввода/вывода. Впрочем, пока еще только ввода. Да и то... Ask конешно

вводит туда строку, но сам же её и использует. Да и операции с ней отсутствуют

как класс. Но это пока...

Второй подход к снаряду.

Начался со скандала: надо было ввести нечто типа: 33А 47Б 11Ц...

Нет, число то с помощью Ask N; — это пожалуйста, а вот следующая за ним

буковка с помощью Set M=FCHR(-1); — ну никак! Оказывается, оператор Ask

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

прочитать буковку непосредственно из канала ввода, где её уже нет...

Ну так это же неправильно!

Нехай функция FCHR берет символы непосредственно из канала ввода только

когда входной буфер оператора Ask пуст. А если нет — то из него, пока не

исчерпается. Ага. В смысле куда конь с копытом, туда и рак с клешнёй! То есть

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

но и писать их туда — той же самое FCHr. (С разными видами параметров....)

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

(якобы) использованы, а после — еще нет. И напридумывали. Правда писать в этот

А2 символы получилость только в режиме "замены символов"... Но и это хоть

что-то!

Однако, осталась еще проблема ввода и вывода.

Оператор Ask конешно вводит туда строку, но во-первых только когда

полностью использовал предыдущую (или если вдруг буфер был пуст), а во-вторых

сам же её и использует. Ну во-первых постановим, что оператор Ask с АБСОЛЮТНО

пустым списком ввода — только вводит. А во-вторых поручим ему-же делать этот

его буфер пустым: Ask % — перетащим сюда "формат" из оператора Type: там

одиночный символ % восстанавливает формат по-умолчанию, вот пусть и тут будет

что-то подобное. И, кстати, на будущее: Ask %число пусть вводит не до

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

Пригодится.

Осталась проблема вывода.

Миграция формата в оператор Write на предмет просмотра текстовых файлов.

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

Начиналось всё с того, что надо было выдать из командного файла на экран

довольно длинный текст, повествующий о... А, не важно о чем! Что-то типа

примитивненькой демонстрационно-обучающей системы. Текст там, естественно,

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

заключенных в кавычки текстовых констант. На строку — всего по паре символов в

начале и в конце: Т".....текст....."! но всё равно набирать муторно и править

неудобно...

А давайте поручим оператору Write, и без того специализирующемуся на

сообщении нам полезной информации, еще и просмотр текстов — копирование

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

(Например до конца файла.) Один в один, или с некоторым (указанным форматом)

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

Вообще-то это задумано было и в самом деле для просмотра содержимого

текстовых файлов. А формат — на случай если они в другой кодировке: для

преобразования текста в ДОС`овскую, с которой только и работает Фокал. Однако,

и для вывода текста из командного файла на экран — тоже годится. Но каждый раз

считать строчки — неудобно. А пусть у оператора Write % будет еще один

аргумент в виде текстовой константы — "метка". Каковую метку он теперь будет

искать в каждой копируемой строке. Как нашел — шабаш! А "метку" эту поместим в

следующую строку после выводимого текста.

Сразу же решается проблема передачи управления в скриптовом файле: есть

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

любое количество скопированной туда информации. (И откуда можно прочитать

неограниченное количество нулей, только это нам пока не надо.) Найти теперь

нужное нам место в файле — элементарно: скопировать всё от начала файла до

нужной нам метки на NUL. А строку с меткой на всякий случай сделать

комментарием.

Но нам то это как поможет? А вот: рассмотрим, как именно копирует Write %

строку со входа на выход? Через всё тот же входной буфер оператора Ask! Кстати,

строка с меткой в нём и останется. Потом чистить придётся с помощью Ask %

А если у нас Write % 1; и вот этот самый А2 не пуст — это и будет вывод

его содержимого. А вот если пуст — тогда беда: потащит строку из канала ввода.

Поэтому лучше так: Write % ""; (Обратим внимание: метка есть, но пустая. Ввод

здесь подавляется, а вывод нет: это специально сделанное исключение.)

Итак, подведём итоги: ввод — есть, вывод — есть, с операциями правда

жиденько: посимвольное чтение/запись и манипуляция с символами как с числами.

Но плюс к этому — использование содержимого А2 там, где допустима текстовая

константа: указанием ! вместо "...". Кроме операторов Ask, Type и ф-ии FCHr,

где А2 и без того используется, а ! имеет другой смысл. (Глядишь, и

самомодефикация не понадобится...) И еще плюс к этому — текстовый "побочный

эффект" — тоже в А2. Для тех спецфункций у которых он есть. Например

FTEll("шаблон_имени_файла",) ищущая файлы в текущем каталоге. Одна только

функция FTMP(t) из этого ряда выбивается — выдаёт текстовую строку (результат

преобразования t в удобочитаемый вид) прямо в канал вывода. Но так уж

исторически сложилось... Хотя конешно же безобразие!

При переключении канала ввода оператором Oper, входной буфер оператора Ask

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



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