Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MUMPS СУБД. Практика применения и опыт программирования.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
1.12. ШАБЛОНЫ 141
A Буквы. C Непечатные символы. Символы с ко-
дами от 0 до 31 и с кодом 127. E Любой символ. L Буква в нижнем регистре. N Цифра. P Знаки пунктуации и пробел. U Буква в верхнем регистре.
Коды классов символов могут задаваться как в верхнем, так и в
нижнем регистре.
Формально, это перечень кодов, предусмотренных стандартом язы­ка. При этом реализации MUMPS систем могут поддерживать дополни­тельные коды классов символов. Для уточнения полного перечня нужно обратиться к документации на используемую MUMPS систему.
Коды классов символов могут следовать один за другим. В этом слу­чае MUMPS система строит объединенное множество из их множеств. Например, последовательность
AN
означает множество символов букв и цифр.
Формально говоря, стандарт языка MUMPS предусматривает приме­нение оператора отрицания к коду класса символа для получения мно­жества, не включающего указанный класс, например
1.3’N - от 1 до 3 не цифр
1.3’A - от 1 до 3 не букв
но такой функционал поддерживают в настоящее время не все реали­зации MUMPS систем. При использовании отрицания класса символов, таким образом, необходимо проверить в документации на используемую MUMPS систему, поддерживаются ли они. В случае если не поддер­живаются, но шаблон был передан в виде внешних данных и применен косвенно, то возникнет ошибка на этапе выполнения, а не компиляции.
Примеры шаблонов образованных счетчиком повторов и классами символов:
2.AN 2 или больше букв или цифр 1A.E 1 буква, после которой любое число любых
символов
.’C любое число печатных символов
142 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Второй вариант задания символов - это задание последовательности символов (одного или нескольких) явно в виде строки. Строка должна быть указана в двойных кавычках, как обычная строковая константа языка:
1"%"4AN Один символ процента после которого 4
буквы или цифры
1.12AN1"@mail.ru" От 1 до 12 букв или цифр после которых 1 строка "@mail.ru"
Сопоставление явно заданным символам выполняется чувствительно
к регистру.
Альтернативы задаются круглыми скобками с перечислением вари­антов через запятую. Сопоставление считается успешным, если система находит соответствие для подходящего участка строки по меньшей мере одной из указанных альтернатив. Например:
1.12AN1"@"1(1"mail.ru",1"yandex.ru") От 1 до 12 букв или цифр, ко­сле которых 1 символ "@", по­сле которого 1 повтор из альтер­нативы из 1 последовательности "mail.ru" или 1 последователь­ности "yandex.ru"
Нужно отметить, что в приведенном примере вместо спецификации числа повторов 1 также могут быть указаны любые числа, в этом случае проверка по шаблону будет искать повторы заданных строк подряд, одна за другой.
Альтернативы шаблонов могут быть вложены друг в друга.
Механизм сопоставления строки шаблону был разработан давно, при­нят в стандарте 1977-го года. В стандарт тогда входило задание классов символов и строк, в качестве числа повторов можно было указывать либо число либо точку, означающие что должно быть либо строго ука­занное число повторов либо любое число повторов. В стандарте 1984-го года было дополнено возможностью указывать число повторов либо от и до указанного числа, либо до, либо от указанного числа. В стандарте 1995-го года были приняты альтернативы.
Намного более сложные правила задаются регулярными выражени­ями. В определенном смысле, что такое регулярные выражения, задает тон язык PERL, и многие другие системы ориентируются на его возмож­ности и правила спецификации.
1.13. КОСВЕННОСТЬ 143
В системах MUMPS полновесные регулярные выражения могут быть использованы лишь в виде внешних модулей либо если MUMPS система поддерживает встроенные системные функции для регулярных выраже­ний, в частности MiniM поддерживает семейство функций $ZPCRE для проверки по регулярному выражению, для поиска и для замены под­строк. Но все эти возможности, несмотря на поддержку и наличие, не входят в стандарт переносимости и разработчики должны проверять как именно регулярные выражения поддерживаются на целевой системе.
Поддержка полноценных регулярных выражений в синтаксисе языка PERL в той или иной функциональной форме видится существенным улучшением с точки зрения прикладных программ. В действительности, многие данные проходят или фильтр по определенным правилам про­верки и нормализации, или разбор структуры также по определенным правилам. Если стандартные шаблоны MUMPS могут лишь выполнить проверку, то регулярные выражения могут также выполнить поиск с за­меной и выделение набора подходящих фрагментов. Вводить регулярные выражения в язык MUMPS на уровне синтаксиса языка в настоящее вре­мя выглядит нецелесообразным, но расширенная функциональная под­держка в стиле многих других языков видится удачной.

