Встроенный язык программирования

Для организации вычислений и реализации сложных действий по формированию выходного документа в систему встроен простой процедурный язык программирования. Он включает все основные возможности процедурных языков:
ведение системы переменных (включая массивы произвольной размерности);
вычислений выражений произвольной сложности;
организацию условных вычислений произвольного уровня вложенности;
организацию циклических вычислений произвольного уровня вложенности;
большуя библиотеку встроенных функций;
возможность вызова функций пользователя с произвольным уровнем вложенности.
Программы размещаются в секциях .do и .module. Они могут непосредственно включаться в описание документа или импортироваться из других документов. Программы, размещенные в секциях .do, выполняются сразу после завершения секции. Программы (модули), размещенные в секциях .module, при завершении секции компилируются во внутренний байт-код, но не выполняются до тех пор, пока не будут вызваны из программ секций .do или других модулей. Модули могут иметь формальные параметры, замещаемые фактическими при вызове, и могут возвращать результаты своих действий вызвавшей программе.
Порядок написания программ исходит из принципа: одна строка - один оператор (логически завершенная часть оператора для if и while). Если первый непустой символ строки *, то строка игнорируется (комментарий).
Числовые константы задаются обычным образом. Разделителем дробных разрядов является точка (.). Строковые константы можно задавать либо внутри пары одинарных кавычек ('текст'), либо внутри пары двойных кавычек ("текст"). В первом случае текст может содержать любое количество двойных кавычек, а во втором - любое количество одинарных кавычек.

Переменные

Переменные предназначены для хранения информации, которая может измениться в процессе выполнения программы или обработки документа. Переменные не нужно объявлять заранее, а хранимая в них информация является безтиповой. Числовым значением строковых данных, которые не могут быть преобразованы число, является ноль.
Если переменной ранее не присвоено никакое значение, то считается, что она имеет специальное значение %null или null() (записи эквивалентны). В частности, если какой-либо фактический параметр не передан в модуль, то значением соответствующего формального параметра является %null.
Имена переменных должны содержать только латинские буквы, цифры, а также символ подчеркивания (_). Имя должно начинаться с буквы. Имена являются регистронезависимыми. Если после имени следует открывающаяся скобка, то система рассматривает имя как имя встроенной функции или массива. Если встроенная функция с таким именем не определена в конфигурации, то считается, что переменная указывает на массив. Поэтому надо очень осторожно подходить к именованию массивов: имя массива не должно совпадать с именем какой-либо встроенной функции. Если это правило будет нарушено, то система попытается выполнить функцию, а не обратиться к массиву.
Обращение ко всему массиву осуществляется указанием его имени (без скобок), а к элементам массива - с помощью индексов. Индексом может быть либо любое целое число, либо строка (в одинарных или двойных кавычках), либо скалярная переменная, содержащая целое число или строку. Для многомерных массивов указание части первых индексов интерпретируется как обращение к подмассиву массива. Например, если переменная х содержит матрицу, то обращение x('data') возвратит строку матрицы x c индексом data, если она существует и %null в противном случае.
Каждый модуль (включая каждую секцию .do, которые рассматриваются как модули первого уровня) имеет свое пространство имен (контекст). Отдельным контекстом является также уровень документа. Переменные каждого контекста независимы. Попросту говоря, переменные с одинаковыми именами в разных контекстах могут иметь разные значение. С помощью встроенных функций можно получить и изменить переменную в любом другом контексте. Все переменные в любом контексте являются статическими. То есть, при выходе из модуля, созданные в нем переменные (включая формальные параметры) сохраняют свои значения. Поэтому, если повторный вход в данный модуль должен начинаться с "чистого листа", то перед выходом из него или сразу после входа следует предусмотреть уничтожение нежелательных переменных. Для этого можно использовать встроенные функции kill() и hold().
При выполнении программ в секциях .do система автоматически копирует все переменные, определенные в контексте документа в контекст данного модуля. Изменение этих переменных программой секции .do не приводит к автоматическому изменению их в контексте документа. Для переноса переменных в контекст документа следует использовать встроенные функции copy() и dvput(). При завершении обработки документа измененные переменные не сохраняются. Если необходимо сохранить их значения для следующего сеанса работы данного пользователя с данным документом, необходимо выполнить их принудительное сохранение с помощью встроенной функции save().
Загружать переменные контекста документа не нужно - это действие выполняется автоматически при входе в документ. Кроме них в контекст документа в виде отдельных переменных записываются значения параметров, переданных скрипту, а также переменных, введенных через HTML-формы, обработчиком которых назначен данный документ. Следует также иметь ввиду, что с помощью специальных встроенных функций при необходимости можно получить значение любой переменной, установленной при работе данного пользователя с любым другим документом.

