Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MUMPS СУБД. Практика применения и опыт программирования.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
1.1. КОМАНДЫ 51
Неприятность второго случая в том, что если округление дало нуле­вую величину, то задержка не выполняется и команда может вообще не выполнить обращение к процедуре приостанова. В случае если задержка на малую величину вставляется в цикл для отдачи процессорного вре­мени, то в этом случае процесс может вообще не отдать процессорное время на время своего ожидания.
При этом характер отсчета задержки также может варьироваться в зависимости от реализации:
1. Задержка отсчитывается от начала выполнения команды.
2. Задержка прерывается при достижении соответствующего внутрен­него кванта переключения контекстов job.
Во втором случае проявляется эффект нестабильного времени за­держки с непредсказуемым характером округления как в меньшую, так и в большую сторону. И чем меньше время задержки, тем больше отно­сительная погрешность ее выполнения.
Если частью сервера приложений, написанного на MUMPS, является фрагмент игрового характера, для которого важен таймаут с величина­ми менее секунды, то разработчикам необходимо проверять поведение задержек на каждой из MUMPS систем, которые предполагается ис­пользовать. Характер реализации задержки может совпадать также для других команд, использующих таймауты, для таких команд как LOCK, JOB, READ или OPEN.
Команда HANG выполняет безусловную задержку. В случае если пользователю нужно дать возможность прервать выполнение задержки, рекомендуется использовать команду чтения символа READ с задерж­кой. При ее выполнении, если произошел ввод символа с клавиатуры, то команда возвращает управление до истечения задержки.
Команда JOB (J) полностью аналогична команде DO (D) за двумя исключениями:
1. После выполнения команды порождается новый процесс MUMPS и управление возвращается вызвавшему процессу.
2. Нельзя передать локальные переменные по ссылке.
Если есть подпрограмма, например такая:
label(param,...)
; commands ... q
52 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
то ее можно вызвать как подпрограмму командой DO и тогда она вы­полнится как часть последовательного выполнения процесса. Либо ее же можно вызвать командой JOB, и тогда породится новый процесс и его выполнение начнется с этой метки в этой рутине и параметры param станут локальными переменными нового процесса.
Синтаксис вызова полностью аналогичен команде do:
do label^rtn(expr1,expr2,...) job label^rtn(expr1,expr2,...)
Кроме того, команде job можно через двоеточие указать дополнитель­ные опции запуска процесса и таймаут ожидания запуска. В случае если таймаут указан, то команда записывает в системную переменную $test значение 1 при успехе запуска дочернего процесса или 0 при неуспехе.
Команда job возвращает управление сразу как только выполнен за­пуск дочернего процесса либо стало известно, что такое действие невоз­можно по каким-либо причинам. Команда job не ожидает завершения выполнения дочернего процесса.
Состав и назначение дополнительных опций команды job определяют­ся реализацией и версией MUMPS системы. Традиционно в них специ­фицируются, например, передача дополнительных локальных перемен­ных целиком в виде дерева, передача конкурентного сокета, указание какой объем памяти необходимо использовать, в какой базе данных на­чать новый процесс, и другие параметры. В случае использования опций команды job необходимо проверить в документации на используемую MUMPS систему их состав и точный синтаксис.
Общий формат команды job специфицируется так:
job label^routine(params,...):(options,...):timeout
Также, как и для команды do, может быть опущено имя рутины, в таком случае для старта нового процесса используется текущая рутина.
Традиционно, различные реализации MUMPS систем поддерживают специальные расширенные системные переменные чтобы получить ин­формацию о номере запущенного дочернего процесса в родительском процессе и о номере родительского процесса в дочернем процессе. На­пример, это могут быть системные переменные $zparent и $zchild.
После запуска дочерний процесс выполняется параллельно и не свя­занно с родительским, и любой из них может завершить работу незави­симо друг от друга.
Команда LOCK (L) занимает или освобождает блокировку. Сама бло­кировка имеет имя совпадающее с именем локальной или глобальной
1.1. КОМАНДЫ 53
переменной. При этом существование и значение этих локальных или глобальных имен для команды lock не имеют значения. Доступ к этим переменным ничуть не препятствуется.
По своему назначению блокировка - это механизм синхронизации двух или более процессов в рамках одного сервера MUMPS системы. Если процесс может получить блокировку, то он получает и продолжает выполнение. Если не может, то выполнение процесса приостанавлива­ется до обнаружения состояния когда получить блокировку становится возможным.
Блокировки, установленные процессом, имеют время жизни либо до ее снятия самим процессом-владельцем, либо до окончания процесса. Многие современные реализации MUMPS систем имеют возможности принудительно снять блокировки, установленные в другом процессе. Этот функционал уже находится за пределами стандарта и выполняется средствами, зависимыми от реализации.
Команда VIEW (V), как и системная функция $view(), введена спе­циально для вынесения в нее всех возможностей, специфических для реализации MUMPS системы, например, просмотр значений операцион­ного окружения, значения внутренних структур памяти, прямого управ­ления сбросом буферов и многого другого.
Что интересно, сама команда VIEW стандартом предусмотрена, но назначение и точный синтаксис оставлен на усмотрение реализации. При портировании программ, разработанных на MUMPS, обычно именно ис­пользование команды view, функции $view и расширенных системных переменных начинающихся на $Z, является предметом внимания для поиска эквивалентной замены по функционалу.