1.13 Косвенность

Во многих языках используются синтаксические конструкции, означаю­щие не прямое использование значения, а использование значения как указания что именно нужно использовать на самом деле, или вместо ука­занного. В этом случае производится непрямое использование значения (indirection). В языке MUMPS эта операция также называется косвен­ностью. В те годы, когда разрабатывался язык MUMPS, было принято использовать для обозначения косвенности символ "@". Во многих про­граммных средствах он же используется и до сих пор.
Слабым аналогом косвенности является использование указателей или ссылок, когда код использует не значение самого указателя или ссылки, а тот объект, но который они указывают. Аналогом косвенности выражения является функция eval в языке JavaScript, например.
Если при чтении программного кода разработчик видит символ @, то это означает оператор косвенности. Оператор косвенности применяется к тому, что стоит непосредственно справа от него. В языке MUMPS опе­ратор косвенности может быть применен к большинству синтаксических конструкций. Это:
144 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
1. Косвенность имени переменной
2. Косвенность индексов
3. Косвенность метки
4. Косвенность аргумента команды
5. Косвенность шаблона
Исключением являются косвенность оператора, выражения, и кос­венность команды. Вместо косвенности собственно команды использу­ется команда XECUTE, задающая выполнение не одной, а нескольких команд. Вместо косвенности выражения используется косвенность аргу­мента для тех команд, которые в качестве аргумента используют выра­жение. Например, это команда QUIT или команда IF.
Вариант косвенного выполнения команды, или задание команды в виде отдельной строки:
USER>s command="kill"
...
USER>x command_" varname"
Здесь к аргументу varname применяется команда, указанная ранее. Но полноценной заменой косвенности команды это не является, посколь­ку используется команда xecute, автоматически создающая новый уро­вень стека и выполнение, в частности, команды new будет отменено при возврате из команды xecute.
Вариант косвенности выражения сопряжен с использованием коман­ды quit в аргументной форме и требует отдельной метки в рутине:
eval(expr) q @expr
Такую метку можно использовать для вычисления выражений, за­данных косвенно:
w $$eval("2*2"),! w $$eval("$sy_$zd($h)"),!
Оператор косвенности применяется к выражению после его вычис­ления и выражение может быть задано с произвольной сложностью. В случае использования неатомарного выражения, например составленно­го из операторов, необходимо все выражение заключить в скобки, чтобы
1.13. КОСВЕННОСТЬ 145
указать что оператор применяется к результату вычисления всего вы­ражения полностью, за исключением косвенности индексов. В случае косвенности индексов индексы добавляются именно как указано.
Стандарт, вообще говоря, допускает применение косвенности про­извольного уровня вложенности. Интерпретатор на этапе выполнения будет раскрывать все встреченные им синтаксические конструкции кос­венности пока все выражение не будет раскрыто полностью. Выполнение этой операции с точки зрения внутренних алгоритмов и архитектуры, а также требуемых ресурсов компьютера может представлять некоторую сложность, поэтому при использовании рекурсии в операторе косвенно­сти не все синтаксические конструкции могут быть выполнены.
В частности, система MiniM при использовании рекурсии генерирует следующую ошибку:
USER>s x="@x"
USER>w @x
<MAXOBJCODE>
система Cach´e генерирует ошибку:
USER>s x="@x" w @x
S x="@x" W @x
<FRAMESTACK>
^
и система M3-Lite генерирует ошибку:
3>s x="@x" w @x <STKOV>
Кроме того, отдельные реализации могут содержать ограниченные возможности по рекурсивному раскрытию косвенности, либо по соче­танию видов косвенности, либо по глубине вложенности архитектурно, либо, как было показано в примерах, косвенно из-за ограниченности вы­деляемых на операцию раскрытия ресурсов. В частности, приведенные выше примеры показывают, что было запрошено бесконечное рекурсив­ное развертывание аргумента команды, определенное через само себя. В обоих случаях системы натыкаются на израсходование внутренних пределов выполнения кода, в зависимости от внутренних архитектур и методов развертывания.
146 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Оператор косвенности не имеет синтаксических отличий для его раз­личных форм, форма косвенности определяется по контексту. В случае если трактовка косвенности может быть многозначной, система выбирает наиболее общий вариант. Например, если указано
write @string
то синтаксически это может соответствовать как косвенности имени для вычисления значения переменной и вывода этого значения, так и кос­венности аргумента команды write.
Но случай косвенности аргумента включает в себя возможный вари­ант, что в аргументе может быть использовано вычисляемое выражение, или имя переменной, или перечисление нескольких допустимых аргу­ментов команды, поэтому MUMPS система выбирает наиболее общий из этих вариантов и трактует данный случай как косвенность аргумента команды.

