Skip to content

Commit

Permalink
feat: Render function names in mermaid/dot (#1583)
Browse files Browse the repository at this point in the history
Shows the function names when rendering a hugr.
This should come useful when working with bigger graphs like those
emitted by guppy.

```mermaid
graph LR
    subgraph 0 ["(0) FuncDefn: #quot;test#quot;"]
        direction LR
        1["(1) Input"]
        2["(2) Output"]
        1--"0:0<br>[]+[]"-->2
    end
```
  • Loading branch information
aborgna-q authored Oct 17, 2024
1 parent d899bd3 commit 0f6c25a
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 8 deletions.
16 changes: 16 additions & 0 deletions hugr-core/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,22 @@ pub(crate) mod test {
dfg_builder.finish_prelude_hugr_with_outputs([i1]).unwrap()
}

#[fixture]
pub(crate) fn simple_funcdef_hugr() -> Hugr {
let fn_builder =
FunctionBuilder::new("test", Signature::new(type_row![BIT], type_row![BIT])).unwrap();
let [i1] = fn_builder.input_wires_arr();
fn_builder.finish_prelude_hugr_with_outputs([i1]).unwrap()
}

#[fixture]
pub(crate) fn simple_module_hugr() -> Hugr {
let mut builder = ModuleBuilder::new();
let sig = Signature::new(type_row![BIT], type_row![BIT]);
builder.declare("test", sig.into()).unwrap();
builder.finish_prelude_hugr().unwrap()
}

#[fixture]
pub(crate) fn simple_cfg_hugr() -> Hugr {
let mut cfg_builder =
Expand Down
14 changes: 11 additions & 3 deletions hugr-core/src/hugr/views/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use portgraph::render::{EdgeStyle, NodeStyle, PortStyle};
use portgraph::{LinkView, NodeIndex, PortIndex, PortView};

use crate::ops::NamedOp;
use crate::ops::{NamedOp, OpType};
use crate::types::EdgeKind;
use crate::HugrView;

Expand Down Expand Up @@ -35,16 +35,24 @@ pub(super) fn node_style<H: HugrView + ?Sized>(
h: &H,
config: RenderConfig,
) -> Box<dyn FnMut(NodeIndex) -> NodeStyle + '_> {
fn node_name<H: HugrView + ?Sized>(h: &H, n: NodeIndex) -> String {
match h.get_optype(n.into()) {
OpType::FuncDecl(f) => format!("FuncDecl: \"{}\"", f.name),
OpType::FuncDefn(f) => format!("FuncDefn: \"{}\"", f.name),
op => op.name().to_string(),
}
}

if config.node_indices {
Box::new(move |n| {
NodeStyle::Box(format!(
"({ni}) {name}",
ni = n.index(),
name = h.get_optype(n.into()).name()
name = node_name(h, n)
))
})
} else {
Box::new(move |n| NodeStyle::Box(h.get_optype(n.into()).name().to_string()))
Box::new(move |n| NodeStyle::Box(node_name(h, n)))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
source: hugr-core/src/hugr/views/tests.rs
expression: h.dot_string()
---
digraph {
0 [shape=plain label=<<table border="1"><tr><td align="text" border="0" colspan="1">(0) FuncDefn: "test"</td></tr><tr><td port="out0" align="text" colspan="1" cellpadding="1" >0: [[]+[]] -&gt; [[]][[]+[]]</td></tr></table>>]
1 [shape=plain label=<<table border="1"><tr><td align="text" border="0" colspan="1">(1) Input</td></tr><tr><td port="out0" align="text" colspan="1" cellpadding="1" >0: []+[]</td></tr></table>>]
1:out0 -> 2:in0 [style=""]
2 [shape=plain label=<<table border="1"><tr><td port="in0" align="text" colspan="1" cellpadding="1" >0: []+[]</td></tr><tr><td align="text" border="0" colspan="1">(2) Output</td></tr></table>>]
hier0 [shape=plain label="0"]
hier0 -> hier1 [style = "dashed"]
hier0 -> hier2 [style = "dashed"]
hier1 [shape=plain label="1"]
hier2 [shape=plain label="2"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: hugr-core/src/hugr/views/tests.rs
expression: h.dot_string()
---
digraph {
0 [shape=plain label=<<table border="1"><tr><td align="text" border="0" colspan="1">(0) Module</td></tr></table>>]
1 [shape=plain label=<<table border="1"><tr><td align="text" border="0" colspan="1">(1) FuncDecl: "test"</td></tr><tr><td port="out0" align="text" colspan="1" cellpadding="1" >0: [[]+[]] -&gt; [[]][[]+[]]</td></tr></table>>]
hier0 [shape=plain label="0"]
hier0 -> hier1 [style = "dashed"]
hier1 [shape=plain label="1"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: hugr-core/src/hugr/views/tests.rs
expression: h.mermaid_string()
---
graph LR
subgraph 0 ["(0) FuncDefn: #quot;test#quot;"]
direction LR
1["(1) Input"]
2["(2) Output"]
1--"0:0<br>[]+[]"-->2
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: hugr-core/src/hugr/views/tests.rs
expression: h.mermaid_string()
---
graph LR
subgraph 0 ["(0) Module"]
direction LR
1["(1) FuncDecl: #quot;test#quot;"]
end
4 changes: 4 additions & 0 deletions hugr-core/src/hugr/views/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ fn node_connections(
#[case::dfg("dot_dfg", sample_hugr().0)]
#[case::cfg("dot_cfg", crate::builder::test::simple_cfg_hugr())]
#[case::empty_dfg("dot_empty_dfg", crate::builder::test::simple_dfg_hugr())]
#[case::func("dot_func", crate::builder::test::simple_funcdef_hugr())]
#[case::module("dot_module", crate::builder::test::simple_module_hugr())]
#[cfg_attr(miri, ignore)] // Opening files is not supported in (isolated) miri
fn dot_string(#[case] test_name: &str, #[case] h: Hugr) {
insta::assert_snapshot!(test_name, h.dot_string());
Expand All @@ -84,6 +86,8 @@ fn dot_string(#[case] test_name: &str, #[case] h: Hugr) {
#[case::dfg("mmd_dfg", sample_hugr().0)]
#[case::cfg("mmd_cfg", crate::builder::test::simple_cfg_hugr())]
#[case::empty_dfg("mmd_empty_dfg", crate::builder::test::simple_dfg_hugr())]
#[case::func("mmd_func", crate::builder::test::simple_funcdef_hugr())]
#[case::module("mmd_module", crate::builder::test::simple_module_hugr())]
#[cfg_attr(miri, ignore)] // Opening files is not supported in (isolated) miri
fn mermaid_string(#[case] test_name: &str, #[case] h: Hugr) {
insta::assert_snapshot!(test_name, h.mermaid_string());
Expand Down
19 changes: 14 additions & 5 deletions hugr-core/src/types/poly_func.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Polymorphic Function Types
use itertools::Itertools;

use crate::extension::{ExtensionRegistry, SignatureError};
#[cfg(test)]
use {
Expand All @@ -22,11 +24,7 @@ use super::{signature::FuncTypeBase, MaybeRV, NoRV, RowVariable};
Clone, PartialEq, Debug, Eq, Hash, derive_more::Display, serde::Serialize, serde::Deserialize,
)]
#[cfg_attr(test, derive(Arbitrary), proptest(params = "RecursionDepth"))]
#[display(
"forall {}. {}",
"params.iter().map(ToString::to_string).join(\" \")",
"body"
)]
#[display("{}{body}", self.display_params())]
pub struct PolyFuncTypeBase<RV: MaybeRV> {
/// The declared type parameters, i.e., these must be instantiated with
/// the same number of [TypeArg]s before the function can be called. This
Expand Down Expand Up @@ -136,6 +134,17 @@ impl<RV: MaybeRV> PolyFuncTypeBase<RV> {
// TODO https://github.com/CQCL/hugr/issues/624 validate TypeParams declared here, too
self.body.validate(reg, &self.params)
}

/// Helper function for the Display implementation
fn display_params(&self) -> String {
if self.params.is_empty() {
return String::new();
}
format!(
"forall {}. ",
self.params.iter().map(ToString::to_string).join(" ")
)
}
}

#[cfg(test)]
Expand Down

0 comments on commit 0f6c25a

Please sign in to comment.