Abstract macro

Abstract macro

This is a trick which can be done when you need to have multiple places in code which can do different things with the same names.

For example, once I was developing a solution to integrate Dynamics Ax with external system. To enable cross system identification I've introduced the new GUID field to several tables.

It has been set at insert methods of tables, but i need a job for initialisation of the fields of existing data.

Solution

1. Lets declare macro which simply enumerates tables:

#t(InventTable) #t(InventJournalTable)
 * 1) localmacro.tables
 * 1) endmacro

the trick is in #t macro - it is not declared, but used, so you can not apply #tables macro directly and so it called 'abstract'.

It is need to declare the local version of macro to apply the #tables macro

2. Lets declare record variables to each table:

%1 %1;
 * 1) localmacro.t
 * 1) endmacro
 * 2) tables

Here the local version of the #t macro is declared and then the #tables macro is applied, which applies the recently defined #t macro for each table. This fragment generates the following code:

InventTable inventTable; InventJournalTable inventJournalTable;

3. Now we need to update GUID for each table:

ttsBegin; while select forUpdate %1 {       %1.GUID = WinApi::createGUID; }   ttsCommit;
 * 1) localmacro.t
 * 1) endmacro
 * 2) tables

The macro #t is redeclared and the new definition is applied to each table by #tables macro

The resulting code is: static void test_job(Args _args) {   #localmacro.tables #t(InventTable) #t(InventJournalTable) #endmacro #localmacro.t       %1 %1; #endmacro #tables ;   #localmacro.t        ttsBegin; while select forUpdate %1 {           %1.GUID = WinApi::createGUID; }       ttsCommit; #endmacro #tables } If you want to add initialization of extra table - you just insert #t() in the definition of the #tables macro