Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:MUMPS СУБД. Практика применения и опыт программирования.pdf
X
- •Предисловие
- •Введение
- •Среда исполнения
- •Команды
- •Команды присваивания
- •Условные команды
- •Команды передачи управления
- •Команды ввода-вывода
- •Служебные команды
- •Постусловия
- •Операторы
- •Переменные
- •Числа и строки
- •Функции
- •$DATA
- •$GET
- •$ORDER
- •$NEXT
- •$QUERY
- •$NAME
- •$QLENGTH
- •$QSUBSCRIPT
- •$ASCII
- •$CHAR
- •$EXTRACT
- •$PIECE
- •$LENGTH
- •$REVERSE
- •$FIND
- •$TRANSLATE
- •$JUSTIFY
- •$FNUMBER
- •$TEXT
- •$RANDOM
- •$VIEW
- •$SELECT
- •$STACK
- •Списковые функции
- •Битовые функции
- •Модули
- •Рутины
- •Передача параметров
- •Неопределенные значения
- •Шаблоны
- •Косвенность
- •Косвенность имени
- •Косвенность индексов
- •Косвенность метки
- •Косвенность аргумента
- •Косвенность шаблона
- •Интерпретатор
- •Голая ссылка
- •Очередность выполнения
- •Очередность вычисления выражений
- •Очередность вычисления имен
- •Стекование $test
- •Комментарий
- •Стандарт и расширения
- •Глобалы
- •B-дерево
- •Кодирование индексов
- •Размер блока
- •Кеширование блоков
- •Структуры
- •Индексация
- •Группировка
- •Каноничность индексов
- •Маппинг
- •Индексация данных
- •Общие принципы
- •Механизм поддержки индекса
- •Простой индекс
- •Составной индекс
- •Покрывающий индекс
- •Кластерный индекс
- •Хеш-индекс
- •Битмап индекс (bitmap)
- •Битслайс индекс (bitslice)
- •Нормирование значений
- •Выборки по индексу
- •Многоиндексная выборка (zig-zag)
- •Дифференциальное индексирование
- •Индексация длинных атрибутов
- •Межтабличный индекс
- •Индекс с условием на вставку
- •Индекс на вычисляемый атрибут
- •Индекс поиска по фрагменту
- •Индексация для шаблона (like)
- •Индексация уникального атрибута
- •Массовое перестроение индексов
- •Операции с древовидными индексами
- •Операции с битовыми индексами
- •Сортировка по индексу
- •Статистики и кардинальность
- •Конкурентный доступ
- •Параллельность выполнения
- •Блокировки
- •Функция $INCREMENT
- •Транзакции
- •Блокировки в транзакциях
- •Функция $BIT
- •Дедлоки
- •Обработка ошибок
- •Состояние ошибки
- •ZTRAP
- •GT.M
- •MiniM
- •ETRAP
- •Определение
- •$ETRAP
- •$ECODE
- •$ESTACK
- •Ошибки в обработчике ошибок
- •$STACK()
- •Трассировка
- •BREAK
- •MiniM Debugger
- •Serenji Debugger
- •Внешний мир
- •Общие принципы
- •Терминальный интерфейс
- •Сокеты
- •HTTP клиент
- •Вебсервер на MUMPS
- •WebLink
- •Проблемы HTTP
- •Поверх HTTP
- •Подключаемые DLL (SO)
- •Файлы
- •Внешние процессы
- •Порты
- •Практика применения
- •Терминальный режим
- •Редакторы рутин
- •Экспорт и импорт
- •Препроцессор
- •Формат $HOROLOG
- •Опции устройств
- •$X и $Y
- •Возврат результатов
- •Возврат по значению ($$)
- •Возврат по ссылке
- •Запись в предопределенную переменную
- •Возврат значений косвенно
- •Итеративный возврат
- •Потоковый возврат
- •%Z - рутины
- •Планирование файлов
- •Память и сборка мусора

