1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <memory>
20 #include <vector>
21 
22 #include <thrift/compiler/ast/t_const.h>
23 #include <thrift/compiler/ast/t_enum.h>
24 #include <thrift/compiler/ast/t_field.h>
25 #include <thrift/compiler/ast/t_program.h>
26 #include <thrift/compiler/ast/t_service.h>
27 #include <thrift/compiler/ast/t_struct.h>
28 
29 namespace apache {
30 namespace thrift {
31 namespace compiler {
32 
33 // TODO(afuller): Replace usage with ast_visitor and remove.
34 class visitor {
35  public:
36   virtual ~visitor() = default;
37 
38   /***
39    *  The entry point for traversal. Call-sites should call this method.
40    */
41   void traverse(t_program* program);
42 
43   /***
44    *  Derived visitor types will generally override these virtual methods.
45    *
46    *  Return whether or not to visit children AST nodes afterward. For example,
47    *  if `visit(t_program*)` returns `true`, then the visitor will
48    *  continue visiting the program's members.
49    *
50    *  The default implementations of these virtual methods is simply to return
51    *  `true`. This allows derived visitor types to implement only the particular
52    *  overloads that they specifically need.
53    *
54    *  Note: These are extension points, not entry points for traversal.
55    */
56   virtual bool visit(t_program* program);
57   virtual bool visit(t_service* service);
58   virtual bool visit(t_enum* tenum);
59   virtual bool visit(t_struct* tstruct);
60   virtual bool visit(t_field* tfield);
61   virtual bool visit(t_const* tconst);
62 
63  protected:
64   visitor() = default;
65 
66   /***
67    *  Visitor combinator types will generally override these virutal methods.
68    *
69    *  General derived visitors should not need to.
70    */
71   virtual void visit_and_recurse(t_program* program);
72   virtual void visit_and_recurse(t_service* service);
73   virtual void visit_and_recurse(t_enum* tenum);
74   virtual void visit_and_recurse(t_struct* tstruct);
75   virtual void visit_and_recurse(t_field* tfield);
76   virtual void visit_and_recurse(t_const* tconst);
77 
78   void recurse(t_program* program);
79   void recurse(t_service* service);
80   void recurse(t_enum* tenum);
81   void recurse(t_struct* tstruct);
82   void recurse(t_field* tfield);
83   void recurse(t_const* tconst);
84 };
85 
86 /***
87  *  Useful for splitting up a single large visitor into multiple smaller ones,
88  *  each doing its own portion of the work.
89  *
90  *  Runs the visitors across the AST nodes in lockstep with each other, taking
91  *  care to recurse with only those visitors which return true from visit().
92  *
93  *  Performs a single concurrent traversal will all visitors, rather than a
94  *  sequence of traversals with one visitor each. The concurrent traversal will
95  *  interleave all the visitor traversals in lockstep.
96  */
97 class interleaved_visitor : public visitor {
98  public:
99   explicit interleaved_visitor(std::vector<visitor*> visitors);
100 
101  protected:
102   void visit_and_recurse(t_program* program) override;
103   void visit_and_recurse(t_service* service) override;
104   void visit_and_recurse(t_enum* tenum) override;
105   void visit_and_recurse(t_struct* tstruct) override;
106   void visit_and_recurse(t_field* tfield) override;
107   void visit_and_recurse(t_const* tconst) override;
108 
109  private:
110   template <typename Visitee>
111   void visit_and_recurse_gen(Visitee* visitee);
112 
113   std::vector<visitor*> visitors_;
114   std::vector<bool> rec_mask_{std::vector<bool>(visitors_.size(), true)};
115 };
116 
117 } // namespace compiler
118 } // namespace thrift
119 } // namespace apache
120