11using namespace std::string_literals;
18std::string
escape(
const T& val) {
19 std::ostringstream oss;
29 Dot(std::ostream& ostream,
bool types,
const Def* root =
nullptr)
35 (tab_++).
println(os_,
"digraph {{");
36 tab_.println(os_,
"ordering=out;");
37 tab_.println(os_,
"splines=ortho;");
38 tab_.println(os_,
"newrank=true;");
39 tab_.println(os_,
"nodesep=0.6;");
40 tab_.println(os_,
"ranksep=1.2;");
41 tab_.println(os_,
"node [shape=box,style=filled,fontname=\"monospace\"];");
44 void epilogue() { (--tab_).
println(os_,
"}}"); }
46 void run(
const Def* root, uint32_t max) {
52 void recurse(
const Def* def, uint32_t max) {
53 if (max == 0 || !done_.emplace(def).second)
return;
55 tab_.print(os_,
"_{}[", def->gid());
59 os_ <<
"style=\"filled,diagonals,bold\"";
61 os_ <<
"style=\"filled,diagonals\",penwidth=2";
62 else if (def == root_)
63 os_ <<
"style=\"filled,bold\"";
67 if (def->is_closed()) os_ <<
"rank=min,";
68 tooltip(def) <<
"];\n";
71 for (
size_t i = 0, e = def->num_ops(); i != e; ++i) {
74 if (
op->isa<
Lit>() ||
op->isa<
Axm>() || def->isa<
Var>() || def->isa<
Nat>() || def->isa<
Idx>())
75 tab_.println(os_,
"_{}:{} -> _{}[color=\"#00000000\",constraint=false];", def->gid(), i,
op->
gid());
77 tab_.println(os_,
"_{}:{} -> _{};", def->gid(), i,
op->
gid());
81 if (
auto t = def->type(); t && types_) {
83 tab_.println(os_,
"_{} -> _{}[color=\"#00000000\",constraint=false,style=dashed];", def->gid(),
t->gid());
87 std::ostream& label(
const Def* def) {
88 auto n = def->is_set() ? def->num_ops() : size_t(0);
90 print(os_,
"label=<<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td colspan=\"{}\">", n);
92 os_ <<
"</td></tr><tr>";
93 for (
size_t i = 0; i < n; ++i)
94 print(os_,
"<td port=\"{}\" cellpadding=\"0\" height=\"1\" width=\"8\"></td>", i);
95 os_ <<
"</tr></table>>";
104 void emit_name(
const Def* def) {
105 if (
auto lit = def->isa<
Lit>())
108 os_ << def->node_name();
109 print(os_,
"<br/><font point-size=\"9\">{}</font>",
escape(def->unique_name()));
112 std::ostream& color(
const Def* def) {
115 if (def->is_form()) hue = 0.60f;
116 else if (def->is_intro()) hue = 0.35f;
117 else if (def->is_elim()) hue = 0.00f;
118 else if (def->is_meta()) hue = 0.15f;
121 return print(os_,
"fillcolor=\"{} 0.5 0.75\"", hue);
124 std::ostream& tooltip(
const Def* def) {
125 static constexpr auto NL =
" ";
127 auto loc =
escape(def->loc());
129 print(os_,
"tooltip=\"");
130 print(os_,
"<b>expr:</b> {}{}", def, NL);
131 print(os_,
"<b>type:</b> {}{}", type, NL);
132 print(os_,
"<b>name:</b> {}{}", def->sym(), NL);
133 print(os_,
"<b>gid:</b> {}{}", def->gid(), NL);
134 print(os_,
"<b>flags:</b> 0x{x}{}", def->flags(), NL);
135 print(os_,
"<b>mark:</b> 0x{x}{}", def->mark(), NL);
136 print(os_,
"<b>local_muts:</b> {, }{}", def->local_muts(), NL);
137 print(os_,
"<b>local_vars:</b> {, }{}", def->local_vars(), NL);
138 print(os_,
"<b>free_vars:</b> {, }{}", def->free_vars(), NL);
139 if (
auto mut = def->isa_mut())
print(os_,
"<b>users:</b> {{{, }}}{}", mut->users(), NL);
140 print(os_,
"<b>loc:</b> {}", loc);
141 return print(os_,
"\"");
154void Def::dot(std::ostream& ostream, uint32_t max,
bool types)
const { Dot(ostream, types,
this).run(
this, max); }
156void Def::dot(
const char* file, uint32_t max,
bool types)
const {
158 dot(std::cout, max, types);
160 auto of = std::ofstream(file);
169 auto of = std::ofstream(file);
174void World::dot(std::ostream& os,
bool anx,
bool types)
const {
178 dot.recurse(external, uint32_t(-1));
193 auto of = std::ofstream(file);
200 (tab++).
println(os,
"digraph {{");
201 tab.
println(os,
"ordering=out;");
202 tab.
println(os,
"node [shape=box,style=filled];");
203 root()->dot(tab, os);
207void Nest::Node::dot(
Tab tab, std::ostream& os)
const {
209 for (
const auto& scc : topo_) {
211 for (
auto sep =
""s;
auto n : *scc) {
212 s += sep + n->name();
219 tab.
println(os,
"\"{}\":s -> \"{}\":s [style=dashed,constraint=false,splines=true]",
name(), sibl->name());
222 auto html =
"<b>" +
name() +
"</b>";
223 if (*rec) html +=
"<br/><i>"s + rec +
"</i>";
224 html +=
"<br/><font point-size=\"8\">depth " + std::to_string(
loop_depth()) +
"</font>";
225 tab.
println(os,
"\"{}\" [label=<{}>,tooltip=\"{}\"]",
name(), html, s);
227 tab.
println(os,
"\"{}\" -> \"{}\" [splines=false]",
name(), child->name());
232 if (
idom()) tab.
println(os,
"\"{}\" -> \"{}\" [color=red,style=bold,constraint=false]",
idom()->
name(),
name());
void dot(std::ostream &os, uint32_t max=0xFFFFFF, bool types=false) const
const Def * op(size_t i) const noexcept
constexpr u32 gid() const noexcept
Global id - unique number for this Def.
const Children & children() const
auto idom() const
Immediate Dominator for children in connected components.
bool is_directly_recursive() const
bool is_mutually_recursive() const
uint32_t loop_depth() const
void dot(std::ostream &os) const
const Node * root() const
Keeps track of indentation level.
std::ostream & println(std::ostream &os, const char *s, Args &&... args)
Same as Tab::print but appends a std::endl to os.
const Def * annex(Id id)
Lookup annex by Axm::id.
const Externals & externals() const
void dot(std::ostream &os, bool annexes=false, bool types=false) const
Dumps DOT to os.
const Def * op(trait o, const Def *type)
int run(std::string cmd, std::string args={})
Wraps sys::system and puts .exe at the back (Windows) and ./ at the front (otherwise) of cmd.
std::string escape(const std::filesystem::path &path)
Returns the path as std::string and escapes all whitespaces with backslash.
std::ostream & print(std::ostream &os, const char *s)
Base case.
void find_and_replace(std::string &str, std::string_view what, std::string_view repl)
Replaces all occurrences of what with repl.
GIDSet< const Def * > DefSet
std::ostream & println(std::ostream &os, const char *fmt, Args &&... args)
As above but end with std::endl.