1.1.6 Постусловия

Постусловия - это условия выполнения или использования, записанные после команды или аргумента команды, к которым они применяются. В других языках аналогичная конструкция не встречается и может вызвать первое время непонимание. В действительности это некоторый более короткий аналог команды if, но локального действия.
Синтаксически постусловие отделяется двоеточием и является произ­вольным вычисляемым выражением. При выполнении программы испол­няющая системы вычисляет указанное в постусловии выражение. После чего приводит его к числу и сравнивает с нулем. Если результат полу­чится эквивалентом числового нуля, то постусловие считается ложным, если результат - числовой не ноль, то постусловие считается истинным.
54 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Постусловие команды применяется к команде. Если команде указа­но несколько аргументов, то постусловие распространяется на все эти аргументы. Общий синтаксис:
cmd:postcond arg1,arg2,....
Некоторые команды, например, команды GOTO и DO с аргументами допускают указание постусловия для аргумента. В этом случае посту­словие указывается через двоеточие для аргумента. Общий синтаксис постусловия для аргумента:
cmd arg1:postcond1,arg2:postcond2,...
В некотором смысле постусловие это укороченный аналог команды if но с применением не ко всей последующей строке а только к указанной команде или аргументу. В отличие от команды if, которая изменяет зна­чение системной переменной $test, постусловие ни в какой форме его не изменяет, если конечно самостоятельно не содержит соответствующих побочных эффектов.
Если постусловие применено к команде, то при его невыполнении команда не выполняется, но управление все равно передается следующей команде.
Если постусловие применено к команде с несколькими аргументами, то оно применяется к всем указанным аргументам. Например, если при выполнении кода
write:a*b 123,!,456,! write 789,!
условие a * b вычислилось как 0, то команда
write 123,!,456,!
не выполняется полностью, но команда
write 789,!
все равно выполняется.
Постусловие для команд не может быть указано для условных ко­манд IF, ELSE и FOR. В самом деле, положим что в языке разрешено применять постусловие к командам IF, ELSE, FOR. В этом случае мы должны в зависимости от значения постусловия применить команду к ар­гументу. И, если постусловие не выполнилось, то перейти к следующей команде. В этом случае мы при ложном постусловии все равно выпол­няем команды, расположенные после команды IF, и один раз выполняем
1.2. ОПЕРАТОРЫ 55
команды расположенные в теле цикла, после команды FOR, несмотря на собственные правила выполнения цикла, описанные в команде FOR. Таким образом, разрешение постусловий для условных команд приводит к недоразумениям.
Хотя постусловное выражение записывается после ключевого слова команды, но вычисляется и проверяется перед выполнением или невы­полнением команды.
Даже в случае, если постусловное выражение не выполняется (ре­зультат вычисления равен нулю), тем не менее, выражение вычисляется, и вычисление может иметь побочные эффекты. На это разработчик обя­зательно должен обращать внимание.
Постусловие для аргумента указывает применять ли постусловие к этому аргументу если команда выполняется. Не все команды поддер­живают постусловия для аргумента. В частности, команды do и goto поддерживают постусловия на аргументы.
Если постусловие аргумента не указано, то команда применяется к нему, иначе, сначала вычисляется постусловие аргумента, проверяется как число на равенство нулю, и в зависимости от результата команда применяется к этому аргументу, либо применяется к следующему, если он есть. При этом, если есть постусловие как на аргумент команды, так и на команду, то сначала вычисляется и проверяется постусловие на команду, а затем, если оно выполняется, вычисляются и проверяются постусловия на аргументы. Например:
do:pc label1:pc1,label2:pc2
Здесь, если выражение pc вычисляется как 0, то все аргументы и постусловия аргументов игнорируются, и управление переходит к сле­дующей команде. Иначе, далее вычисляется и проверяется постусловие pc1, и если выполняется, то вызывается подпрограмма с метки label1. После обработки первого аргумента управление переходит ко второму, вычисляется и проверяется постусловие pc2. Если оно выполняется, то вызывается подпрограмма с метки label2.
В случае команды goto управление безусловно передается первому из аргументов, для которого выполнилось постусловие, и дальнейшие проверки не выполняются.

