8 #include <hilti/base/logger.h> 9 #include <hilti/base/visitor-types.h> 12 namespace detail::visitor {
14 enum class Order { Pre, Post };
20 template<
class C,
typename FuncSig,
typename =
void>
23 template<
class C,
typename FuncSig>
24 struct hasCallback<C, FuncSig,
std::void_t<decltype(std::remove_cv_t<FuncSig C::*>{&C::operator()})>> : std::true_type {
27 template<
class C,
typename... FuncSig>
30 template<
typename Result>
31 using DispatchResult = std::conditional_t<std::is_void_v<Result>, bool, std::optional<Result>>;
33 template<
typename Result,
typename Erased,
typename Dispatcher,
typename Iterator>
34 DispatchResult<Result> do_dispatch(Erased& n, Dispatcher& d,
typename Iterator::Position& i,
35 bool& no_match_so_far);
37 template<
typename Result,
typename Type,
typename Erased,
typename Dispatcher,
typename Iterator>
38 DispatchResult<Result> do_dispatch_one(Erased& n,
const std::type_info& ti, Dispatcher& d,
40 if ( ti !=
typeid(Type) )
43 using T = std::conditional_t<std::is_const_v<Erased>,
const Type, Type>;
45 using CBc =
Result(T
const&);
48 auto& x = n.template as<Type>();
49 DispatchResult<Result> result = {};
52 if constexpr ( std::is_base_of_v<util::type_erasure::trait::TypeErased, Type> )
53 result = do_dispatch<Result, T, Dispatcher, Iterator>(x, d, i, no_match_so_far);
55 if constexpr ( std::is_void_v<Result> ) {
58 if constexpr ( has_callback<Dispatcher, CBc> ) {
59 no_match_so_far =
false;
63 if constexpr ( has_callback<Dispatcher, CBcIP> ) {
64 no_match_so_far =
false;
76 if constexpr ( has_callback<Dispatcher, CBc> ) {
77 no_match_so_far =
false;
81 if constexpr ( has_callback<Dispatcher, CBcIP> ) {
82 no_match_so_far =
false;
90 template<
typename Result,
typename Erased,
typename Dispatcher,
typename Iterator>
91 DispatchResult<Result> do_dispatch(Erased& n, Dispatcher& d,
typename Iterator::Position& i,
92 bool& no_match_so_far) {
93 auto& tn = n.typeid_();
95 #ifdef VISITOR_DISPATCHERS 98 #error "VISITOR_DISPATCHERS not defined, did you include 'autogen/dispatchers.h'?" 101 if constexpr ( std::is_void_v<Result> )
102 return ! no_match_so_far;
109 template<
typename Erased, Order order,
bool isConst>
112 using E = std::conditional_t<isConst, const Erased&, Erased&>;
117 Iterator(E root) { _path.emplace_back(root, -1); }
128 Position operator*()
const {
return current(); }
132 bool operator==(
const Iterator& other)
const {
return _path.empty() && other._path.empty(); }
134 bool operator!=(
const Iterator& other)
const {
return ! (*
this == other); }
141 auto& p = _path.back();
144 if ( p.child == -1 ) {
145 if constexpr ( order == Order::Pre )
152 assert(p.child >= 0);
154 if ( p.child < static_cast<int>(p.node.childs().size()) ) {
155 _path.emplace_back(p.node.childs()[p.child], -2);
160 if ( p.child == static_cast<int>(p.node.childs().size()) ) {
161 if constexpr ( order == Order::Post )
167 if ( p.child > static_cast<int>(p.node.childs().size()) ) {
176 throw std::runtime_error(
"invalid reference of visitor's iterator");
178 auto& p = _path.back();
183 if ( p.child == static_cast<int>(p.node.childs().size()) )
186 assert(p.child < static_cast<int>(p.node.childs().size()));
187 return Position{.
node = p.node.childs()[p.child], .path = _path};
190 std::vector<Location> _path;
193 template<
typename Visitor>
198 ConstView(
const typename Visitor::erased_t& root) : _root(root) {}
201 if constexpr ( Visitor::order_ == Order::Pre )
202 return iterator_t(_root);
204 return ++iterator_t(_root);
207 auto end() {
return iterator_t(); }
210 const typename Visitor::erased_t& _root;
213 template<
typename Visitor>
218 NonConstView(
typename Visitor::erased_t& root) : _root(root) {}
221 if constexpr ( Visitor::order_ == Order::Pre )
222 return iterator_t(_root);
224 return ++iterator_t(_root);
227 auto end() {
return iterator_t(); }
230 typename Visitor::erased_t& _root;
241 template<
typename Result,
typename Dispatcher,
typename Erased, Order order>
245 using erased_t = Erased;
247 using visitor_t = Dispatcher;
252 static const Order order_ = order;
257 virtual void preDispatch(
const Erased& ,
int ){};
261 bool no_match_so_far =
true;
262 preDispatch(i.node, i.pathLength());
263 return do_dispatch<Result, Erased, Dispatcher, iterator_t>(i.node, *
static_cast<Dispatcher*
>(
this), i,
269 bool no_match_so_far =
true;
270 preDispatch(i.node, i.pathLength());
271 return do_dispatch<Result, const Erased, Dispatcher, const_iterator_t>(i.node, *
static_cast<Dispatcher*
>(
this),
282 bool no_match_so_far =
true;
283 std::vector<typename iterator_t::Location> path;
284 position_t i = {*n, path};
286 return do_dispatch<Result, Erased, Dispatcher, iterator_t>(*n, *
static_cast<Dispatcher*
>(
this), i,
298 bool no_match_so_far =
true;
299 std::vector<typename iterator_t::Location> path;
300 position_t i = {n_, path};
302 return do_dispatch<Result, Erased, Dispatcher, iterator_t>(n_, *
static_cast<Dispatcher*
>(
this), i,
329 using NoDispatcher =
struct {};
337 template<
typename Result =
void,
typename Dispatcher = detail::visitor::NoDispatcher,
typename Erased = Node>
343 template<
typename Result =
void,
typename Dispatcher = detail::visitor::NoDispatcher,
typename Erased = Node>
auto walk(Erased *root)
Definition: visitor.h:326
Definition: visitor-types.h:26
Definition: optional.h:79
auto dispatch(const_position_t &i)
Definition: visitor.h:268
E node
Definition: visitor-types.h:31
auto dispatch(position_t &i)
Definition: visitor.h:260
Definition: visitor.h:214
auto walk(const Erased &root)
Definition: visitor.h:315
Definition: visitor.h:110
Definition: visitor.h:194
auto dispatch(const Erased &n)
Definition: visitor.h:296
Definition: visitor.h:242
auto dispatch(Erased *n)
Definition: visitor.h:281
Definition: visitor-types.h:12