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

Дополнение к гл. 4 книжки о Фокале


Автор:
Жанр:
Изобретательство
Опубликован:
20.07.2022 — 20.07.2022
Читателей:
1
Аннотация:
Нет описания
Предыдущая глава  
↓ Содержание ↓
↑ Свернуть ↑
  Следующая глава
 
 

Уже читает из буфера (и вот как раз ровно один символ) функция FCHR. Есть мнение поручить ей и всё остальное.

4.2.1 Функция FCHR (с аргументом -1) берет из оного буфера код очередного символа и сдвигает указатель "текущего места", отделяющий уже использованную часть строки от еще нет... Но символ всё равно остаётся в буфере, и ничего не стоит "возвратить" его назад, просто сдвинув указатель обратно.

Это делает сама же FCHR() но без аргументов. И за одно сообщает — сколько там в буфере еще осталось не введенных символов.

Она же: FCHR( ,N) — двигает не на одну, а сразу на N позиций. В том числе и в другую сторону, если N — отрицательное. Или никуда, если 0. Только сообщает.

Она же: FCHR( , ) — измеряет буфер в другую сторону: сообщает сколько в нём "уже введенных" символов.


* * *

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

4.2.2 Хотим получить в виде числа код символа "а". (Нет, ну ей богу — надоело постоянно заглядывать в таблицу кодов символов!) Это сделает FCHR("а").

А если в текстовой константе их будет два: FCHR("аб"), то второй получим следующий раз. Для чего поместим его... А вот в текущее место буфера и поместим! Прямо поверх того, что там уже было. И все следующие аргументы функции, если они есть — тоже.


* * *

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

4.3 Если мы затеяли написать что ни будь демонстрационно-обучающее, выводящие на экран длинные тексты, то никакой памяти хранить всё это не напасешься! Однако, здесь мы никуда не спешим: делать что либо всё равно надо в темпе восприятия пользователя. Потому подобное есть смысл выполнять прямо из файла, где эта программа хранится. Вон в первых ЭВМ вообще памяти для программ не было (её и для данных то не хватало), вводили снаружи (типа с перфоленты), и ничего... И мы тоже не баре.

В общем это и будет "скриптовый" (он же "командный") файл. Ничего сложного: Строки из файла выполняются в точности так же как и введенные с терминала. С линейным алгоритмом вообще никаких проблем нет. Разветвленный конешно требует меток и операторов перехода к ним, но в этом качестве прекрасно сойдут файловые адреса (положение указателя чтения/записи файла) которые можно получить с помощью FTEll, хранить в переменных (т.к. это просто числа) и применять для позиционирования с помощью оператора Oper. Это и будет аналог оператора перехода. В хелпе про всё про это — целый раздел (под N 7).

Однако, применительно к выводу текста есть проблема: его придётся выводить в точности так же, как и программе загруженной в память: каждую строку заключить в кавычки, поместить получившуюся текстовую константу в оператор Type и еще снабдить символом ! для перехода на следующую строку.

Хотя казалось бы — чего проще: текст хранить в файле "как есть" (так его и набирать и потом править куда удобней) и просто копировать в канал вывода нужное количество очередных строчек. Ну может быть с некоторым преобразованием. Или же просто "как есть". (А дальше будут опять команды.)

Ан, в Фокале нету подходящего средства!

Ну не побайтно же копировать в цикле, с помощью FCHr! (Хотя можно, и вполне работает.)

Это дело решили поручить оператору Write, указав преобразование в виде конструкции "формат". (Который прямо на глазах становится всё более и более таинственным.) Или без преобразования, если формат пустой — состоит из одного только символа %.

В общем теперь W % N выдаст в канал вывода N строк. Прочитав их из канала ввода через тот же самый входной буфер оператора Ask.

Но вот если буфер не пуст, а вывести велено ровно одну строку, то единственное, что сделает W % 1 — выдаст содержимое буфера в канал вывода.


* * *

ага, вот и вожделенный вывод, которого нам так не хватало.

4.3.1 Но практика показала, что так оно конешно лучше, чем каждую строку в виде текстовой константы в отдельный оператор Type. Но подсчитывать строчки — тоже не фонтан. И поэтому для оператора Write с форматом была придумана "метка".

Это параметр в виде текстовой константы, которую W % "..." ищет внутри каждой введенной в буфер строки, и обнаружив — прекращает работу. Строка остаётся в буфере, а количество скопированных строк — в числовом аккумуляторе. (Откуда его не трудно достать функцией FSUBr().) Если указаны и метка и количество — то что сработает раньше. Если ни то ни другое — то до конца файла. Будет ошибка. Или, если ввод с терминала — пока пользователь не нажмет ESC. Тогда ошибки не будет. Если указано отрицательное количество строк — то тоже до конца файла, но ошибки не будет.

