| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /*! |
| * \file src/relay/doc.cc |
| * \brief Doc ADT used for pretty printing. |
| * |
| * Reference: Philip Wadler. A Prettier Printer. Journal of Functional Programming'98 |
| */ |
| #include "doc.h" |
| |
| #include <tvm/runtime/packed_func.h> |
| |
| #include <sstream> |
| #include <vector> |
| |
| namespace tvm { |
| |
| /*! |
| * \brief Represent a piece of text in the doc. |
| */ |
| class DocTextNode : public DocAtomNode { |
| public: |
| /*! \brief The str content in the text. */ |
| std::string str; |
| |
| explicit DocTextNode(std::string str_val) : str(str_val) {} |
| |
| static constexpr const char* _type_key = "printer.DocText"; |
| TVM_DECLARE_FINAL_OBJECT_INFO(DocTextNode, DocAtomNode); |
| }; |
| |
| TVM_REGISTER_OBJECT_TYPE(DocTextNode); |
| |
| class DocText : public DocAtom { |
| public: |
| explicit DocText(std::string str) { |
| if (str.find_first_of("\t\n") != str.npos) { |
| LOG(WARNING) << "text node: '" << str << "' should not has tab or newline."; |
| } |
| data_ = runtime::make_object<DocTextNode>(str); |
| } |
| |
| TVM_DEFINE_OBJECT_REF_METHODS(DocText, DocAtom, DocTextNode); |
| }; |
| |
| /*! |
| * \brief Represent a line breaker in the doc. |
| */ |
| class DocLineNode : public DocAtomNode { |
| public: |
| /*! \brief The amount of indent in newline. */ |
| int indent; |
| |
| explicit DocLineNode(int indent) : indent(indent) {} |
| |
| static constexpr const char* _type_key = "printer.DocLine"; |
| TVM_DECLARE_FINAL_OBJECT_INFO(DocLineNode, DocAtomNode); |
| }; |
| |
| TVM_REGISTER_OBJECT_TYPE(DocLineNode); |
| |
| class DocLine : public DocAtom { |
| public: |
| explicit DocLine(int indent) { data_ = runtime::make_object<DocLineNode>(indent); } |
| |
| TVM_DEFINE_OBJECT_REF_METHODS(DocLine, DocAtom, DocLineNode); |
| }; |
| |
| // DSL function implementations |
| Doc& Doc::operator<<(const Doc& right) { |
| CHECK(this != &right); |
| this->stream_.insert(this->stream_.end(), right.stream_.begin(), right.stream_.end()); |
| return *this; |
| } |
| |
| Doc& Doc::operator<<(std::string right) { return *this << DocText(right); } |
| |
| Doc& Doc::operator<<(const DocAtom& right) { |
| this->stream_.push_back(right); |
| return *this; |
| } |
| |
| std::string Doc::str() { |
| std::ostringstream os; |
| for (auto atom : this->stream_) { |
| if (auto* text = atom.as<DocTextNode>()) { |
| os << text->str; |
| } else if (auto* line = atom.as<DocLineNode>()) { |
| os << "\n" << std::string(line->indent, ' '); |
| } else { |
| LOG(FATAL) << "do not expect type " << atom->GetTypeKey(); |
| } |
| } |
| return os.str(); |
| } |
| |
| Doc Doc::NewLine(int indent) { return Doc() << DocLine(indent); } |
| |
| Doc Doc::Text(std::string text) { return Doc() << DocText(text); } |
| |
| Doc Doc::RawText(std::string text) { |
| return Doc() << DocAtom(runtime::make_object<DocTextNode>(text)); |
| } |
| |
| Doc Doc::Indent(int indent, Doc doc) { |
| for (size_t i = 0; i < doc.stream_.size(); ++i) { |
| if (auto* line = doc.stream_[i].as<DocLineNode>()) { |
| doc.stream_[i] = DocLine(indent + line->indent); |
| } |
| } |
| return doc; |
| } |
| |
| Doc Doc::StrLiteral(const std::string& value, std::string quote) { |
| // TODO(@M.K.): add escape. |
| Doc doc; |
| return doc << quote << value << quote; |
| } |
| |
| Doc Doc::PyBoolLiteral(bool value) { |
| if (value) { |
| return Doc::Text("True"); |
| } else { |
| return Doc::Text("False"); |
| } |
| } |
| |
| Doc Doc::Brace(std::string open, const Doc& body, std::string close, int indent) { |
| Doc doc; |
| doc << open; |
| doc << Indent(indent, NewLine() << body) << NewLine(); |
| doc << close; |
| return doc; |
| } |
| |
| Doc Doc::Concat(const std::vector<Doc>& vec, const Doc& sep) { |
| Doc seq; |
| if (vec.size() != 0) { |
| if (vec.size() == 1) return vec[0]; |
| seq << vec[0]; |
| for (size_t i = 1; i < vec.size(); ++i) { |
| seq << sep << vec[i]; |
| } |
| } |
| return seq; |
| } |
| } // namespace tvm |