3. ПЕРВЫЕ КОМАНДЫ

Как это выглядит практически. Прежде всего есть пустая команда #parameters или сокращенно #p. Она сама ничего не делает, но, как и для любой другой команды, после нее можно писать поле определения параметров FPD. И как раз для этих целей она и используется. Иногда это бывает удобно. Итак
#p [n=1; b=1; le=1; c=1; ...]
Здесь для примера указаны некоторые часто используемые параметры [n] (number), [b] (begin), [le] (length), [c] (code). Каждая команда использует свои параметры и они будут указываться по ходу описания команд. Полная таблица всех команд и параметров дана в конце книги, в 24-й главе. Далее есть команда окончания
#stop
которая заканчивает чтение текста программы и работу интерпретатора, даже если в нем еще остались команды ACL. Это удобно, так как позволяет хранить в одном файле куски программ для примеров и подсказок. Если такой команды нет, то текст программы читается до конца и программа заканчивается естественным образом. Есть еще команда
#exit
позволяющая полностью завершить работу программы-интерпретатора. Она необходима только при запуске интерпретатора с полностью готовой ACL-программой, когда среда отладки ACL-программ не используется совсем. Это позволяет представить ACL-программу как независимую программу, при использовании которой знание языка ACL не требуется. Далее, в языке есть описания процедуры
#pro NAME  <здесь помещаются все другие команды> @
Символ [@] служит окончанием процедуры (жирная точка). Имя процедуры NAME является первым аргументом такой команды. Оно должно содержать 4 знака в любой комбинации. Любой кусок программы можно предварительно поместить в тело процедуры (он при этом не выполняется, а запоминается). Тело процедуры и символ окончания [@] можно рассматривать как остальные аргументы команды. Код в теле процедуры будет выполнен позже, при вызове процедуры. Порядок записи на строке не имеет значения. Как удобно, так и записываете. Процедуры выполняются с помощью специальной команды, которая должна естественно быть поставлена после определения процедуры
#e [c=1;] NAM1 NAM2 NAM3 #%
Эта команда означает выполнить (execute) процедуры одну за другой из указанного списка. Если у команды #pro есть только аргументы: [NAME] и сама процедура, то у команды #e кроме аргументов есть уже и параметр с именем [c] (code), значение которому можно присвоить прямо тут же, в FPD, а можно и раньше. Все процедуры выполняются только в том случае, если значение параметра [cod] совпадает с текущим значением переменной [&]. Эта переменная должна быть определена заранее. Но если написать
#e [c=&;] NAME #%
то процедура всегда выполнится при любом значении [&]. Для сокращения записи, то же самое можно написать как
#e _NAME #%
Символ подчеркивания перед первым именем в списке процедур означает безусловное выполнение. Важно помнить, что [c] - это целое число, а [&] - это вещественная переменная, поэтому для сравнения берется ее ближайшее целое.

Эта команда усилена дополнительно двумя специальными режимами работы, необходимыми для написания особенно сложных программ. Специальные имена процедур [file] и [text] служат для выполнения команд программы из файла или из текстового массива t(). Пример:
#e [file=pro/calcul.acl;] _file 
Эта команда указывает, что нужно выполнить процедуру, то есть набор команд, записанных в файл "calcul.acl", помещенный в папку "pro" относительно папки интерпретатора. Интерпретатор специально сделан так, что он не работает с внешними папками, а работает только с папками внутри "нулевой" папки, то есть папки, в которой находится сам интерпретатор "vkACL.jar" (или "vkACL.ewe" для КПК). Папка - это место, где хранятся файлы, другое ее название Директория использовалось в ДОСе, а я перешел на оконный язык. Здесь уже используется второй текстовый параметр [file] для указания пути к файлу. В этой команде путь к файлу указывается полный, то есть относительно "нулевой" папки. Это необходимо по той причине, что имя текущей рабочей папки используется для других файлов. С другой стороны, иногда полезно держать все файлы с процедурами в одном месте независимо от прикладной программы. Процедуры, помещенные в файлы, могут быть довольно универсальными и могут использоваться многими программами. Поэтому они должны удовлетворять некоторым ограничениям поскольку интерпретатор использует одни и те же ресурсы для всех программ. Но можно и просто поместить в файл любой кусок программы и затем выполнить его. Еще более сложная команда
#e [b=a; le=b;] _text 
позволяет выполнить команды, динамически записанные в часть текстового массива t(), начиная c элемента t(a) и длиной b символов. Понятие строки текста в ACL не существует. Любая строка, как известно, состоит из набора символов и имеет имя и длину. Значения числовых параметров [b] (begin) и [le] (length) можно рассматривать как имя и длину строки. Просто в ACL имя строки - это число, которое указывает размещение символов в текстовом массиве. Этого вполне достаточно. Программа, которую выполняет данная командам, исходно не существует, поэтому ее надо предварительно записать. Естественно и параметр [c] тоже можно использовать в обоих случаях. Записанный вариант безусловного исполнения просто короче.

