14 std::stringstream edges;
15 std::map<const TTBase*, std::stringstream> tt_nodes;
16 std::multimap<const TTBase *, const TTBase *> ttg_hierarchy;
23 Dot(
bool disable_type =
false) : disable_type(disable_type){};
26 std::string
escape(
const std::string &in) {
29 if (c ==
'<' || c ==
'>' || c ==
'"' || c ==
'|')
40 s <<
"n" << (
void *)op;
48 auto search = ttg_hierarchy.find(tt->
ttg_ptr());
49 if(search == ttg_hierarchy.end()) {
52 search = ttg_hierarchy.find(tt);
53 if(search == ttg_hierarchy.end()) {
54 ttg_hierarchy.insert( decltype(ttg_hierarchy)::value_type(tt->
ttg_ptr(), tt) );
64 std::stringstream ttss;
66 ttss <<
" " << ttnm <<
" [shape=record,style=filled,fillcolor=gray90,label=\"{";
72 if (count != in->get_index())
throw "ttg::Dot: lost count of ins";
74 ttss <<
" <in" << count <<
">"
75 <<
" " <<
escape(in->get_key_type_str()) <<
" " <<
escape(in->get_name());
77 ttss <<
" <in" << count <<
">"
78 <<
" " <<
escape(
"<" + in->get_key_type_str() +
"," + in->get_value_type_str() +
">") <<
" "
82 ttss <<
" <in" << count <<
">"
86 if (count < tt->get_inputs().
size()) ttss <<
" |";
88 if (tt->
get_inputs().size() > 0) ttss <<
"} |";
97 if (count != out->get_index())
throw "ttg::Dot: lost count of outs";
99 ttss <<
" <out" << count <<
">"
100 <<
" " <<
escape(out->get_key_type_str()) <<
" " << out->get_name();
102 ttss <<
" <out" << count <<
">"
103 <<
" " <<
escape(
"<" + out->get_key_type_str() +
"," + out->get_value_type_str() +
">") <<
" "
107 ttss <<
" <out" << count <<
">"
111 if (count < tt->get_outputs().
size()) ttss <<
" |";
118 auto search = tt_nodes.find(ttc);
119 if( tt_nodes.end() == search ) {
120 tt_nodes.insert( {ttc, std::move(ttss)} );
122 search->second << ttss.str();
125 std::cout << ttnm <<
" is a TTG" << std::endl;
130 for (
auto successor : out->get_connections()) {
132 edges << ttnm <<
":out" << out->get_index() <<
":s -> " <<
nodename(successor->get_tt()) <<
":in"
133 << successor->get_index() <<
":n;\n";
145 if(node ==
nullptr || node->
is_ttg()) {
146 if(
nullptr != node) {
147 buf <<
"subgraph cluster_" << cluster_cnt++ <<
" {\n";
149 auto children = ttg_hierarchy.equal_range(node);
150 for(
auto child = children.first; child != children.second; child++) {
151 assert(child->first == node);
154 if(
nullptr != node) {
155 buf <<
" label = \"" << node->
get_name() <<
"\";\n";
159 auto child = tt_nodes.find(node);
160 if( child != tt_nodes.end()) {
161 assert(child->first == node);
162 buf << child->second.str();
169 template <
typename... TTBasePtrs>
170 std::enable_if_t<(std::is_convertible_v<std::remove_const_t<std::remove_reference_t<TTBasePtrs>>,
TTBase *> && ...),
174 std::stringstream buf;
175 buf.str(std::string());
178 edges.str(std::string());
182 ttg_hierarchy.clear();
184 buf <<
"digraph G {\n";
185 buf <<
" ranksep=1.5;\n";
187 t &= (
traverse(std::forward<TTBasePtrs>(ops)) && ... );
196 std::string result = buf.str();
197 buf.str(std::string());
Prints the graph to a std::string in the format understood by GraphViz's dot program.
void infunc(TerminalBase *in)
void outfunc(TerminalBase *out)
std::string nodename(const TTBase *op)
std::string escape(const std::string &in)
void tree_down(int level, const TTBase *node, std::stringstream &buf)
Dot(bool disable_type=false)
std::enable_if_t<(std::is_convertible_v< std::remove_const_t< std::remove_reference_t< TTBasePtrs >>, TTBase * > &&...), std::string > operator()(TTBasePtrs &&... ops)
void build_ttg_hierarchy(const TTBase *tt)
A base class for all template tasks.
const std::vector< TerminalBase * > & get_inputs() const
Returns the vector of input terminals.
const std::vector< TerminalBase * > & get_outputs() const
Returns the vector of output terminals.
const std::string & get_name() const
Gets the name of this operation.
const TTBase * ttg_ptr() const
Traverses a graph of TTs in depth-first manner following out edges.
bool traverse(TTBase *tt)
top-level TTG namespace contains runtime-neutral functionality
int size(World world=default_execution_context())
auto edges(inedgesT &&...args)
Make a tuple of Edges to pass to.