P4C
The P4 Compiler
Loading...
Searching...
No Matches
source_file.h
1/*
2 * SPDX-FileCopyrightText: 2013 Barefoot Networks, Inc.
3 * Copyright 2013-present Barefoot Networks, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8/* -*-c++-*- */
9
10/* Source-level information for a P4 program */
11
12#ifndef LIB_SOURCE_FILE_H_
13#define LIB_SOURCE_FILE_H_
14
15#include <map>
16#include <sstream>
17#include <string_view>
18#include <vector>
19
20#include "absl/strings/str_format.h"
21#include "config.h"
22#include "cstring.h"
23#include "stringify.h"
24
25// GTest
26#ifdef P4C_GTEST_ENABLED
27#include "gtest/gtest_prod.h"
28#endif
29
30namespace P4::Test {
31class UtilSourceFile;
32}
33
34namespace P4::Util {
35using namespace P4::literals;
36
37struct SourceFileLine;
47class SourcePosition final {
48 public:
50 SourcePosition() = default;
51
52 SourcePosition(unsigned lineNumber, unsigned columnNumber);
53
54 SourcePosition(const SourcePosition &other) = default;
55 SourcePosition &operator=(const SourcePosition &) = default;
56
57 inline bool operator==(const SourcePosition &rhs) const {
58 return columnNumber == rhs.columnNumber && lineNumber == rhs.lineNumber;
59 }
60 inline bool operator!=(const SourcePosition &rhs) const { return !this->operator==(rhs); }
61
62 inline bool operator<(const SourcePosition &rhs) const {
63 return (lineNumber < rhs.lineNumber) ||
64 (lineNumber == rhs.lineNumber && columnNumber < rhs.columnNumber);
65 }
66 inline bool operator>(const SourcePosition &rhs) const { return rhs.operator<(*this); }
67 inline bool operator<=(const SourcePosition &rhs) const { return !this->operator>(rhs); }
68 inline bool operator>=(const SourcePosition &rhs) const { return !this->operator<(rhs); }
69
72 if (columnNumber > 0) columnNumber--;
73 return *this;
74 }
76 SourcePosition tmp(*this);
77 this->operator--();
78 return tmp;
79 }
80
81 inline const SourcePosition &min(const SourcePosition &rhs) const {
82 if (this->operator<(rhs)) return *this;
83 return rhs;
84 }
85
86 inline const SourcePosition &max(const SourcePosition &rhs) const {
87 if (this->operator>(rhs)) return *this;
88 return rhs;
89 }
90
91 cstring toString() const;
92
93 bool isValid() const { return lineNumber != 0; }
94
95 unsigned getLineNumber() const { return lineNumber; }
96
97 unsigned getColumnNumber() const { return columnNumber; }
98
99 template <typename Sink>
100 friend void AbslStringify(Sink &sink, const SourcePosition &p) {
101 absl::Format(&sink, "%d:%d", p.lineNumber, p.columnNumber);
102 }
103
104 private:
105 // Input sources where this character position is interpreted.
106 unsigned lineNumber = 0;
107 unsigned columnNumber = 0;
108};
109
110class InputSources;
111class Comment;
112
123class SourceInfo final {
124 public:
125 cstring filename = ""_cs;
126 int line = -1;
127 int column = -1;
128 cstring srcBrief = ""_cs;
129 SourceInfo(cstring filename, int line, int column, cstring srcBrief);
131 SourceInfo() = default;
132
134 SourceInfo(const InputSources *sources, SourcePosition point);
135
136 SourceInfo(const InputSources *sources, SourcePosition start, SourcePosition end);
137
138 SourceInfo(const SourceInfo &other) = default;
139 SourceInfo &operator=(const SourceInfo &other) = default;
140 ~SourceInfo() = default;
141
145 SourceInfo operator+(const SourceInfo &rhs) const {
146 if (!this->isValid()) return rhs;
147 if (!rhs.isValid()) return *this;
148 SourcePosition s = start.min(rhs.start);
149 SourcePosition e = end.max(rhs.end);
150 return SourceInfo(sources, s, e);
151 }
152 SourceInfo &operator+=(const SourceInfo &rhs) {
153 if (!isValid()) {
154 *this = rhs;
155 } else if (rhs.isValid()) {
156 start = start.min(rhs.start);
157 end = end.max(rhs.end);
158 }
159 return *this;
160 }
161
162 bool operator==(const SourceInfo &rhs) const { return start == rhs.start && end == rhs.end; }
163
164 cstring toString() const;
165
166 void dbprint(std::ostream &out) const { out << this->toString(); }
167
174 cstring toSourceFragment(int trimWidth = -1, bool useMarker = true) const;
175 cstring toSourceFragment(bool useMarker) const { return toSourceFragment(-1, useMarker); }
176 cstring toBriefSourceFragment() const;
177 cstring toPositionString() const;
178 cstring toSourcePositionData(unsigned *outLineNumber, unsigned *outColumnNumber) const;
179 SourceFileLine toPosition() const;
180 SourceFileLine toPositionEnd() const;
181
182 bool isValid() const { return this->start.isValid(); }
183 explicit operator bool() const { return isValid(); }
184
185 cstring getSourceFile() const;
186 cstring getLineNum() const;
187
188 const SourcePosition &getStart() const { return this->start; }
189
190 const SourcePosition &getEnd() const { return this->end; }
191
197 bool operator<(const SourceInfo &rhs) const {
198 if (!rhs.isValid()) return false;
199 if (!isValid()) return true;
200 return this->start < rhs.start;
201 }
202 inline bool operator>(const SourceInfo &rhs) const { return rhs.operator<(*this); }
203 inline bool operator<=(const SourceInfo &rhs) const { return !this->operator>(rhs); }
204 inline bool operator>=(const SourceInfo &rhs) const { return !this->operator<(rhs); }
205
206 friend std::ostream &operator<<(std::ostream &os, const SourceInfo &info);
207
208 private:
209 const InputSources *sources = nullptr;
210 SourcePosition start = SourcePosition();
211 SourcePosition end = SourcePosition();
212};
213
215 public:
216 virtual SourceInfo getSourceInfo() const = 0;
217 virtual cstring toString() const = 0;
218 virtual ~IHasSourceInfo() {}
219};
220
222template <class, class = void>
223struct has_SourceInfo : std::false_type {};
224
225template <class T>
226struct has_SourceInfo<T, std::void_t<decltype(std::declval<T>().getSourceInfo())>>
227 : std::true_type {};
228
229template <class T>
230inline constexpr bool has_SourceInfo_v = has_SourceInfo<T>::value;
231
233struct SourceFileLine {
236 unsigned sourceLine;
237
238 SourceFileLine(std::string_view file, unsigned line) : fileName(file), sourceLine(line) {}
239
240 cstring toString() const;
241};
242
243class Comment final : IHasDbPrint, IHasSourceInfo {
244 private:
245 SourceInfo srcInfo;
246 bool singleLine;
247 cstring body;
248
249 public:
250 Comment(SourceInfo srcInfo, bool singleLine, cstring body)
251 : srcInfo(srcInfo), singleLine(singleLine), body(body) {}
252 cstring toString() const override {
253 std::stringstream str;
254 dbprint(str);
255 return {str};
256 }
257 void dbprint(std::ostream &out) const override {
258 if (singleLine)
259 out << "//";
260 else
261 out << "/*";
262 out << body;
263 if (!singleLine) out << "*/";
264 }
265
267 [[nodiscard]] SourceInfo getSourceInfo() const override { return srcInfo; }
268};
269
280class InputSources final {
281#ifdef P4C_GTEST_ENABLED
282 FRIEND_TEST(UtilSourceFile, InputSources);
283#endif
284
285 public:
286 InputSources();
287 std::string_view getLine(unsigned lineNumber) const;
289 SourceFileLine getSourceLine(unsigned line) const;
290
291 unsigned lineCount() const;
292 SourcePosition getCurrentPosition() const;
293 unsigned getCurrentLineNumber() const;
294
296 void seal();
297
299 void appendText(const char *text);
300
304 void mapLine(std::string_view file, unsigned originalSourceLineNo);
305
311 cstring getSourceFragment(const SourcePosition &position, int trimWidth, bool useMarker) const;
312 cstring getSourceFragment(const SourceInfo &position, int trimWidth, bool useMarker) const;
313 cstring getBriefSourceFragment(const SourceInfo &position) const;
314
315 cstring toDebugString() const;
316 void addComment(SourceInfo srcInfo, bool singleLine, cstring body);
317
319 const std::vector<Comment *> &getAllComments() const;
320
321 private:
323 void appendToLastLine(std::string_view text);
325 void appendNewline(std::string_view newline);
326
328 bool sealed;
329
330 std::map<unsigned, SourceFileLine> line_file_map;
331
333 std::vector<std::string> contents;
335 std::vector<Comment *> comments;
336};
337
338} // namespace P4::Util
339
340namespace P4 {
341
342void dbprint(const IHasDbPrint *o);
343
344} // namespace P4
345
346#endif /* LIB_SOURCE_FILE_H_ */
Definition stringify.h:24
Definition source_file.h:243
SourceInfo getSourceInfo() const override
Retrieve the source position associated with this comment.
Definition source_file.h:267
Definition source_file.h:214
Definition source_file.h:280
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
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:84
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:123
bool operator<(const SourceInfo &rhs) const
Definition source_file.h:197
SourceInfo operator+(const SourceInfo &rhs) const
Definition source_file.h:145
SourceInfo()=default
Creates an "invalid" SourceInfo.
cstring toSourceFragment(int trimWidth=-1, bool useMarker=true) const
Definition source_file.cpp:318
Definition source_file.h:47
SourcePosition & operator--()
Move one column back. This never moves one line back.
Definition source_file.h:71
SourcePosition()=default
Creates an invalid source position.
Definition cstring.h:76
Definition lib/json.h:26
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:13
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:158
STL namespace.
Definition source_file.h:233
cstring fileName
an empty filename indicates stdin
Definition source_file.h:235
SFINAE helper to check if given class has a getSourceInfo method.
Definition source_file.h:223