Перейти к основному содержимому
Версия: 7.0

Метапрограммирование

Метапрограммирование - это вид программирования, связанный с написанием программного кода, который в качестве результата порождает другой программный код. Метапрограммирование используется для повторной используемости кода и ускорения времени разработки.

Метакод​

В языке lsFusion в качестве средства метапрограммирования используется метакод, который описывается инструкцией META. Метакод состоит из заголовка и блока кода на языке lsFusion, описывающего последовательность инструкций. Этот блок кода должен завершаться ключевым словом END. Рассмотрим пример метакода, который позволяет добавить на произвольную форму два действия:

META addActions(formName)
EXTEND FORM formName
PROPERTIES() showMessage, closeForm
;
END

В первой строке приведенного примера находится заголовок метакода. Он состоит из ключевого слова META, имени метакода и списка параметров. В данном примере метакод addActions имеет один параметр formName. Это имя формы, на которую будут добавлены действия. Рассмотрим возможные варианты использования этого метакода, которые описываются инструкцией @.

@addActions(documentForm);
@addActions(orderForm);

Инструкция использования метакода обозначается специальным символом @, затем идет имя метакода и передаваемые параметры. При генерации кода каждый параметр метакода будет заменен на значение, передаваемое в качестве параметра инструкции @, во всех местах использования параметра метакода. В данном примере параметр метакода formName будет заменяться на documentForm и на orderForm. Приведенные выше использования метакода порождают следующий блок кода:

EXTEND FORM documentForm
PROPERTIES() showMessage, closeForm
;

EXTEND FORM orderForm
PROPERTIES() showMessage, closeForm
;

Объединение лексем​

Простой подстановки идентификатора вместо параметра метакода часто бывает недостаточно. Например, при создании большого количества новых элементов системы внутри метакода нужно иметь возможность задавать эти новые имена. Передавать все имена в качестве параметров метакода бывает неудобно. Поэтому в метакоде существует специальная операция ##, которая работает на уровне лексем. Эта операция может объединить две соседние лексемы в одну. Если же одна из объединяемых лексем является строковым литералом, то результатом объединения будет один строковый литерал.

META objectProperties(object, caption)
object##Name 'Имя '##caption = DATA BPSTRING[100](object);
object##Type 'Тип '##caption = DATA Type (object);
object##Value 'Стоимость '##caption = DATA INTEGER (object);
END

@objectProperties(Document, 'документа');

Результатом использования метакода objectProperties будет следующий код:

DocumentName 'Имя документа' = DATA BPSTRING[100](Document);
DocumentType 'Тип документа' = DATA Type (Document);
DocumentValue 'Стоимость документа' = DATA INTEGER (Document);

Также существует специальная операция ###, эквивалентная операции ##, за исключением того, что во второй из объединяемых лексем первый символ, если он является буквой, переводится в верхний регистр.

к сведению

При использовании операции ### действует одно исключение. Если все лексемы слева от текущей операции ### после подстановки параметров оказываются пустыми, и все объединение не начинается с операции ###, то первая буква следующей лексемы не переводится в верхний регистр.

prefix###name -> name // если prefix пустой

Чтобы получить заглавную букву в этой ситуации, нужно добавить перед всем объединением ###:

###prefix###name -> Name // если prefix пустой

Примеры​

META objectProperties(object, type, caption)
object##Name 'Имя'##caption = DATA BPSTRING[100](###object); // делаем заглавной первую букву
object##Type 'Тип'##caption = DATA type (###object);
object##Value 'Стоимость'##caption = DATA INTEGER (###object);
END

META objectProperties(object, type)
@objectProperties(object, type, '');
END