1.13.1 Косвенность имени

Косвенность имени означает замену оператора косвенности вместе с его значением на использование того, что указано в значении. Если выраже­ние было вычислено как строка, содержащая допустимое имя локальной, глобальной, или структурной системной переменной, то система исполь­зует это имя вместо оператора косвенности. Например:
USER>s name="abcdef"
USER>w name="abcdef"
USER>s @name=123456
USER>w abcdef=123456 name="abcdef"
USER>
Здесь оператор косвенности применен к переменной name, что для команды set означает применение операции не к переменной name, а к значению переменной name. Оператор может быть применен к результату выражения, вычисленному произвольным образом. В частности:
1.13. КОСВЕННОСТЬ 147
USER>w
USER>f i=1:1:5 s @("aa"_i_"bb")=i*i
USER>w aa1bb=1 aa2bb=4 aa3bb=9 aa4bb=16 aa5bb=25 i=5
USER>
При конструировании выражения с именем переменной код может конструировать как неиндексированное имя, как в примере выше, так и индексированное, если оно построено по синтаксическим правилам языка MUMPS:
USER>w
USER>f i=1:1:5 s @("aa"_i_"(i)")=i*i
USER>w aa1(1)=1 aa2(2)=4 aa3(3)=9 aa4(4)=16 aa5(5)=25 i=5
USER>
Конечно, в случае использования строковых индексов разработчик должен самостоятельно принять меры, чтобы кавычки были удвоены там, где это необходимо, для получения корректного синтаксического имени.

1.13.2 Косвенность индексов

Косвенность индексов задается только после косвенности имени и озна­чает дописывание указанных индексов к вычисленному имени перемен­ной. Имя переменной может вычисляться как локальное или глобальное имя.
Если имя было вычислено как неиндексированное, при применении косвенности индексов образуется имя с указанными индексами. Если
148 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
было вычислено индексированное имя, то индексы добавляются после его последнего индекса.
Примеры дополнения неиндексированного имени:
USER>w
USER>s @("abc"_123)@(11,22,33)="value"
USER>w abc123(11,22,33)="value"
USER>s @"name"="value2"
USER>w abc123(11,22,33)="value" name="value2"
Примеры дополнения индексированного имени:
USER>s @("abcd(1,2,3)")@(11,22,33)="value"
USER>s name=$na(local($j,$p))
USER>s @name@(11,22,33)="value2"
USER>w abcd(1,2,3,11,22,33)="value" local(2560,"|CON|",11,22,33)="value2" name="local(2560,"|CON|")"
При развертывании косвенности индексов MUMPS система сначала вычисляет и выполняет все необходимые подстановки для начального имени переменной, затем вычисляет значения индексов переданные по­сле оператора косвенности индексов и получает полное имя переменной.
Результаты операций косвенности имен и косвенности индексов могут быть использованы в любом месте, где допускается применение имени переменной.
В случае если функция, принимающая имя переменной, не допускает использование структурной системной переменной, но оно было переда­но косвенно, MUMPS система генерирует ошибку на этапе выполнения операции в зависимости от выполняемой функции.
Операции косвенности имен и индексов часто используются разра­ботчиками для передачи строк в качестве аргументов функций, чтобы функции могли применять обобщенные алгоритмы к произвольным пе­ременным. Во многих случаях разработчики применяют также хранение
1.13. КОСВЕННОСТЬ 149
реальных имен переменных в глобалах с настройками прикладной про­граммы, с тем, чтобы программа оперировала данными в указанных ей переменных, глобалах. В этом случае администратор может направить действия программы на необходимое сочетание глобалов.

