Jlm
MatchType.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2025 Helge Bahmann <hcb@chaoticmind.net>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_RVSDG_MATCH_TYPE_HPP
7 #define JLM_RVSDG_MATCH_TYPE_HPP
8 
9 #include <stdexcept>
10 #include <string>
11 #include <tuple>
12 
13 namespace jlm::rvsdg
14 {
15 
22 template<typename MFP>
24 
25 // Partial specialization to deduce type from non-const member function pointers.
26 template<typename MFP, typename Ret, typename... Args>
27 struct member_function_pointer_argtype<Ret (MFP::*)(Args...)>
28 {
29  // Deduce for non-const member functions.
30  using type = std::tuple_element_t<0, std::tuple<Args...>>;
31 };
32 
33 // Partial specialization to deduce type from const member function pointers.
34 template<typename MFP, typename Ret, typename... Args>
35 struct member_function_pointer_argtype<Ret (MFP::*)(Args...) const>
36 {
37  // Deduce for const member functions.
38  using type = std::tuple_element_t<0, std::tuple<Args...>>;
39 };
40 
47 template<typename MFP>
49 
50 // Partial specialization to deduce type from non-const member function pointers.
51 template<typename MFP, typename Ret, typename... Args>
52 struct member_function_pointer_restype<Ret (MFP::*)(Args...)>
53 {
54  // Deduce for non-const member functions.
55  using type = Ret;
56 };
57 
58 // Partial specialization to deduce type from const member function pointers.
59 template<typename MFP, typename Ret, typename... Args>
60 struct member_function_pointer_restype<Ret (MFP::*)(Args...) const>
61 {
62  // Deduce for const member functions.
63  using type = Ret;
64 };
65 
72 template<typename Callable>
74 {
75  // Deduce for object types.
76  using type = typename member_function_pointer_argtype<decltype(&Callable::operator())>::type;
77 };
78 
79 // Partial specialization to deduce if callabale object is a function pointer type.
80 template<typename Ret, typename... Args>
81 struct CallableArgumentType<Ret(Args...)>
82 {
83  // Specialization to deduce for function pointer types.
84  using type = std::tuple_element_t<0, std::tuple<Args...>>;
85 };
86 
93 template<typename Callable>
95 {
96  // Deduce for object types.
97  using type = typename member_function_pointer_restype<decltype(&Callable::operator())>::type;
98 };
99 
100 // Partial specialization to deduce if callable object is a function pointer type.
101 template<typename Ret, typename... Args>
102 struct CallableResultType<Ret(Args...)>
103 {
104  // Specialization to deduce for function pointer types.
105  using type = Ret;
106 };
107 
122 template<typename T, typename... Fns>
123 void
124 MatchType(T & obj, const Fns &... fns);
125 
126 // Specialization to handle the termination (empty handlers) case.
127 template<typename T>
128 void
129 MatchType(T & x)
130 {}
131 
132 // Specialization to handle the head case.
133 template<typename T, typename Fn, typename... Fns>
134 void
135 MatchType(T & x, const Fn & fn, const Fns &... fns)
136 {
138  if (auto i = dynamic_cast<S *>(&x))
139  {
140  fn(*i);
141  }
142  else
143  {
144  MatchType(x, fns...);
145  }
146 };
147 
165 template<typename T, typename... Fns>
166 void
167 MatchTypeWithDefault(T & obj, const Fns &... fns);
168 
169 // Specialization to handle the termination (empty handlers) case.
170 template<typename T, typename Fn>
172 MatchTypeWithDefault(T & /* x */, const Fn & fn)
173 {
174  return fn();
175 }
176 
177 // Specialization to handle the head case.
178 template<typename T, typename Fn, typename... Fns>
180 MatchTypeWithDefault(T & x, const Fn & fn, const Fns &... fns)
181 {
183  if (auto i = dynamic_cast<S *>(&x))
184  {
185  return fn(*i);
186  }
187  else
188  {
189  return MatchTypeWithDefault(x, fns...);
190  }
191 };
192 
208 template<typename T, typename... Fns>
209 void
210 MatchTypeOrFail(T & obj, const Fns &... fns);
211 
212 // Specialization to handle the termination (last handler) case.
213 template<typename T, typename Fn>
215 MatchTypeOrFail(T & x, const Fn & fn)
216 {
218  if (auto i = dynamic_cast<S *>(&x))
219  {
220  return fn(*i);
221  }
222  else
223  {
224  throw std::logic_error(std::string("Incomplete pattern matching on ") + typeid(T).name());
225  }
226 }
227 
228 // Specialization to handle the head case.
229 template<typename T, typename Fn, typename... Fns>
231 MatchTypeOrFail(T & x, const Fn & fn, const Fns &... fns)
232 {
234  if (auto i = dynamic_cast<S *>(&x))
235  {
236  return fn(*i);
237  }
238  else
239  {
240  return MatchTypeOrFail(x, fns...);
241  }
242 };
243 
244 }
245 
246 #endif
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
void MatchTypeOrFail(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
void MatchType(T &obj, const Fns &... fns)
Pattern match over subclass type of given object.
static std::string type(const Node *n)
Definition: view.cpp:255
std::tuple_element_t< 0, std::tuple< Args... > > type
Definition: MatchType.hpp:84
Template helper to deduce first argument of a callable object.
Definition: MatchType.hpp:74
typename member_function_pointer_argtype< decltype(&Callable::operator())>::type type
Definition: MatchType.hpp:76
Template helper to deduce result of a callable object.
Definition: MatchType.hpp:95
typename member_function_pointer_restype< decltype(&Callable::operator())>::type type
Definition: MatchType.hpp:97
std::tuple_element_t< 0, std::tuple< Args... > > type
Definition: MatchType.hpp:38
std::tuple_element_t< 0, std::tuple< Args... > > type
Definition: MatchType.hpp:30
Template helper to deduce argument type of member function pointer.
Definition: MatchType.hpp:23
Template helper to deduce result type of member function pointer.
Definition: MatchType.hpp:48