1.13. КОСВЕННОСТЬ 151
check(value)
d @$s(value#2:"odd",1:"even")
q
even
w "subroutine for even values",!
q
odd
w "subroutine for odd values",!
q
Здесь, в зависимости от того, является значение value четным или
нечетным, вызываются различные подпрограммы.
Косвенность метки позволяет разработчикам на MUMPS, в отличие
от многих других языков программирования, использовать вычисляемый
GOTO, когда метка для перехода вычисляется выражением или подпрограммой произвольной сложности, включая использование настроек в
глобалах, и результат в силу позднего связывания системы выполнения может указывать куда угодно. В случае если в действительности к
моменту выполнения такой метки не найдено, система выполнения генерирует ошибку.
В частности, такой обобщенный механизм может использоваться в
системах, выполняющих проверку прав пользователей, выполнения кода в зависимости от типа применяемой MUMPS системы, выполнения
меток, передаваемых от клиентской программы, и во многих других задачах.
Косвенность метки может быть использована в любом месте, где синтаксически по контексту ожидается метка. Вычисление значения происходит перед использованием метки. В случае если само выражение также содержит операторы косвенности, то выражение продолжает развертываться до тех пор, пока не будет развернуто и вычислено полностью.
После этого значение проверяется синтаксически и MUMPS система использует соответствующие указанные в значении фрагменты метки.
1.13.4 Косвенность аргумента
Косвенностью аргумента команды называется применение команды к вычисленному содержанию выражения. Сама форма косвенности в свою
очередь также является допустимым аргументом, поэтому язык MUMPS
допускает синтаксическую рекурсию косвенности аргументов произвольной сложности.
При применении команды к косвенно заданному аргументу сначала
вычисляется выражение, и затем его значение используется как аргумент

152 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
команды. В значении могут быть указаны через запятую последовательность нескольких аргументов, в этом случае команда применяется к ним
последовательно слева направо так же, как если бы они были указаны
явно.
Примеры косвенного указания аргумента команды:
s arg="#,123,!"
w @arg
w @(^Settings(123))
s if="count,total"
i @if ...
Все стандартные команды языка поддерживают косвенность аргумента кроме команды FOR. Кроме того, производители MUMPS систем поддерживают дух MUMPS с возможностью задать аргумент косвенно в
том числе и для расширенных дополнительных команд.
Например, многие MUMPS системы поддерживают семейство команд
ZLOAD / ZSAVE / ZREMOVE, в аргументе которых указывается отдельная синтаксическая конструкция, отсутствующая в определении стандартного языка - имя рутины, соответствующее фрагменту определения
метки. Например:
ZLOAD EXTEN2
ZSAVE VIEW5
Здесь идентификаторы EXTEN2 и VIEW5 MUMPS система воспринимает по контесту, как имена рутин. Чтобы передать командам имя рутины, которое содержится в переменной, нужно применить косвенность
аргумента команд ZLOAD и ZSAVE:
s name="EXTEN2"
ZLOAD @name
s name="VIEW5"
ZSAVE @name
Общее правило развертывания косвенностей аргументов определено
в таком виде, что является некоторым (не полным) аналогом команде
XECUTE со скрытым специальным конструированием аргумента путем
добавления имени команды, например некоторым аналогом может быть
замена
w @arg -> x "w "_arg
s @arg -> x "s "_arg

1.13. КОСВЕННОСТЬ 153
Многие реализации MUMPS систем для снижения трудоемкости выполнения системы именно таким способом и воспользовались. В случае
если применяемая MUMPS система выполнена именно так, то нужно
быть очень внимательным к ее реальному поведению и обязательно проверить соответствуют ли MUMPS система задачам которые необходимо
выполнить. Отличие косвенности аргумента от выполнения тех же действий командой XECUTE состоит в проверке допустимости синтаксиса
как аргумента именно этой команды, в создании командой XECUTE дополнительного уровня стека и в характере диагностики в случае ошибки.
Как это проверить - нужно подставить в аргумент команды, передаваемый косвенно, кроме синтаксически корректного для этой команды
аргумента, дополнительно пробел и другую команду, или несколько, с
возможными аргументами. Согласно стандарта языка, MUMPS система должна отказаться выполнять такой аргумент команды, поскольку
он не соответствует команде синтаксически. Во-вторых, такая передача дополнительных команд случайно выполнить недопустимый с точки
зрения безопасности приложения код. И, в-третьих, даже при передаче
безопасного кода система может переключиться в некорректное состояние, например изменить область видимости переменных и нарушить не
данные, а ход выполнения процесса.
Кроме того, при выполнении такого синтаксически некорректного аргумента MUMPS система может дать диагностическое сообщение об
ошибке, реально соответствующее лишь внутреннему состоянию эмулятора, не указывая на реальную ошибку.
Другим пунктом, который может потребовать проверки соответствуют ли применяемая система и код на MUMPS который предстоит ей
выполнять, является возможность вложений косвенности. Случай с бесконечной рекурсией, очевидно, не может быть выполнен в техническом
отношении в конечном итоге, независимо от архитектуры MUMPS системы, но какое-то количество уровней косвенности может понадобиться
для приложения. Для проверки этого пункта нужно проверить, корректно ли MUMPS система выполняет необходимые вложения сочетаний,
используемых видов косвенностей, и аргументов команды XECUTE.
1.13.5 Косвенность шаблона
Косвенность шаблона является, видимо, наиболее простой формой косвенности. В этом случае вычисляемое выражение, к которому применен
оператор косвенности, трактуется как шаблон. Например:
USER>s pat="1E"

154 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
USER>w 1?@pat
1
USER>w 12?@pat
0
При этом, в отличие от метки, косвенность в шаблонах синтаксически
не допускается для отдельных его фрагментов, шаблон всегда должен
быть задан целиком либо по месту применения, либо целиком в виде
результата вычисления выражения.
Операторы косвенности вместе с командой XECUTE образуют основное препятствие для построения MUMPS системы в виде строго компилирующей системы, работающей с кодом, точный алгоритм которого
может быть определен на этапе трансляции.
При этом косвенность образует очень сильное средство для построения модулей инструментального характера, модулей с обобщенными алгоритмами, с развитыми настройками. Механизм косвенности MUMPS
дает намного больше возможностей, чем другие языки, включая методы,
не применимые в других языках.
Как иллюстративный пример можно привести построение систем,
ориентированных на консольный алфавитно-цифровой ввод-вывод. Различные терминальные устройства могут иметь различные последовательности операций, которые необходимо выполнять для одних и тех же
действий. Для таких терминалов можно вести глобал с настройками, в
которых хранятся выполняемые для этих терминалов команды или аргументы команд. Для добавления еще одного типа терминала в этом
случае будет достаточно добавить соответствующие ему настройки.
Как еще одну иллюстрацию можно привести применение функций
с обобщенными алгоритмами, которые описывают непосредственно сам
алгоритм, но с использованием косвенности могут быть применены к
самым различным данным. В частности, к обобщенным алгоритмам относятся операции на индексных структурах.
1.14 Интерпретатор
Как уже было описано в разделе косвенности, язык MUMPS содержит
определения синтаксических конструкций, не позволяющих выполнить
систему выполнения кода по схеме традиционных компиляторов с одним только неизменяемым исполняемым кодом. Этому препятствуют и
операции косвенности, и команда XECUTE.
Все имеющиеся реализации MUMPS систем в той или иной мере являются интерпретаторами. Это либо интерпретаторы интерпретирующего

1.14. ИНТЕРПРЕТАТОР 155
типа или интерпретаторы компилирующего типа или комбинированные.
Интерпретаторы интерпретирующего типа получают на входе строку, разбирают ее и выполняют. Интерпретаторы компилирующего типа
получают исходный код и транслируют в промежуточный байткод, который уже может быть исполнен виртуальной машиной интерпретатора.
Интерпретаторы комбинированного типа сочетают эти две возможности,
например весь код может быть странслирован в команды процессора, но
при выполнении косвенности или команды XECUTE система выполнения
переходит к режиму интерпретатора, или одна строка может целиком
транслироваться в байткод, выполняться, но полученный промежуточный байткод не сохраняется для дальнейшего использования.
Большинство современных реализаций MUMPS систем строятся как
интерпретаторы компилирующего типа, включая генерацию промежуточного нехранимого байткода для команды XECUTE. Такой режим работы
обеспечивает наибольшую скорость работы в сочетании с соблюдением
требований языка, или наилучший баланс возможности / производительность.
При генерации байткода разработчики различных систем используют различные собственные определения состояний виртуальной машины исполнения, коды, схему преобразований, форматы компилированных
рутин.
В укрупненном виде байткод, получаемый трансляцией рутины, состоит из нескольких секций - секция заголовка, описывающая размещение других секций, секция констант, секция строк помещенных целиком,
секция списка меток, секция последовательности байткодов строк и другие, в зависимости от реализации.
Основная схема работы интерпретатора строится на модели виртуальной машины - регистровая или стековая. Определение языка MUMPS
наиболе близко к определению стековой машины. Для такой машины исполнения кроме обычного стека фреймов для работы подпрограмм поддерживается стек вычисления. Это внутренняя структура, недоступная
для языка.
Для стека вычислений поддерживаются операции положить на стек
значение, целое число, метку или имя, и взять со стека значение, целое
число, метку или имя. Определение значения может варьироваться также в зависимости от реализации MUMPS системы, например это может
быть структура содержащая тип значения и само значение кодированное
в соответствии с используемым типом.
Для всего набора элементарных действий для виртуальной машины
определяются коды операций. Например, пусть будет определена виртуальная машина с кодами операций:

156 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
Код операции Действие
op_const Взять следующий байт и, считая его номером кон-
станты, взять из секции констант значение и поместить его на стек.
op_plus Взять со стека два значения, сложить и поместить
результат на стек.
op_mult Взять со стека два значения, умножить и поместить
результат на стек.
op_horolog Вычислить значение даты и времени в формате
$HOROLOG и поместить значение на стек.
op_concat Взять со стека два значения, выполнить конкатена-
цию и поместить результат на стек.
op_writestr Взять со стека значение, привести к строке и вывести
в текущее устройство.
op_writenl Вывести в текущее устройство перевод строки.
op_lenght_2 Взять со стека значение, привести к строке, вычис-
лить длину и результат поместить на стек как значе-
ние.
Используя такую виртуальную машину, можно подать ей на трансля-
цию и затем на выполнение уже несколько заданий:
1) write $h,!
2) write 12+45*78,!
3) write 123_456_789,!
При трансляции строки
write $h,!
получаем последовательность байткодов:
1) op_horolog
2) op_writestr
3) op_writenl
При их последовательносм выполнении сначала вычисляется значение $H, заносится на стек, затем значение вынимается со стека и выводится в текущее устройство, затем в текущее устройство выводится
перевод строки.
При трансляции строки
write 12+45*78,!

