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

Руководство по Фокалу


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

функционалность не вводя новых имён, а "маневрируя" параметрами, коснулось

и уже существующих. Но если для корня и логарифма — всего лишь решили

указывать основание вторым аргументом, то на FSBr отыгрались по полной!

Спецфункция FSUbroutine ("подпрограмма": sub — "под", а routine — рутина

и есть!) это такое-же как и оператор Do обращение к подпрограммме — передача

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

эта группа или строка завершится — управление перейдёт не к следующей за ней,

а к следующему после Do оператору. (Там в конце даже наличие оператора Ret не

обязательно.)

FSUbr отличается от Do тем, что во-первых обращение идёт из середины

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

продолжено. Во-вторых в подпрограмму передаётся параметр, указанный вторым

аргументом функции FSUbr (первый — номер строки или группы), и возвращается

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

Параметр попадает в спецпеременную & a возвращается значение, которое

было вычислено в последнем перед возвратом из подпрограммы операторе.

Надо это так понимать, что каждый оператор, вычислив очередное выражение,

помещает его результат в некоторую скрытую в недрах Фокала переменную — вот

как раз на такой случай. Эту переменную и будем называть "числовым

аккумулятором" или А1. (Потому что в последствии были обнаружены и другие

подобные аккумуляторы А2 и А3 для значений других типов.)

Казалось бы, оператор, просто делает своё дело, и никакого значения

"вернуть" не может (даже в том случае, когда ему есть что "сказать") — для

этого функция нужна. Вот и пришлось к оператору Опер, перемещающему в частности

указатель ввода/вывода файла, прилагать функцию FTEll, сообщающую его

положение. А к оператору Vizual, переключающему в частности видеорежим работы

терминала, фунцию с таким же именем, сообщающую его. (Ну и еще кое что

по-мелочи...) Потому что заводить спецпеременные — некрасиво это!

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

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

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

только функция FSUbr... Поэтому первое, что ей разрешили, это при отсутствии

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

содержимое А1.

Далее: спецпеременная &, куда попадает передаваемый подпрограмме параметр,

в (1.0) — кроме экзотического имени в остальном скорее всего — самая что ни на

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

ничего такого особенного про неё не написано. Значит наверно да.)

Обратим внимание, что все переменные Фокала по нынешним меркам — глобальные.

Здесь нету концепции "операторных скобок", заключающих в себе и ограничивающих

локальную "область видимости". В которой и "обитали" бы эти самые локальные

переменные.

Вот в Фортране — есть. Более того — там вообще нет глобальной среды. А есть

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

компилируется отдельно), а между ними — межпланетный вакуум. И кусочки такой

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

"коммон-блоков", описывая их в каждой из подпрограмм. Типа если имена

одинаковые, то значит и коммон-блок один и тот же. Впрочем, и подпрограммы

друг к дружке тоже по именам обращаются. А что они друг про дружку думают -

в плане списка параметров, и про состав этих самых коммон-блоков — пусть об

этом у компоновщика голова болит! (Того, который разместит всё это в

оперативной памяти и связи меж ними установит...)

Вот в Си внешняя среда очень даже есть: это образ вот той самой оперативной

памяти машины, где все программные объекты и находятся. И фрагменты кода,

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

переменные. Вот они существуют всегда, потому и глобальные. Но фрагмент кода,

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

памяти для личных нужд (и вернуть вместе с возвратом управления). Вот

размещенные там переменные и будут локальными. Да и параметры подпрограмме

тоже передаются через взятые вот так же взаймы ячейки памяти.

А в Фортране параметр — окошко в область данных вызывающей программы. Через

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

передать управление. (Это если в ячейке области данных — адрес еще какой-то

подпрограммы — вот ей.) В Си для этого честно передаются адреса (указатели).)

А в Фокале нету ничего другого, кроме вот этой вот "внешней среды":

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

отгораживаются. За ненадобностью. И все переменные, соответственно, общие.

Общедоступные.

Но если подпрограмма, запущенная как функция (с передачей ей параметра),

сама захочет обратиться еще к кому-то тоже как к функции — с помощью FSUbr

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

