v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
utils.cc
Go to the documentation of this file.
1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/torque/utils.h"
6
7#include <algorithm>
8#include <fstream>
9#include <iostream>
10#include <optional>
11#include <string>
12
13#include "src/base/bits.h"
14#include "src/base/logging.h"
15#include "src/torque/ast.h"
18
19EXPORT_CONTEXTUAL_VARIABLE(v8::internal::torque::TorqueMessages)
20
21namespace v8::internal::torque {
22
23std::string StringLiteralUnquote(const std::string& s) {
24 DCHECK(('"' == s.front() && '"' == s.back()) ||
25 ('\'' == s.front() && '\'' == s.back()));
26 std::stringstream result;
27 for (size_t i = 1; i < s.length() - 1; ++i) {
28 if (s[i] == '\\') {
29 switch (s[++i]) {
30 case 'n':
31 result << '\n';
32 break;
33 case 'r':
34 result << '\r';
35 break;
36 case 't':
37 result << '\t';
38 break;
39 case '\'':
40 case '"':
41 case '\\':
42 result << s[i];
43 break;
44 default:
46 }
47 } else {
48 result << s[i];
49 }
50 }
51 return result.str();
52}
53
54std::string StringLiteralQuote(const std::string& s) {
55 std::stringstream result;
56 result << '"';
57 for (size_t i = 0; i < s.length(); ++i) {
58 switch (s[i]) {
59 case '\n':
60 result << "\\n";
61 break;
62 case '\r':
63 result << "\\r";
64 break;
65 case '\t':
66 result << "\\t";
67 break;
68 case '"':
69 case '\\':
70 result << "\\" << s[i];
71 break;
72 default:
73 result << s[i];
74 }
75 }
76 result << '"';
77 return result.str();
78}
79
80#ifdef V8_OS_WIN
81static const char kFileUriPrefix[] = "file:///";
82#else
83static const char kFileUriPrefix[] = "file://";
84#endif
85static const int kFileUriPrefixLength = sizeof(kFileUriPrefix) - 1;
86
87static int HexCharToInt(unsigned char c) {
88 if (isdigit(c)) return c - '0';
89 if (isupper(c)) return c - 'A' + 10;
90 DCHECK(islower(c));
91 return c - 'a' + 10;
92}
93
94std::optional<std::string> FileUriDecode(const std::string& uri) {
95 // Abort decoding of URIs that don't start with "file://".
96 if (uri.rfind(kFileUriPrefix) != 0) return std::nullopt;
97
98 const std::string path = uri.substr(kFileUriPrefixLength);
99 std::ostringstream decoded;
100
101 for (auto iter = path.begin(), end = path.end(); iter != end; ++iter) {
102 std::string::value_type c = (*iter);
103
104 // Normal characters are appended.
105 if (c != '%') {
106 decoded << c;
107 continue;
108 }
109
110 // If '%' is not followed by at least two hex digits, we abort.
111 if (std::distance(iter, end) <= 2) return std::nullopt;
112
113 unsigned char first = (*++iter);
114 unsigned char second = (*++iter);
115 if (!isxdigit(first) || !isxdigit(second)) return std::nullopt;
116
117 // An escaped hex value needs converting.
118 unsigned char value = HexCharToInt(first) * 16 + HexCharToInt(second);
119 decoded << value;
120 }
121
122 return decoded.str();
123}
124
125MessageBuilder::MessageBuilder(const std::string& message,
127 std::optional<SourcePosition> position;
128 if (CurrentSourcePosition::HasScope()) {
129 position = CurrentSourcePosition::Get();
130 }
131 message_ = TorqueMessage{message, position, kind};
132 if (CurrentScope::HasScope()) {
133 // Traverse the parent scopes to find one that was created to represent a
134 // specialization of something generic. If we find one, then log it and
135 // continue walking the scope tree of the code that requested that
136 // specialization. This allows us to collect the stack of locations that
137 // caused a specialization.
138 Scope* scope = CurrentScope::Get();
139 while (scope) {
141 if (!requester.IsNone()) {
142 extra_messages_.push_back(
143 {"Note: in specialization " + requester.name + " requested here",
144 requester.position, kind});
145 scope = requester.scope;
146 } else {
147 scope = scope->ParentScope();
148 }
149 }
150 }
151}
152
154 TorqueMessages::Get().push_back(message_);
155 for (const auto& message : extra_messages_) {
156 TorqueMessages::Get().push_back(message);
157 }
158}
159
160[[noreturn]] void MessageBuilder::Throw() const {
162}
163
164namespace {
165
166bool ContainsUnderscore(const std::string& s) {
167 if (s.empty()) return false;
168 return s.find("_") != std::string::npos;
169}
170
171bool ContainsUpperCase(const std::string& s) {
172 if (s.empty()) return false;
173 return std::any_of(s.begin(), s.end(), [](char c) { return isupper(c); });
174}
175
176// Torque has some namespace constants that are used like language level
177// keywords, e.g.: 'True', 'Undefined', etc.
178// These do not need to follow the default naming convention for constants.
179bool IsKeywordLikeName(const std::string& s) {
180 static const char* const keyword_like_constants[]{
181 "True", "False", "TheHole", "PromiseHole", "Null", "Undefined"};
182
183 return std::find(std::begin(keyword_like_constants),
184 std::end(keyword_like_constants),
185 s) != std::end(keyword_like_constants);
186}
187
188// Untagged/MachineTypes like 'int32', 'intptr' etc. follow a 'all-lowercase'
189// naming convention and are those exempt from the normal type convention.
190bool IsMachineType(const std::string& s) {
191 static const char* const machine_types[]{
211 "string",
215 return std::find(std::begin(machine_types), std::end(machine_types), s) !=
216 std::end(machine_types);
217}
218
219} // namespace
220
221bool IsLowerCamelCase(const std::string& s) {
222 if (s.empty()) return false;
223 size_t start = 0;
224 if (s[0] == '_') start = 1;
225 return islower(s[start]) && !ContainsUnderscore(s.substr(start));
226}
227
228bool IsUpperCamelCase(const std::string& s) {
229 if (s.empty()) return false;
230 size_t start = 0;
231 if (s[0] == '_') start = 1;
232 return isupper(s[start]);
233}
234
235bool IsSnakeCase(const std::string& s) {
236 if (s.empty()) return false;
237 return !ContainsUpperCase(s);
238}
239
240bool IsValidNamespaceConstName(const std::string& s) {
241 if (s.empty()) return false;
242 if (IsKeywordLikeName(s)) return true;
243
244 return s[0] == 'k' && IsUpperCamelCase(s.substr(1));
245}
246
247bool IsValidTypeName(const std::string& s) {
248 if (s.empty()) return false;
249 if (IsMachineType(s)) return true;
250
251 return IsUpperCamelCase(s);
252}
253
254std::string CapifyStringWithUnderscores(const std::string& camellified_string) {
255 // Special case: JSAbc yields JS_ABC, not JSABC, for any Abc.
256 size_t js_position = camellified_string.find("JS");
257
258 std::string result;
259 bool previousWasLowerOrDigit = false;
260 for (size_t index = 0; index < camellified_string.size(); ++index) {
261 char current = camellified_string[index];
262 if ((previousWasLowerOrDigit && isupper(current)) ||
263 (js_position != std::string::npos &&
264 index == js_position + strlen("JS"))) {
265 result += "_";
266 }
267 if (current == '.' || current == '-') {
268 result += "_";
269 previousWasLowerOrDigit = false;
270 continue;
271 }
272 result += toupper(current);
273 previousWasLowerOrDigit = islower(current) || isdigit(current);
274 }
275 return result;
276}
277
278std::string CamelifyString(const std::string& underscore_string) {
279 std::string result;
280 bool word_beginning = true;
281 for (auto current : underscore_string) {
282 if (current == '_' || current == '-') {
283 word_beginning = true;
284 continue;
285 }
286 if (word_beginning) {
287 current = toupper(current);
288 }
289 result += current;
290 word_beginning = false;
291 }
292 return result;
293}
294
295std::string SnakeifyString(const std::string& camel_string) {
296 std::string result;
297 bool previousWasLower = false;
298 for (auto current : camel_string) {
299 if (previousWasLower && isupper(current)) {
300 result += "_";
301 }
302 result += tolower(current);
303 previousWasLower = (islower(current));
304 }
305 return result;
306}
307
308std::string DashifyString(const std::string& underscore_string) {
309 std::string result = underscore_string;
310 std::replace(result.begin(), result.end(), '_', '-');
311 return result;
312}
313
314std::string UnderlinifyPath(std::string path) {
315 std::replace(path.begin(), path.end(), '-', '_');
316 std::replace(path.begin(), path.end(), '/', '_');
317 std::replace(path.begin(), path.end(), '\\', '_');
318 std::replace(path.begin(), path.end(), '.', '_');
319 transform(path.begin(), path.end(), path.begin(), ::toupper);
320 return path;
321}
322
323bool StartsWithSingleUnderscore(const std::string& str) {
324 return str.length() >= 2 && str[0] == '_' && str[1] != '_';
325}
326
327void ReplaceFileContentsIfDifferent(const std::string& file_path,
328 const std::string& contents) {
329 std::ifstream old_contents_stream(file_path.c_str());
330 std::string old_contents;
331 bool file_exists = false;
332 if (old_contents_stream.good()) {
333 file_exists = true;
334 std::istreambuf_iterator<char> eos;
335 old_contents =
336 std::string(std::istreambuf_iterator<char>(old_contents_stream), eos);
337 old_contents_stream.close();
338 }
339 if (!file_exists || old_contents != contents) {
340 std::ofstream new_contents_stream;
341 new_contents_stream.open(file_path.c_str());
342 new_contents_stream << contents;
343 new_contents_stream.close();
344 }
345}
346
347IfDefScope::IfDefScope(std::ostream& os, std::string d)
348 : os_(os), d_(std::move(d)) {
349 os_ << "#ifdef " << d_ << "\n";
350}
351IfDefScope::~IfDefScope() { os_ << "#endif // " << d_ << "\n"; }
352
354 std::initializer_list<std::string> namespaces)
355 : os_(os), d_(std::move(namespaces)) {
356 for (const std::string& s : d_) {
357 os_ << "namespace " << s << " {\n";
358 }
359}
361 for (auto i = d_.rbegin(); i != d_.rend(); ++i) {
362 os_ << "} // namespace " << *i << "\n";
363 }
364}
365
366IncludeGuardScope::IncludeGuardScope(std::ostream& os, std::string file_name)
367 : os_(os),
368 d_("V8_GEN_TORQUE_GENERATED_" + CapifyStringWithUnderscores(file_name) +
369 "_") {
370 os_ << "#ifndef " << d_ << "\n";
371 os_ << "#define " << d_ << "\n\n";
372}
373IncludeGuardScope::~IncludeGuardScope() { os_ << "#endif // " << d_ << "\n"; }
374
376 os_ << "\n// Has to be the last include (doesn't have include guards):\n"
377 "#include \"src/objects/object-macros.h\"\n";
378}
380 os_ << "\n#include \"src/objects/object-macros-undef.h\"\n";
381}
382
384 if (value_ == 0) return modulus_log_2_;
386}
387
389
390std::ostream& operator<<(std::ostream& os, const ResidueClass& a) {
391 if (a.SingleValue().has_value()) return os << *a.SingleValue();
392 return os << "[" << a.value_ << " mod 2^" << a.modulus_log_2_ << "]";
393}
394
395} // namespace v8::internal::torque
Builtins::Kind kind
Definition builtins.cc:40
IfDefScope(std::ostream &os, std::string d)
Definition utils.cc:347
IncludeGuardScope(std::ostream &os, std::string file_name)
Definition utils.cc:366
std::vector< TorqueMessage > extra_messages_
Definition utils.h:68
NamespaceScope(std::ostream &os, std::initializer_list< std::string > namespaces)
Definition utils.cc:353
std::vector< std::string > d_
Definition utils.h:388
static const size_t kMaxModulusLog2
Definition utils.h:492
const SpecializationRequester & GetSpecializationRequester() const
Definition declarable.h:201
#define EXPORT_CONTEXTUAL_VARIABLE(VarName)
Definition contextual.h:94
int start
int end
LineAndColumn current
double second
ZoneVector< RpoNumber > & result
int position
Definition liveedit.cc:290
STL namespace.
constexpr unsigned CountTrailingZeros(T value)
Definition bits.h:144
static const char *const INT31_TYPE_STRING
Definition constants.h:57
static const char kFileUriPrefix[]
Definition utils.cc:83
static const char *const NEVER_TYPE_STRING
Definition constants.h:18
static const char *const FLOAT32_TYPE_STRING
Definition constants.h:69
static const char *const BOOL_TYPE_STRING
Definition constants.h:24
bool IsUpperCamelCase(const std::string &s)
Definition utils.cc:228
std::string CapifyStringWithUnderscores(const std::string &camellified_string)
Definition utils.cc:254
static const char *const INT16_TYPE_STRING
Definition constants.h:61
static const char *const UINT64_TYPE_STRING
Definition constants.h:56
std::ostream & operator<<(std::ostream &os, Identifier *id)
Definition ast.h:263
static const char *const FLOAT16_RAW_BITS_TYPE_STRING
Definition constants.h:68
std::string StringLiteralQuote(const std::string &s)
Definition utils.cc:54
static const char *const INT8_TYPE_STRING
Definition constants.h:63
void ReplaceFileContentsIfDifferent(const std::string &file_path, const std::string &contents)
Definition utils.cc:327
static const char *const INT32_TYPE_STRING
Definition constants.h:58
static const char *const UINT8_TYPE_STRING
Definition constants.h:64
static const char *const FLOAT64_OR_UNDEFINED_OR_HOLE_TYPE_STRING
Definition constants.h:71
static const char *const VOID_TYPE_STRING
Definition constants.h:25
static const char *const UINTPTR_TYPE_STRING
Definition constants.h:54
static const char *const BINT_TYPE_STRING
Definition constants.h:65
static const char *const UINT16_TYPE_STRING
Definition constants.h:62
static const char *const UINT32_TYPE_STRING
Definition constants.h:60
std::string SnakeifyString(const std::string &camel_string)
Definition utils.cc:295
static const char *const CHAR8_TYPE_STRING
Definition constants.h:66
static const char *const INTPTR_TYPE_STRING
Definition constants.h:53
static const char *const INT64_TYPE_STRING
Definition constants.h:55
static int HexCharToInt(unsigned char c)
Definition utils.cc:87
bool IsValidTypeName(const std::string &s)
Definition utils.cc:247
std::string DashifyString(const std::string &underscore_string)
Definition utils.cc:308
bool StartsWithSingleUnderscore(const std::string &str)
Definition utils.cc:323
static const int kFileUriPrefixLength
Definition utils.cc:85
bool IsSnakeCase(const std::string &s)
Definition utils.cc:235
std::string CamelifyString(const std::string &underscore_string)
Definition utils.cc:278
std::optional< std::string > FileUriDecode(const std::string &uri)
Definition utils.cc:94
bool IsLowerCamelCase(const std::string &s)
Definition utils.cc:221
bool IsValidNamespaceConstName(const std::string &s)
Definition utils.cc:240
std::string UnderlinifyPath(std::string path)
Definition utils.cc:314
static const char *const FLOAT64_TYPE_STRING
Definition constants.h:70
static const char *const CHAR16_TYPE_STRING
Definition constants.h:67
std::string StringLiteralUnquote(const std::string &s)
Definition utils.cc:23
static const char *const UINT31_TYPE_STRING
Definition constants.h:59
return value
Definition map-inl.h:893
base::Vector< const char > contents
#define DCHECK(condition)
Definition logging.h:482
std::ostream * os_