Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Relay][Text Format] Text Printer Refactor and Debug Printing (apache…
Browse files Browse the repository at this point in the history
joshpoll authored and wweic committed Mar 24, 2019

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
1 parent 1330da0 commit 495b52c
Showing 10 changed files with 961 additions and 918 deletions.
7 changes: 3 additions & 4 deletions include/tvm/relay/expr.h
Original file line number Diff line number Diff line change
@@ -551,10 +551,9 @@ inline const TTypeNode* ExprNode::type_as() const {
* additional comment block to an expr.
* \return The text representation.
*/
std::string RelayPrint(
const NodeRef& node,
bool show_meta_data = true,
runtime::TypedPackedFunc<std::string(Expr)> annotate = nullptr);
std::string RelayPrint(const NodeRef& node,
bool show_meta_data = true,
runtime::TypedPackedFunc<std::string(Expr)> annotate = nullptr);
} // namespace relay
} // namespace tvm
#endif // TVM_RELAY_EXPR_H_
3 changes: 3 additions & 0 deletions python/tvm/relay/_parser.py
Original file line number Diff line number Diff line change
@@ -512,6 +512,9 @@ def make_parser(data):
def fromtext(data, source_name=None):
# type: (str, str) -> Union[expr.Expr, module.Module]
"""Parse a Relay program."""
if data == "":
raise ParseError("Cannot parse the empty string.")

global __source_name_counter__

