SpecStruc-Macro.xml 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
  4. <sect1 id="MACRO_Structure">
  5. <title>MACRO Structure<indexterm>
  6. <primary>MACRO Structure</primary>
  7. </indexterm></title>
  8. <para><emphasis>[</emphasis><emphasis>resulttype</emphasis><emphasis
  9. role="bold">]</emphasis><emphasis> macroname </emphasis><emphasis
  10. role="bold">(</emphasis><emphasis> parameterlist </emphasis><emphasis
  11. role="bold">) := MACRO</emphasis><emphasis role="bold"><indexterm>
  12. <primary>MACRO</primary>
  13. </indexterm> </emphasis><emphasis></emphasis></para>
  14. <para><emphasis> tokenstream</emphasis>;<emphasis
  15. role="bold"></emphasis></para>
  16. <para><emphasis role="bold">ENDMACRO<indexterm>
  17. <primary>ENDMACRO</primary>
  18. </indexterm>;</emphasis></para>
  19. <informaltable colsep="1" frame="all" rowsep="1">
  20. <tgroup cols="2">
  21. <colspec align="left" colwidth="122.40pt" />
  22. <colspec />
  23. <tbody>
  24. <row>
  25. <entry><emphasis>resulttype</emphasis></entry>
  26. <entry>Optional. The result type of the macro. The only valid type
  27. is DATASET. If omitted and the <emphasis>tokenstream</emphasis>
  28. contains no Attribute definitions, then the macro is treated as
  29. returning a value (typically INTEGER or STRING).</entry>
  30. </row>
  31. <row>
  32. <entry><emphasis>macroname</emphasis></entry>
  33. <entry><para>The name of the function the MACRO structure
  34. defines.</para></entry>
  35. </row>
  36. <row>
  37. <entry><emphasis>parameterlist</emphasis></entry>
  38. <entry>A list of names (tokens) of the parameters that will be
  39. passed to the macro. These names are used in the
  40. <emphasis>tokenstream</emphasis> to indicate where the passed
  41. parameters are substituted when the macro is used. Value types for
  42. these parameters are not allowed, but default values may be
  43. specified as string constants.</entry>
  44. </row>
  45. <row>
  46. <entry><emphasis>tokenstream</emphasis></entry>
  47. <entry>The Attribute definitions or Actions that the macro will
  48. perform.</entry>
  49. </row>
  50. </tbody>
  51. </tgroup>
  52. </informaltable>
  53. <para>The <emphasis role="bold">MACRO </emphasis>structure makes it possible
  54. to create a function without knowing the value types of the parameters that
  55. will eventually be passed to it. The most common use would be performing
  56. functions upon arbitrary datasets.</para>
  57. <para>A macro behaves as if you had typed the
  58. <emphasis>tokenstream</emphasis> into the exact position you use it, using
  59. lexical substitution—the tokens defined in the
  60. <emphasis>parameterlist</emphasis> are substituted everywhere they appear in
  61. the <emphasis>tokenstream </emphasis>by the text passed to the macro. This
  62. makes it entirely possible to write a valid MACRO definition that could be
  63. called with a set of parameters that result in obscure compile time
  64. errors.</para>
  65. <para>There are two basic type of macros: Value or Attribute. A Value macro
  66. does not contain any Attribute definitions, and may therefore be used
  67. wherever the value type it will generate would be appropriate to use. An
  68. Attribute macro does contain Attribute definitions (detected by the presence
  69. of the := in the <emphasis>tokenstream</emphasis>) and may therefore only be
  70. used where an Attribute definition is valid (a line by itself) and one item
  71. in the <emphasis>parameterlist</emphasis> should generally name the
  72. Attribute to be used to contain the result of the macro (so any code
  73. following the macro call can make use of the result).</para>
  74. <para>Example:</para>
  75. <programlisting>// This is a DATASET Value macro that results in a crosstab
  76. DATASET CrossTab(File,X,Y) := MACRO
  77. TABLE(File,{X, Y, COUNT(GROUP)},X,Y)
  78. ENDMACRO;
  79. // and would be used something like this:
  80. OUTPUT(CrossTab(Person,person.per_st,Person.per_sex))
  81. // this macro usage is the equivalent of:
  82. // OUTPUT(TABLE(Person,{person.per_st,Person.per_sex,COUNT(GROUP)},
  83. // person.per_st,Person.per_sex)
  84. //The advantage of using this macro is that it can be re-used to
  85. // produce another cross-tab without recoding
  86. // The following macro takes a LeftFile and looks up a field of it in
  87. // the RightFile and then sets a field in the LeftFile indicating if
  88. // the lookup worked.
  89. IsThere(OutFile ,RecType,LeftFile,RightFile,LinkId ,SetField ) := MACRO
  90. RecType Trans(RecType L, RecType R) := TRANSFORM
  91. SELF.SetField := IF(NOT R.LinkId,0,1);
  92. SELF := L;
  93. END;
  94. OutFile := JOIN(LeftFile,
  95. RightFile,
  96. LEFT.LinkId=RIGHT.LinkId,
  97. Trans(LEFT,RIGHT),LEFT OUTER);
  98. ENDMACRO;
  99. // and would be used something like this:
  100. MyRec := RECORD
  101. Person.per_cid;
  102. Person.per_st;
  103. Person.per_sex;
  104. Flag:=FALSE;
  105. END;
  106. MyTable1 := TABLE(Person(per_first_name[1]='R'),MyRec);
  107. MyTable2 := TABLE(Person(per_first_name[1]='R',per_sex='F'),MyRec);
  108. IsThere(MyOutTable,MyRec,MyTable1,MyTable2,per_cid,Flag)
  109. // This macro call generates the following code:
  110. // MyRec Trans(MyRec L, MyRec R) := TRANSFORM
  111. // SELF.Flag := IF(NOT R.per_cid ,0,1);
  112. // SELF := L;
  113. // END;
  114. // MyOutTable := JOIN(MyTable1,
  115. // MyTable2,
  116. // LEFT.per_cid=RIGHT.per_cid,
  117. // Trans(LEFT,RIGHT),
  118. // LEFT OUTER );
  119. OUTPUT(MyOutTable);
  120. //***********************************************************
  121. //This macro has defaults for its second and third parameters
  122. MyMac(FirstParm,yParm='22',zParm='42') := MACRO
  123. FirstParm := yParm + zParm;
  124. ENDMACRO;
  125. // and would be used something like this:
  126. MyMac(Fred)
  127. // This macro call generates the following code:
  128. // Fred := 22 + 42;
  129. //***********************************************************
  130. //This macro uses #EXPAND
  131. MAC_join(attrname, leftDS, rightDS, linkflags) := MACRO
  132. attrname := JOIN(leftDS,rightDS,#EXPAND(linkflags));
  133. ENDMACRO;
  134. MAC_join(J1,People,Property,'LEFT.ID=RIGHT.PeopleID,LEFT OUTER')
  135. //expands out to:
  136. // J1 := JOIN(People,Property,LEFT.ID=RIGHT.PeopleID,LEFT OUTER);</programlisting>
  137. <para>See Also: <link linkend="TRANSFORM_Structure">TRANSFORM Structure</link>, <link linkend="RECORD_Structure">RECORD Structure</link>, <link linkend="_UNIQUENAME">#UNIQUENAME</link>,
  138. <link linkend="_EXPAND">#EXPAND</link></para>
  139. </sect1>