Наконец, нужно отметить одно важное свойство этой команды. Она читает имена процедур для выполнения неограниченно, пока не встретит символ [#] или символ [@], означающие начало новой команды или окончание процедуры. Исключение составляют только специальные имена file и text. Ни до, ни после них никакие другие процедуры не выполняются. Поэтому они не могут быть в цепочке. Если после команды необходимо вставить текст комментария или данная команда является последней в файле, то после нее надо поставить любую другую команду с фиксированной длиной. Самой короткой командой является #% поэтому проще всего использовать эту команду. Ее реальный смысл - засылка текущего номера символа текста программы в переменную [%] для последующего использования в разных целях. Но в данном случае она просто играет роль ограничителя предыдущей команды. Если этого не сделать, то интерпретатор выдаст ошибку несуществующей процедуры.

Как это очевидно из сказанного, сначала надо определить все процедуры, а потом писать текст основной программы. Иногда это бывает неудобно, так как приходится начинать изучение программы с конца файла. Но можно использовать простой прием. Основной текст программы тоже поместить в процедуру
#pro main ... @
Теперь уже можно писать любые процедуры в любом порядке, а в конце программы написать стандартную строку
#e _main  #stop  или  #e _main #% 
Второй вариант необходим, если программа записана в файл и является частью более сложной программы, поэтому остановка нежелательна. Последнюю строку смотреть не обязательно. В таком виде вся программа состоит из процедур.

Выполнение команд из файла часто бывает очень удобным приемом, потому что такую процедуру не надо переписывать в каждую программу. Допустим вы разработали некий универсальный код, который выполняет определенную работу над данными. Достаточно поместить этот код в файл, приготовить нужные данные и просто запустить процедуру. Так как таких процедур со временем может накопиться много, удобно сократить для них способ их вызова. Такой аппарат действительно развит в виде вызова суперкоманды. Cуперкомандой называется специальным образом организованная процедура, которая записана в файл "name.acl", где "name" - любое имя, и помещена в папку "proc", которая специально создана для аккумуляции суперкоманд. Все файлы из папки "proc" можно запускать на выполнение конструкцией, похожей на команду, а именно ##name - то есть перед именем файла без расширения надо поставить два символа [#]. В отличие от обычной команды, такая суперкоманда не может определять ни параметры, ни аргументы. Но параметры она может наследовать от команды #p [...], а аргументы можно предварительно напечатать в текстовый массив t(), из которого суперкоманда их прочитает. Таким образом, можно оформить суперкоманду с входными параметрами, выполняющую некоторую общую работу. Вот пример. Команда #w имеет очень много параметров. Можно выделить из них важные, а остальные определить раз и навсегда и сделать суперкоманду, которая будет иметь меньше параметров. Дополнительно, можно включить в нее определенные процедуры предварительной обработки данных. Но суперкоманда может иметь форму и самой обычной процедуры. Другими словами мы просто заменяем вызов #e [file=proc/name.acl;] _file на ##name. Очевидно суперкоманды можно создавать по ходу разработки какой-либо программы. Их можно модифицировать, дописывать, изменять. Те суперкоманды, которые создаются мной, входят в стандартную поставку программы интерпретатора. Но пользователь может создавать и свои собственные суперкоманды. В этих условиях описание работы суперкоманд не могут входить в общее описание. Разумно включать описание суперкоманд в сам текст суперкоманды, то есть в файл, в виде комментария. Каталог таких суперкоманд является частью каталога файлов в папке "proc". Очевидно суперкоманды нельзя ставить в циклы с большим числом повторений, но их разумно использовать при разработке графических объектов, разных стандартных операций с картинками. Более того, любую программу разумно разбить на блоки и выделить стандартный кусок, который затем можно преобразовать в суперкоманду. Это облегчит программирование в будущем. При программировании Фактически все, что нужно знать о суперкоманде - это ее функцию и набор данных на входе и выходе. А конкретная ее реализация уже не играет роли. Суперкоманда может быть максимально оптимизирована и затем необходимость вникать в то, как она разработана, отпадает. С другой стороны, суперкоманды могут служить образцами кода и методов программирования, их можно использовать как пособие и предмет для подражания. Вместе с тем, так как память у всех процедур общая, надо точно знать какие переменные и элементы массивов переопределяются в процедуре суперкоманды, с тем чтобы разрешить все возможные конфликты. Желательно запоминать и затем восстанавливать испорченные данные по мере возможности. По этой причине использовать суперкоманды надо с осторожностью, постепенно осваивая этот механизм. При возникновении любых проблем следует от них отказаться, либо попытаться поменять порядок действий, перемещая суперкоманды на конец.