1.2 Операторы

Операторами называются действия над значениями, в результате кото­рых получается также значение.
56 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Операторы используются для укороченной записи специальных часто используемых функций, и используют специальные символы для облег­чения чтения и записи действий. Например, для записи сложения можно использовать функцию, принимающую два аргумента, и имеющую, на­пример, имя sum или summa или add, или иное, или обозначить одним символом плюс:
a+b
Конечно, вариант с записью такого действия в виде отдельно опреде­ленного оператора намного читабельнее.
В языке MUMPS используются операторы двух видов - унарные (пре­фиксные), применяемые к одному аргументу, и бинарные (инфиксные), применяемые к двум аргументам.
Унарный оператор в префиксной форме применяется к аргументу сле­дующим за ним. Примеры унарных операторов языка MUMPS:
+varname
-varname ’logical
Бинарные операторы в инфиксной форме применяются к двум аргу­ментам, и располагаются между ними. Примеры бинарных операторов языка MUMPS:
a+b a*b
Часть бинарных операторов может состоять из одного символа, часть из двух. В случае если оператор обозначен двумя символами, для него дается отдельная трактовка, например два символа используется для оператора отрицания логического оператора:
a’=b a’>b a’<b a’]b
Определение оператора отрицания оператора задается как последова­тельное применение сначала оригинального оператора, затем к резуль­тату применяется оператор логического отрицания. В частности, эквива­лентны замены:
1.2. ОПЕРАТОРЫ 57
a’=b -> ’(a=b) a’>b -> ’(a>b) a’<b -> ’(a<b) a’]b -> ’(a]b)
При этом, некоторые современные реализации MUMPS систем, на­пример MiniM и Cach´e, дополнительно поддерживают нестандартные расширенные операторы из двух символов. В частности, операторы срав­нения и ленивой логики
a>=b a<=b a||b a&&b
Применение расширенных нестандартных операторов, конечно, долж­но входить в соглашения, принятые при разработке - можно ли их при­менять или нет, поскольку при портировании кода на другую MUMPS систему они могут как поддерживаться, так и не поддерживаться.
Самым важным в применении операторов языка MUMPS для про­граммистов, работавших с другими языками, является правило отсут­ствия приоритетов операторов. Все вычисления выполняются слева на­право, как они написаны, и изменение порядка необходимо задавать явно, указав круглыми скобками очередность вычисления выражений. Так, если есть выражение
a+b*c
то интерпретатор MUMPS выполняет сначала сложение, затем умно­жение. Если программисту необходимо, чтобы сначала было выполнено умножение, а затем сложение, это нужно описать явно:
a+(b*c)
Для начинающих разработчиков на MUMPS этот факт некоторое время может быть источником проблем. В частности, при портирова­нии кода вычисления выражений написанных на языке, использующем приоритеты операций, или при модификации выражения, записанного без скобок, или при модификации выражения, использующем порядок вычисления слева направо.
Так, если было условие
a=b
58 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
и к нему необходимо добавить логическое ИЛИ с условием
c=d
то недостаточно дописать
a=b!c=d
Такое выражение будет соответствовать не ожидаемому
(a=b)!(c=d)
а совсем другому. Если записать его же с указанием порядка скобками, то оно будет вычисляться так:
((a=b)!c)=d
Так что получится что значение d будет сравниваться с результатом
вычисления
(a=b)!c
Что интересно, автору доводилось видеть именно такую некоррект­ную замену, причем этот код работал не проявляя ошибки больше по­лугода, потому что значения переменных перед вычислением принимали такие значения, что результат, вычисленный неправильно, подходил под правильный ответ.
Кроме операторов, вычисляющих выражение, в языке MUMPS так­же присутствует входящий в стандарт оператор отрицания кода шаблона, сам по себе не вычисляющий выражение, а формирующий правило со­поставления шаблону:
USER>w "a"?1N 0 USER>w "a"?1’N 1
Здесь первый шаблон задает правило "один символ цифра", а вто­рой отрицает тип символа и задает правило "один символ не цифра". С оператором отрицания типа символа в шаблоне у разработчиков могут возникнуть затруднения при его использовании, поскольку этот опера­тор довольно сложен в выполнении и не все реализации MUMPS его поддерживают.
В дополнение к стандартным операторам системы MiniM и Cach´e поддерживают операторную запись битовых операций и порядка их вы­полнения для битовых строк в аргументе функции $BITLOGIC:
1.2. ОПЕРАТОРЫ 59
& (И, бинарный) | (ИЛИ, бинарный) ~ (НЕ, унарный)
Аргументами оператора могут быть любые значения, если они мо­гут быть вычислены. Это могут быть константы, значения локальных, системных, или глобальных переменных, результат возврата системных и пользовательских функций, результаты других операторов. Если ин­терпретатор встречает использование оператора, то его аргументы син­таксически рассматриваются именно в этом контексте. В частности, для указания что необходимо вызвать подпрограмму с возвращаемым зна­чением, необходимо перед меткой указать символы $$, иначе литерал метки интерпретатор будет оценивать как имя переменной или как чис­ло, если имя метки состоит из цифр.
В отличие от других языков, где есть предварительная декларация типов, в языке MUMPS все литералы и имена рассматриваются как синтаксические конструкции по контексту операции. В частности, раз­личные элементы языка могут иметь совпадающие имена, и интерпре­татор оценивает тип элемента не по его имени, а по синтаксическому способу его использования:
1. name - локальная переменная
2. name(a,b,...) - индексированная локальная переменная
3. ˆname - глобальная переменная
4. ˆname(a,b,...) - индексированная глобальная переменная
5. $name - системная переменная
6. $name(a,...) - системная функция
7. $$name - пользовательская переменная в текущей рутине
8. $$name(a,...) - пользовательская функция в текущей рутине
9. $$nameˆrname - пользовательская переменная в рутине rname
10. $$nameˆrname(a,...) - пользовательская функция в рутине rname
Операторы языка по своему действию могут быть сгруппированы по различным критериям, наиболее часто используется критерий группиро­вания по типу действия - арифметические (численные), строковые (ли­теральные), логические (булевские).
60 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Формально, такое деление условно и не строгое, поскольку строковые и арифметические операторы могут быть использованы для вычисления значения используемого как логическое условие, а логические операторы могут быть использованы для вычисления строкового значения ("1" или "0").
Арифметические операторы выполняют действия над операндами рас­сматривая их как числа и выполняют числовые операции. Множество операторов языка покрывает традиционный для языков программирова­ния набор операций. К таким операторам в языке MUMPS относятся:
1. Унарный плюс (+), применяется к аргументу справа от оператора, приводит аргумент к числовому значению.
2. Унарный минус (-), применяется к аргументу справа от оператора, приводит аргумент к числовому значению и меняет знак на проти­воположный.
3. Сложение (+), возвращает арифметическую сумму операндов.
4. Вычитание (-), возвращает арифметическую разность левого и пра­вого операндов.
5. Умножение (*), возвращает произведение операндов.
6. Деление (/), возвращает отношение левого и правого операндов.
7. Целочисленное деление (\), возвращает целую часть отношения левого и правого операндов.
8. Возведение в степень (**), возвращает результат возведения левого операнда в степень равную второму операнду.
9. Деление по модулю (#), возвращает остаток от деления нацело первого операнда на второй операнд.
10. Больше (>), возвращает булевское значение числового сравнения операндов, проверяет что левый операнд арифметически больше второго.
11. Меньше (<), возвращает булевское значение числового сравнения операндов, проверяет что левый операнд арифметически меньше второго.