1.14. ИНТЕРПРЕТАТОР 157
получаем последовательность байткодов:
1) op_const
2) 1
3) op_const
4) 2
5) op_plus
6) op_const
7) 3
8) op_mult
9) op_writestr
10)op_writenl
и соответствующую ей таблицу констант:
1 12
2 45
3 78
При их последовательном выполнении виртуальная машина выполня-
ет следующие действия при пустом начальном стеке вычисления:
1. op_const, 1: Берет константу номер 1 (значение по таблице = 12) и
помещает на стек. Состояние стека
12
2. op_const, 2: Берет константу номер 2 (значение по таблице = 45) и
помещает на стек. Состояние стека
45
12
3. op_plus: Берет со стека два значения, состояние стека пусто (в данном примере записи на стеке кончились). Вычисляет сумму (получается 57) и помещает значение на стек, состояние стека
57
4. op_const, 3: Берет константу номер 3 (значение по таблице = 78) и
помещает на стек. Состояние стека
78
57
5. op_mult: Берет со стека два значения, состояние стека пусто (в
данном примере записи на стеке кончились). Вычисляет произведение (получается 4446) и помещает значение на стек, состояние
стека

158 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
4446
6. op_writestr: Берет со стека значение, состояние стека - пусто. Значение приводится к строке и выводится в текущее устройство. Состояние стека - пусто.
7. op_writenl: Выводит в текущее устройство перевод строки, состояние стека - пусто.
Третий пример транслируется соответственно в последовательность
байткодов:
1) op_const
2) 1
3) op_const
4) 2
5) op_concat
6) op_const
7) 3
8) op_concat
9) op_writestr
10)op_writenl
и соответствующую таблицу констант:
1 123
2 456
3 789
Соответственно, при последовательном выполнении такого байткода
со стеком вычисления производятся операции:
1. На стек помещается значение 123.
2. На стек помещается значение 456.
3. Со стека снимаются два значения, стек пуст.
4. На стек помещается значение 123456.
5. На стек помещается значение 789.
6. Со стека снимается два значения, стек пуст.
7. На стек помещается значение 123456789.
8. Со стека снимается значение.

