Line data Source code
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 : #ifndef V8_TORQUE_UTILS_H_
6 : #define V8_TORQUE_UTILS_H_
7 :
8 : #include <ostream>
9 : #include <streambuf>
10 : #include <string>
11 : #include <unordered_set>
12 : #include <vector>
13 :
14 : #include "src/base/functional.h"
15 : #include "src/torque/contextual.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace torque {
20 :
21 : typedef std::vector<std::string> NameVector;
22 :
23 : std::string StringLiteralUnquote(const std::string& s);
24 : std::string StringLiteralQuote(const std::string& s);
25 :
26 : class LintErrorStatus : public ContextualClass<LintErrorStatus> {
27 : public:
28 1 : LintErrorStatus() : has_lint_errors_(false) {}
29 :
30 1 : static bool HasLintErrors() { return Get().has_lint_errors_; }
31 0 : static void SetLintError() { Get().has_lint_errors_ = true; }
32 :
33 : private:
34 : bool has_lint_errors_;
35 : };
36 :
37 : void LintError(const std::string& error);
38 :
39 : // Prints a LintError with the format "{type} '{name}' doesn't follow
40 : // '{convention}' naming convention".
41 : void NamingConventionError(const std::string& type, const std::string& name,
42 : const std::string& convention);
43 :
44 : bool IsLowerCamelCase(const std::string& s);
45 : bool IsUpperCamelCase(const std::string& s);
46 : bool IsSnakeCase(const std::string& s);
47 : bool IsValidNamespaceConstName(const std::string& s);
48 : bool IsValidTypeName(const std::string& s);
49 :
50 : [[noreturn]] void ReportErrorString(const std::string& error);
51 : template <class... Args>
52 0 : [[noreturn]] void ReportError(Args&&... args) {
53 0 : std::stringstream s;
54 0 : USE((s << std::forward<Args>(args))...);
55 0 : ReportErrorString(s.str());
56 : }
57 :
58 : std::string CapifyStringWithUnderscores(const std::string& camellified_string);
59 : std::string CamelifyString(const std::string& underscore_string);
60 : std::string DashifyString(const std::string& underscore_string);
61 :
62 : void ReplaceFileContentsIfDifferent(const std::string& file_path,
63 : const std::string& contents);
64 :
65 : std::string CurrentPositionAsString();
66 :
67 : template <class T>
68 2 : class Deduplicator {
69 : public:
70 : const T* Add(T x) { return &*(storage_.insert(std::move(x)).first); }
71 :
72 : private:
73 : std::unordered_set<T, base::hash<T>> storage_;
74 : };
75 :
76 : template <class C, class T>
77 5530 : void PrintCommaSeparatedList(std::ostream& os, const T& list, C transform) {
78 : bool first = true;
79 41189 : for (auto& e : list) {
80 41189 : if (first) {
81 : first = false;
82 : } else {
83 36094 : os << ", ";
84 : }
85 82378 : os << transform(e);
86 : }
87 5530 : }
88 :
89 : template <class T,
90 : typename std::enable_if<
91 : std::is_pointer<typename T::value_type>::value, int>::type = 0>
92 0 : void PrintCommaSeparatedList(std::ostream& os, const T& list) {
93 : bool first = true;
94 0 : for (auto& e : list) {
95 0 : if (first) {
96 : first = false;
97 : } else {
98 0 : os << ", ";
99 : }
100 0 : os << *e;
101 : }
102 0 : }
103 :
104 : template <class T,
105 : typename std::enable_if<
106 : !std::is_pointer<typename T::value_type>::value, int>::type = 0>
107 5106 : void PrintCommaSeparatedList(std::ostream& os, const T& list) {
108 : bool first = true;
109 19119 : for (auto& e : list) {
110 8907 : if (first) {
111 : first = false;
112 : } else {
113 3879 : os << ", ";
114 : }
115 211 : os << e;
116 : }
117 5106 : }
118 :
119 : struct BottomOffset {
120 : size_t offset;
121 : BottomOffset& operator++() {
122 11641 : ++offset;
123 : return *this;
124 : }
125 18474 : BottomOffset operator+(size_t x) const { return BottomOffset{offset + x}; }
126 : BottomOffset operator-(size_t x) const {
127 : DCHECK_LE(x, offset);
128 114283 : return BottomOffset{offset - x};
129 : }
130 : bool operator<(const BottomOffset& other) const {
131 : return offset < other.offset;
132 : }
133 : bool operator<=(const BottomOffset& other) const {
134 : return offset <= other.offset;
135 : }
136 : bool operator==(const BottomOffset& other) const {
137 192 : return offset == other.offset;
138 : }
139 : bool operator!=(const BottomOffset& other) const {
140 : return offset != other.offset;
141 : }
142 : };
143 :
144 : inline std::ostream& operator<<(std::ostream& out, BottomOffset from_bottom) {
145 : return out << "BottomOffset{" << from_bottom.offset << "}";
146 : }
147 :
148 : // An iterator-style range of stack slots.
149 : class StackRange {
150 : public:
151 50285 : StackRange(BottomOffset begin, BottomOffset end) : begin_(begin), end_(end) {
152 : DCHECK_LE(begin_, end_);
153 : }
154 :
155 : bool operator==(const StackRange& other) const {
156 192 : return begin_ == other.begin_ && end_ == other.end_;
157 : }
158 :
159 : void Extend(StackRange adjacent) {
160 : DCHECK_EQ(end_, adjacent.begin_);
161 6813 : end_ = adjacent.end_;
162 : }
163 :
164 80488 : size_t Size() const { return end_.offset - begin_.offset; }
165 : BottomOffset begin() const { return begin_; }
166 : BottomOffset end() const { return end_; }
167 :
168 : private:
169 : BottomOffset begin_;
170 : BottomOffset end_;
171 : };
172 :
173 : inline std::ostream& operator<<(std::ostream& out, StackRange range) {
174 : return out << "StackRange{" << range.begin() << ", " << range.end() << "}";
175 : }
176 :
177 : template <class T>
178 30472 : class Stack {
179 : public:
180 : using value_type = T;
181 : Stack() = default;
182 2 : Stack(std::initializer_list<T> initializer)
183 2 : : Stack(std::vector<T>(initializer)) {}
184 : explicit Stack(std::vector<T> v) : elements_(std::move(v)) {}
185 229122 : size_t Size() const { return elements_.size(); }
186 : const T& Peek(BottomOffset from_bottom) const {
187 : return elements_.at(from_bottom.offset);
188 : }
189 1927 : void Poke(BottomOffset from_bottom, T x) {
190 2892 : elements_.at(from_bottom.offset) = std::move(x);
191 1927 : }
192 82372 : void Push(T x) { elements_.push_back(std::move(x)); }
193 : StackRange TopRange(size_t slot_count) const {
194 : DCHECK_GE(Size(), slot_count);
195 : return StackRange{AboveTop() - slot_count, AboveTop()};
196 : }
197 16240 : StackRange PushMany(const std::vector<T>& v) {
198 23493 : for (const T& x : v) {
199 7253 : Push(x);
200 : }
201 8120 : return TopRange(v.size());
202 : }
203 104156 : const T& Top() const { return Peek(AboveTop() - 1); }
204 2060 : T Pop() {
205 7514 : T result = std::move(elements_.back());
206 : elements_.pop_back();
207 2060 : return result;
208 : }
209 6547 : std::vector<T> PopMany(size_t count) {
210 : DCHECK_GE(elements_.size(), count);
211 : std::vector<T> result;
212 6547 : result.reserve(count);
213 20589 : for (auto it = elements_.end() - count; it != elements_.end(); ++it) {
214 : result.push_back(std::move(*it));
215 : }
216 6547 : elements_.resize(elements_.size() - count);
217 6547 : return result;
218 : }
219 : // The invalid offset above the top element. This is useful for StackRange.
220 : BottomOffset AboveTop() const { return BottomOffset{Size()}; }
221 : // Delete the slots in {range}, moving higher slots to fill the gap.
222 15707 : void DeleteRange(StackRange range) {
223 : DCHECK_LE(range.end(), AboveTop());
224 31414 : if (range.Size() == 0) return;
225 27060 : for (BottomOffset i = range.end(); i < AboveTop(); ++i) {
226 17552 : elements_[i.offset - range.Size()] = std::move(elements_[i.offset]);
227 : }
228 15419 : elements_.resize(elements_.size() - range.Size());
229 : }
230 :
231 : bool operator==(const Stack& other) const {
232 3620 : return elements_ == other.elements_;
233 : }
234 : bool operator!=(const Stack& other) const {
235 : return elements_ != other.elements_;
236 : }
237 :
238 : T* begin() { return elements_.data(); }
239 42258 : T* end() { return begin() + elements_.size(); }
240 : const T* begin() const { return elements_.data(); }
241 22120 : const T* end() const { return begin() + elements_.size(); }
242 :
243 : private:
244 : std::vector<T> elements_;
245 : };
246 :
247 : template <class T>
248 : T* CheckNotNull(T* x) {
249 : CHECK_NOT_NULL(x);
250 : return x;
251 : }
252 :
253 : template <class T>
254 : inline std::ostream& operator<<(std::ostream& os, Stack<T>& t) {
255 : os << "Stack{";
256 : PrintCommaSeparatedList(os, t);
257 : os << "}";
258 : return os;
259 : }
260 : class ToString {
261 : public:
262 : template <class T>
263 : ToString& operator<<(T&& x) {
264 : s_ << std::forward<T>(x);
265 : return *this;
266 : }
267 : operator std::string() { return s_.str(); }
268 :
269 : private:
270 : std::stringstream s_;
271 : };
272 :
273 : constexpr int kTaggedSize = sizeof(void*);
274 :
275 : static const char* const kBaseNamespaceName = "base";
276 : static const char* const kTestNamespaceName = "test";
277 : static const char* const kConstructMethodName = "constructor";
278 : static const char* const kSuperMethodName = "super";
279 : static const char* const kConstructorStructSuperFieldName = "_super";
280 : static const char* const kClassConstructorThisStructPrefix = "_ThisStruct";
281 :
282 : // Erase elements of a container that has a constant-time erase function, like
283 : // std::set or std::list. Calling this on std::vector would have quadratic
284 : // complexity.
285 : template <class Container, class F>
286 72 : void EraseIf(Container* container, F f) {
287 260 : for (auto it = container->begin(); it != container->end();) {
288 232 : if (f(*it)) {
289 3 : it = container->erase(it);
290 : } else {
291 : ++it;
292 : }
293 : }
294 72 : }
295 :
296 2 : class NullStreambuf : public std::streambuf {
297 : public:
298 6596 : virtual int overflow(int c) {
299 6596 : setp(buffer_, buffer_ + sizeof(buffer_));
300 6596 : return (c == traits_type::eof()) ? '\0' : c;
301 : }
302 :
303 : private:
304 : char buffer_[64];
305 : };
306 :
307 2 : class NullOStream : public std::ostream {
308 : public:
309 3 : NullOStream() : std::ostream(&buffer_) {}
310 :
311 : private:
312 : NullStreambuf buffer_;
313 : };
314 :
315 : } // namespace torque
316 : } // namespace internal
317 : } // namespace v8
318 :
319 : #endif // V8_TORQUE_UTILS_H_
|