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
175 cstring toSourceFragment(bool useMarker = true) const;
176 cstring toBriefSourceFragment() const;
177 cstring toPositionString() const;
178 cstring toSourcePositionData(unsigned *outLineNumber, unsigned *outColumnNumber) const;
179 SourceFileLine toPosition() const;
180
181 bool isValid() const { return this->start.isValid(); }
182 explicit operator bool() const { return isValid(); }
183
184 cstring getSourceFile() const;
185 cstring getLineNum() const;
186
187 const SourcePosition &getStart() const { return this->start; }
188
189 const SourcePosition &getEnd() const { return this->end; }
190
196 bool operator<(const SourceInfo &rhs) const {
197 if (!rhs.isValid()) return false;
198 if (!isValid()) return true;
199 return this->start < rhs.start;
200 }
201 inline bool operator>(const SourceInfo &rhs) const { return rhs.operator<(*this); }
202 inline bool operator<=(const SourceInfo &rhs) const { return !this->operator>(rhs); }
203 inline bool operator>=(const SourceInfo &rhs) const { return !this->operator<(rhs); }
204
205 friend std::ostream &operator<<(std::ostream &os, const SourceInfo &info);
206
207 private:
208 const InputSources *sources = nullptr;
209 SourcePosition start = SourcePosition();
210 SourcePosition end = SourcePosition();
211};
212
214 public:
215 virtual SourceInfo getSourceInfo() const = 0;
216 virtual cstring toString() const = 0;
217 virtual ~IHasSourceInfo() {}
218};
219
221template <class, class = void>
222struct has_SourceInfo : std::false_type {};
223
224template <class T>
225struct has_SourceInfo<T, std::void_t<decltype(std::declval<T>().getSourceInfo())>>
226 : std::true_type {};
227
228template <class T>
229inline constexpr bool has_SourceInfo_v = has_SourceInfo<T>::value;
230
232struct SourceFileLine {
235 unsigned sourceLine;
236
237 SourceFileLine(std::string_view file, unsigned line) : fileName(file), sourceLine(line) {}
238
239 cstring toString() const;
240};
241
242class Comment final : IHasDbPrint {
243 private:
244 SourceInfo srcInfo;
245 bool singleLine;
246 cstring body;
247
248 public:
249 Comment(SourceInfo srcInfo, bool singleLine, cstring body)
250 : srcInfo(srcInfo), singleLine(singleLine), body(body) {}
251 cstring toString() const {
252 std::stringstream str;
253 dbprint(str);
254 return str.str();
255 }
256 void dbprint(std::ostream &out) const override {
257 if (singleLine)
258 out << "//";
259 else
260 out << "/*";
261 out << body;
262 if (!singleLine) out << "*/";
263 }
264};
265
276class InputSources final {
277#ifdef P4C_GTEST_ENABLED
278 FRIEND_TEST(UtilSourceFile, InputSources);
279#endif
280
281 public:
282 InputSources();
283
284 std::string_view getLine(unsigned lineNumber) const;
286 SourceFileLine getSourceLine(unsigned line) const;
287
288 unsigned lineCount() const;
289 SourcePosition getCurrentPosition() const;
290 unsigned getCurrentLineNumber() const;
291
293 void seal();
294
296 void appendText(const char *text);
297
301 void mapLine(std::string_view file, unsigned originalSourceLineNo);
302
308 cstring getSourceFragment(const SourcePosition &position, bool useMarker) const;
309 cstring getSourceFragment(const SourceInfo &position, bool useMarker) const;
310 cstring getBriefSourceFragment(const SourceInfo &position) const;
311
312 cstring toDebugString() const;
313 void addComment(SourceInfo srcInfo, bool singleLine, cstring body);
314
315 private:
317 void appendToLastLine(std::string_view text);
319 void appendNewline(std::string_view newline);
320
322 bool sealed;
323
324 std::map<unsigned, SourceFileLine> line_file_map;
325
327 std::vector<std::string> contents;
329 std::vector<Comment *> comments;
330};
331
332} // namespace P4::Util
333
334namespace P4 {
335
336void dbprint(const IHasDbPrint *o);
337
338} // namespace P4
339
340#endif /* LIB_SOURCE_FILE_H_ */
Definition stringify.h:33
Definition source_file.h:213
Definition source_file.h:276
void appendText(const char *text)
Append this text; it is either a newline or a text with no newlines.
Definition source_file.cpp:121
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
cstring getSourceFragment(const SourcePosition &position, bool useMarker) const
Definition source_file.cpp:198
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:196
SourceInfo operator+(const SourceInfo &rhs) const
Definition source_file.h:152
SourceInfo()=default
Creates an "invalid" SourceInfo.
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
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:232
cstring fileName
an empty filename indicates stdin
Definition source_file.h:234
SFINAE helper to check if given class has a getSourceInfo method.
Definition source_file.h:222