QDP++
ForEachInOrder.h
Go to the documentation of this file.
1// -*- C++ -*-
2// ACL:license
3// ----------------------------------------------------------------------
4// This software and ancillary information (herein called "SOFTWARE")
5// called PETE (Portable Expression Template Engine) is
6// made available under the terms described here. The SOFTWARE has been
7// approved for release with associated LA-CC Number LA-CC-99-5.
8//
9// Unless otherwise indicated, this SOFTWARE has been authored by an
10// employee or employees of the University of California, operator of the
11// Los Alamos National Laboratory under Contract No. W-7405-ENG-36 with
12// the U.S. Department of Energy. The U.S. Government has rights to use,
13// reproduce, and distribute this SOFTWARE. The public may copy, distribute,
14// prepare derivative works and publicly display this SOFTWARE without
15// charge, provided that this Notice and any statement of authorship are
16// reproduced on all copies. Neither the Government nor the University
17// makes any warranty, express or implied, or assumes any liability or
18// responsibility for the use of this SOFTWARE.
19//
20// If SOFTWARE is modified to produce derivative works, such modified
21// SOFTWARE should be clearly marked, so as not to confuse it with the
22// version available from LANL.
23//
24// For more information about PETE, send e-mail to pete@acl.lanl.gov,
25// or visit the PETE web page at http://www.acl.lanl.gov/pete/.
26// ----------------------------------------------------------------------
27// ACL:license
28
29//-----------------------------------------------------------------------------
30// Classes:
31// ForEachInOrder
32// TagVisitor
33//-----------------------------------------------------------------------------
34
35#ifndef POOMA_PETE_FOREACHINORDER_H
36#define POOMA_PETE_FOREACHINORDER_H
37
38//-----------------------------------------------------------------------------
39// Overview:
40//
41// ForEachInOrder is like ForEach except that it traverses the parse
42// tree "in order", meaning it visits the parts of a TBTree as follows:
43//
44// visit left child
45// visit value
46// visit right child
47//
48// In addition, it calls a start() function on the visit tag before
49// visit(left) and a finish() function after visit(right). This
50// additional bit of generality allows special actions to be taken,
51// in essence, when the ForEachInOrder::apply moves down and back up
52// the edges of the parse tree (such as printing parentheses).
53//
54// An "in order" traversal is not what one does for evaluating
55// expressions, so this may not be useful for much, but I wanted to
56// do it to gain some more experience with PETE.
57//
58// This first cut will only do TBTrees.
59//
60// The TagFunctor and TagCombine structs from ForEach.h can be reused.
61//
62// TagVisitor is a new class that visits the "value" node prior,
63// between, and after the left and right children are visited.
64//
65//-----------------------------------------------------------------------------
66
67//-----------------------------------------------------------------------------
68// Typedefs:
69//-----------------------------------------------------------------------------
70
71//-----------------------------------------------------------------------------
72// Includes:
73//-----------------------------------------------------------------------------
74
75#include "PETE/PETE.h"
76
77//-----------------------------------------------------------------------------
78// Forward Declarations:
79//-----------------------------------------------------------------------------
80
81//-----------------------------------------------------------------------------
82//
83// Full Description:
84//
85// The ForEachInOrder struct implements a template meta-program
86// traversal of a PETE Expression parse-tree. As explained above, this
87// is done "in order" rather than the "post order" traversal done by
88// ForEach.
89//
90// The ForEachInOrder struct defines:
91//
92// typename ForEachInOrder<Expr,FTag,VTag,CTag>::Type_t
93//
94// Type_t::apply(Expr& expr, FTag f, VTag v, CTag c) {...};
95//
96// where
97//
98// Expr is the type of an expression tree.
99// FTag is the type of a functor tag.
100// VTag is the type of a visitor tag.
101// CTag is the type of a combiner tag.
102//
103// Details:
104//
105// Type_t::apply(Expr &e, FTag f, VTag v, CTag c)
106//
107// function that traverses the expression tree defined by e, and for
108// each binary-tree node it does:
109//
110// TagVisitor<...>::start(e.value_m,v);
111//
112// left_val = ForEachInOrder<...>::apply(e.left_m,f,v,c),
113//
114// TagVisitor<...>::visit(e.value_m,v);
115//
116// right_val = ForEachInOrder<...>::apply(e.right_m,f,v,c),
117//
118// retval = TagCombineInOrdere<...>::
119// apply(left_val, right_val, e.value_m, c)
120//
121// TagVisitor<...>::finish(e.value_m,v);
122//
123// return retval;
124//
125// The TagFunctor is specialized to perform a specific action at the
126// leaf nodes.
127//
128// The TagVisitor is specialized to perform specific actions both at
129// the start and finish of a new TBTree node, and to perform a
130// specific operation when it visits the "value" node of the parse
131// tree (i.e. this can be specialized to perform specific operations
132// for every type of operator). Note that the value returned by
133// TagVisitor::apply must be of the type Op. This usually means
134// that TagVisitor::apply will just return e.value_m after it does
135// its calculation.
136//
137// The TagCombiner is specialized to combine the results of visiting
138// the left, right, and value fields.
139//
140// The type of object returned is given by:
141//
142// typename ForEachInOrder<Expr,FTag,VTag,CTag>::Type_t
143//
144//-----------------------------------------------------------------------------
145
146//
147// struct TagVisitor
148//
149// "Visitor" functor whose apply() method is applied to the value_m
150// field of an expression between the left-traversal and the
151// right-traversal.
152//
153// Default is "null" behavior. Just return the op. This should make
154// this equivalent to ForEach. This should probably always return the
155// unless it is ignored by everything else. But it can take other
156// actions as well.
157//
158// Also includes start() and finish() functions that are called when
159// the traversal moves down and back up an edge, respectively.
160//
161
162template <class Op, class VTag>
164{
165 static void start(Op, VTag) { }
166 static void center(Op, VTag) { }
167 static void visit(Op, VTag) { }
168 static void finish(Op, VTag) { }
169};
170
171
172//
173// struct ForEachInOrder
174//
175// Template meta-program for traversing the parse tree.
176//
177// Default behaviour assumes you're at a leaf, in which case
178// it just applies the FTag functor
179//
180
181template<class Expr, class FTag, class VTag, class CTag>
183{
185 typedef typename Tag_t::Type_t Type_t;
186
187 static Type_t apply(const Expr &expr, const FTag &f, const VTag &v,
188 const CTag &c)
189 {
190 return Tag_t::apply(expr,f);
191 }
192};
193
194//
195// The Refernce case needs to apply the functor to the wrapped object.
196//
197
198template<class T, class FTag, class VTag, class CTag>
199struct ForEachInOrder<Reference<T>,FTag,VTag,CTag>
200{
202 typedef typename Tag_t::Type_t Type_t;
203
204 static Type_t apply(const Reference<T> &expr, const FTag &f,
205 const VTag &v, const CTag &c)
206 {
207 return Tag_t::apply(expr.reference(),f);
208 }
209};
210
211//
212// struct ForEachInOrder
213//
214// Specialization for a TBTree. This just performs the recursive
215// traversal described above.
216//
217
218template<class Op, class A, class FTag, class VTag,
219 class CTag>
220struct ForEachInOrder<UnaryNode<Op, A>, FTag, VTag, CTag>
221{
224
225 typedef typename ForEachA_t::Type_t TypeA_t;
226
228
229 typedef typename Combiner_t::Type_t Type_t;
230
231 static Type_t apply(const UnaryNode<Op, A> &expr, const FTag &f,
232 const VTag &v, const CTag &c)
233 {
234 Visitor_t::visit(expr.operation(),v);
235
236 Visitor_t::start(expr.operation(),v);
237
238 TypeA_t A_val = ForEachA_t::apply(expr.child(), f, v, c);
239 Type_t val = Combiner_t::combine(A_val, expr.operation(), c);
240
242
243 return val;
244 }
245};
246
247
251
252template<class Op, class A, class B, class FTag, class VTag,
253 class CTag>
254struct ForEachInOrder<BinaryNode<Op, A, B>, FTag, VTag, CTag>
255{
259
260 typedef typename ForEachA_t::Type_t TypeA_t;
261 typedef typename ForEachB_t::Type_t TypeB_t;
262
264
265 typedef typename Combiner_t::Type_t Type_t;
266
267 static Type_t apply(const BinaryNode<Op, A, B> &expr, const FTag &f,
268 const VTag &v, const CTag &c)
269 {
270 Visitor_t::visit(expr.operation(),v);
271
272 Visitor_t::start(expr.operation(),v);
273
274 TypeA_t left_val = ForEachA_t::apply(expr.left(), f, v, c);
275
277
278 TypeB_t right_val = ForEachB_t::apply(expr.right(), f, v, c);
279
280 Type_t val = Combiner_t::combine(left_val, right_val, expr.operation(), c);
281
283
284 return val;
285 }
286};
287
288
292
293template<class Op, class A, class B, class C, class FTag, class VTag,
294 class CTag>
295struct ForEachInOrder<TrinaryNode<Op, A, B, C>, FTag, VTag, CTag>
296{
301
302 typedef typename ForEachA_t::Type_t TypeA_t;
303 typedef typename ForEachB_t::Type_t TypeB_t;
304 typedef typename ForEachC_t::Type_t TypeC_t;
305
307
308 typedef typename Combiner_t::Type_t Type_t;
309
310 static Type_t apply(const TrinaryNode<Op, A, B, C> &expr, const FTag &f,
311 const VTag &v, const CTag &c)
312 {
313 Visitor_t::visit(expr.operation(),v);
314
315 Visitor_t::start(expr.operation(),v);
316
317 TypeA_t left_val = ForEachA_t::apply(expr.left(), f, v, c);
318
320
321 TypeB_t middle_val= ForEachB_t::apply(expr.middle(), f, v, c);
322
324
325 TypeC_t right_val = ForEachC_t::apply(expr.right(), f, v, c);
326
327 Type_t val = Combiner_t::combine(left_val, middle_val, right_val, expr.operation(), c);
328
330
331 return val;
332 }
333};
334
335
336//
337// Specializations of Combine2 for NullTag()
338// (seems like something like this should be in ForEach.h)
339//
340
341struct NullTag {};
342
343template<class A,class B,class Op>
344struct Combine2<A, B, Op, NullTag>
345{
346 typedef int Type_t;
347 static Type_t combine(A, B, Op, NullTag)
348 { return 0; }
349};
350
351#endif // PETE_PETE_FOREACHINORDER_H
352
353// ACL:rcsinfo
354// ----------------------------------------------------------------------
355// $RCSfile: ForEachInOrder.h,v $ $Author: edwards $
356// $Revision: 1.2 $ $Date: 2004-07-27 05:24:35 $
357// ----------------------------------------------------------------------
358// ACL:rcsinfo
DeReference< Left >::Return_t left() const
Definition TreeNodes.h:247
DeReference< Right >::Return_t right() const
Definition TreeNodes.h:251
const Op & operation() const
Definition TreeNodes.h:243
DeReference< Left >::Return_t left() const
Definition TreeNodes.h:361
DeReference< Right >::Return_t right() const
Definition TreeNodes.h:365
DeReference< Middle >::Return_t middle() const
Definition TreeNodes.h:369
const Op & operation() const
Definition TreeNodes.h:357
DeReference< Child >::Return_t child() const
Definition TreeNodes.h:151
const Op & operation() const
Definition TreeNodes.h:147
OLattice< PScalar< PColorMatrix< RComplexFloat, 3 > > > C
static Type_t combine(const TypeA_t &a, const Op &, const CTag &)
Definition Combiners.h:88
static Type_t combine(A, B, Op, NullTag)
static Type_t combine(const TypeA_t &a, const TypeB_t &b, const TypeC_t &c, const Op &op, const CTag &t)
Definition Combiners.h:103
Combine2< Type1_t, TypeC_t, Op, CTag >::Type_t Type_t
Definition Combiners.h:101
Combine2< TypeA_t, TypeB_t, Op, CTag > Combiner_t
static Type_t apply(const BinaryNode< Op, A, B > &expr, const FTag &f, const VTag &v, const CTag &c)
static Type_t apply(const Reference< T > &expr, const FTag &f, const VTag &v, const CTag &c)
Combine3< TypeA_t, TypeB_t, TypeC_t, Op, CTag > Combiner_t
static Type_t apply(const TrinaryNode< Op, A, B, C > &expr, const FTag &f, const VTag &v, const CTag &c)
static Type_t apply(const UnaryNode< Op, A > &expr, const FTag &f, const VTag &v, const CTag &c)
ForEachInOrder< A, FTag, VTag, CTag > ForEachA_t
Tag_t::Type_t Type_t
static Type_t apply(const Expr &expr, const FTag &f, const VTag &v, const CTag &c)
LeafFunctor< Expr, FTag > Tag_t
const T & reference() const
Definition TreeNodes.h:81
static void finish(Op, VTag)
static void visit(Op, VTag)
static void start(Op, VTag)
static void center(Op, VTag)