1.13.3 Косвенность метки

Оператор косвенность метки определяется по контексту, в котором долж­на быть использована метка. Метки используются для безусловного пе­рехода командой GOTO, для вызова подпрограмм командой DO, для вызова функций с возвращаемым значением ($$) и как аргумент функ­ции $TEXT. Во всех этих случаях MUMPS система будет подставлять вместо метки вычисленное значение.
В каком-то смысле слабым аналогом косвенности метки является вы-
зов функции по указателю на функцию в других языках.
Метка состоит из четырех частей - собственно имя метки, величи­на смещения, имя базы данных где находится рутина и имя рутины. Синтаксически имя базы данных рутины и номер смещения являются вычисляемыми значениями, а имена метки и рутины указываются как есть. Для конструирования полного имени метки и используются раз­личные формы косвенности метки:
1. @expr - в значении expr MUMPS система ожидает полный набор из 4-х компонент, часть из которых может быть опущена на усмот­рение разработчика.
2. @exprˆrouname - в значении expr MUMPS система ожидает ком­бинирование имени метки и смещения.
3. label+@nameˆrouname - косвенность для смещения не поддержива­ется, здесь символы @name трактуются как вычисляемое выраже­ние и синтаксически соответствуют косвенности имени. Значение смещения берется из переменной, имя которой содержится в пере­менной name (в данном случае).
4. label[+offset]ˆ@expr - в значении expr MUMPS система ожидает имя рутины с опционально заданной базой данных.
5. label[+offset]ˆ|@name|routine - косвенность для имени базы дан­ных не поддерживается, здесь символы @name трактуются как вычисляемое выражение и синтаксически соответствуют косвенно­сти имени. Имя базы данных рутины берется из переменной, имя которой содержится в переменной name (в данном случае).
150 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Разработчики могут комбинировать косвенность частей метки про­извольно, если после развертывания MUMPS система может получить корректный результат.
Косвенность метки в том виде как она была определена при созда­нии языка MUMPS, позволяет использовать аналог механизма функций высшего порядка, когда функции могут передать и принять в качестве параметров другие функции. Передать непосредственно функцию в язы­ке MUMPS нельзя, поскольку отсутствует типизация в любом виде, но можно передать строку, которую можно использовать в качестве имени функции. Более того, со строкой можно поступить как с просто данными и провести необходимые вычисления, например проверить допустимость вызова, существует ли такая метка, добавить суффикс в зависимости от контекста работы процесса и многое другое. Например, пусть есть рутина fun в виде:
fun
w $$g("f",7),! q
f(x)
q x+3
g(func,x)
q $$@(func)(x)*$$@(func)(x)
Здесь при вызове метки fun производится обращение к функции g, и ей передаются строки "f" и 7. При этом функция g использует один параметр для косвенного вызова функции, второй как передаваемый ей параметр. При выполнении подпрограмма fun выводит в текущее устрой­ство значение 100.
Здесь нужно обратить внимание на использование скобок в записи:
$$@(func)(x)
Такая запись означает взятие имени метки из переменной func. В случае если скобки для func будут опущены и будет использована запись
$$@func(x)
то это означает взятие имени метки из индексированной переменной
func(x)
Одним из часто используемых применений косвенности метки явля­ется выполнение перехода в зависимости от каких-либо условий в со­четании с функцией $SELECT. Функция $SELECT проверяет условия и возвращает строку с меткой для перехода или для вызова подпро­граммы. К ее результату применяется оператор косвенности и результат используется как метка. Например: