@@ -30,6 +30,9 @@ class SafeNames::Impl
30
30
{
31
31
Corpus const & corpus_;
32
32
33
+ // name used for the global namespace
34
+ std::string global_ns_;
35
+
33
36
// store all info required to generate a safename
34
37
struct SafeNameInfo
35
38
{
@@ -44,6 +47,11 @@ class SafeNames::Impl
44
47
45
48
std::unordered_map<SymbolID, SafeNameInfo> map_;
46
49
50
+ // maps unqualified names to all symbols
51
+ // with that name within the current scope
52
+ std::unordered_multimap<
53
+ std::string_view, SafeNameInfo*> disambiguation_map__;
54
+
47
55
std::string_view
48
56
getReserved (const Info& I)
49
57
{
@@ -97,16 +105,13 @@ class SafeNames::Impl
97
105
getUnqualified (
98
106
const Info& I)
99
107
{
108
+ MRDOX_ASSERT (I.id != SymbolID::zero);
100
109
return visit (I, [&]<typename T>(
101
110
const T& t) -> std::string_view
102
111
{
103
112
// namespaces can be unnamed (i.e. anonymous)
104
113
if constexpr (T::isNamespace ())
105
114
{
106
- // special case for the global namespace
107
- if (t.id == SymbolID::zero)
108
- return std::string_view ();
109
-
110
115
if (t.specs .isAnonymous .get ())
111
116
return getReserved (t);
112
117
MRDOX_ASSERT (! t.Name .empty ());
@@ -184,6 +189,73 @@ class SafeNames::Impl
184
189
185
190
// --------------------------------------------
186
191
192
+ void
193
+ buildSafeMember (
194
+ const Info& I,
195
+ std::string_view name)
196
+ {
197
+ // generate the unqualified name and SymbolID string
198
+ auto it = map_.emplace (I.id , SafeNameInfo (
199
+ name, 0 , toBase16 (I.id , true ))).first ;
200
+ #if 0
201
+ // update the disambiguation map
202
+ auto [disambig_it, disambig_emplaced] =
203
+ disambiguation_map_.try_emplace(name);
204
+ // if there are other symbols with the same name, then disambiguation
205
+ // is required. iterate over the other symbols with the same unqualified name,
206
+ // and calculate the minimum number of characters from the SymbolID needed
207
+ // to uniquely identify each symbol. then, update all symbols with the new value.
208
+ if(! disambig_emplaced)
209
+ {
210
+ std::uint8_t n_chars = 0;
211
+ std::string_view id_str = it->second.id_str;
212
+ for(const SymbolID& other_id : disambig_it->second)
213
+ {
214
+ auto& other = map_.at(other_id);
215
+ auto mismatch_it = std::ranges::mismatch(
216
+ id_str, other.id_str).in1;
217
+ std::uint8_t n_required = std::distance(
218
+ id_str.begin(), mismatch_it) + 1;
219
+ n_chars = std::max({
220
+ n_chars, other.disambig_chars, n_required});
221
+ }
222
+
223
+ MRDOX_ASSERT(n_chars);
224
+ // update the number of disambiguation characters for each symbol
225
+ it->second.disambig_chars = n_chars;
226
+ for(const SymbolID& other_id : disambig_it->second)
227
+ map_.at(other_id).disambig_chars = n_chars;
228
+ }
229
+ disambig_it->second.push_back(I.id);
230
+ #else
231
+ std::uint8_t n_chars = 0 ;
232
+ std::string_view id_str = it->second .id_str ;
233
+ auto [first, last] = disambiguation_map__.equal_range (name);
234
+ for (const auto & other : std::ranges::subrange (
235
+ first, last) | std::views::values)
236
+ {
237
+ // auto& other = map_.at(other_id);
238
+ auto mismatch_it = std::ranges::mismatch (
239
+ id_str, other->id_str ).in1 ;
240
+ std::uint8_t n_required = std::distance (
241
+ id_str.begin (), mismatch_it) + 1 ;
242
+ n_chars = std::max ({
243
+ n_chars, other->disambig_chars , n_required});
244
+ }
245
+
246
+ if (n_chars)
247
+ {
248
+ for (const auto & other : std::ranges::subrange (
249
+ first, last) | std::views::values)
250
+ other->disambig_chars = n_chars;
251
+ it->second .disambig_chars = n_chars;
252
+ }
253
+ disambiguation_map__.emplace (name, &it->second );
254
+
255
+ #endif
256
+ }
257
+
258
+ #if 0
187
259
template<typename Range>
188
260
void
189
261
buildSafeMembers(
@@ -237,18 +309,32 @@ class SafeNames::Impl
237
309
disambig_it->second.push_back(I->id);
238
310
}
239
311
}
312
+ #endif
240
313
241
314
// --------------------------------------------
242
315
243
316
public:
244
- explicit
245
- Impl (Corpus const & corpus)
317
+ Impl (Corpus const & corpus, std::string_view global_ns)
246
318
: corpus_(corpus)
319
+ , global_ns_(global_ns)
247
320
{
321
+ #if 0
248
322
map_.try_emplace(SymbolID::zero, SafeNameInfo(
249
323
"global_namespace", 0, toBase16(SymbolID::zero, true)));
250
324
251
325
visit(corpus_.globalNamespace(), *this);
326
+ #else
327
+ const NamespaceInfo& global =
328
+ corpus_.globalNamespace ();
329
+ // treat the global namespace as-if its "name"
330
+ // is in the same scope as its members
331
+ buildSafeMember (global, global_ns_);
332
+ visit (global, *this );
333
+ // after generating safenames for every symbol,
334
+ // set the number of disambiguation characters
335
+ // used for the global namespace to zero
336
+ map_.at (global.id ).disambig_chars = 0 ;
337
+ #endif
252
338
}
253
339
254
340
void
@@ -297,6 +383,48 @@ class SafeNames::Impl
297
383
getSafeUnqualified (result, id);
298
384
}
299
385
386
+ template <typename InfoTy, typename Fn>
387
+ void traverse (const InfoTy& I, Fn&& F)
388
+ {
389
+ static constexpr auto getMember = [](const auto & M)
390
+ {
391
+ if constexpr (requires { M.Specialized ; })
392
+ return M.Specialized ;
393
+ else
394
+ return M;
395
+ };
396
+
397
+ if constexpr (InfoTy::isSpecialization () ||
398
+ InfoTy::isNamespace () || InfoTy::isRecord ())
399
+ {
400
+ std::ranges::for_each (I.Members , F, getMember);
401
+ }
402
+
403
+ if constexpr (InfoTy::isNamespace () || InfoTy::isRecord ())
404
+ {
405
+ std::ranges::for_each (I.Specializations , F);
406
+ }
407
+ }
408
+
409
+ template <typename InfoTy>
410
+ void operator ()(const InfoTy& I)
411
+ {
412
+ traverse (I, [this ](const SymbolID& id)
413
+ {
414
+ if (const Info* M = corpus_.find (id))
415
+ buildSafeMember (*M, getUnqualified (*M));
416
+ });
417
+ // clear the disambiguation map after visiting the members,
418
+ // then build disambiguation information for each member
419
+ disambiguation_map__.clear ();
420
+ traverse (I, [this ](const SymbolID& id)
421
+ {
422
+ if (const Info* M = corpus_.find (id))
423
+ visit (*M, *this );
424
+ });
425
+ }
426
+
427
+ #if 0
300
428
template<class T>
301
429
void operator()(T const& I)
302
430
{
@@ -330,13 +458,14 @@ class SafeNames::Impl
330
458
}
331
459
}
332
460
}
461
+ #endif
333
462
};
334
463
335
464
// ------------------------------------------------
336
465
337
466
SafeNames::
338
467
SafeNames (Corpus const & corpus)
339
- : impl_(std::make_unique<Impl>(corpus))
468
+ : impl_(std::make_unique<Impl>(corpus, " index " ))
340
469
{
341
470
}
342
471
0 commit comments