From 3fc374d04a35389b231077c07548c4c503a1bf29 Mon Sep 17 00:00:00 2001 From: xFrednet Date: Fri, 1 Nov 2024 16:11:47 +0100 Subject: [PATCH] Mermaid: Draw nested regions as nested subgraphs --- src/rt/ui/mermaid.cc | 155 +++++++++++++++++++++++++------------- tests/regions/region4.vpy | 30 ++++++++ 2 files changed, 132 insertions(+), 53 deletions(-) create mode 100644 tests/regions/region4.vpy diff --git a/src/rt/ui/mermaid.cc b/src/rt/ui/mermaid.cc index 7805486..a8b626e 100644 --- a/src/rt/ui/mermaid.cc +++ b/src/rt/ui/mermaid.cc @@ -21,6 +21,17 @@ namespace rt::ui const char* IMMUTABLE_REGION_COLOR = "#485464"; const char* IMMUTABLE_EDGE_COLOR = "#94f7ff"; + // const char* REGION_COLORS[] = { + // "#6d6d6d", + // "#626262", + // "#575757", + // "#4c4c4c", + // "#414141", + // "#363636", + // "#2b2b2b"}; + const char* REGION_COLORS[] = { + "#666", "#555", "#444", "#333", "#222", "#111"}; + const char* LOCAL_REGION_ID = "LocalReg"; const char* IMM_REGION_ID = "ImmReg"; const char* COWN_REGION_ID = "CownReg"; @@ -64,6 +75,13 @@ namespace rt::ui return os; } + struct RegionInfo + { + std::vector nodes; + std::vector regions; + bool drawn; + }; + class MermaidDiagram { MermaidUI* info; @@ -75,13 +93,14 @@ namespace rt::ui // Give a nice id to each object. std::map nodes; std::map> region_strings; + std::map regions; public: MermaidDiagram(MermaidUI* info_) : info(info_), out(info->out) { // Add nullptr nodes[nullptr] = {0}; - region_strings[rt::objects::immutable_region].push_back(0); + regions[objects::immutable_region].nodes.push_back(0); } void color_edge(size_t edge_id, const char* color) @@ -186,8 +205,9 @@ namespace rt::ui // Footer out << markers.second; - out << (reachable ? "" : ":::unreachable"); - out << (dst->is_immutable() ? ":::immutable" : ""); + out + << (dst->is_immutable() ? ":::immutable" : + (reachable ? "" : ":::unreachable")); out << std::endl; result = node; @@ -232,7 +252,7 @@ namespace rt::ui auto region = objects::get_region(dst); if (region != nullptr) { - region_strings[region].push_back(node->id); + regions[region].nodes.push_back(node->id); } return true; @@ -251,70 +271,99 @@ namespace rt::ui } } - void draw_regions() + void + draw_region_body(objects::Region* r, RegionInfo* info, std::string& indent) { - // Output any region parent edges. - for (auto [region, objects] : region_strings) + indent += " "; + for (auto obj : info->nodes) { - if (region->parent == nullptr) - { - continue; - } - if ((!info->draw_cown_region) && region->parent == objects::cown_region) - { - continue; - } - - out << " region" << region->parent << " <-.-o region" << region - << std::endl; - edge_counter += 1; + out << indent << "id" << obj << std::endl; } + for (auto reg : info->regions) + { + draw_region(reg, indent); + } + indent.erase(indent.size() - 2); + } - // Output all the region membership information - for (auto [region, objects] : region_strings) + void draw_region(objects::Region* r, std::string& indent) + { + auto info = ®ions[r]; + if (info->drawn) { - if ( - ((!info->draw_cown_region) && region == objects::cown_region) || - ((!info->draw_immutable_region) && - region == objects::immutable_region)) - { - continue; - } + return; + } + info->drawn = true; + auto depth = indent.size() / 2; - out << "subgraph "; + // Header + out << indent << "subgraph "; + out << "reg" << r << "[\" \"]" << std::endl; - if (region == objects::get_local_region()) - { - out << LOCAL_REGION_ID << "[\"Local region\"]" << std::endl; - } - else if (region == objects::immutable_region) - { - out << IMM_REGION_ID << "[\"Immutable region\"]" << std::endl; - out << " id0" << std::endl; - } - else if (region == objects::cown_region) - { - out << COWN_REGION_ID << "[\"Cown region\"]" << std::endl; - out << " region" << region << "[\\" << region - << "
sbrc=" << region->sub_region_reference_count << "/]" - << std::endl; - } - else - { - out << "region" << region << "[\" \"]" << std::endl; - } - for (auto obj : objects) - { - out << " id" << obj << std::endl; - } + // Content + draw_region_body(r, info, indent); + + // Footer + out << indent << "end" << std::endl; + out << indent << "style reg" << r + << " fill:" << REGION_COLORS[depth % std::size(REGION_COLORS)] + << std::endl; + } + + void draw_regions() + { + // Build parent relations + for (auto [reg, _] : regions) + { + regions[reg->parent].regions.push_back(reg); + } + + std::string indent; + if (info->draw_cown_region) + { + auto region = objects::cown_region; + out << "subgraph " << COWN_REGION_ID << "[\"Cown region\"]" + << std::endl; + draw_region_body(region, ®ions[region], indent); out << "end" << std::endl; + out << "style " << COWN_REGION_ID << " fill:" << REGION_COLORS[0] + << std::endl; } + regions[objects::cown_region].drawn = true; if (info->draw_immutable_region) { + auto region = objects::immutable_region; + out << "subgraph " << IMM_REGION_ID << "[\"Immutable region\"]" + << std::endl; + draw_region_body(region, ®ions[region], indent); + out << "end" << std::endl; out << "style " << IMM_REGION_ID << " fill:" << IMMUTABLE_REGION_COLOR << std::endl; } + regions[objects::immutable_region].drawn = true; + + // Local region + { + auto region = objects::get_local_region(); + out << "subgraph " << LOCAL_REGION_ID << "[\"Local region\"]" + << std::endl; + draw_region_body(objects::cown_region, ®ions[region], indent); + out << "end" << std::endl; + out << "style " << LOCAL_REGION_ID << " fill:" << REGION_COLORS[0] + << std::endl; + } + regions[objects::get_local_region()].drawn = true; + + // Draw all other regions + for (auto reg : regions[nullptr].regions) + { + draw_region(reg, indent); + } + for (auto reg : regions[objects::cown_region].regions) + { + draw_region(reg, indent); + } } void draw_taint() diff --git a/tests/regions/region4.vpy b/tests/regions/region4.vpy new file mode 100644 index 0000000..92da4a2 --- /dev/null +++ b/tests/regions/region4.vpy @@ -0,0 +1,30 @@ +# Create multiple regions +r1 = Region() +r1.level = "One" + +r2 = Region() +r2.level = "Two" + +r3 = Region() +r3.level = "Three" + +r4 = Region() +r4.level = "Four" + +r5 = Region() +r5.level = "Five" + +# Stack regions +r1.n = move r2 +r1.n.n = r3 + +r4.n = move r5 +r3.n = move r4 +drop r3 + +# Move this into a cown +c = cown(move r1) + +# Check the visuals +mermaid_show_cown_region() +mermaid_show_immutable_region()