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 #include <thrift/compiler/ast/visitor.h> 18 19 namespace apache { 20 namespace thrift { 21 namespace compiler { 22 traverse(t_program * const program)23void visitor::traverse(t_program* const program) { 24 visit_and_recurse(program); 25 } 26 visit(t_program * const)27bool visitor::visit(t_program* const /* program */) { 28 return true; 29 } 30 visit(t_service * const)31bool visitor::visit(t_service* const /* service */) { 32 return true; 33 } 34 visit(t_enum * const)35bool visitor::visit(t_enum* const /* tenum */) { 36 return true; 37 } 38 visit(t_struct * const)39bool visitor::visit(t_struct* const /* tstruct */) { 40 return true; 41 } 42 visit(t_field * const)43bool visitor::visit(t_field* const /* tfield */) { 44 return true; 45 } 46 visit(t_const * const)47bool visitor::visit(t_const* const /* tconst */) { 48 return true; 49 } 50 visit_and_recurse(t_program * const program)51void visitor::visit_and_recurse(t_program* const program) { 52 if (visit(program)) { 53 recurse(program); 54 } 55 } 56 visit_and_recurse(t_service * const service)57void visitor::visit_and_recurse(t_service* const service) { 58 if (visit(service)) { 59 recurse(service); 60 } 61 } 62 visit_and_recurse(t_enum * const tenum)63void visitor::visit_and_recurse(t_enum* const tenum) { 64 if (visit(tenum)) { 65 recurse(tenum); 66 } 67 } 68 visit_and_recurse(t_struct * const tstruct)69void visitor::visit_and_recurse(t_struct* const tstruct) { 70 if (visit(tstruct)) { 71 recurse(tstruct); 72 } 73 } 74 visit_and_recurse(t_field * const tfield)75void visitor::visit_and_recurse(t_field* const tfield) { 76 if (visit(tfield)) { 77 recurse(tfield); 78 } 79 } 80 visit_and_recurse(t_const * const tconst)81void visitor::visit_and_recurse(t_const* const tconst) { 82 if (visit(tconst)) { 83 recurse(tconst); 84 } 85 } 86 recurse(t_program * const program)87void visitor::recurse(t_program* const program) { 88 for (auto* const service : program->services()) { 89 visit_and_recurse(service); 90 } 91 for (auto* const tenum : program->enums()) { 92 visit_and_recurse(tenum); 93 } 94 for (auto* tstruct : program->structs()) { 95 visit_and_recurse(tstruct); 96 } 97 for (auto* texception : program->exceptions()) { 98 visit_and_recurse(texception); 99 } 100 for (auto* tconst : program->consts()) { 101 visit_and_recurse(tconst); 102 } 103 } 104 recurse(t_service * const)105void visitor::recurse(t_service* const /* service */) { 106 // partial implementation - that's the end of the line for now 107 } 108 recurse(t_enum * const)109void visitor::recurse(t_enum* const /* tenum */) { 110 // partial implementation - that's the end of the line for now 111 } 112 recurse(t_struct * const tstruct)113void visitor::recurse(t_struct* const tstruct) { 114 for (auto* tfield : tstruct->get_members()) { 115 visit_and_recurse(tfield); 116 } 117 } 118 recurse(t_field * const)119void visitor::recurse(t_field* const /* tfield */) { 120 // partial implementation - that's the end of the line for now 121 } 122 recurse(t_const * const)123void visitor::recurse(t_const* const /* tconst */) { 124 // partial implementation - that's the end of the line for now 125 } 126 interleaved_visitor(std::vector<visitor * > visitors)127interleaved_visitor::interleaved_visitor(std::vector<visitor*> visitors) 128 : visitor(), visitors_(std::move(visitors)) {} 129 visit_and_recurse(t_program * const program)130void interleaved_visitor::visit_and_recurse(t_program* const program) { 131 visit_and_recurse_gen(program); 132 } 133 visit_and_recurse(t_service * const service)134void interleaved_visitor::visit_and_recurse(t_service* const service) { 135 visit_and_recurse_gen(service); 136 } 137 visit_and_recurse(t_enum * const tenum)138void interleaved_visitor::visit_and_recurse(t_enum* const tenum) { 139 visit_and_recurse_gen(tenum); 140 } 141 visit_and_recurse(t_struct * const tstruct)142void interleaved_visitor::visit_and_recurse(t_struct* const tstruct) { 143 visit_and_recurse_gen(tstruct); 144 } 145 visit_and_recurse(t_field * const tfield)146void interleaved_visitor::visit_and_recurse(t_field* const tfield) { 147 visit_and_recurse_gen(tfield); 148 } 149 visit_and_recurse(t_const * const tconst)150void interleaved_visitor::visit_and_recurse(t_const* const tconst) { 151 visit_and_recurse_gen(tconst); 152 } 153 154 template <typename Visitee> visit_and_recurse_gen(Visitee * const visitee)155void interleaved_visitor::visit_and_recurse_gen(Visitee* const visitee) { 156 // track the set of visitors which return true from visit() 157 auto rec_mask = std::vector<bool>(visitors_.size()); 158 auto any = false; 159 for (size_t i = 0; i < visitors_.size(); ++i) { 160 auto const rec = rec_mask_[i] && visitors_[i]->visit(visitee); 161 rec_mask[i] = rec; 162 any = any || rec; 163 } 164 // only recurse with the set of visitors which return true from visit() 165 if (any) { 166 std::swap(rec_mask_, rec_mask); 167 recurse(visitee); 168 std::swap(rec_mask_, rec_mask); 169 } 170 } 171 172 } // namespace compiler 173 } // namespace thrift 174 } // namespace apache 175