1.14. ИНТЕРПРЕТАТОР 159
Последнее снятое со стека значение выводится в текущее устройство,
и следом выводится символ перевода строки.
Примерно по такой схеме выполняется большинство стековых виртуальных машин. Реальная виртуальная машина дополнительно поддерживает более сложные записи на стек, такие как вычисленная метка для
выполнения перехода или вызова подпрограммы, и вычисленное имя для
взятия значения переменной или для записи.
Реальная виртуальная машина должна будет поддерживать не операцию взять со стека значение, а взять со стека то что там есть и по нему
вычислить значение. В частности, там может оказаться не само значение, а имя переменной или индикатор голой ссылки. При этом для множества команд и функций требуется передавать не значения, а именно
вычисленные имена переменных, например для функции $INCREMENT,
$NAME или $ORDER.
В определении языка MUMPS описаны несколько функций, которые
поддерживают несколько форм, например функции $GET, $PIECE. Для
них виртуальная машина должна сгенерировать код исполнения или на
каждую поддерживаемую форму, или единый байткод для все форм, но
для сокращенных вариантов дополнительно генерировать код вычисления значения по умолчанию.
Структурно система исполнения виртуальной машины интерпретатора состоит из цикла выборки следующего байткода, помещения на стек и
взятия со стека значений, имен, констант, и набора собственно исполняющих функций, выполняющих непосредственно операции со значениями
и именами, например функции сложения, конкатенации, вычисления $H,
вывода значения в текущее устройство.
У каждой виртуальной машины, если она не стандартизирована, определение таких операций собственное. Существуют относительно стандартизированные виртуальные машины исполнения интерпретаторов, например виртуальные машины Java, .NET, Lua. Для таких машин возможна трансляция других языков программирования в их байткод для
того чтобы эти виртуальные машины использовались для выполнения
как готовые. Для систем выполнения MUMPS такие стандарты на формат исполняемых бйткодов официально не поддерживаются и построение системы исполнения полностью определяет производитель MUMPS
системы.
Сам генератор байткода по исходному тексту опирается на определение языка, данное для каждой синтаксической конструкции. Рассмотрим
парсинг с кодогенерацией на примере разбора выражения. Выражение в
языке MUMPS определено так:

