15 std::stringstream edges;
16 std::map<const TTBase*, std::stringstream> tt_nodes;
17 std::multimap<const TTBase *, const TTBase *> ttg_hierarchy;
24 Dot(
bool disable_type =
false) : disable_type(disable_type){};
27 std::string
escape(
const std::string &in) {
30 if (c ==
'<' || c ==
'>' || c ==
'"' || c ==
'|')
41 s <<
"n" << (
void *)op;
49 auto search = ttg_hierarchy.find(tt->
ttg_ptr());
50 if(search == ttg_hierarchy.end()) {
53 search = ttg_hierarchy.find(tt);
54 if(search == ttg_hierarchy.end()) {
55 ttg_hierarchy.insert(
decltype(ttg_hierarchy)::value_type(tt->
ttg_ptr(), tt) );
65 std::stringstream ttss;
67 ttss <<
" " << ttnm <<
" [shape=record,style=filled,fillcolor=gray90,label=\"{";
73 if (count != in->get_index())
throw "ttg::Dot: lost count of ins";
75 ttss <<
" <in" << count <<
">" <<
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 <<
">" << out->get_name();
101 ttss <<
" <out" << count <<
">"
102 <<
" " <<
escape(
"<" + out->get_key_type_str() +
"," + out->get_value_type_str() +
">") <<
" "
106 ttss <<
" <out" << count <<
">"
110 if (count < tt->get_outputs().
size()) ttss <<
" |";
117 auto search = tt_nodes.find(ttc);
118 if( tt_nodes.end() == search ) {
119 tt_nodes.insert( {ttc, std::move(ttss)} );
121 search->second << ttss.str();
124 std::cout << ttnm <<
" is a TTG" << std::endl;
129 for (
auto successor : out->get_connections()) {
131 edges << ttnm <<
":out" << out->get_index() <<
":s -> " <<
nodename(successor->get_tt()) <<
":in"
132 << successor->get_index() <<
":n;\n";
144 if(node ==
nullptr || node->
is_ttg()) {
145 if(
nullptr != node) {
146 buf <<
"subgraph cluster_" << cluster_cnt++ <<
" {\n";
148 auto children = ttg_hierarchy.equal_range(node);
149 for(
auto child = children.first; child != children.second; child++) {
150 assert(child->first == node);
153 if(
nullptr != node) {
154 buf <<
" label = \"" << node->
get_name() <<
"\";\n";
158 auto child = tt_nodes.find(node);
159 if( child != tt_nodes.end()) {
160 assert(child->first == node);
161 buf << child->second.str();
168 template <
typename... TTBasePtrs>
169 std::enable_if_t<(std::is_convertible_v<std::remove_const_t<std::remove_reference_t<TTBasePtrs>>,
TTBase *> && ...),
173 std::stringstream buf;
174 buf.str(std::string());
177 edges.str(std::string());
181 ttg_hierarchy.clear();
183 buf <<
"digraph G {\n";
184 buf <<
" ranksep=1.5;\n";
186 t &= (
traverse(std::forward<TTBasePtrs>(ops)) && ... );
195 std::string result = buf.str();
196 buf.str(std::string());
Prints the graph to a std::string in the format understood by GraphViz's dot program.
std::enable_if_t<(std::is_convertible_v< std::remove_const_t< std::remove_reference_t< TTBasePtrs > >, TTBase * > &&...), std::string > operator()(TTBasePtrs &&... ops)
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)
void build_ttg_hierarchy(const TTBase *tt)
A base class for all template tasks.
const std::vector< TerminalBase * > & get_outputs() const
Returns the vector of output terminals.
const std::vector< TerminalBase * > & get_inputs() const
Returns the vector of input terminals.
const TTBase * ttg_ptr() const
const std::string & get_name() const
Gets the name of this operation.
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.