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 "cstring.h"
30#include "stringify.h"
31
32// GTest
33#ifdef P4C_GTEST_ENABLED
34#include "gtest/gtest_prod.h"
35#endif
36
37namespace P4::Test {
38class UtilSourceFile;
39}
40
41namespace P4::Util {
42using namespace P4::literals;
43
44struct SourceFileLine;
54class SourcePosition final {
55 public:
57 SourcePosition() = default;
58
59 SourcePosition(unsigned lineNumber, unsigned columnNumber);
60
61 SourcePosition(const SourcePosition &other) = default;
62 SourcePosition &operator=(const SourcePosition &) = default;
63
64 inline bool operator==(const SourcePosition &rhs) const {
65 return columnNumber == rhs.columnNumber && lineNumber == rhs.lineNumber;
66 }
67 inline bool operator!=(const SourcePosition &rhs) const { return !this->operator==(rhs); }
68
69 inline bool operator<(const SourcePosition &rhs) const {
70 return (lineNumber < rhs.lineNumber) ||
71 (lineNumber == rhs.lineNumber && columnNumber < rhs.columnNumber);
72 }
73 inline bool operator>(const SourcePosition &rhs) const { return rhs.operator<(*this); }
74 inline bool operator<=(const SourcePosition &rhs) const { return !this->operator>(rhs); }
75 inline bool operator>=(const SourcePosition &rhs) const { return !this->operator<(rhs); }
76
79 if (columnNumber > 0) columnNumber--;
80 return *this;
81 }
83 SourcePosition tmp(*this);
84 this->operator--();
85 return tmp;
86 }
87
88 inline const SourcePosition &min(const SourcePosition &rhs) const {
89 if (this->operator<(rhs)) return *this;
90 return rhs;
91 }
92
93 inline const SourcePosition &max(const SourcePosition &rhs) const {
94 if (this->operator>(rhs)) return *this;
95 return rhs;
96 }
97
98 cstring toString() const;
99
100 bool isValid() const { return lineNumber != 0; }
101
102 unsigned getLineNumber() const { return lineNumber; }
103
104 unsigned getColumnNumber() const { return columnNumber; }
105
106 private:
107 // Input sources where this character position is interpreted.
108 unsigned lineNumber = 0;
109 unsigned columnNumber = 0;
110};
111
112class InputSources;
113class Comment;
114
125class SourceInfo final {
126 public:
127 cstring filename = ""_cs;
128 int line = -1;
129 int column = -1;
130 cstring srcBrief = ""_cs;
131 SourceInfo(cstring filename, int line, int column, cstring srcBrief) {
132 this->filename = filename;
133 this->line = line;
134 this->column = column;
135 this->srcBrief = srcBrief;
136 }
138 SourceInfo() = default;
139
142 : sources(sources), start(point), end(point) {}
143
144 SourceInfo(const InputSources *sources, SourcePosition start, SourcePosition end);
145
146 SourceInfo(const SourceInfo &other) = default;
147 SourceInfo &operator=(const SourceInfo &other) = default;
148 ~SourceInfo() = default;
149
153 SourceInfo operator+(const SourceInfo &rhs) const {
154 if (!this->isValid()) return rhs;
155 if (!rhs.isValid()) return *this;
156 SourcePosition s = start.min(rhs.start);
157 SourcePosition e = end.max(rhs.end);
158 return SourceInfo(sources, s, e);
159 }
160 SourceInfo &operator+=(const SourceInfo &rhs) {
161 if (!isValid()) {
162 *this = rhs;
163 } else if (rhs.isValid()) {
164 start = start.min(rhs.start);
165 end = end.max(rhs.end);
166 }
167 return *this;
168 }
169
170 bool operator==(const SourceInfo &rhs) const { return start == rhs.start && end == rhs.end; }
171
172 cstring toString() const;
173
174 void dbprint(std::ostream &out) const { out << this->toString(); }
175
182 cstring toSourceFragment(int trimWidth = -1, bool useMarker = true) const;
183 cstring toSourceFragment(bool useMarker) const { return toSourceFragment(-1, useMarker); }
184 cstring toBriefSourceFragment() const;
185 cstring toPositionString() const;
186 cstring toSourcePositionData(unsigned *outLineNumber, unsigned *outColumnNumber) const;
187 SourceFileLine toPosition() const;
188
189 bool isValid() const { return this->start.isValid(); }
190 explicit operator bool() const { return isValid(); }
191
192 cstring getSourceFile() const;
193 cstring getLineNum() const;
194
195 const SourcePosition &getStart() const { return this->start; }
196
197 const SourcePosition &getEnd() const { return this->end; }
198
204 bool operator<(const SourceInfo &rhs) const {
205 if (!rhs.isValid()) return false;
206 if (!isValid()) return true;
207 return this->start < rhs.start;
208 }
209 inline bool operator>(const SourceInfo &rhs) const { return rhs.operator<(*this); }
210 inline bool operator<=(const SourceInfo &rhs) const { return !this->operator>(rhs); }
211 inline bool operator>=(const SourceInfo &rhs) const { return !this->operator<(rhs); }
212
213 friend std::ostream &operator<<(std::ostream &os, const SourceInfo &info);
214
215 private:
216 const InputSources *sources = nullptr;
217 SourcePosition start = SourcePosition();
218 SourcePosition end = SourcePosition();
219};
220
222 public:
223 virtual SourceInfo getSourceInfo() const = 0;
224 virtual cstring toString() const = 0;
225 virtual ~IHasSourceInfo() {}
226};
227
229template <class, class = void>
230struct has_SourceInfo : std::false_type {};
231
232template <class T>
233struct has_SourceInfo<T, std::void_t<decltype(std::declval<T>().getSourceInfo())>>
234 : std::true_type {};
235
236template <class T>
237inline constexpr bool has_SourceInfo_v = has_SourceInfo<T>::value;
238
243 unsigned sourceLine;
244
245 SourceFileLine(std::string_view file, unsigned line) : fileName(file), sourceLine(line) {}
246
247 cstring toString() const;
248};
249
251 private:
252 SourceInfo srcInfo;
253 bool singleLine;
254 cstring body;
255
256 public:
257 Comment(SourceInfo srcInfo, bool singleLine, cstring body)
258 : srcInfo(srcInfo), singleLine(singleLine), body(body) {}
259 cstring toString() const override {
260 std::stringstream str;
261 dbprint(str);
262 return str.str();
263 }
264 void dbprint(std::ostream &out) const override {
265 if (singleLine)
266 out << "//";
267 else
268 out << "/*";
269 out << body;
270 if (!singleLine) out << "*/";
271 }
272
274 [[nodiscard]] SourceInfo getSourceInfo() const override { return srcInfo; }
275};
276
287class InputSources final {
288#ifdef P4C_GTEST_ENABLED
289 FRIEND_TEST(UtilSourceFile, InputSources);
290#endif
291
292 public:
293 InputSources();
294 std::string_view getLine(unsigned lineNumber) const;
296 SourceFileLine getSourceLine(unsigned line) const;
297
298 unsigned lineCount() const;
299 SourcePosition getCurrentPosition() const;
300 unsigned getCurrentLineNumber() const;
301
303 void seal();
304
306 void appendText(const char *text);
307
311 void mapLine(std::string_view file, unsigned originalSourceLineNo);
312
318 cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const;
319 cstring getSourceFragment(const SourceInfo &position, int trimWidth, bool useMarker) const;
320 cstring getBriefSourceFragment(const SourceInfo &position) const;
321
322 cstring toDebugString() const;
323 void addComment(SourceInfo srcInfo, bool singleLine, cstring body);
324
326 const std::vector<Comment *> &getAllComments() const;
327
328 private:
330 void appendToLastLine(std::string_view text);
332 void appendNewline(std::string_view newline);
333
335 bool sealed;
336
337 std::map<unsigned, SourceFileLine> line_file_map;
338
340 std::vector<std::string> contents;
342 std::vector<Comment *> comments;
343};
344
345} // namespace P4::Util
346
347namespace P4 {
348
349void dbprint(const IHasDbPrint *o);
350
351} // namespace P4
352
353#endif /* LIB_SOURCE_FILE_H_ */
Definition stringify.h:33
Definition source_file.h:250
SourceInfo getSourceInfo() const override
Retrieve the source position associated with this comment.
Definition source_file.h:274
Definition source_file.h:221
Definition source_file.h:287
void appendText(const char *text)
Append this text; it is either a newline or a text with no newlines.
Definition source_file.cpp:123
cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const
Definition source_file.cpp:200
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:86
void mapLine(std::string_view file, unsigned originalSourceLineNo)
Definition source_file.cpp:165
SourceFileLine getSourceLine(unsigned line) const
Original source line that produced the line with the specified number.
Definition source_file.cpp:171
void seal()
Prevents further changes; currently not used.
Definition source_file.cpp:89
Definition source_file.h:125
SourceInfo(const InputSources *sources, SourcePosition point)
Creates a SourceInfo for a 'point' in the source, or invalid.
Definition source_file.h:141
bool operator<(const SourceInfo &rhs) const
Definition source_file.h:204
SourceInfo operator+(const SourceInfo &rhs) const
Definition source_file.h:153
SourceInfo()=default
Creates an "invalid" SourceInfo.
cstring toSourceFragment(int trimWidth=-1, bool useMarker=true) const
Definition source_file.cpp:320
Definition source_file.h:54
SourcePosition & operator--()
Move one column back. This never moves one line back.
Definition source_file.h:78
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:240
cstring fileName
an empty filename indicates stdin
Definition source_file.h:242
SFINAE helper to check if given class has a getSourceInfo method.
Definition source_file.h:230