Выражения и однострочные операторы

Выражения строятся по правилам, аналогичным традиционным системам программирования. Допускаются следующие знаки операций:
+ сложение;
- вычитание или унарный минус;
* умножение;
/ деление;
| логическое ИЛИ;
& логическое И;
= равно;
# не равно;
> больше;
< меньше;
>= больше или равно;
<= меньше или равно;
<> не равно.
Логическим значением "истина" является любое число не равное нулю. Значением операций сравнения или логических операций является 1, если условие истинно, и 0, если условие ложно.
Операндами в выражениях могут быть константы, скалярные переменные, массивы, элементы массивов, обращения к встроенным функциям.
Некорректные с точки зрения математики операции не приводят к остановке выполнения программы (если иное не предусмотрено установкой режимов выполнения программы встроенными функциями). При делении на ноль происходит запись соответствующего сообщения в виде комментария (пользователь не видит) в HTML-код выходного документа, а результатом выполнения операции является %null. Числовое значение строки, которая не может быть преобразована в число является ноль. Поэтому, если такое значение участвует в арифметической операции, то это эквивалентно тому, что один из операндов - ноль. То же касается использования в выражениях значения %null.
Все операторы, кроме if и while являются однострочными. Для них действует правило: одна строка - один оператор. Ими могут быть:
оператор присваивания;
вызов встроенной функции;
операторы loop и exit (см. далее).
Оператор присваивания строится по обычным правилам:
имя_переменной=выражение

Условный оператор

Для организации условных вычислений в языке используется оператор: if elseif else end. Структура оператора:
if выражение0
   операторы
elseif выражение1
   операторы
elseif выражение2
   операторы
 ...
elseif выражениеN
   операторы
else
   операторы
end
Если выражение0 верно, то выполняются последующие операторы (до elseif (если есть), else (если есть) или end (если нет elseif и else)), в противном случае они пропускаются и вычисляется выражение1. Если оно верно, то выполняются последующие операторы до следующего elseif или else, в противном случае проверяется выражение2 и т.д. Если ни одно из выражений 0-N неверно, выполняются операторы, следующие после else. Фрагменты elseif и else необязательны и могут использоваться по необходимости. Условные вычисления могут иметь сколько угодно уровней вложенности.

Оператор цикла

Для организации циклических вычислений в языке используется оператор: while выражение. Структура оператора:
while выражение
    операторы
    loop
    операторы
    exit
    операторы
end
Операторы между while и end выполняются до тех пор, пока выражение (условие продолжения цикла) является истинным (не равно нулю). Оператор loop инициирует переход к началу цикла и проверке условия продолжения цикла в обход последующих операторов. Оператор exit осуществляет немедленный выход из цикла к следующему после end оператору. Циклы могут иметь неограниченное число уровней вложенности. Операторы loop и exit необязательны и могут использоваться по необходимости.
Для принудительного выхода из цикла может использоваться также функция return(), осуществляющая возврат к вызвавшему модулю.
Общая характеристика возможностей виртуального издательства
Создание/Изменение узлов и документов
Функции выполнения экономических расчетов
Команды первой позиции
Функции формирования выходного документа