mimic++ v9.2.1
Loading...
Searching...
No Matches
NamePrintVisitor.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_PRINTING_TYPE_NAME_PRINT_VISITOR_HPP
7#define MIMICPP_PRINTING_TYPE_NAME_PRINT_VISITOR_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
14
15#ifndef MIMICPP_DETAIL_IS_MODULE
16 #include <algorithm>
17 #include <ranges>
18 #include <type_traits>
19 #include <unordered_map>
20 #include <unordered_set>
21 #include <utility>
22 #include <vector>
23#endif
24
26{
27 [[nodiscard]]
28 inline auto const& alias_map()
29 {
30 static std::unordered_map<StringViewT, StringViewT> const aliases{
31 {"(anonymous namespace)", "{anon-ns}"},
32 { "{anonymous}", "{anon-ns}"},
33 {"anonymous namespace", "{anon-ns}"},
34 {"anonymous-namespace", "{anon-ns}"},
35 { "<lambda()>", "lambda"}
36 };
37
38 return aliases;
39 }
40
41 [[nodiscard]]
42 inline auto const& ignored_identifiers()
43 {
44 static std::unordered_set<StringViewT> const collection{
45 "__cxx11",
46 "__1"};
47
48 return collection;
49 }
50
51 template <print_iterator OutIter>
53 {
54 public:
55 [[nodiscard]]
56 explicit PrintVisitor(OutIter out) noexcept(std::is_nothrow_move_constructible_v<OutIter>)
57 : m_Out{std::move(out)}
58 {
59 }
60
61 [[nodiscard]]
62 constexpr OutIter out() const noexcept
63 {
64 return m_Out;
65 }
66
67 constexpr void unrecognized(StringViewT const content)
68 {
69 print(content);
70 }
71
72 static constexpr void begin()
73 {
74 }
75
76 static constexpr void end()
77 {
78 }
79
80 static constexpr void begin_type()
81 {
82 }
83
84 static constexpr void end_type()
85 {
86 }
87
88 constexpr void begin_scope()
89 {
90 m_Context.push_scope();
91 }
92
93 constexpr void end_scope()
94 {
95 if (!std::exchange(m_IgnoreNextScopeResolution, false))
96 {
97 print("::");
98 }
99
100 m_Context.pop_scope();
101 }
102
103 constexpr void add_identifier(StringViewT content)
104 {
105 if (content.starts_with("{lambda(")
106 && content.ends_with('}'))
107 {
108 auto const closingIter = std::ranges::find(content.crbegin(), content.crend(), ')');
109 print("lambda");
110 print(StringViewT{closingIter.base(), content.cend() - 1});
111
112 return;
113 }
114
115 // Lambdas can have the for `'lambda\\d*'`. Just print everything between ''.
116 if (constexpr StringViewT lambdaPrefix{"'lambda"};
117 content.starts_with(lambdaPrefix)
118 && content.ends_with('\''))
119 {
120 print(content.substr(1u, content.size() - 2u));
121
122 return;
123 }
124
125 // Msvc yields lambdas in form of `<lambda_\d+>`
126 if (constexpr StringViewT lambdaPrefix{"<lambda_"};
127 content.starts_with(lambdaPrefix)
128 && content.ends_with('>'))
129 {
130 print("lambda");
131
132 auto const numberBegin = content.cbegin() + lambdaPrefix.size();
133 if (auto const numberEnd = std::ranges::find_if_not(numberBegin, content.cend() - 1u, lexing::is_digit);
134 numberBegin != numberEnd)
135 {
136 print("#");
137 print({numberBegin, numberEnd});
138 }
139
140 return;
141 }
142
143 if (content.starts_with('`')
144 && content.ends_with('\''))
145 {
146 // msvc injects `\d+' as auxiliar namespaces. Ignore them.
147 if (std::ranges::all_of(content.substr(1u, content.size() - 2u), lexing::is_digit))
148 {
149 m_IgnoreNextScopeResolution = true;
150
151 return;
152 }
153
154 content = content.substr(1u, content.size() - 2u);
155 }
156
157 if (ignored_identifiers().contains(content))
158 {
159 m_IgnoreNextScopeResolution = true;
160
161 return;
162 }
163
164 auto const& aliases = alias_map();
165 if (auto const iter = aliases.find(content);
166 iter != aliases.cend())
167 {
168 content = iter->second;
169 }
170 print(content);
171 }
172
173 constexpr void begin_template_args([[maybe_unused]] std::ptrdiff_t const count)
174 {
175 m_Context.push_arg_sequence();
176
177 print("<");
178 }
179
180 constexpr void end_template_args()
181 {
182 print(">");
183
184 m_Context.pop_arg_sequence();
185 }
186
187 constexpr void add_arg()
188 {
189 print(", ");
190 }
191
192 static constexpr void begin_function()
193 {
194 }
195
196 static constexpr void end_function()
197 {
198 }
199
200 static constexpr void begin_return_type()
201 {
202 }
203
204 constexpr void end_return_type()
205 {
206 print(" ");
207 }
208
209 constexpr void begin_function_args([[maybe_unused]] std::ptrdiff_t const count)
210 {
211 m_Context.push_arg_sequence();
212
213 print("(");
214 }
215
216 constexpr void end_function_args()
217 {
218 print(")");
219
220 m_Context.pop_arg_sequence();
221 }
222
223 constexpr void begin_function_ptr()
224 {
225 print("(");
226 }
227
228 constexpr void end_function_ptr()
229 {
230 print(")");
231 }
232
234 {
235 print("operator ");
236 }
237
238 static constexpr void end_operator_identifier()
239 {
240 }
241
242 constexpr void add_const()
243 {
244 if (m_Context.is_spec_printable())
245 {
246 print(" const");
247 }
248 }
249
250 constexpr void add_volatile()
251 {
252 if (m_Context.is_spec_printable())
253 {
254 print(" volatile");
255 }
256 }
257
258 constexpr void add_noexcept()
259 {
260 if (m_Context.is_spec_printable())
261 {
262 print(" noexcept");
263 }
264 }
265
266 constexpr void add_ptr()
267 {
268 if (m_Context.is_spec_printable())
269 {
270 print("*");
271 }
272 }
273
274 constexpr void add_lvalue_ref()
275 {
276 if (m_Context.is_spec_printable())
277 {
278 print("&");
279 }
280 }
281
282 constexpr void add_rvalue_ref()
283 {
284 if (m_Context.is_spec_printable())
285 {
286 print("&&");
287 }
288 }
289
290 private:
291 OutIter m_Out;
292 bool m_IgnoreNextScopeResolution{false};
293
294 class Context
295 {
296 public:
297 [[nodiscard]]
298 constexpr bool is_printable() const noexcept
299 {
300 if (auto const size = m_Stack.size();
301 size <= 1u)
302 {
303 return true;
304 }
305 else if (2u == size)
306 {
307 return Type::argSequence == m_Stack.front()
308 && Type::scope == m_Stack.back();
309 }
310
311 return false;
312 }
313
314 [[nodiscard]]
315 constexpr bool is_spec_printable() const noexcept
316 {
317 return 0 == m_ScopeDepth;
318 }
319
320 void push_scope()
321 {
322 m_Stack.emplace_back(Type::scope);
323 ++m_ScopeDepth;
324 }
325
326 void pop_scope()
327 {
328 MIMICPP_ASSERT(0 < m_ScopeDepth, "Unbalanced depth.");
329 --m_ScopeDepth;
330 MIMICPP_ASSERT(!m_Stack.empty() && Type::scope == m_Stack.back(), "Context-stack out of sync.");
331 m_Stack.pop_back();
332 }
333
334 void push_arg_sequence()
335 {
336 m_Stack.emplace_back(Type::argSequence);
337 ++m_ArgSeqDepth;
338 }
339
340 void pop_arg_sequence()
341 {
342 MIMICPP_ASSERT(0 < m_ArgSeqDepth, "Unbalanced depth.");
343 --m_ArgSeqDepth;
344 MIMICPP_ASSERT(!m_Stack.empty() && Type::argSequence == m_Stack.back(), "Context-stack out of sync.");
345 m_Stack.pop_back();
346 }
347
348 private:
349 enum class Type : std::uint8_t
350 {
351 scope,
352 argSequence
353 };
354
355 std::vector<Type> m_Stack{};
356 int m_ScopeDepth{};
357 int m_ArgSeqDepth{};
358 };
359
360 Context m_Context{};
361
362 constexpr void print(StringViewT const text)
363 {
364 if (m_Context.is_printable())
365 {
366 m_Out = std::ranges::copy(text, std::move(m_Out)).out;
367 }
368 }
369 };
370}
371
372#endif
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:51
constexpr void add_const()
Definition NamePrintVisitor.hpp:242
constexpr void end_function_args()
Definition NamePrintVisitor.hpp:216
constexpr void add_rvalue_ref()
Definition NamePrintVisitor.hpp:282
constexpr void unrecognized(StringViewT const content)
Definition NamePrintVisitor.hpp:67
constexpr void begin_operator_identifier()
Definition NamePrintVisitor.hpp:233
static constexpr void end_operator_identifier()
Definition NamePrintVisitor.hpp:238
constexpr void begin_function_ptr()
Definition NamePrintVisitor.hpp:223
constexpr void end_template_args()
Definition NamePrintVisitor.hpp:180
static constexpr void begin()
Definition NamePrintVisitor.hpp:72
constexpr void end_scope()
Definition NamePrintVisitor.hpp:93
constexpr void begin_scope()
Definition NamePrintVisitor.hpp:88
static constexpr void end_function()
Definition NamePrintVisitor.hpp:196
static constexpr void begin_type()
Definition NamePrintVisitor.hpp:80
constexpr void add_lvalue_ref()
Definition NamePrintVisitor.hpp:274
constexpr void begin_function_args(std::ptrdiff_t const count)
Definition NamePrintVisitor.hpp:209
constexpr OutIter out() const noexcept
Definition NamePrintVisitor.hpp:62
constexpr void add_identifier(StringViewT content)
Definition NamePrintVisitor.hpp:103
constexpr void begin_template_args(std::ptrdiff_t const count)
Definition NamePrintVisitor.hpp:173
constexpr void end_return_type()
Definition NamePrintVisitor.hpp:204
constexpr void add_ptr()
Definition NamePrintVisitor.hpp:266
constexpr void add_volatile()
Definition NamePrintVisitor.hpp:250
static constexpr void begin_function()
Definition NamePrintVisitor.hpp:192
constexpr void end_function_ptr()
Definition NamePrintVisitor.hpp:228
static constexpr void end()
Definition NamePrintVisitor.hpp:76
constexpr void add_arg()
Definition NamePrintVisitor.hpp:187
PrintVisitor(OutIter out) noexcept(std::is_nothrow_move_constructible_v< OutIter >)
Definition NamePrintVisitor.hpp:56
static constexpr void end_type()
Definition NamePrintVisitor.hpp:84
constexpr void add_noexcept()
Definition NamePrintVisitor.hpp:258
static constexpr void begin_return_type()
Definition NamePrintVisitor.hpp:200
constexpr printing::PrintFn print
Functional object, converting the given object to its textual representation.
Definition Print.hpp:183
auto constexpr is_digit
Definition NameLexer.hpp:34
Definition Fwd.hpp:54
auto const & alias_map()
Definition NamePrintVisitor.hpp:28
auto const & ignored_identifiers()
Definition NamePrintVisitor.hpp:42
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:392