AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 16.11.2007, 04:23   #1  
Blog bot is offline
Blog bot
Участник
 
25,631 / 848 (80) +++++++
Регистрация: 28.10.2006
axaptapedia: Macro
Источник: http://www.axaptapedia.com/Macro
==============

Summary: New page: originated at [http://blogs.msdn.com/x/archive/2007...-of-1-etc.aspx Issues concerning X++ : Macros - Definitions and Pitfalls] == Macros - Definitions and Pitfalls ...
originated at [http://blogs.msdn.com/x/archive/2007...-of-1-etc.aspx Issues concerning X++ : Macros - Definitions and Pitfalls]

== Macros - Definitions and Pitfalls ==

The [[X++]] language features a macro expansion facility. With it, you can define macros, use macro values, do conditional compilation etc. In this blog I'll describe the semantics of the constructs and provide some guidance to resolve some of the problems beginners and experts alike are having with this language feature.

Macros are unstructured in that they are not defined by the grammar of the language. The handling of macros takes place before the text reaches the compiler.

Macros may appear inside methods and class declarations anywhere that white space is permitted, and may also appear after the ending } in class definitions.

The semantics of each of the macro keywords are described below:
=== Macro constructs ===

==== #define ====

The syntax is


#define.MyName(SomeValue)


This defines a macro called MyName with the value SomeValue. When this definition is in effect, any references to #MyName will be replaced with the character sequence SomeValue. The definition has no other semantics aside from defining the symbol MyName: The text does not reach the compiler itself. When the compilation of the current method is over, the symbol (MyName in this case) is no longer remembered. If the symbol is already defined, the old value is discarded and replaced by the new value.

==== #globaldefine ====
The syntax is


#globaldefine.MyName(SomeValue)


This has the same semantics as #define, described above.

==== #definc ====
The syntax is


#definc.MyName


This macro construct is used mainly when the value is a integer value. The preprocessor will increment the value of the symbol by one. If the value was not defined before the #definc occurs, an error is issued by the compiler. If the value before the #definc is not an integer, the old value will be overwritten with the value 0 and then incremented, yielding the value 1.

==== #defdec ====
The syntax is


#defdec.MyName


This macro construct is used mainly when the value is a integer value. The preprocessor will decrement the value of the symbol by one. If the value was not defined before the #defdec occurs an error is issued by the compiler. If the value before the #defdec is not an integer, the old value will be overwritten with the value 0 and then decremented, yielding the value -1.


==== #undef ====
The syntax is

#undef.MyName


The effect of this is to remove the symbol MyName from the list of current macro definitions. It is not considered an error to remove a symbol that has not previously been #defined.

==== #if ... #endif ====
The syntax is


#if.MySymbol

#endif


Or


#if.MySymbol(SomeValue)

#endif


In the first case the textual content marked with … in the examples above is inserted into the source stream if MySymbol has previously been defined. In the second case, the content is inserted into the source stream if and only if the symbol is defined and has the indicated value.

The #if constructs may be nested to any level but there is no #else construct.


==== #ifnot ... #endif ====
The syntax is


#ifnot.MySymbol

#endif


Or


#ifnot.MySymbol(SomeValue)

#endif


In the first case the textual content marked with … in the examples above is inserted into the source stream if MySymbol has not been defined. In the second case, the content is inserted into the source stream if the symbol is not defined or is defined but does not have the indicated value.

The #if constructs may be nested to any level. There is no #else construct.

==== #macrolib ====

The syntax is


#macrolib.MyName


The name must denote a node in the macros branch of the AOT. The text in that node is processed by the preprocessor. The net effect is to insert the content of the named macro in the source text where the directive appears. It is an error if the node is not found in the macros branch in the AOT.

==== #macro / #localmacro ====

The keywords #macro and #localmacro are interchangeable; there is no difference in the semantics of the two. This construct is used to define a symbol to denote textual content possibly spanning several lines.

The syntax is


#localmacro.MySymbol
….
#endmacro


Example:

class MyBaseClass extends Runbase
{
int v1;
#define.myMacro(“Hello world”)
#localmacro.currentlist
v1
#endmacro

public container pack()
{
return [#currentlist]; // #currentlist expands to v1
}

public void run()
{
print #myMacro; // #myMacro expands to “Hello world”
}
}

class MyDerivedClass extends myBaseClass
{
int v2;
#localmacro.currentlist
v2
#endmacro


public container pack()
{
return [super(), #currentlist]; // #currentlist expands to v2
}

public void run()
{
print #myMacro; // #myMacro expands to “Hello world”
}
}


==== #MySymbol ====

The syntax is


#MySymbol


This inserts the value of the symbol into the source stream. It is an error to refer to a symbol that has not been defined.
If the name denotes a node in the macros branch of the AOT, the text in that node is processed by the preprocessor (in this case #MySymbol is a shorthand for #macrolib.MySymbol).

=== Common Problems ===

In this part of the blog post, I'd like to describe some of the problems programmers have when dealing with macros.
Macro parameters
It seems to be a little known fact and a source of some confusion that macros can be parametrized: Values can be given to the % placeholders at the macro expansion site. Simple textual substitution of the positional parameter with the given, actual parameter then takes place. If no parameter is supplied, the empty string is used. So


#define.MyString("Hello World from %1")


will define a named macro (MyString) with one parameter. If that macro is expanded as shown below:


#MyString(X++)


the resulting string will be


"Hello World from X++"


Note that the place of expansion did not supply the letters X++ inside quotes. That would have generated a compiletime error:


#MyString("X++")


would have generated


"Hello World from "X++""


That is what is meant by simple string substitution.

The confusion can also occur because the % notation is also used for parameter substitution in the strFmt string formatting function. As you know, this function has a variable length parameter list, and each reference of %n in the first argument (a string) will be expanded to contain a textual representation of the n'th argument, as shown below:


print strfmt("The value is %1", theValue);


Now, some programmers have been known to want to specify the first argument, i.e. the string containing the substitutions, with a macro symbol:


#define.TheText("The value is %1")
print strfmt(#TheText, theValue);


But, the macro substition kicks in before the compiler sees the source code. The macro substition engive will not find a parameter to place where the %1 is, so the compiler will see:


print strfmt("The value is ", theValue);


which is probably not what the programmer intended.

It can be avoided by escaping the percent character with backslash


#define.TheText("The value is \%1")
print strfmt(#TheText, theValue);


this is equivalent of code


print strfmt("The value is \%1", theValue);


You can also mix escaped and not escaped placeholders


static void Job1(Args _args)
{
#define.TheText("The value of %1 is '\%1'")
;
info(strFmt(#TheText(the variable), "one"));
}


Output of this job is:

The value of the variable is 'one'

=== Macros in class declarations ===

Some confusion stems from the situation where macros are defined in class declarations. In order to understand how this is handled it is useful to review what the compiler does when it compiles a method. It starts by calculating the sequence of class derivations that the class is part of. It then parses each of the class declarations with the least derived one first, filling its internal symbol table with the macros as it goes along. After compiling the most local class declaration (the most derived one) the compiler compiles the method itself. Any symbol defined in any of the class declarations will subsequently be available for use in the methods. Symbols defined in a class declaration may be replaced by values defined in more derived class declarations.
Parenthesis in macro strings

The scanner dealing with macro strings is quite simple minded. It will not handle the situation where closing parenthesis characters are included in the string. So,


#define.Another("(This is text in parenthesis)")


will generate a compiler lexical error. If you need to do this, you should use the #localmacro directive instead:


#localmacro.Another
"(This is text in parenthesis)"
#endmacro


In this context the end of the macro is signalled by the #endmacro string, not a right parenthesis.

=== Macro patterns ===
*[[Abstract macro]]
*[[Macrolabel]]


Источник: http://www.axaptapedia.com/Macro
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
Старый 16.11.2007, 09:48   #2  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2925 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
просто скопировано отсюда с разрешения авторов (плюс чуть дописал от себя)
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
axaptapedia: RunBaseBatch Blog bot DAX Blogs 0 04.04.2009 22:05
axaptapedia: RunBaseBatch Blog bot DAX Blogs 0 31.03.2009 06:06
axaptapedia: Macrolabel Blog bot DAX Blogs 0 16.11.2007 04:23
casperkamal: #InventDimDevelop macro in Dynamics Ax Blog bot DAX Blogs 1 03.05.2007 08:42

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 13:31.