|
| 1 | +/*! |
| 2 | + * Copyright (c) 2019 by Contributors |
| 3 | + * \file tvm/relay/doc.h |
| 4 | + * \brief Doc ADT used for pretty printing. |
| 5 | + * Based on Section 1 of |
| 6 | + * https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf, but with |
| 7 | + * a vector instead of an implicitly linked list. |
| 8 | + */ |
| 9 | +#ifndef TVM_RELAY_IR_DOC_H_ |
| 10 | +#define TVM_RELAY_IR_DOC_H_ |
| 11 | + |
| 12 | +#include <tvm/relay/expr.h> |
| 13 | +#include <memory> |
| 14 | +#include <string> |
| 15 | +#include <vector> |
| 16 | + |
| 17 | +namespace tvm { |
| 18 | +namespace relay { |
| 19 | + |
| 20 | +// Doc Atom ADT |
| 21 | +struct DocAtomNode { |
| 22 | + virtual ~DocAtomNode() = default; |
| 23 | +}; |
| 24 | + |
| 25 | +using DocAtom = std::shared_ptr<DocAtomNode>; |
| 26 | + |
| 27 | +struct TextNode : DocAtomNode { |
| 28 | + std::string str; |
| 29 | + |
| 30 | + explicit TextNode(const std::string& str) : str(str) {} |
| 31 | +}; |
| 32 | + |
| 33 | +struct LineNode : DocAtomNode { |
| 34 | + int indent; |
| 35 | + |
| 36 | + explicit LineNode(int indent) : indent(indent) {} |
| 37 | +}; |
| 38 | + |
| 39 | +// Doc is a stream-like interface |
| 40 | +class Doc { |
| 41 | + public: |
| 42 | + Doc() {} |
| 43 | + explicit Doc(const std::string& str); |
| 44 | + |
| 45 | + // Append right to this. |
| 46 | + Doc& operator<<(const Doc& right); |
| 47 | + // Like above, but automatically lifts string to a Doc. |
| 48 | + Doc& operator<<(const std::string& right); |
| 49 | + // Like above, but converts right to a string first. |
| 50 | + template<typename T> |
| 51 | + Doc& operator<<(const T& right) { |
| 52 | + std::ostringstream os; |
| 53 | + os << right; |
| 54 | + return *this << os.str(); |
| 55 | + } |
| 56 | + |
| 57 | + // Indent a doc stream. |
| 58 | + friend Doc Indent(int indent, const Doc& doc); |
| 59 | + |
| 60 | + // Wadler's `layout` |
| 61 | + std::string str(); |
| 62 | + |
| 63 | + private: |
| 64 | + std::vector<DocAtom> stream_; |
| 65 | +}; |
| 66 | + |
| 67 | +// DSL functions |
| 68 | + |
| 69 | +// Render vectors of docs with a separator. e.g. PrintVec([1, 2, 3], f) -> 1f2f3 |
| 70 | +Doc PrintVec(const std::vector<Doc>& vec, const Doc& sep = Doc(", ")); |
| 71 | +// Print a constant bool value. |
| 72 | +Doc PrintBool(bool value); |
| 73 | +// Print a data type. |
| 74 | +Doc PrintDType(DataType dtype); |
| 75 | +// Print a string. |
| 76 | +Doc PrintString(const std::string& value); |
| 77 | +/*! |
| 78 | + * \brief special method to print out const scalar |
| 79 | + * \param dtype The data type |
| 80 | + * \param data The pointer to hold the data. |
| 81 | + */ |
| 82 | +template<typename T> |
| 83 | +Doc PrintConstScalar(DataType dtype, const T* data) { |
| 84 | + std::ostringstream os; |
| 85 | + if (dtype == Int(32)) { |
| 86 | + os << data[0]; |
| 87 | + } else if (dtype == Float(32)) { |
| 88 | + os << data[0] << 'f'; |
| 89 | + } else if (dtype == Bool()) { |
| 90 | + return PrintBool(data[0] != 0); |
| 91 | + } else { |
| 92 | + os << dtype << "(" << data[0] << ")"; |
| 93 | + } |
| 94 | + return Doc(os.str()); |
| 95 | +} |
| 96 | + |
| 97 | +} // namespace relay |
| 98 | +} // namespace tvm |
| 99 | +#endif // TVM_RELAY_IR_DOC_H_ |
0 commit comments