-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmangle.cc
More file actions
90 lines (74 loc) · 2.08 KB
/
mangle.cc
File metadata and controls
90 lines (74 loc) · 2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <sourcemeta/codegen/generator.h>
namespace {
auto is_alpha(char character) -> bool {
return (character >= 'a' && character <= 'z') ||
(character >= 'A' && character <= 'Z');
}
auto is_digit(char character) -> bool {
return character >= '0' && character <= '9';
}
auto to_upper(char character) -> char {
if (character >= 'a' && character <= 'z') {
return static_cast<char>(character - 'a' + 'A');
}
return character;
}
auto symbol_to_identifier(const std::string_view prefix,
const std::vector<std::string> &symbol)
-> std::string {
std::string result{prefix};
for (const auto &segment : symbol) {
if (segment.empty()) {
continue;
}
bool first_in_segment{true};
for (const auto character : segment) {
if (is_alpha(character)) {
if (first_in_segment) {
result += to_upper(character);
first_in_segment = false;
} else {
result += character;
}
} else if (is_digit(character)) {
if (first_in_segment) {
result += '_';
}
result += character;
first_in_segment = false;
} else if (character == '_' || character == '$') {
result += character;
first_in_segment = false;
}
}
}
if (result.empty()) {
return "_";
}
if (is_digit(result[0])) {
result.insert(0, "_");
}
return result;
}
} // namespace
namespace sourcemeta::codegen {
auto mangle(const std::string_view prefix,
const sourcemeta::core::Pointer &pointer,
const std::vector<std::string> &symbol,
std::map<std::string, sourcemeta::core::Pointer> &cache)
-> const std::string & {
auto name{symbol_to_identifier(prefix, symbol)};
while (true) {
auto iterator{cache.find(name)};
if (iterator != cache.end()) {
if (iterator->second == pointer) {
return iterator->first;
}
name.insert(0, "_");
} else {
auto result{cache.insert({std::move(name), pointer})};
return result.first->first;
}
}
}
} // namespace sourcemeta::codegen