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
20/*!
21 * \file tvm/printer/doc.h
22 * \brief Doc ADT used for pretty printing.
23 *
24 * Reference: Philip Wadler. A Prettier Printer. Journal of Functional Programming'98
25 */
26#ifndef TVM_RELAY_PRINTER_DOC_H_
27#define TVM_RELAY_PRINTER_DOC_H_
28
29#include <tvm/node/node.h>
30#include <tvm/runtime/data_type.h>
31#include <tvm/runtime/object.h>
32
33#include <string>
34#include <type_traits>
35#include <vector>
36
37namespace tvm {
38namespace relay {
39
40/*!
41 * \brief Doc atom node for the ADT.
42 * \sa DocAtom
43 */
44class DocAtomNode : public Object {
45 public:
46 static constexpr const char* _type_key = "printer.DocAtom";
47 TVM_DECLARE_BASE_OBJECT_INFO(DocAtomNode, Object);
48};
49
50/*!
51 * \brief Managed reference to DocAtomNode.
52 * \sa DocAtomNode.
53 */
54class DocAtom : public ObjectRef {
55 public:
56 TVM_DEFINE_OBJECT_REF_METHODS(DocAtom, ObjectRef, DocAtomNode);
57};
58
59/*!
60 * \brief Stream-like interface for Doc DSL.
61 *
62 * The Doc DSL de-couples the layout decision from the printing decision.
63 *
64 * The layout(code formating) decisions include:
65 * - Change indentation.
66 * - Break single line into multiple ones(subjected to future improvements).
67 */
68class Doc {
69 public:
70 /*! \brief default constructor */
71 Doc() {}
72 /*!
73 * \brief Append right to the end of the current doc stream.
74 * \param right The doc to be appended.
75 * \return reference to self.
76 */
77 Doc& operator<<(const Doc& right);
78 /*!
79 * \brief Append right to the end of the current doc stream.
80 * \param right The doc to be appended.
81 * \return reference to self.
82 * \note pass by value to allow copy elison optimization.
83 */
84 Doc& operator<<(std::string right);
85 /*!
86 * \brief Append right to the end of the current doc stream.
87 * \param right The doc to be appended.
88 * \return reference to self.
89 */
90 Doc& operator<<(const DocAtom& right);
91 /*!
92 * \brief Convert value to string via std::ostreamstream
93 * the append to the current doc stream.
94 * \param right The doc to be appended.
95 * \tparam T the type of the value.
96 * \return reference to self.
97 */
98 template <typename T, typename = typename std::enable_if<!std::is_class<T>::value>::type>
99 Doc& operator<<(const T& value) {
100 std::ostringstream os;
101 os << value;
102 return *this << os.str();
103 }
104 /*!
105 * \brief Convert the doc stream into string.
106 * \return The string representation.
107 */
108 std::string str();
109 /*!
110 * \brief Create a doc that represents text content.
111 * \return The created doc.
112 */
113 static Doc Text(std::string value);
114 /*!
115 * \brief Create a doc that represents raw text(can have new lines)
116 * \return The created doc.
117 */
118 static Doc RawText(std::string value);
119 /*!
120 * \brief Create a doc that represents a new line.
121 * \return The created doc.
122 */
123 static Doc NewLine(int indent = 0);
124 /*!
125 * \brief Create a new doc that adds indentation to everyline of the doc.
126 * \param indent The indent to be added.
127 * \param doc The doc to be indented.
128 * \return The created doc.
129 * \note pass by value to allow copy elison optimization.
130 */
131 static Doc Indent(int indent, Doc doc);
132 /*!
133 * \brief Create a Doc that represents a string literal.
134 * \param value The content of the string literal.
135 * \param quote The quote in the literal.
136 * \return The created doc.
137 */
138 static Doc StrLiteral(const std::string& value, std::string quote = "\"");
139 /*!
140 * \brief Create a Doc that represents a boolean literal in python syntax.
141 * \param value The bool value.
142 * \return The created doc.
143 */
144 static Doc PyBoolLiteral(bool value);
145 /*!
146 * \brief Enclose body by brace and add indent.
147 * \param body The body
148 * \param open The open brace.
149 * \param close The close brace.
150 * \param indent amount of indentation.
151 * \return The created doc.
152 */
153 static Doc Brace(std::string open, const Doc& body, std::string close, int indent = 2);
154 /*!
155 * \brief Create a doc by concatenating together with separator.
156 * \param vec The docs to be concatenated.
157 * \param sep The seperator.
158 * \return The created doc.
159 */
160 static Doc Concat(const std::vector<Doc>& vec, const Doc& sep = Text(", "));
161
162 private:
163 /*! \brief Internal doc stream. */
164 std::vector<DocAtom> stream_;
165};
166} // namespace relay
167} // namespace tvm
168#endif // TVM_RELAY_PRINTER_DOC_H_
169