if source_name is None:
2 changes: 1 addition & 1 deletion python/tvm/relay/base.py
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ def astext(self, show_meta_data=True, annotate=None):
Note
----
The metadata section is necessary to fully parse the text format.
The meta data section is necessary to fully parse the text format.
However, it can contain dumps that are big (e.g constant weights),
so it can be helpful to skip printing the meta data section.
32 changes: 32 additions & 0 deletions python/tvm/relay/ir_pass.py
Original file line number Diff line number Diff line change
@@ -905,3 +905,35 @@ def eliminate_common_subexpr(expr, fskip=None):
The output expression.
"""
return _ir_pass.eliminate_common_subexpr(expr, fskip)


def pass_debug_print(ast, show_meta_data=True, annotate=None, gnf=True):
"""
THIS SHOULD BE USED ONLY FOR DEBUGGING, NOT AS AN INTERCHANGE FORMAT!
USE `.astext()` INSTEAD!
A version of the pretty printer intended for debugging passes. Contains
advanced printing options.
Parameters
----------
ast : Union[relay.Expr, relay.Module, relay.Type]
The relay fragment to be turned into text.
show_meta_data : bool
Whether to include meta data section in the text
if there is meta data.
annotate: Optional[relay.Expr->str]
Optional annotate function to provide additional
information in the comment block.
gnf : bool
Whether to print in GNF. If it is disabled, pointers are left implicit.
Returns
-------
text : str
A text representation of `ast`.
"""
return _ir_pass.pass_debug_print(ast, show_meta_data, annotate, gnf)
98 changes: 98 additions & 0 deletions src/relay/ir/doc.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*!
* Copyright (c) 2019 by Contributors
* \file src/tvm/relay/doc.cc
* \brief Doc ADT used for pretty printing.
* Based on Section 1 of https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf.
*/
#include <memory>
#include <vector>
#include "doc.h"

namespace tvm {
namespace relay {

// Text constructor
DocAtom Text(const std::string& str) {
return std::make_shared<TextNode>(str);
}

// Line constructor
DocAtom Line(int indent = 0) {
return std::make_shared<LineNode>(indent);
}

Doc::Doc(const std::string& str) {
if (str == "\n") {
this->stream_ = {Line()};
} else {
this->stream_ = {Text(str)};
}
}

// DSL function implementations

Doc& Doc::operator<<(const Doc& right) {
assert(this != &right);
this->stream_.insert(this->stream_.end(), right.stream_.begin(), right.stream_.end());
return *this;
}

Doc& Doc::operator<<(const std::string& right) {
return *this << Doc(right);
}

Doc Indent(int indent, const Doc& doc) {
Doc ret;
for (auto atom : doc.stream_) {
if (auto text = std::dynamic_pointer_cast<TextNode>(atom)) {
ret.stream_.push_back(text);
} else if (auto line = std::dynamic_pointer_cast<LineNode>(atom)) {
ret.stream_.push_back(Line(indent + line->indent));
} else {assert(false);}
}
return ret;
}

std::string Doc::str() {
std::ostringstream os;
for (auto atom : this->stream_) {
if (auto text = std::dynamic_pointer_cast<TextNode>(atom)) {
os << text->str;
} else if (auto line = std::dynamic_pointer_cast<LineNode>(atom)) {
os << "\n" << std::string(line->indent, ' ');
} else {assert(false);}
}
return os.str();
}

Doc PrintVec(const std::vector<Doc>& vec, const Doc& sep) {
Doc seq;
if (vec.size() != 0) {
seq = vec[0];
for (size_t i = 1; i < vec.size(); i++) {
seq << sep << vec[i];
}
}
return seq;
}

Doc PrintBool(bool value) {
if (value) {
return Doc("True");
} else {
return Doc("False");
}
}

Doc PrintDType(DataType dtype) {
return Doc(runtime::TVMType2String(Type2TVMType(dtype)));
}

Doc PrintString(const std::string& value) {
// TODO(M.K.): add escape.
Doc doc;
return doc << "\"" << value << "\"";
}

} // namespace relay
} // namespace tvm
99 changes: 99 additions & 0 deletions src/relay/ir/doc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*!
* Copyright (c) 2019 by Contributors
* \file tvm/relay/doc.h
* \brief Doc ADT used for pretty printing.
* Based on Section 1 of
* https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf, but with
* a vector instead of an implicitly linked list.
*/
#ifndef TVM_RELAY_IR_DOC_H_
#define TVM_RELAY_IR_DOC_H_

#include <tvm/relay/expr.h>
#include <memory>
#include <string>
#include <vector>

namespace tvm {
namespace relay {

// Doc Atom ADT
struct DocAtomNode {
virtual ~DocAtomNode() = default;
};

using DocAtom = std::shared_ptr<DocAtomNode>;

struct TextNode : DocAtomNode {
std::string str;

explicit TextNode(const std::string& str) : str(str) {}
};

struct LineNode : DocAtomNode {
int indent;

explicit LineNode(int indent) : indent(indent) {}
};

// Doc is a stream-like interface
class Doc {
public:
Doc() {}
explicit Doc(const std::string& str);

// Append right to this.
Doc& operator<<(const Doc& right);
// Like above, but automatically lifts string to a Doc.
Doc& operator<<(const std::string& right);
// Like above, but converts right to a string first.
template<typename T>
Doc& operator<<(const T& right) {
std::ostringstream os;
os << right;
return *this << os.str();
}

// Indent a doc stream.
friend Doc Indent(int indent, const Doc& doc);

// Wadler's `layout`
std::string str();

private:
std::vector<DocAtom> stream_;
};

// DSL functions

// Render vectors of docs with a separator. e.g. PrintVec([1, 2, 3], f) -> 1f2f3
Doc PrintVec(const std::vector<Doc>& vec, const Doc& sep = Doc(", "));
// Print a constant bool value.
Doc PrintBool(bool value);
// Print a data type.
Doc PrintDType(DataType dtype);
// Print a string.
Doc PrintString(const std::string& value);
/*!
* \brief special method to print out const scalar
* \param dtype The data type
* \param data The pointer to hold the data.
*/
template<typename T>
Doc PrintConstScalar(DataType dtype, const T* data) {
std::ostringstream os;
if (dtype == Int(32)) {
os << data[0];
} else if (dtype == Float(32)) {
os << data[0] << 'f';
} else if (dtype == Bool()) {
return PrintBool(data[0] != 0);
} else {
os << dtype << "(" << data[0] << ")";
}
return Doc(os.str());
}

} // namespace relay
} // namespace tvm
#endif // TVM_RELAY_IR_DOC_H_
716 changes: 716 additions & 0 deletions src/relay/ir/pretty_printer.cc

Large diffs are not rendered by default.

904 changes: 0 additions & 904 deletions src/relay/ir/text_printer.cc

This file was deleted.

6 changes: 3 additions & 3 deletions tests/python/relay/test_ir_text_printer.py
Original file line number Diff line number Diff line change
@@ -33,8 +33,8 @@ def test_env():
text = env.astext()
assert "def @myf" in text
assert "def @myf" in str(env)
assert "%1 = add(%0, %0) # ty=float32" in text
assert "%1 = add(%0, %0) # ty=float32" in str(env)
assert "%1 = add(%0, %0) // ty=float32" in text
assert "%1 = add(%0, %0) // ty=float32" in str(env)
show(env.astext(annotate=lambda x: str(x.checked_type.dtype)))
show(text)

@@ -95,7 +95,7 @@ def test_let_if_scope():

f = relay.Function([x, y, cond], result)
text = f.astext()
assert text.count("{") == 4
assert text.count("{") == 6
assert "%cond: bool" in text
show(f.astext())

12 changes: 6 additions & 6 deletions tests/python/relay/test_type_infer.py
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ def initialize_box_adt(mod):


def test_monomorphic_let():
"Program: let x = 1; return x"
"Program: let x = 1; x"
sb = relay.ScopeBuilder()
x = sb.let('x', relay.const(1.0, "float64"))
sb.ret(x)
@@ -48,7 +48,7 @@ def test_add_broadcast_op():
"""
Program:
fn (x: Tensor[(10, 4), f32], y: Tensor[(5, 10, 1), f32]) -> Tensor[(5, 10, 4), f32] {
return x + y;
x + y
}
"""
x = relay.var('x', shape=(10, 4))
@@ -67,7 +67,7 @@ def test_dual_op():
fn (x : Tensor[f32, (10, 10)]) {
let t1 = log(x);
let t2 = add(t1, x);
return t1;
t1
}
"""
tp = relay.TensorType((10, 10), "float32")
@@ -84,7 +84,7 @@ def test_dual_op():
def test_decl():
"""Program:
def f(x : Tensor[(10, 10), f32]) {
return log(x);
log(x)
}
"""
tp = relay.TensorType((10, 10))
@@ -99,9 +99,9 @@ def test_recursion():
Program:
def f(n: i32, data: f32) -> f32 {
if (n == 0) {
return data;
data
} else {
return f(n - 1, log(data));
f(n - 1, log(data))
}
}
"""

0 comments on commit 495b52c

Please sign in to comment.