P4C
The P4 Compiler
Loading...
Searching...
No Matches
source_file.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17/* -*-c++-*- */
18
19/* Source-level information for a P4 program */
20
21#ifndef LIB_SOURCE_FILE_H_
22#define LIB_SOURCE_FILE_H_
23
24#include <map>
25#include <sstream>
26#include <string_view>
27#include <vector>
28
29#include "absl/strings/str_format.h"
30#include "cstring.h"
31#include "stringify.h"
32
33// GTest
34#ifdef P4C_GTEST_ENABLED
35#include "gtest/gtest_prod.h"
36#endif
37
38namespace P4::Test {
39class UtilSourceFile;
40}
41
42namespace P4::Util {
43using namespace P4::literals;
44
45struct SourceFileLine;
55class SourcePosition final {
56 public:
58 SourcePosition() = default;
59
60 SourcePosition(unsigned lineNumber, unsigned columnNumber);
61
62 SourcePosition(const SourcePosition &other) = default;
63 SourcePosition &operator=(const SourcePosition &) = default;
64
65 inline bool operator==(const SourcePosition &rhs) const {
66 return columnNumber == rhs.columnNumber && lineNumber == rhs.lineNumber;
67 }
68 inline bool operator!=(const SourcePosition &rhs) const { return !this->operator==(rhs); }
69
70 inline bool operator<(const SourcePosition &rhs) const {
71 return (lineNumber < rhs.lineNumber) ||
72 (lineNumber == rhs.lineNumber && columnNumber < rhs.columnNumber);
73 }
74 inline bool operator>(const SourcePosition &rhs) const { return rhs.operator<(*this); }
75 inline bool operator<=(const SourcePosition &rhs) const { return !this->operator>(rhs); }
76 inline bool operator>=(const SourcePosition &rhs) const { return !this->operator<(rhs); }
77
80 if (columnNumber > 0) columnNumber--;
81 return *this;
82 }
84 SourcePosition tmp(*this);
85 this->operator--();
86 return tmp;
87 }
88
89 inline const SourcePosition &min(const SourcePosition &rhs) const {
90 if (this->operator<(rhs)) return *this;
91 return rhs;
92 }
93
94 inline const SourcePosition &max(const SourcePosition &rhs) const {
95 if (this->operator>(rhs)) return *this;
96 return rhs;
97 }
98
99 cstring toString() const;
100
101 bool isValid() const { return lineNumber != 0; }
102
103 unsigned getLineNumber() const { return lineNumber; }
104
105 unsigned getColumnNumber() const { return columnNumber; }
106
107 template <typename Sink>
108 friend void AbslStringify(Sink &sink, const SourcePosition &p) {
109 absl::Format(&sink, "%d:%d", p.lineNumber, p.columnNumber);
110 }
111
112 private:
113 // Input sources where this character position is interpreted.
114 unsigned lineNumber = 0;
115 unsigned columnNumber = 0;
116};
117
118class InputSources;
119class Comment;
120
131class SourceInfo final {
132 public:
133 cstring filename = ""_cs;
134 int line = -1;
135 int column = -1;
136 cstring srcBrief = ""_cs;
137 SourceInfo(cstring filename, int line, int column, cstring srcBrief) {
138 this->filename = filename;
139 this->line = line;
140 this->column = column;
141 this->srcBrief = srcBrief;
142 }
144 SourceInfo() = default;
145
148 : sources(sources), start(point), end(point) {}
149
150 SourceInfo(const InputSources *sources, SourcePosition start, SourcePosition end);
151
152 SourceInfo(const SourceInfo &other) = default;
153 SourceInfo &operator=(const SourceInfo &other) = default;
154 ~SourceInfo() = default;
155
159 SourceInfo operator+(const SourceInfo &rhs) const {
160 if (!this->isValid()) return rhs;
161 if (!rhs.isValid()) return *this;
162 SourcePosition s = start.min(rhs.start);
163 SourcePosition e = end.max(rhs.end);
164 return SourceInfo(sources, s, e);
165 }
166 SourceInfo &operator+=(const SourceInfo &rhs) {
167 if (!isValid()) {
168 *this = rhs;
169 } else if (rhs.isValid()) {
170 start = start.min(rhs.start);
171 end = end.max(rhs.end);
172 }
173 return *this;
174 }
175
176 bool operator==(const SourceInfo &rhs) const { return start == rhs.start && end == rhs.end; }
177
178 cstring toString() const;
179
180 void dbprint(std::ostream &out) const { out << this->toString(); }
181
188 cstring toSourceFragment(int trimWidth = -1, bool useMarker = true) const;
189 cstring toSourceFragment(bool useMarker) const { return toSourceFragment(-1, useMarker); }
190 cstring toBriefSourceFragment() const;
191 cstring toPositionString() const;
192 cstring toSourcePositionData(unsigned *outLineNumber, unsigned *outColumnNumber) const;
193 SourceFileLine toPosition() const;
194
195 bool isValid() const { return this->start.isValid(); }
196 explicit operator bool() const { return isValid(); }
197
198 cstring getSourceFile() const;
199 cstring getLineNum() const;
200
201 const SourcePosition &getStart() const { return this->start; }
202
203 const SourcePosition &getEnd() const { return this->end; }
204
210 bool operator<(const SourceInfo &rhs) const {
211 if (!rhs.isValid()) return false;
212 if (!isValid()) return true;
213 return this->start < rhs.start;
214 }
215 inline bool operator>(const SourceInfo &rhs) const { return rhs.operator<(*this); }
216 inline bool operator<=(const SourceInfo &rhs) const { return !this->operator>(rhs); }
217 inline bool operator>=(const SourceInfo &rhs) const { return !this->operator<(rhs); }
218
219 friend std::ostream &operator<<(std::ostream &os, const SourceInfo &info);
220
221 private:
222 const InputSources *sources = nullptr;
223 SourcePosition start = SourcePosition();
224 SourcePosition end = SourcePosition();
225};
226
228 public:
229 virtual SourceInfo getSourceInfo() const = 0;
230 virtual cstring toString() const = 0;
231 virtual ~IHasSourceInfo() {}
232};
233
235template <class, class = void>
236struct has_SourceInfo : std::false_type {};
237
238template <class T>
239struct has_SourceInfo<T, std::void_t<decltype(std::declval<T>().getSourceInfo())>>
240 : std::true_type {};
241
242template <class T>
243inline constexpr bool has_SourceInfo_v = has_SourceInfo<T>::value;
244
249 unsigned sourceLine;
250
251 SourceFileLine(std::string_view file, unsigned line) : fileName(file), sourceLine(line) {}
252
253 cstring toString() const;
254};
255
257 private:
258 SourceInfo srcInfo;
259 bool singleLine;
260 cstring body;
261
262 public:
263 Comment(SourceInfo srcInfo, bool singleLine, cstring body)
264 : srcInfo(srcInfo), singleLine(singleLine), body(body) {}
265 cstring toString() const override {
266 std::stringstream str;
267 dbprint(str);
268 return {str};
269 }
270 void dbprint(std::ostream &out) const override {
271 if (singleLine)
272 out << "//";
273 else
274 out << "/*";
275 out << body;
276 if (!singleLine) out << "*/";
277 }
278
280 [[nodiscard]] SourceInfo getSourceInfo() const override { return srcInfo; }
281};
282
293class InputSources final {
294#ifdef P4C_GTEST_ENABLED
295 FRIEND_TEST(UtilSourceFile, InputSources);
296#endif
297
298 public:
299 InputSources();
300 std::string_view getLine(unsigned lineNumber) const;
302 SourceFileLine getSourceLine(unsigned line) const;
303
304 unsigned lineCount() const;
305 SourcePosition getCurrentPosition() const;
306 unsigned getCurrentLineNumber() const;
307
309 void seal();
310
312 void appendText(const char *text);
313
317 void mapLine(std::string_view file, unsigned originalSourceLineNo);
318
324 cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const;
325 cstring getSourceFragment(const SourceInfo &position, int trimWidth, bool useMarker) const;
326 cstring getBriefSourceFragment(const SourceInfo &position) const;
327
328 cstring toDebugString() const;
329 void addComment(SourceInfo srcInfo, bool singleLine, cstring body);
330
332 const std::vector<Comment *> &getAllComments() const;
333
334 private:
336 void appendToLastLine(std::string_view text);
338 void appendNewline(std::string_view newline);
339
341 bool sealed;
342
343 std::map<unsigned, SourceFileLine> line_file_map;
344
346 std::vector<std::string> contents;
348 std::vector<Comment *> comments;
349};
350
351} // namespace P4::Util
352
353namespace P4 {
354
355void dbprint(const IHasDbPrint *o);
356
357} // namespace P4
358
359#endif /* LIB_SOURCE_FILE_H_ */
Definition stringify.h:33
Definition source_file.h:256
SourceInfo getSourceInfo() const override
Retrieve the source position associated with this comment.
Definition source_file.h:280
Definition source_file.h:227
Definition source_file.h:293
void appendText(const char *text)
Append this text; it is either a newline or a text with no newlines.
Definition source_file.cpp:120
cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const
Definition source_file.cpp:197
const std::vector< Comment * > & getAllComments() const
Returns a list of all the comments found in the file, stored as a part of InputSources
Definition source_file.cpp:83
void mapLine(std::string_view file, unsigned originalSourceLineNo)
Definition source_file.cpp:162
SourceFileLine getSourceLine(unsigned line) const
Original source line that produced the line with the specified number.
Definition source_file.cpp:168
void seal()
Prevents further changes; currently not used.
Definition source_file.cpp:86
Definition source_file.h:131
SourceInfo(const InputSources *sources, SourcePosition point)
Creates a SourceInfo for a 'point' in the source, or invalid.
Definition source_file.h:147
bool operator<(const SourceInfo &rhs) const
Definition source_file.h:210
SourceInfo operator+(const SourceInfo &rhs) const
Definition source_file.h:159
SourceInfo()=default
Creates an "invalid" SourceInfo.
cstring toSourceFragment(int trimWidth=-1, bool useMarker=true) const
Definition source_file.cpp:317
Definition source_file.h:55
SourcePosition & operator--()
Move one column back. This never moves one line back.
Definition source_file.h:79
SourcePosition()=default
Creates an invalid source position.
Definition cstring.h:85
Definition json.h:34
Definition cstring.h:80
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void info(const int kind, const char *format, const T *node, Args &&...args)
Report info messages of type kind. Requires that the node argument have source info.
Definition lib/error.h:148
STL namespace.
Definition source_file.h:246
cstring fileName
an empty filename indicates stdin
Definition source_file.h:248
SFINAE helper to check if given class has a getSourceInfo method.
Definition source_file.h:236