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