123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
- <sect1 id="MACRO_Structure">
- <title>MACRO Structure<indexterm>
- <primary>MACRO Structure</primary>
- </indexterm></title>
- <para><emphasis>[</emphasis><emphasis>resulttype</emphasis><emphasis
- role="bold">]</emphasis><emphasis> macroname </emphasis><emphasis
- role="bold">(</emphasis><emphasis> parameterlist </emphasis><emphasis
- role="bold">) := MACRO</emphasis><emphasis role="bold"><indexterm>
- <primary>MACRO</primary>
- </indexterm> </emphasis><emphasis></emphasis></para>
- <para><emphasis> tokenstream</emphasis>;<emphasis
- role="bold"></emphasis></para>
- <para><emphasis role="bold">ENDMACRO<indexterm>
- <primary>ENDMACRO</primary>
- </indexterm>;</emphasis></para>
- <informaltable colsep="1" frame="all" rowsep="1">
- <tgroup cols="2">
- <colspec align="left" colwidth="122.40pt" />
- <colspec />
- <tbody>
- <row>
- <entry><emphasis>resulttype</emphasis></entry>
- <entry>Optional. The result type of the macro. The only valid type
- is DATASET. If omitted and the <emphasis>tokenstream</emphasis>
- contains no Attribute definitions, then the macro is treated as
- returning a value (typically INTEGER or STRING).</entry>
- </row>
- <row>
- <entry><emphasis>macroname</emphasis></entry>
- <entry><para>The name of the function the MACRO structure
- defines.</para></entry>
- </row>
- <row>
- <entry><emphasis>parameterlist</emphasis></entry>
- <entry>A list of names (tokens) of the parameters that will be
- passed to the macro. These names are used in the
- <emphasis>tokenstream</emphasis> to indicate where the passed
- parameters are substituted when the macro is used. Value types for
- these parameters are not allowed, but default values may be
- specified as string constants.</entry>
- </row>
- <row>
- <entry><emphasis>tokenstream</emphasis></entry>
- <entry>The Attribute definitions or Actions that the macro will
- perform.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- <para>The <emphasis role="bold">MACRO </emphasis>structure makes it possible
- to create a function without knowing the value types of the parameters that
- will eventually be passed to it. The most common use would be performing
- functions upon arbitrary datasets.</para>
- <para>A macro behaves as if you had typed the
- <emphasis>tokenstream</emphasis> into the exact position you use it, using
- lexical substitution—the tokens defined in the
- <emphasis>parameterlist</emphasis> are substituted everywhere they appear in
- the <emphasis>tokenstream </emphasis>by the text passed to the macro. This
- makes it entirely possible to write a valid MACRO definition that could be
- called with a set of parameters that result in obscure compile time
- errors.</para>
- <para>There are two basic type of macros: Value or Attribute. A Value macro
- does not contain any Attribute definitions, and may therefore be used
- wherever the value type it will generate would be appropriate to use. An
- Attribute macro does contain Attribute definitions (detected by the presence
- of the := in the <emphasis>tokenstream</emphasis>) and may therefore only be
- used where an Attribute definition is valid (a line by itself) and one item
- in the <emphasis>parameterlist</emphasis> should generally name the
- Attribute to be used to contain the result of the macro (so any code
- following the macro call can make use of the result).</para>
- <para>Example:</para>
- <programlisting>// This is a DATASET Value macro that results in a crosstab
- DATASET CrossTab(File,X,Y) := MACRO
- TABLE(File,{X, Y, COUNT(GROUP)},X,Y)
- ENDMACRO;
- // and would be used something like this:
- OUTPUT(CrossTab(Person,person.per_st,Person.per_sex))
- // this macro usage is the equivalent of:
- // OUTPUT(TABLE(Person,{person.per_st,Person.per_sex,COUNT(GROUP)},
- // person.per_st,Person.per_sex)
- //The advantage of using this macro is that it can be re-used to
- // produce another cross-tab without recoding
- // The following macro takes a LeftFile and looks up a field of it in
- // the RightFile and then sets a field in the LeftFile indicating if
- // the lookup worked.
- IsThere(OutFile ,RecType,LeftFile,RightFile,LinkId ,SetField ) := MACRO
- RecType Trans(RecType L, RecType R) := TRANSFORM
- SELF.SetField := IF(NOT R.LinkId,0,1);
- SELF := L;
- END;
- OutFile := JOIN(LeftFile,
- RightFile,
- LEFT.LinkId=RIGHT.LinkId,
- Trans(LEFT,RIGHT),LEFT OUTER);
- ENDMACRO;
-
- // and would be used something like this:
- MyRec := RECORD
- Person.per_cid;
- Person.per_st;
- Person.per_sex;
- Flag:=FALSE;
- END;
- MyTable1 := TABLE(Person(per_first_name[1]='R'),MyRec);
- MyTable2 := TABLE(Person(per_first_name[1]='R',per_sex='F'),MyRec);
- IsThere(MyOutTable,MyRec,MyTable1,MyTable2,per_cid,Flag)
- // This macro call generates the following code:
- // MyRec Trans(MyRec L, MyRec R) := TRANSFORM
- // SELF.Flag := IF(NOT R.per_cid ,0,1);
- // SELF := L;
- // END;
- // MyOutTable := JOIN(MyTable1,
- // MyTable2,
- // LEFT.per_cid=RIGHT.per_cid,
- // Trans(LEFT,RIGHT),
- // LEFT OUTER );
- OUTPUT(MyOutTable);
- //***********************************************************
- //This macro has defaults for its second and third parameters
- MyMac(FirstParm,yParm='22',zParm='42') := MACRO
- FirstParm := yParm + zParm;
- ENDMACRO;
- // and would be used something like this:
- MyMac(Fred)
- // This macro call generates the following code:
- // Fred := 22 + 42;
- //***********************************************************
- //This macro uses #EXPAND
-
- MAC_join(attrname, leftDS, rightDS, linkflags) := MACRO
- attrname := JOIN(leftDS,rightDS,#EXPAND(linkflags));
- ENDMACRO;
- MAC_join(J1,People,Property,'LEFT.ID=RIGHT.PeopleID,LEFT OUTER')
- //expands out to:
- // J1 := JOIN(People,Property,LEFT.ID=RIGHT.PeopleID,LEFT OUTER);</programlisting>
- <para>See Also: <link linkend="TRANSFORM_Structure">TRANSFORM Structure</link>, <link linkend="RECORD_Structure">RECORD Structure</link>, <link linkend="_UNIQUENAME">#UNIQUENAME</link>,
- <link linkend="_EXPAND">#EXPAND</link></para>
- </sect1>
|