5.4.7 А сам оператор Write (без формата) тоже немножко доопределён — чтобы он выдавал не только программные строки, но и другие сведения о внутреннем состоянии интерпретатора (например значения переменных). Причем в форме, пригодной для последующего обратного ввода. Что именно — указывается вторым ключевым словом:

— А — как и раньше — вся программа и перед нею заголовок (кто и когда вывел).

— S — результат работы оператора Set (т.е. значения переменных)

— O — результат работы оператора Open (т.е. псевдонимы открытых файлов)

— B — результат работы оператора Break (т.е. реакция на события)

— D — результат работы оператора Do (т.е. состояние стека возвратов)

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

Еще есть ключевое слово П (от слова "пул"), заставляющее поместить в этот самый пул содержимое строчного аккумулятора. Так как "пул" это мешок, только по нерусски, то и ключевое слово М делает то же самое.

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

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

5.4.8 Точно так же сделано и в операторе Eraze: теперь он тоже может удалить не только все переменные разом (когда без параметров), но и одну конкретную, указанную текстовой константой.

С ключевым словом Пул или Мешок оператор очищает этот самый пул редактора,

С ключевым словом Break — обнуляет счетчики все отслеживаемых внешних событий.

С ключевым словом Ales оператор удаляет всё что можно: кроме переменных и программных строк, еще и все псевдонимы открытых файлов. Но кроме тех, на которые указывают каналы ввода и вывода.

4.4 А теперь к "...." добавим еще и ! указывающий на строчный аккумулятор. Чтобы строку из него можно было использовать везде, где и строчную константу. Кроме операторов Ask и Type, где восклицательный знак уже испокон веку используется для обозначения конца строки и перехода на следующую.

5.4.9 В том числе в операторе !, который в этом случае будет выглядеть как !! Как и в UNIX`е, это обращение к операционной системе. Ей в качестве командной строки передаётся вся строка после восклицательного знака. (А теперь вот — и из аккумулятора.)

Потому что например создать новый файл Фокал может, а удалить после того как попользовался и он стал не нужен — нет. И переместить/переименовать — тоже нет. Но всё это можно сделать командами операционной системы.

Этак можно и утилиту какую запустить (Если ей конешно памяти хватит.) Текстовый редактор например. Или аналог Нортон-командера — по каталогам полазить. (А редактор в нём встроенный. И просмотрщик...) Сам Нортон или например Дос-навигатор — вряд-ли, а Волков-командер — как с куста!


* * *

В результате, теперь можно сказать, что Фокал немножко научился работать и со строками. Правда хранить их по-прежнему приходится снаружи — в виде файлов...

Потому что совсем немножко он и раньше умел: посимвольно, таская их функцией FCHR и сохраняя как числа в элементах массива. (Что конешно же стрельба из пушек по воробьям.)

Однако, и сейчас, если мы например организуем диалог с пользователем, для исправления некой даты/времени, то прочитать набранную пользователем строку и преобразовать её обратно в число — запросто. А вот чтобы использовать в качестве начального значения то, что выдаёт FTMP — временный файл понадобится. (Который потом еще и удалять придётся.) Потому что FTMP(t) выдаёт текстовый результат прямо в канал вывода.

Да и для самомодификации программы — тоже временный файл. Конешно сейчас это уже не очень нужно. Но всё равно остались места, где только и исключительно константы. (Вон этот самый таинственный "формат".) А вдруг понадобится сделать его таким, как вычислила программа...

6.3 Самомодификация программы — это круто! Эффектно, эффективно и чрезвычайно опасно. Ну прямо цирковой номер: выполняющаяся программа на ходу переписывает и исправляет сама себя! Да, в Фокале такая возможность была всегда. (В отличии от...) Хотя и ограниченная. Но с появлением доступа к файлам, в которые можно сначала записать, а потом перемотав в начало прочитать написанное...

Ну так берем такой временный файл, формируем в нём какие нам надо программные строки, перематываем в начало, переключаем на него канал ввода и останавливаем выполнение программы оператором Quit. Управление получает интерфейсная часть интерпретатора; она читает и помещает в память всё то, что мы вот только сейчас написали. Главное — не забыть в конец добавить команду, которая бы запустила программу заново с нужного нам места.


* * *

А нельзя ли как-то без временного файла обойтись? Например немножко доопределив оператор Modify, каковой как раз программные строчки исправляет...

Можно.

5.4.10 Оператор Modify.

Предназначен для того, чтобы пользователь мог исправлять программные строки, а не вводить их заново. Реализован простейшим образом: всего лишь для каждой из строк, ну например указанной ему группы, по очереди запускает редактор.

Сначала он позволял исправлять только текст строки; потом и её номер — чтобы можно было например переместить строку в другую группу. Но это же получается что теперь он (частично) выполняет функции интерфейсной части интерпретатора. Вот пусть и...

Было решено:

— во-первых разрешить в Modify параметр в виде текстовой константы. (И "..." и ! разумеется.) Чтобы делал с этой строкой в точности то же самое, что и интерфейсная часть: если там в начале есть корректный номер — помещал в память, а если нет — сразу выполнял. И всё это без манипуляций с файлами и остановки программы. (А то локальные объекты теряются.)

— во-вторых ввести форму "с присваиванием". Якобы для перемещения программных строк из одной группы в другую: Mоve N = M; (где N и M — числовые выражения.) В результате чего строка с номером M перемещается в группу N, или просто получает другой номер.

— и наконец в третьих разрешить в форме с присваиванием использовать строчные константы. (В левой части присваивания — только !.) Что даёт возможность перемещать программные строки в аккумулятор и обратно.


* * *

Обратим внимание, что на грамматическую правильность помещаемые в память программные строки никто никогда не проверяет. (Проверяет "исполнительная" часть интерпретатора — в по ходу выполнения.) Так что храниться там может абсолютно что угодно. Только на выполнение не запускай!

### К сожалению не всё что угодно: только "печатные" символы (а не произвольный код), потому что конец строки определяется по символу с кодом 0. Поэтому же в операторах Ask и Write не реализован для чтения из файлов формат %N — чтение не построчно, а порциями по N байт.

И кроме того — ограничение на длину строки. (По размеру текстового буфера, в данной версии — 122 символа.)


* * *

Это же аналог переменных для строчных значений получается!

Обратим внимание: для хранения числа используются "переменная", которая идентифицируется строкой (хотя пока это и только первые её два символа), а вот аналог переменной для хранения строки идентифицируется числом. Тоже ограниченным до двух (ан нет, уже четырех) десятичных цифр до и после запятой.


* * *

Ага-ага: хранить, вводить/выводить и применять строчные значения для специфических целей (например пропикать азбукой морзе с помощью FBIp) научились. А вот средства анализа и преобразования — крайне слабые.

Однако, еще не вечер. Что там у нас с форматом в операторе W, якобы сложным и таинственным?

4.5 Формат в операторе Write (делающий из него совершенно другой оператор!) до сей поры представлялся одним только символом % указывающим, что строки копируются как есть.

Но было задумано что преобразования указываются буквами. (Например %К преобразует русские буквы из кодировки КОИ-8 в текущую — ДОС`овскую, известную как cp866, а %W соответственно из виндовой cp1251.) А %Число так же как и в Ask ограничивает размер поля ввода — это если для терминала. А для файла — чтобы указывало размер порции, вводимой за раз.

