1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19#ifndef TVM_SCRIPT_PRINTER_DOC_PRINTER_BASE_DOC_PRINTER_H_
20#define TVM_SCRIPT_PRINTER_DOC_PRINTER_BASE_DOC_PRINTER_H_
21
22#include <tvm/script/printer/doc.h>
23
24#include <limits>
25#include <memory>
26#include <ostream>
27#include <string>
28#include <utility>
29#include <vector>
30
31namespace tvm {
32namespace script {
33namespace printer {
34
35/*! \brief Range of byte offsets in a string */
36using ByteSpan = std::pair<size_t, size_t>;
37
38/*!
39 * \brief DocPrinter is responsible for printing Doc tree into text format
40 * \details This is the base class for translating Doc into string.
41 * Each target language needs to have its subclass of DocPrinter
42 * to define the actual logic of printing Doc.
43 *
44 * \sa Doc
45 */
46class DocPrinter {
47 public:
48 /*!
49 * \brief The constructor of DocPrinter
50 *
51 * \param options the option for printer
52 */
53 explicit DocPrinter(const PrinterConfig& options);
54
55 virtual ~DocPrinter() = default;
56
57 /*!
58 * \brief Append a doc into the final content
59 *
60 * \param doc the Doc to be printed
61 *
62 * \sa GetString
63 */
64 void Append(const Doc& doc);
65
66 /*!
67 * \brief Append a doc to the final content
68 *
69 * \param doc Doc to be printed
70 * \param path_to_underline Object path to be underlined
71 *
72 * \sa GetString
73 */
74 void Append(const Doc& doc, const PrinterConfig& cfg);
75
76 /*!
77 * \brief Get the printed string of all Doc appended
78 *
79 * The content of each Doc in the returned string will
80 * appear in the same order as they are appended.
81 *
82 * \sa Append
83 */
84 String GetString() const;
85
86 protected:
87 /*!
88 * \brief Get the printed string
89 *
90 * It will dispatch to the PrintTypedDoc method based on
91 * the actual type of Doc.
92 *
93 * \sa PrintTypedDoc
94 */
95 void PrintDoc(const Doc& doc);
96
97 /*!
98 * \brief Virtual method to print a LiteralDoc
99 */
100 virtual void PrintTypedDoc(const LiteralDoc& doc) = 0;
101
102 /*!
103 * \brief Virtual method to print an IdDoc
104 */
105 virtual void PrintTypedDoc(const IdDoc& doc) = 0;
106
107 /*!
108 * \brief Virtual method to print an AttrAccessDoc
109 */
110 virtual void PrintTypedDoc(const AttrAccessDoc& doc) = 0;
111
112 /*!
113 * \brief Virtual method to print an IndexDoc
114 */
115 virtual void PrintTypedDoc(const IndexDoc& doc) = 0;
116
117 /*!
118 * \brief Virtual method to print an OperationDoc
119 */
120 virtual void PrintTypedDoc(const OperationDoc& doc) = 0;
121
122 /*!
123 * \brief Virtual method to print a CallDoc
124 */
125 virtual void PrintTypedDoc(const CallDoc& doc) = 0;
126
127 /*!
128 * \brief Virtual method to print a LambdaDoc
129 */
130 virtual void PrintTypedDoc(const LambdaDoc& doc) = 0;
131
132 /*!
133 * \brief Virtual method to print a ListDoc
134 */
135 virtual void PrintTypedDoc(const ListDoc& doc) = 0;
136
137 /*!
138 * \brief Virtual method to print a TupleDoc
139 */
140 virtual void PrintTypedDoc(const TupleDoc& doc) = 0;
141
142 /*!
143 * \brief Virtual method to print a DictDoc
144 */
145 virtual void PrintTypedDoc(const DictDoc& doc) = 0;
146
147 /*!
148 * \brief Virtual method to print a SliceDoc
149 */
150 virtual void PrintTypedDoc(const SliceDoc& doc) = 0;
151
152 /*!
153 * \brief Virtual method to print a StmtBlockDoc
154 */
155 virtual void PrintTypedDoc(const StmtBlockDoc& doc) = 0;
156
157 /*!
158 * \brief Virtual method to print an AssignDoc
159 */
160 virtual void PrintTypedDoc(const AssignDoc& doc) = 0;
161
162 /*!
163 * \brief Virtual method to print an IfDoc
164 */
165 virtual void PrintTypedDoc(const IfDoc& doc) = 0;
166
167 /*!
168 * \brief Virtual method to print a WhileDoc
169 */
170 virtual void PrintTypedDoc(const WhileDoc& doc) = 0;
171
172 /*!
173 * \brief Virtual method to print a ForDoc
174 */
175 virtual void PrintTypedDoc(const ForDoc& doc) = 0;
176
177 /*!
178 * \brief Virtual method to print a ScopeDoc
179 */
180 virtual void PrintTypedDoc(const ScopeDoc& doc) = 0;
181
182 /*!
183 * \brief Virtual method to print an ExprStmtDoc
184 */
185 virtual void PrintTypedDoc(const ExprStmtDoc& doc) = 0;
186
187 /*!
188 * \brief Virtual method to print an AssertDoc
189 */
190 virtual void PrintTypedDoc(const AssertDoc& doc) = 0;
191
192 /*!
193 * \brief Virtual method to print a ReturnDoc
194 */
195 virtual void PrintTypedDoc(const ReturnDoc& doc) = 0;
196
197 /*!
198 * \brief Virtual method to print a FunctionDoc
199 */
200 virtual void PrintTypedDoc(const FunctionDoc& doc) = 0;
201
202 /*!
203 * \brief Virtual method to print a ClassDoc
204 */
205 virtual void PrintTypedDoc(const ClassDoc& doc) = 0;
206
207 /*!
208 * \brief Virtual method to print a CommentDoc
209 */
210 virtual void PrintTypedDoc(const CommentDoc& doc) = 0;
211
212 /*!
213 * \brief Virtual method to print a DocStringDoc
214 */
215 virtual void PrintTypedDoc(const DocStringDoc& doc) = 0;
216
217 /*!
218 * \brief Increase the indent level of any content to be
219 * printed after this call
220 */
221 void IncreaseIndent() { indent_ += options_->indent_spaces; }
222
223 /*!
224 * \brief Decrease the indent level of any content to be
225 * printed after this call
226 */
227 void DecreaseIndent() { indent_ -= options_->indent_spaces; }
228
229 /*!
230 * \brief Add a new line into the output stream
231 *
232 * \sa output_
233 */
234 std::ostream& NewLine() {
235 size_t start_pos = output_.tellp();
236 output_ << "\n";
237 line_starts_.push_back(output_.tellp());
238 output_ << std::string(indent_, ' ');
239 size_t end_pos = output_.tellp();
240 underlines_exempted_.push_back({start_pos, end_pos});
241 return output_;
242 }
243
244 /*!
245 * \brief The output stream of printer
246 *
247 * All printed content will be stored in this stream and returned
248 * when GetString is called.
249 *
250 * \sa GetString
251 */
252 std::ostringstream output_;
253
254 /*! \brief Spans that we have already committed to underline exemption. */
255 std::vector<ByteSpan> underlines_exempted_;
256
257 private:
258 void MarkSpan(const ByteSpan& span, const ObjectPath& path);
259
260 /*! \brief Options to customize certain aspects of the output */
261 PrinterConfig options_;
262
263 /*! \brief the current level of indent */
264 int indent_ = 0;
265
266 /*! \brief For each line in the output_, byte offset of its first character */
267 std::vector<size_t> line_starts_;
268
269 /*! \brief Path of the object that we would like to underline */
270 Array<ObjectPath> path_to_underline_;
271
272 /*!
273 * \brief Candidate spans to be underlined, until we find a better match.
274 * (A better match is an object with a longer path that is still a prefix of path_to_underline_.)
275 */
276 std::vector<std::vector<ByteSpan>> current_underline_candidates_;
277
278 /*! \brief Path length of the objects that are current candidates for underlining. */
279 std::vector<int> current_max_path_length_;
280
281 /*! \brief Spans that we have already committed to underline. */
282 std::vector<ByteSpan> underlines_;
283};
284
285} // namespace printer
286} // namespace script
287} // namespace tvm
288
289#endif // TVM_SCRIPT_PRINTER_DOC_PRINTER_BASE_DOC_PRINTER_H_
290