|
1 | 1 | #pragma once |
2 | 2 | #include <c10/util/Exception.h> |
| 3 | +#include <c10/util/Optional.h> |
3 | 4 |
|
4 | 5 | #include <algorithm> |
5 | 6 | #include <memory> |
6 | 7 | #include <iostream> |
7 | 8 | namespace torch { |
8 | 9 | namespace jit { |
9 | 10 |
|
10 | | -// a range of a shared string 'file_' with functions to help debug by highlight |
11 | | -// that |
12 | | -// range. |
| 11 | +// Source represents a code segment. It keeps track of: |
| 12 | +// - text : the text of the code segment |
| 13 | +// - filename (optional) : if present, represents the name of the file from |
| 14 | +// which the code semgemnt originated. |
| 15 | +// - starting_line_no : represents the line in the original file where the |
| 16 | +// code segment started. |
| 17 | +struct Source { |
| 18 | + explicit Source(std::string text) |
| 19 | + : text_(std::move(text)), filename_(c10::nullopt) { |
| 20 | + calc_line_start_offsets(); |
| 21 | + } |
| 22 | + |
| 23 | + Source( |
| 24 | + std::string text, |
| 25 | + c10::optional<std::string> filename, |
| 26 | + size_t starting_line_no) |
| 27 | + : text_(std::move(text)), |
| 28 | + filename_(std::move(filename)), |
| 29 | + starting_line_no_(starting_line_no) { |
| 30 | + calc_line_start_offsets(); |
| 31 | + } |
| 32 | + |
| 33 | + // Given a line number (within source_), return the byte offset of the |
| 34 | + // beginning of that line. |
| 35 | + size_t offset_for_line(size_t line) const { |
| 36 | + return line_starting_offsets_.at(line); |
| 37 | + } |
| 38 | + |
| 39 | + // Calculate the line (within the code segment) on which `offset` resides. |
| 40 | + size_t lineno_for_offset(size_t offset) const { |
| 41 | + return std::upper_bound( |
| 42 | + line_starting_offsets_.begin(), |
| 43 | + line_starting_offsets_.end(), |
| 44 | + offset) - |
| 45 | + line_starting_offsets_.begin() - 1; |
| 46 | + } |
| 47 | + |
| 48 | + // Calculate the line (within the original source file, if present) on which |
| 49 | + // `lineno` resides. |
| 50 | + size_t lineno_to_source_lineno(size_t lineno) const { |
| 51 | + if (filename_) { |
| 52 | + return lineno + starting_line_no_; |
| 53 | + } else { |
| 54 | + return lineno; |
| 55 | + } |
| 56 | + } |
| 57 | + |
| 58 | + const std::string& text() const { |
| 59 | + return text_; |
| 60 | + } |
| 61 | + |
| 62 | + const c10::optional<std::string>& filename() const { |
| 63 | + return filename_; |
| 64 | + } |
| 65 | + |
| 66 | + size_t starting_line_no() const { |
| 67 | + return starting_line_no_; |
| 68 | + } |
| 69 | + |
| 70 | + private: |
| 71 | + void calc_line_start_offsets() { |
| 72 | + size_t pos = 0; |
| 73 | + do { |
| 74 | + line_starting_offsets_.push_back(pos); |
| 75 | + pos++; |
| 76 | + } while ((pos = text_.find('\n', pos)) != std::string::npos); |
| 77 | + } |
| 78 | + std::string text_; |
| 79 | + c10::optional<std::string> filename_; |
| 80 | + // If filename_ is not present, starting_line_no_ is don't care |
| 81 | + size_t starting_line_no_; |
| 82 | + // Starting offsets for lines into the source. e.g. line 0 starts at |
| 83 | + // line_starting_offsets_[0], etc. |
| 84 | + std::vector<size_t> line_starting_offsets_; |
| 85 | +}; |
| 86 | + |
| 87 | +// A SourceRange is a view into a Source, that points to a subset of the source, |
| 88 | +// specified by `start` and `end` byte offsets into the source text. |
13 | 89 | struct CAFFE2_API SourceRange { |
14 | | - SourceRange(std::shared_ptr<std::string> file_, size_t start_, size_t end_) |
15 | | - : file_(std::move(file_)), start_(start_), end_(end_) {} |
| 90 | + SourceRange(std::shared_ptr<Source> source_, size_t start_, size_t end_) |
| 91 | + : source_(std::move(source_)), start_(start_), end_(end_) {} |
16 | 92 | explicit SourceRange(std::string string_range) |
17 | | - : file_(std::make_shared<std::string>(std::move(string_range))), |
| 93 | + : source_(std::make_shared<Source>(std::move(string_range))), |
18 | 94 | start_(0), |
19 | | - end_(file_->size()) {} |
| 95 | + end_(source_->text().size()) {} |
20 | 96 |
|
21 | 97 | const std::string text() const { |
22 | | - return file().substr(start(), end() - start()); |
| 98 | + return source_->text().substr(start(), end() - start()); |
23 | 99 | } |
24 | 100 | size_t size() const { |
25 | 101 | return end() - start(); |
26 | 102 | } |
27 | 103 | static const size_t CONTEXT = 10; |
28 | 104 | void highlight(std::ostream& out) const; |
29 | | - const std::string& file() const { |
30 | | - return *file_; |
31 | | - } |
32 | | - const std::shared_ptr<std::string>& file_ptr() const { |
33 | | - return file_; |
| 105 | + const std::shared_ptr<Source>& source() const { |
| 106 | + return source_; |
34 | 107 | } |
35 | 108 | size_t start() const { |
36 | 109 | return start_; |
@@ -68,7 +141,7 @@ struct CAFFE2_API SourceRange { |
68 | 141 | } |
69 | 142 |
|
70 | 143 | private: |
71 | | - std::shared_ptr<std::string> file_; |
| 144 | + std::shared_ptr<Source> source_; |
72 | 145 | size_t start_; |
73 | 146 | size_t end_; |
74 | 147 | }; |
|
0 commit comments