Ни то ни другое до сих пор не реализовано. А реализованы некие "операции". Операции типа удалить, вставить, передвинуть маркер... Каждая, как и полагается, один символ. Вот эти самые буковки, если и когда будут — тоже будут такими операциями.

Выполняются эти операции без какого либо старшинства (такого, как у арифметических операций в фокаловских выражениях) — просто слева направо. И "левым операндом" каждой является вот этот самый регистр-аккумулятор — содержащийся в нём текст и/или вышеупомянутый маркер, указывающий его фрагмент. Но некоторые могут иметь так же и правый операнд. Типа "число" или "строка". В простейшем случае это числовая константа в виде последовательности циферок, или строчная константа в виде любых символов, заключенных в кавычки.

4.5.1 "Маркером" таки назовём этот самый указатель, отделяющий уже использованную часть входного буфера оператора Ask, от еще нет. Он указывает начало "фрагмента" и дополнен его размером. После сдвига маркера этот размер равен нулю. А после поиска фрагмента — равен размеру найденного. Но операцией ~ этот размер можно установить искусственно. Или изменить.

Маркер можно поставить в начало и в конец строки (операциями ^ и $), сдвинуть на указанное количество позиций или переместить путем поиска. Операцией поиска служит "строка", сама же и указывающая что искать, если не является чьим-то операндом. А так же "шаблон" — конструкция, заключенная в угловые скобки <...>, где некоторые символы выполняют служебные функции. (В отличии от строчной константы, в которой каждый символ изображает сам себя.) Операцией сдвига служит "число" — тоже если не является чьим-то операндом.

Как сдвиг маркера так и поиск могут быть как вперёд (к концу строки), так и назад — к началу. Это указывают префиксы + и -. Они именно префиксы, действующие на различные операции. (Хотя и родились из идеи, что числу, указывающему на сколько сдвинуть маркер, нужен знак — направление.)

Сами + и -, когда не префиксы (например перед ^ $ или _) указывают сдвиг вперёд и назад на одну позицию.

Например команда ~N устанавливает размер фрагмента ровно N символов независимо от того, какой он был до этого. А вот +~N и -~N увеличивают его на N символов в сторону конца и соответственно начала строчки. Уменьшают только если само число N отрицательное. Чего можно добиться, написав {-N} — вот тут минус это действительно знак. А само N в фигурных скобках может быть полноценным фокаловским выражением.

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



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