переменную & и бывшее там значение будет утрачено, что не есть хорошо.

Чтобы это исправить — надо брать память под переменную & так же "взаймы" как

и в Си, а при возврате из подпрограммы — возвращать. То есть сделать её

по-настоящему локальной.

Так и было сделано.

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

параметров (де лишние они проигнорируют), для FSUbr сделана была возможность

завести не одну единственную локальную переменную & а сколько угодно. Но

под номерами вместо имён: это же вообще-то параметры, переданные "позиционным"

способом. (В противоположность "именному".) Вот пусть именем переменной и

будет номер позиции: &0 &1 &2 &3... Вернее сначала сгоряча (и по аналогии с

макропеременными UNIX`овского sh, которые все начинаются с символа $) сделано

было $0 $1 $2 $3... (Ну забыл я, забыл как в Фокале переменная под параметр

называется!) А потом решено было разрешить чтобы и так и так.

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

элементами массива &(). (Одномерного.) А в его элемент &(-1) пусть FSUbr

помещает количество переданных параметров. Вернее номер последнего из них.

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

их запятых).

От обычных переменных, локальные отличаются только тем, что если переменной

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

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

Так что теперь и с рекурсией — никаких проблем. В качестве примера

рекурсивной программы обычно приводят вычисление N-факториала. (Хотя по-мне

так его куда проще с помощью цикла: Set x=1; For i=1,N; Set x=x*i

Но традиции...) Так что:

7.1 If(&) 7.2,7.2; X &*FSBr(7.1, &-1); Ret

7.2 X 1 ; Ret; Coment Вызывать: FSBr(7.1, N)

Или лучше и нагляднее: 7.1 If(&) 7.2,7.2; Ret &*FSBr(7.1, &-1);

7.2 Ret 1

Но это только после (1.5) когда оператор Ret малость усовершенствовали вот как

раз на такой случай...

(1.7) улучшение функций. Подробности — в хелпе, здесь только обзор:

— немножко "синтаксического сахара": если у функции ровно один аргумент, то

скобки вокруг него можно опустить: вместо FBip(440) (нота Ля) — FBip 440

— эта самая FBip издающая звуки, сразу была сделана так, чтобы можно было

указать не только частоту, но и длительность. Тогда звук ставится в очередь

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

длины остатка этой очереди. А без указания длительности очередь сбрасывается

и звук включается (или выключается: FBip 0) немедленно. Функция доработана

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

то это ноты. А если в место второго (длительности) то это текст для передачи

("пропикивания") азбукой морзе. Правда без скорости передачи тоже не обойтись:

пришлось указывать её третьим аргументом. Для нот предусмотрена так же

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

есть "темперированный"...

— функция FЦвет (она же FCOLor) устанавливающая цвет выводимых символов,

доработана чтобы править VGA-шную палитру. (Но пока там сделано еще не всё что

задумано — отложено до повторной реализации графики.)

— функция FKурсор (она же FCS), перемещающая курсор по экрану, доработана

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

координат курсора (а так же размеров экрана, что впрочем потом передали фунции

FViz); считывания кода символа под курсором и изменения цвета знакоместа, до

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

(Указание размеров и положения которого сразу возложили на функцию FViz.)

— функция FTmp, сообщающая текущие дату и время в виде целой и дробной части

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

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

обратно.

— функция FМЫшь (она же FMUso) всего лишь включает/выключает отображение

мышиного маркера, а так же сообщает его текущие координаты и нажатость кнопок.

Заказ порождения связанных с мышью событий — по нажатию кнопок в заданной

области экрана, а так же по пересечению её границ — там же где и указание этих

областей — функцией FViz.

— функция FTEll, сообщающая текущее положение указателя чтения/записи того

файла, который поучаствовал в последней по времени операции ввода/вывода (т.е.

попавшего в аккумулятор А3) доработана... Да свалили на неё всё, что не знали

кому поручить! Включая поиск файлов в текущем каталоге, "добывание" элементов

командной строки и "среды" (которая environ), и даже текста сообщения о

последней по времени ошибке. Так уж исторически сложилось: она была самая

первая...

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

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

опасная (мой шеф, помнится, придумал "запирать" её функцией FF от случайного

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

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

операции. Впринципе она их и с устройством производит: не только читает

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

устройства к следующей операции.) А нам например надо чтобы считав функцией

FTEll() коды нажатости спецкнопок клавиатуры, выделить оттуда состояние

кнопки "левый Shift". Пожалуйста: FX(,FTEll(),2)

— функция FCHr производящая побайтный ввод/вывод (ввод — если её аргумент

отрицательный: он должен быть последним или единственным) доработана чтобы

могла вернуть обратно уже введённый символ...


* * *

(4.0) (4.2)

— функция FCHr, производящая побайтный ввод/вывод, пишет-то конечно

непосредственно в канал вывода, а вот читает... А вот читает она

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

оператора Ask. А если не пуст — то из него, пока не исчерпается.

Этот самый оператор ввода Ask читает за раз целую строку (ну Фокал же

строчно-ориентированный!) а вот использует для каждой указанной в списке ввода

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

строки хранит в некотором буфере... Вот оттуда и вынуждена брать очередные

байты FCHr, а то некрасиво получается.

И вот ей поручили вернуть уже взятый байт обратно — фактически сдвинуть

назад указатель текущего байта в этом самом буфере. Пожалуйста: FCHr() (т.е.

без аргументов). И за одно пусть сообщает сколько символов теперь в буфере

осталось.

Ага.

— А не на один, а сразу на N байтов — слабо?

— Запросто: FCHr(,N).

— Ха, а если N отрицательное?

— Ну значит в другую сторону.

— А узнать, сколько там в другую сторону (якобы уже использованных)?

— Тоже можно: FCHr(,).

А общая длина строчки в буфере соответственно: FCHr(,)+FCHr(,0).

Ладно.

— А если аргумент в виде текстовой константы? FCHr ведь коды символов

возвращает, не так ли?

— Ну значит FCHr("Б") вернёт код буквы Б. Но только одной.

— А если их будет несколько: FCHr("БВГД") — код буквы Б вернёт, а остальные

куда?

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

— А если константа будет пустая FCHr("")? А если вслед за ней еще несколько

параметров?...

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

(Плюс маркер текущей позиции и средства посимвольного доступа...) Та самая,

которая аккумулятор А2?

— Именно!

Однако, пока что к нему не хватает средств ввода и вывода: мы же с

текстовыми строками работать прицелились? А тексты — вещь громоздкая. Поэтому

храним их исключительно где-то там, за пределами Фокала — в виде файлов

например. А внутрь тащщим только по одной строчке...

Нет, даже вот это — уже большой прогресс! В оные времена по одному символу с помощью FCHr приходилось таскать и под видом массива чисел хранить...))

(4.1)

Вводит-то строку оператор Ask (это же вообще-то его входной буфер!), но

вводит и сам же использует... А сделаем так, что если его список ввода

АБСОЛЮТНО пуст, то только вводит. Если конечно этот его буфер тоже пуст.

А сделать его пустым (на случай, если остаток строки нам почему-то не

нужен) сдедующим незамысловатым образом:

Ask %

(Ничего не поделаешь — изобразительные средства Фокала ограничены, пришлось

стащить "формат" из оператора Type.)

Далее. Если ввод с терминала, то было бы полезно иметь возможность не

заставлять пользователя вводить (ну то, что надо ввести) целиком, "с нуля", а

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

исправить. Вот как при нажатии кнопки ЕСЦ Фокал предлагает нам командную

строку для сохранения программы... И такая возможность есть! Надо чтобы этот

текст уже лежал в этом самом буфере, но при этом он выглядел пустым. Не был

пустым, а ВЫГЛЯДЕЛ. А пустым он будет выглядеть, если в нём больше нету ни

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

его конце. Как туда поставить маркер? Да запросто: FCHr(,-FCHr(,0)).

А вот как туда попадёт нужный нам текст? Может по-разному.

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

123456 ... 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)
Закрыть
Закрыть
Закрыть
↑ Вверх