]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/phoenix/doc/html/phoenix/examples/transforming_the_expression_tree.html
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / phoenix / doc / html / phoenix / examples / transforming_the_expression_tree.html
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Transforming the Expression Tree</title>
5 <link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6 <meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
7 <link rel="home" href="../../index.html" title="Chapter&#160;1.&#160;Phoenix 3.2.0">
8 <link rel="up" href="../examples.html" title="Advanced Examples">
9 <link rel="prev" href="adding_an_expression.html" title="Adding an expression">
10 <link rel="next" href="../lazy_list.html" title="Lazy List">
11 </head>
12 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13 <table cellpadding="2" width="100%"><tr>
14 <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
15 <td align="center"><a href="../../../../../../index.html">Home</a></td>
16 <td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
17 <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18 <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19 <td align="center"><a href="../../../../../../more/index.htm">More</a></td>
20 </tr></table>
21 <hr>
22 <div class="spirit-nav">
23 <a accesskey="p" href="adding_an_expression.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../lazy_list.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
24 </div>
25 <div class="section">
26 <div class="titlepage"><div><div><h3 class="title">
27 <a name="phoenix.examples.transforming_the_expression_tree"></a><a class="link" href="transforming_the_expression_tree.html" title="Transforming the Expression Tree">Transforming
28 the Expression Tree</a>
29 </h3></div></div></div>
30 <p>
31 This example will show how to write <a class="link" href="../inside/actions.html" title="More on Actions">Actions</a>
32 that transform the Phoenix AST.
33 </p>
34 <div class="blockquote"><blockquote class="blockquote">
35 <p>
36 "<span class="emphasis"><em>Lisp macros transform the program structure itself, with
37 the full language available to express such transformations.</em></span>"
38 </p>
39 <p>
40 <a href="http://en.wikipedia.org/wiki/Lisp_macro#Lisp_macros" target="_top">Wikipedia</a>
41 </p>
42 </blockquote></div>
43 <p>
44 What we want to do is to invert some arithmetic operators, i.e. plus will
45 be transformed to minus, minus to plus, multiplication to division and division
46 to multiplication.
47 </p>
48 <p>
49 Let's start with defining our default action:
50 </p>
51 <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">invert_actions</span>
52 <span class="special">{</span>
53 <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Rule</span><span class="special">&gt;</span>
54 <span class="keyword">struct</span> <span class="identifier">when</span>
55 <span class="special">:</span> <span class="identifier">proto</span><span class="special">::</span><span class="identifier">_</span> <span class="comment">// the default is proto::_</span>
56 <span class="special">{};</span>
57 <span class="special">};</span>
58 </pre>
59 <p>
60 By default, we don't want to do anything, well, not exactly nothing, but
61 just return the expression. This is done by <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/_.html" target="_top">proto::_</a>
62 which, used as a transform, just passes the current expression along. Making
63 this action an identity transform.
64 </p>
65 <p>
66 So, after the basics are set up, we can start by writing the transformations
67 we want to have on our tree:
68 </p>
69 <pre class="programlisting"><span class="comment">// Transform plus to minus</span>
70 <span class="keyword">template</span> <span class="special">&lt;&gt;</span>
71 <span class="keyword">struct</span> <span class="identifier">invert_actions</span><span class="special">::</span><span class="identifier">when</span><span class="special">&lt;</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">rule</span><span class="special">::</span><span class="identifier">plus</span><span class="special">&gt;</span>
72 <span class="special">:</span> <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/call.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">call</span></code></a><span class="special">&lt;</span>
73 <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/functional/make_expr.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">functional</span><span class="special">::</span><span class="identifier">make_expr</span></code></a><span class="special">&lt;</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">tag</span><span class="special">::</span><span class="identifier">minus</span><span class="special">&gt;(</span>
74 <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_left</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
75 <span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_right</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
76 <span class="special">)</span>
77 <span class="special">&gt;</span>
78 <span class="special">{};</span>
79 </pre>
80 <p>
81 Wow, this looks complicated! Granted you need to know a little bit about
82 <a href="http://www.boost.org/doc/libs/release/libs/proto/index.html" target="_top">Boost.Proto</a>
83 (For a good introduction read through the <a href="http://cpp-next.com/archive/2010/08/expressive-c-introduction/" target="_top">Expressive
84 C++</a> series).
85 </p>
86 <p>
87 What is done is the following:
88 </p>
89 <div class="itemizedlist"><ul class="itemizedlist" type="disc">
90 <li class="listitem">
91 The left expression is passed to evaluator (with the current context,
92 that contains our invert_actions)
93 </li>
94 <li class="listitem">
95 The right expression is passed to evaluator (with the current context,
96 that contains our invert_actions)
97 </li>
98 <li class="listitem">
99 The result of these two <a href="http://www.boost.org/doc/libs/release/doc/html/Transform.html" target="_top">Proto
100 Transforms</a> is passed to <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/functional/make_expr.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">functional</span><span class="special">::</span><span class="identifier">make_expr</span></code></a> which returns the
101 freshly created expression
102 </li>
103 </ul></div>
104 <p>
105 After you know what is going on, maybe the rest doesn't look so scary anymore:
106 </p>
107 <pre class="programlisting"><span class="comment">// Transform minus to plus</span>
108 <span class="keyword">template</span> <span class="special">&lt;&gt;</span>
109 <span class="keyword">struct</span> <span class="identifier">invert_actions</span><span class="special">::</span><span class="identifier">when</span><span class="special">&lt;</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">rule</span><span class="special">::</span><span class="identifier">minus</span><span class="special">&gt;</span>
110 <span class="special">:</span> <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/call.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">call</span></code></a><span class="special">&lt;</span>
111 <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/functional/make_expr.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">functional</span><span class="special">::</span><span class="identifier">make_expr</span></code></a><span class="special">&lt;</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">tag</span><span class="special">::</span><span class="identifier">plus</span><span class="special">&gt;(</span>
112 <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_left</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
113 <span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_right</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
114 <span class="special">)</span>
115 <span class="special">&gt;</span>
116 <span class="special">{};</span>
117
118 <span class="comment">// Transform multiplies to divides</span>
119 <span class="keyword">template</span> <span class="special">&lt;&gt;</span>
120 <span class="keyword">struct</span> <span class="identifier">invert_actions</span><span class="special">::</span><span class="identifier">when</span><span class="special">&lt;</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">rule</span><span class="special">::</span><span class="identifier">multiplies</span><span class="special">&gt;</span>
121 <span class="special">:</span> <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/call.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">call</span></code></a><span class="special">&lt;</span>
122 <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/functional/make_expr.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">functional</span><span class="special">::</span><span class="identifier">make_expr</span></code></a><span class="special">&lt;</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">tag</span><span class="special">::</span><span class="identifier">divides</span><span class="special">&gt;(</span>
123 <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_left</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
124 <span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_right</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
125 <span class="special">)</span>
126 <span class="special">&gt;</span>
127 <span class="special">{};</span>
128
129 <span class="comment">// Transform divides to multiplies</span>
130 <span class="keyword">template</span> <span class="special">&lt;&gt;</span>
131 <span class="keyword">struct</span> <span class="identifier">invert_actions</span><span class="special">::</span><span class="identifier">when</span><span class="special">&lt;</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">rule</span><span class="special">::</span><span class="identifier">divides</span><span class="special">&gt;</span>
132 <span class="special">:</span> <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/call.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">call</span></code></a><span class="special">&lt;</span>
133 <a href="http://www.boost.org/doc/libs/release/doc/html/boost/proto/functional/make_expr.html" target="_top"><code class="computeroutput"><span class="identifier">proto</span><span class="special">::</span><span class="identifier">functional</span><span class="special">::</span><span class="identifier">make_expr</span></code></a><span class="special">&lt;</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">tag</span><span class="special">::</span><span class="identifier">multiplies</span><span class="special">&gt;(</span>
134 <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_left</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
135 <span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span><span class="identifier">proto</span><span class="special">::</span><span class="identifier">_right</span><span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">_context</span><span class="special">)</span>
136 <span class="special">)</span>
137 <span class="special">&gt;</span>
138 <span class="special">{};</span>
139 </pre>
140 <p>
141 That's it! Now that we have our actions defined, we want to evaluate some
142 of our expressions with them:
143 </p>
144 <pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Expr</span><span class="special">&gt;</span>
145 <span class="comment">// Calculate the result type: our transformed AST</span>
146 <span class="keyword">typename</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">result_of</span><span class="special">&lt;</span>
147 <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">evaluator</span><span class="special">(</span>
148 <span class="identifier">Expr</span> <span class="keyword">const</span><span class="special">&amp;</span>
149 <span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">result_of</span><span class="special">::</span><span class="identifier">context</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">invert_actions</span><span class="special">&gt;::</span><span class="identifier">type</span>
150 <span class="special">)</span>
151 <span class="special">&gt;::</span><span class="identifier">type</span>
152 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">Expr</span> <span class="keyword">const</span> <span class="special">&amp;</span> <span class="identifier">expr</span><span class="special">)</span>
153 <span class="special">{</span>
154 <span class="keyword">return</span>
155 <span class="comment">// Evaluate it with our actions</span>
156 <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">eval</span><span class="special">(</span>
157 <span class="identifier">expr</span>
158 <span class="special">,</span> <span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">context</span><span class="special">(</span>
159 <span class="keyword">int</span><span class="special">()</span>
160 <span class="special">,</span> <span class="identifier">invert_actions</span><span class="special">()</span>
161 <span class="special">)</span>
162 <span class="special">);</span>
163 <span class="special">}</span>
164 </pre>
165 <p>
166 Run some tests to see if it is working:
167 </p>
168 <pre class="programlisting"><span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span><span class="special">);</span> <span class="comment">// --&gt; _1</span>
169 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">+</span> <span class="identifier">_2</span><span class="special">);</span> <span class="comment">// --&gt; _1 - _2</span>
170 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">+</span> <span class="identifier">_2</span> <span class="special">-</span> <span class="identifier">_3</span><span class="special">);</span> <span class="comment">// --&gt; _1 - _2 + _3</span>
171 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">*</span> <span class="identifier">_2</span><span class="special">);</span> <span class="comment">// --&gt; _1 / _2</span>
172 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">*</span> <span class="identifier">_2</span> <span class="special">/</span> <span class="identifier">_3</span><span class="special">);</span> <span class="comment">// --&gt; _1 / _2 * _3</span>
173 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">*</span> <span class="identifier">_2</span> <span class="special">+</span> <span class="identifier">_3</span><span class="special">);</span> <span class="comment">// --&gt; _1 / _2 - _3</span>
174 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">*</span> <span class="identifier">_2</span> <span class="special">-</span> <span class="identifier">_3</span><span class="special">);</span> <span class="comment">// --&gt; _1 / _2 + _2</span>
175 <span class="identifier">invert</span><span class="special">(</span><span class="identifier">if_</span><span class="special">(</span><span class="identifier">_1</span> <span class="special">*</span> <span class="identifier">_4</span><span class="special">)[</span><span class="identifier">_2</span> <span class="special">-</span> <span class="identifier">_3</span><span class="special">]);</span> <span class="comment">// --&gt; if_(_1 / _4)[_2 + _3]</span>
176 <span class="identifier">_1</span> <span class="special">*</span> <span class="identifier">invert</span><span class="special">(</span><span class="identifier">_2</span> <span class="special">-</span> <span class="identifier">_3</span><span class="special">));</span> <span class="comment">// --&gt; _1 * _2 + _3</span>
177 </pre>
178 <p>
179 <span class="inlinemediaobject"><img src="../../images/note.png"></span>
180 The complete example can be found here: <a href="../../../../example/invert.cpp" target="_top">example/invert.cpp</a>
181 </p>
182 <p>
183 <span class="emphasis"><em>Pretty simple ...</em></span>
184 </p>
185 </div>
186 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
187 <td align="left"></td>
188 <td align="right"><div class="copyright-footer">Copyright &#169; 2002-2005, 2010, 2014, 2015 Joel de Guzman, Dan Marsden, Thomas
189 Heller, John Fletcher<p>
190 Distributed under the Boost Software License, Version 1.0. (See accompanying
191 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
192 </p>
193 </div></td>
194 </tr></table>
195 <hr>
196 <div class="spirit-nav">
197 <a accesskey="p" href="adding_an_expression.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../examples.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="../lazy_list.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
198 </div>
199 </body>
200 </html>