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;
113
124class SourceInfo final {
125 public:
126 cstring filename = ""_cs;
127 int line = -1;
128 int column = -1;
129 cstring srcBrief = ""_cs;
130 SourceInfo(cstring filename, int line, int column, cstring srcBrief) {
131 this->filename = filename;
132 this->line = line;
133 this->column = column;
134 this->srcBrief = srcBrief;
135 }
137 SourceInfo() = default;
138
141 : sources(sources), start(point), end(point) {}
142
143 SourceInfo(const InputSources *sources, SourcePosition start, SourcePosition end);
144
145 SourceInfo(const SourceInfo &other) = default;
146 SourceInfo &operator=(const SourceInfo &other) = default;
147 ~SourceInfo() = default;
148
152 SourceInfo operator+(const SourceInfo &rhs) const {
153 if (!this->isValid()) return rhs;
154 if (!rhs.isValid()) return *this;
155 SourcePosition s = start.min(rhs.start);
156 SourcePosition e = end.max(rhs.end);
157 return SourceInfo(sources, s, e);
158 }
159 SourceInfo &operator+=(const SourceInfo &rhs) {
160 if (!isValid()) {
161 *this = rhs;
162 } else if (rhs.isValid()) {
163 start = start.min(rhs.start);
164 end = end.max(rhs.end);
165 }
166 return *this;
167 }
168
169 bool operator==(const SourceInfo &rhs) const { return start == rhs.start && end == rhs.end; }
170
171 cstring toString() const;
172
173 void dbprint(std::ostream &out) const { out << this->toString(); }
174
181 cstring toSourceFragment(int trimWidth = -1, bool useMarker = true) const;
182 cstring toSourceFragment(bool useMarker) const { return toSourceFragment(-1, useMarker); }
183 cstring toBriefSourceFragment() const;
184 cstring toPositionString() const;
185 cstring toSourcePositionData(unsigned *outLineNumber, unsigned *outColumnNumber) const;
186 SourceFileLine toPosition() const;
187
188 bool isValid() const { return this->start.isValid(); }
189 explicit operator bool() const { return isValid(); }
190
191 cstring getSourceFile() const;
192 cstring getLineNum() const;
193
194 const SourcePosition &getStart() const { return this->start; }
195
196 const SourcePosition &getEnd() const { return this->end; }
197
203 bool operator<(const SourceInfo &rhs) const {
204 if (!rhs.isValid()) return false;
205 if (!isValid()) return true;
206 return this->start < rhs.start;
207 }
208 inline bool operator>(const SourceInfo &rhs) const { return rhs.operator<(*this); }
209 inline bool operator<=(const SourceInfo &rhs) const { return !this->operator>(rhs); }
210 inline bool operator>=(const SourceInfo &rhs) const { return !this->operator<(rhs); }
211
212 friend std::ostream &operator<<(std::ostream &os, const SourceInfo &info);
213
214 private:
215 const InputSources *sources = nullptr;
216 SourcePosition start = SourcePosition();
217 SourcePosition end = SourcePosition();
218};
219
221 public:
222 virtual SourceInfo getSourceInfo() const = 0;
223 virtual cstring toString() const = 0;
224 virtual ~IHasSourceInfo() {}
225};
226
228template <class, class = void>
229struct has_SourceInfo : std::false_type {};
230
231template <class T>
232struct has_SourceInfo<T, std::void_t<decltype(std::declval<T>().getSourceInfo())>>
233 : std::true_type {};
234
235template <class T>
236inline constexpr bool has_SourceInfo_v = has_SourceInfo<T>::value;
237
242 unsigned sourceLine;
243
244 SourceFileLine(std::string_view file, unsigned line) : fileName(file), sourceLine(line) {}
245
246 cstring toString() const;
247};
248
249class Comment final : IHasDbPrint {
250 private:
251 SourceInfo srcInfo;
252 bool singleLine;
253 cstring body;
254
255 public:
256 Comment(SourceInfo srcInfo, bool singleLine, cstring body)
257 : srcInfo(srcInfo), singleLine(singleLine), body(body) {}
258 cstring toString() const {
259 std::stringstream str;
260 dbprint(str);
261 return str.str();
262 }
263 void dbprint(std::ostream &out) const override {
264 if (singleLine)
265 out << "//";
266 else
267 out << "/*";
268 out << body;
269 if (!singleLine) out << "*/";
270 }
271};
272
283class InputSources final {
284#ifdef P4C_GTEST_ENABLED
285 FRIEND_TEST(UtilSourceFile, InputSources);
286#endif
287
288 public:
289 InputSources();
290
291 std::string_view getLine(unsigned lineNumber) const;
293 SourceFileLine getSourceLine(unsigned line) const;
294
295 unsigned lineCount() const;
296 SourcePosition getCurrentPosition() const;
297 unsigned getCurrentLineNumber() const;
298
300 void seal();
301
303 void appendText(const char *text);
304
308 void mapLine(std::string_view file, unsigned originalSourceLineNo);
309
315 cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const;
316 cstring getSourceFragment(const SourceInfo &position, int trimWidth, bool useMarker) const;
317 cstring getBriefSourceFragment(const SourceInfo &position) const;
318
319 cstring toDebugString() const;
320 void addComment(SourceInfo srcInfo, bool singleLine, cstring body);
321
322 private:
324 void appendToLastLine(std::string_view text);
326 void appendNewline(std::string_view newline);
327
329 bool sealed;
330
331 std::map<unsigned, SourceFileLine> line_file_map;
332
334 std::vector<std::string> contents;
336 std::vector<Comment *> comments;
337};
338
339} // namespace P4::Util
340
341namespace P4 {
342
343void dbprint(const IHasDbPrint *o);
344
345} // namespace P4
346
347#endif /* LIB_SOURCE_FILE_H_ */
Definition stringify.h:33
Definition source_file.h:249
Definition source_file.h:220
Definition source_file.h:283
void appendText(const char *text)
Append this text; it is either a newline or a text with no newlines.
Definition source_file.cpp:121
cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const
Definition source_file.cpp:198
void mapLine(std::string_view file, unsigned originalSourceLineNo)
Definition source_file.cpp:163
SourceFileLine getSourceLine(unsigned line) const
Original source line that produced the line with the specified number.
Definition source_file.cpp:169
void seal()
Prevents further changes; currently not used.
Definition source_file.cpp:87
Definition source_file.h:124
SourceInfo(const InputSources *sources, SourcePosition point)
Creates a SourceInfo for a 'point' in the source, or invalid.
Definition source_file.h:140
bool operator<(const SourceInfo &rhs) const
Definition source_file.h:203
SourceInfo operator+(const SourceInfo &rhs) const
Definition source_file.h:152
SourceInfo()=default
Creates an "invalid" SourceInfo.
cstring toSourceFragment(int trimWidth=-1, bool useMarker=true) const
Definition source_file.cpp:318
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 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 error.h:148
STL namespace.
Definition source_file.h:239
cstring fileName
an empty filename indicates stdin
Definition source_file.h:241
SFINAE helper to check if given class has a getSourceInfo method.
Definition source_file.h:229