Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Relay][Text Format] Text Printer Refactor and Debug Printing #2605

Merged
merged 74 commits into from
Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from 70 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
c13b2ae
minor bug fix and beginnings of hypothesis testing
joshpoll Feb 15, 2019
aec4724
bump semver. add inline_meta_data flag. implement tuples
joshpoll Feb 15, 2019
1595a46
add simple wadler-style printer infrastructure
joshpoll Feb 17, 2019
7b6ce8b
make things build
joshpoll Feb 17, 2019
c11260a
remove stringstreams. add pretty printer class
joshpoll Feb 17, 2019
0a3210b
commit failing refactoring things. can't return abstract class. may n…
joshpoll Feb 17, 2019
9f56672
switch to tvm-style adts
joshpoll Feb 18, 2019
1f8ff51
tuple projection and more testing
joshpoll Feb 18, 2019
414fab4
revert text_printer changes
joshpoll Feb 18, 2019
497f4eb
derandomize
joshpoll Feb 18, 2019
c921cd0
revert version number bump
joshpoll Feb 18, 2019
b7cdf43
adds separate gnf printer file and factors out some common functions.…
joshpoll Feb 21, 2019
eabd52a
fix some stuff and get compiling again
joshpoll Feb 21, 2019
fd25456
simplify Doc infrastructure
joshpoll Feb 22, 2019
bd21270
fix bugs. improve gnf printer
joshpoll Feb 22, 2019
1a58f64
add stream-like interface for docs
joshpoll Feb 23, 2019
073029d
if nodes in gnf
joshpoll Feb 23, 2019
14e083f
semiworking let. kinda
joshpoll Feb 23, 2019
1ba8a82
fix let and refactor
joshpoll Feb 23, 2019
3ad0ad1
tempvar refactor
joshpoll Feb 23, 2019
fb3d910
Nest -> Indent to avoid confusion with nested scopes
joshpoll Feb 23, 2019
bba6b97
minor changes
joshpoll Feb 23, 2019
1d78b97
fix lets for real (mostly) and combine anf and gnf printing
joshpoll Feb 23, 2019
24f255f
support variables, functions, and fix a corner-case bug when only a t…
joshpoll Feb 24, 2019
61033d0
fix if scope in GNF
joshpoll Feb 28, 2019
73ee892
add global var
joshpoll Mar 1, 2019
00cbd9f
add simple call and op
joshpoll Mar 1, 2019
9795c10
add attrs and small refactoring
joshpoll Mar 2, 2019
2a7e94d
add tensor type printing and refactor attr printing to get it to work
joshpoll Mar 4, 2019
1d45241
indenting and add tests
joshpoll Mar 4, 2019
f6c26f5
func type
joshpoll Mar 4, 2019
10fe7bf
set up PrintMod
joshpoll Mar 4, 2019
7aa71cf
free vars and modules
joshpoll Mar 4, 2019
cf91b02
type annotations
joshpoll Mar 5, 2019
46835e0
scope in let value position
joshpoll Mar 5, 2019
d2cfe74
meta except it doesn't work and it broke old stuff
joshpoll Mar 5, 2019
9b4bad7
fix bugs except for meta bugs
joshpoll Mar 5, 2019
0549d26
fix printing of free variables. meta still broken
joshpoll Mar 5, 2019
d117835
fix free vars for real
joshpoll Mar 5, 2019
d6d4065
fix segfault
joshpoll Mar 5, 2019
772aad9
complete meta
joshpoll Mar 6, 2019
6d5767c
bye bye text printer. hello pretty printer
joshpoll Mar 6, 2019
1bb55bb
pass text printer tests
joshpoll Mar 6, 2019
69370d2
pretty printer lint
joshpoll Mar 6, 2019
589f778
more linting
joshpoll Mar 6, 2019
f27c130
fix typo
joshpoll Mar 6, 2019
3586edf
lint
joshpoll Mar 6, 2019
84b9c13
add default case
joshpoll Mar 7, 2019
e6e2d94
remove trailing whitespace
joshpoll Mar 7, 2019
7fa7cff
trigger ci
joshpoll Mar 7, 2019
cbd7c89
fix some tests, add meta fallback, add hypothesis to python packages
joshpoll Mar 7, 2019
da6642f
references
joshpoll Mar 7, 2019
89f58f6
pattern matching
joshpoll Mar 7, 2019
f3a5728
fix attr printing
joshpoll Mar 7, 2019
d090704
linting
joshpoll Mar 7, 2019
9d8a167
default attr flag, new tests, fix some bugs
joshpoll Mar 9, 2019
1a26c84
revert hypothesis addition
joshpoll Mar 9, 2019
a587a36
linting
joshpoll Mar 9, 2019
fb1345f
revert overeager printing optimizations. untrack roundtrip tests
joshpoll Mar 12, 2019
3a5d1de
separate interfaces for interchange and debug
joshpoll Mar 12, 2019
5807815
bug fix
joshpoll Mar 12, 2019
e7201fa
remove hacks
joshpoll Mar 12, 2019
3184de0
fix atr bug
joshpoll Mar 13, 2019
f5081bd
lint
joshpoll Mar 13, 2019
c8ab556
lint
joshpoll Mar 13, 2019
da68638
improve doc stream interface
joshpoll Mar 14, 2019
c7c8a67
further simplify interface. remove NOLINTs
joshpoll Mar 14, 2019
81ea258
fix bugs and docs
joshpoll Mar 14, 2019
fd43b91
move str to doc.cc
joshpoll Mar 14, 2019
2eb7f6e
remove stale documentation
joshpoll Mar 14, 2019
c9e7d88
Update src/relay/ir/pretty_printer.cc
wweic Mar 17, 2019
a528fe2
address feedback
joshpoll Mar 18, 2019
3a4e41d
erge branch 'parser-roundtrip' of https://github.com/joshpoll/tvm int…
joshpoll Mar 18, 2019
7f9921d
minor comment changes and bump ci
joshpoll Mar 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions include/tvm/relay/expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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 == "":
joshpoll marked this conversation as resolved.
Show resolved Hide resolved
raise ParseError("Cannot parse the empty string.")

global __source_name_counter__

if source_name is None:
Expand Down
2 changes: 1 addition & 1 deletion python/tvm/relay/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
joshpoll marked this conversation as resolved.
Show resolved Hide resolved
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.

Expand Down
32 changes: 32 additions & 0 deletions python/tvm/relay/ir_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
97 changes: 97 additions & 0 deletions src/relay/ir/doc.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*!
* 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) {
this->stream_.insert(this->stream_.end(), right.stream_.begin(), right.stream_.end());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think this is correct.
Use https://en.cppreference.com/w/cpp/iterator/back_insert_iterator instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or just use a for loop.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also check against this == &right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still has to catch against this == &right.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see latest commit

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;
joshpoll marked this conversation as resolved.
Show resolved Hide resolved
}

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. [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_
Loading