10using namespace std::string_literals;
17std::string
escape(
const T& val) {
18 std::ostringstream oss;
28 Dot(std::ostream& ostream,
bool types,
const Def* root =
nullptr)
34 std::println(os_,
"{}digraph {{", tab_);
36 std::println(os_,
"{}ordering=out;", tab_);
37 std::println(os_,
"{}splines=ortho;", tab_);
38 std::println(os_,
"{}newrank=true;", tab_);
39 std::println(os_,
"{}nodesep=0.6;", tab_);
40 std::println(os_,
"{}ranksep=1.2;", tab_);
41 std::println(os_,
"{}node [shape=box,style=filled,fontname=\"monospace\"];", tab_);
46 std::println(os_,
"{}}}", tab_);
49 void run(
const Def* root,
int max) {
55 void recurse(
const Def* def,
int max) {
56 if (max == 0 || !done_.emplace(def).second)
return;
58 std::print(os_,
"{}_{}[", tab_, def->gid());
62 os_ <<
"style=\"filled,diagonals,bold\"";
64 os_ <<
"style=\"filled,diagonals\",penwidth=2";
65 else if (def == root_)
66 os_ <<
"style=\"filled,bold\"";
70 if (def->is_closed()) os_ <<
"rank=min,";
71 tooltip(def) <<
"];\n";
74 for (
size_t i = 0, e = def->num_ops(); i != e; ++i) {
77 if (
op->isa<
Lit>() ||
op->isa<
Axm>() || def->isa<
Var>() || def->isa<
Nat>() || def->isa<
Idx>())
78 std::println(os_,
"{}_{}:{} -> _{}[color=\"#00000000\",constraint=false];", tab_, def->gid(), i,
81 std::println(os_,
"{}_{}:{} -> _{};", tab_, def->gid(), i,
op->gid());
85 if (
auto t = def->type(); t && types_) {
87 std::println(os_,
"{}_{} -> _{}[color=\"#00000000\",constraint=false,style=dashed];", tab_, def->gid(),
92 std::ostream& label(
const Def* def) {
93 auto n = def->is_set() ? def->num_ops() : size_t(0);
95 std::print(os_,
"label=<<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\"><tr><td colspan=\"{}\">",
98 os_ <<
"</td></tr><tr>";
99 for (
size_t i = 0; i < n; ++i)
100 std::print(os_,
"<td port=\"{}\" cellpadding=\"0\" height=\"1\" width=\"8\"></td>", i);
101 os_ <<
"</tr></table>>";
110 void emit_name(
const Def* def) {
111 if (
auto lit = def->isa<
Lit>())
114 os_ << def->node_name();
115 std::print(os_,
"<br/><font point-size=\"9\">{}</font>",
escape(def->unique_name()));
118 std::ostream& color(
const Def* def) {
121 if (def->is_form()) hue = 0.60f;
122 else if (def->is_intro()) hue = 0.35f;
123 else if (def->is_elim()) hue = 0.00f;
124 else if (def->is_meta()) hue = 0.15f;
127 return os_ << std::format(
"fillcolor=\"{} 0.5 0.75\"", hue);
130 std::ostream& tooltip(
const Def* def) {
131 static constexpr auto NL =
" ";
133 auto loc =
escape(def->loc());
135 std::print(os_,
"tooltip=\"");
136 std::print(os_,
"<b>expr:</b> {}{}", def, NL);
137 std::print(os_,
"<b>type:</b> {}{}", type, NL);
138 std::print(os_,
"<b>name:</b> {}{}", def->sym(), NL);
139 std::print(os_,
"<b>gid:</b> {}{}", def->gid(), NL);
140 std::print(os_,
"<b>flags:</b> 0x{:x}{}", def->flags(), NL);
141 std::print(os_,
"<b>mark:</b> 0x{:x}{}", def->mark(), NL);
142 std::print(os_,
"<b>local_muts:</b> {}{}", fe::Join(def->local_muts()), NL);
143 std::print(os_,
"<b>local_vars:</b> {}{}", fe::Join(def->local_vars()), NL);
144 std::print(os_,
"<b>free_vars:</b> {}{}", fe::Join(def->free_vars()), NL);
145 if (
auto mut = def->isa_mut()) std::print(os_,
"<b>users:</b> {{{}}}{}", fe::Join(mut->users()), NL);
146 std::print(os_,
"<b>loc:</b> {}", loc);
147 return os_ << std::format(
"\"");
154 fe::Tab tab_ = fe::Tab::spaces();
160void Def::dot(std::ostream& ostream,
int max,
bool types)
const { Dot(ostream, types,
this).run(
this, max); }
162void Def::dot(
const char* file,
int max,
bool types)
const {
164 dot(std::cout, max, types);
166 auto of = std::ofstream(file);
175 auto of = std::ofstream(file);
180void World::dot(std::ostream& os,
bool anx,
bool types)
const {
184 dot.recurse(external, std::numeric_limits<int>::max());
187 dot.recurse(
annex, std::numeric_limits<int>::max());
199 auto of = std::ofstream(file);
205 auto tab = fe::Tab::spaces();
206 std::println(os,
"{}digraph {{", tab);
208 std::println(os,
"{}ordering=out;", tab);
209 std::println(os,
"{}node [shape=box,style=filled];", tab);
210 root()->dot(tab, os);
212 std::println(os,
"{}}}", tab);
215void Nest::Node::dot(fe::Tab tab, std::ostream& os)
const {
217 for (
const auto& scc : topo_) {
219 for (
auto sep =
""s;
auto n : *scc) {
220 s += sep + n->name();
227 std::println(os,
"{}\"{}\":s -> \"{}\":s [style=dashed,constraint=false,splines=true]", tab,
name(),
231 auto html =
"<b>" +
name() +
"</b>";
232 if (*rec) html +=
"<br/><i>"s + rec +
"</i>";
233 html +=
"<br/><font point-size=\"8\">depth " + std::to_string(
loop_depth()) +
"</font>";
234 std::println(os,
"{}\"{}\" [label=<{}>,tooltip=\"{}\"]", tab,
name(), html, s);
236 std::println(os,
"{}\"{}\" -> \"{}\" [splines=false]", tab,
name(), child->name());
242 std::println(os,
"{}\"{}\" -> \"{}\" [color=red,style=bold,constraint=false]", tab,
idom()->
name(),
name());
void dot(std::ostream &os, int max=std::numeric_limits< int >::max(), bool types=false) const
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
const Def * annex(Sym sym)
Lookup annex by Sym.
const Externals & externals() const
void dot(std::ostream &os, bool annexes=false, bool types=false) const
Dumps DOT to os.
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.
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