160 ГЛАВА 1. СРЕДА ИСПОЛНЕНИЯ
expr := expratom [exprtail]
Это означает что для парсинга выражения (expr) необходимо сначала выполнить парсинг expratom, а затем, если есть символы, то парсинг
exprtail. В свою очередь, определение expratom состоит из двух альтернатив:
expratom := | glvn |
| expritem |
Здесь glvn - определение синтаксической единицы глобальной или
локальной переменной, expritem - самостоятельная синтаксическая единица.
При наличии альтернатив парсер выполняет просмотр дальнейшего
текста на предмет соответствует ли дальнейший текст определению первой альтернативы. При этом может выполняться также параллельная
кодогенерация для вычисления этой альтернативы. Если кодогенерация
альтернативы не получилась, то парсер восстанавливает свое состояние
на момент начала разбора альтернативы и переходит к следующей. И
так далее, пока не кончатся альтернативы.
Если ни одна альтернатива не подошла, то парсер возвращает на
предыдущий уровень парсинга состояние неудачи парсинга. Если на каком - либо уровне парсинга транслятор может принять решение о том,
что отсутствие альтернатив парсинга означает синтаксическую ошибку,
то может вывести сообщение о синтаксической ошибке. В большинстве
случаев это касается неудачи разбора последней альтернативы.
В рассматриваемом примере определение expritem состоит из перечня
более детальных альтернатив, соответствующих вычислению значений:
expritem := | strlit | константная строка
| numlit | константное число
| exfunc | пользовательская функция
| exvar | пользовательская переменная
| svn | системная переменная
| function | системная функция
| unaryop expratom | унарный оператор с
последующим expratom
| (expr) | открывающая круглая скобка,
последующий элемент
в определении
expr, с последующей
закрывающей круглой скобкой
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
