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 | |
31 | namespace tvm { |
32 | namespace script { |
33 | namespace printer { |
34 | |
35 | /*! \brief Range of byte offsets in a string */ |
36 | using 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 | */ |
46 | class 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 (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 | |