Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > bd5c3d824c3db63ffd9226c15941e6ad > files > 1459

mozart-1.4.0-1mdv2010.0.i586.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>1.1 Invoking And Defining Macros</TITLE><LINK href="ozdoc.css" rel="stylesheet" type="text/css"></HEAD><BODY><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node1.html">- Up -</A></TD><TD><A href="node3.html#section.macro.module">Next &gt;&gt;</A></TD></TR></TABLE><DIV id="section.call.and.define"><H2><A name="section.call.and.define">1.1 Invoking And Defining Macros</A></H2><P>Oz macros are invoked with the following new syntax: </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">&lt;&lt;</SPAN>repeat&nbsp;5&nbsp;{Show&nbsp;hello}<SPAN class="keyword">&gt;&gt;</SPAN></CODE></BLOCKQUOTE><P> angle brackets delimit a sequence of phrases (expressions and statements). The first element should be an atom (here <CODE>repeat</CODE>) and names the macro to be invoked.</P><P>When the compiler encounters a macro, it invokes the macro-expansion facility. The latter eventually returns a syntactic representation that is guaranteed to no longer contain any macro invocation.</P><P>A macro is implemented by a <EM>macro expander</EM>. This is a function of two arguments: (1) a macro form (a syntactic representation), (2) a macro environment. It returns a transformed syntactic representation. Syntactic representations of Oz code use the ``Syntax Tree Format'' which is described in <A href="../compiler/node7.html#appendix.syntax">Appendix&nbsp;C of ``The Mozart Compiler''</A>.</P><P>Let's define a very simple macro: </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">&lt;&lt;</SPAN>unless&nbsp;B&nbsp;S1&nbsp;S2&nbsp;S3<SPAN class="keyword">&gt;&gt;</SPAN></CODE></BLOCKQUOTE><P> which executes the body <CODE>S1&nbsp;S2&nbsp;S3</CODE> iff <CODE>B</CODE> evaluates to false.i.&nbsp;e. it is precisely equivalent to: </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">if</SPAN>&nbsp;B&nbsp;<SPAN class="keyword">then</SPAN>&nbsp;<SPAN class="keyword">skip</SPAN>&nbsp;<SPAN class="keyword">else</SPAN>&nbsp;S1&nbsp;S2&nbsp;S3&nbsp;<SPAN class="keyword">end</SPAN></CODE></BLOCKQUOTE><P> Here is the code for the expander: </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">declare</SPAN>&nbsp;<BR><SPAN class="keyword">fun</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">UnlessExpander</SPAN>&nbsp;fMacro(M<SPAN class="keyword">|</SPAN>B<SPAN class="keyword">|</SPAN>L&nbsp;C)&nbsp;Env}<BR>&nbsp;&nbsp;&nbsp;fBoolCase(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fSkip(<SPAN class="keyword">unit</SPAN>)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{Macro<SPAN class="keyword">.</SPAN>listToSequence&nbsp;L}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C)<BR><SPAN class="keyword">end</SPAN></CODE></BLOCKQUOTE><P> The first argument <CODE>fMacro(M<SPAN class="keyword">|</SPAN>B<SPAN class="keyword">|</SPAN>L&nbsp;C)</CODE> is the macro call form. <CODE>M</CODE> is the representation of the atom which is the first element of the macro invocation (here <CODE>fAtom(unless&nbsp;C2)</CODE>, where <CODE>C2</CODE> is a <EM>coordinate</EM> indicating the provenance and location of the token in the input). <CODE>B</CODE> is the 2nd element of the macro call and represents the boolean condition. <CODE>L</CODE> is the list of the remainder of the macro call and represents the body. <CODE>C</CODE> is also a coordinate. <CODE>Env</CODE> is a macro environment and can usually be ignored.</P><P><CODE>{Macro<SPAN class="keyword">.</SPAN>listToSequence&nbsp;L}</CODE> turns the list <CODE>L</CODE> of instructions into the syntactic representation of a sequence. Module <CODE>Macro</CODE> is described in <A href="node3.html#section.macro.module">Section&nbsp;1.2</A>. </P><P>We must now globally register the macro expander: </P><BLOCKQUOTE class="code"><CODE>{Macro<SPAN class="keyword">.</SPAN>defmacro&nbsp;unless&nbsp;UnlessExpander}</CODE></BLOCKQUOTE><P> Here is a test: </P><BLOCKQUOTE class="code"><CODE><SPAN class="keyword">declare</SPAN>&nbsp;<BR><SPAN class="keyword">proc</SPAN><SPAN class="variablename">&nbsp;</SPAN>{<SPAN class="functionname">DO</SPAN>&nbsp;X&nbsp;Y}<BR>&nbsp;&nbsp;&nbsp;<SPAN class="keyword">&lt;&lt;</SPAN>unless&nbsp;X<SPAN class="keyword">&lt;</SPAN>Y&nbsp;{Show&nbsp;X}&nbsp;{Show&nbsp;Y}<SPAN class="keyword">&gt;&gt;</SPAN>&nbsp;<BR><SPAN class="keyword">end</SPAN></CODE></BLOCKQUOTE><P> <CODE>{DO&nbsp;2&nbsp;5}</CODE> prints nothing while <CODE>{DO&nbsp;5&nbsp;2}</CODE> prints 5 then 2.</P><P>A common mistake while using the interactive development environment is to feed a buffer that contains both macro definitions and uses of these macros. This cannot work: when the code in the buffer is being compiled the macros are not yet defined. They become defined only after execution of the code. Thus you must first feed your macro definitions, and only then feed any code that makes use of them.</P></DIV><TABLE align="center" border="0" cellpadding="6" cellspacing="6" class="nav"><TR bgcolor="#DDDDDD"><TD><A href="node1.html">- Up -</A></TD><TD><A href="node3.html#section.macro.module">Next &gt;&gt;</A></TD></TR></TABLE><HR><ADDRESS><A href="http://www.ps.uni-sb.de/~duchier/">Denys&nbsp;Duchier</A><BR><SPAN class="version">Version 1.4.0 (20090610)</SPAN></ADDRESS></BODY></HTML>