diff --git a/hugr-core/src/builder.rs b/hugr-core/src/builder.rs index 196b1ab6a..f955477fd 100644 --- a/hugr-core/src/builder.rs +++ b/hugr-core/src/builder.rs @@ -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 = diff --git a/hugr-core/src/hugr/views/render.rs b/hugr-core/src/hugr/views/render.rs index 5d6bf2ade..caa4770a2 100644 --- a/hugr-core/src/hugr/views/render.rs +++ b/hugr-core/src/hugr/views/render.rs @@ -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; @@ -35,16 +35,24 @@ pub(super) fn node_style( h: &H, config: RenderConfig, ) -> Box NodeStyle + '_> { + fn node_name(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))) } } diff --git a/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__dot_func.snap b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__dot_func.snap new file mode 100644 index 000000000..e1bbeae4e --- /dev/null +++ b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__dot_func.snap @@ -0,0 +1,15 @@ +--- +source: hugr-core/src/hugr/views/tests.rs +expression: h.dot_string() +--- +digraph { +0 [shape=plain label=<
(0) FuncDefn: "test"
0: [[]+[]] -> [[]][[]+[]]
>] +1 [shape=plain label=<
(1) Input
0: []+[]
>] +1:out0 -> 2:in0 [style=""] +2 [shape=plain label=<
0: []+[]
(2) Output
>] +hier0 [shape=plain label="0"] +hier0 -> hier1 [style = "dashed"] +hier0 -> hier2 [style = "dashed"] +hier1 [shape=plain label="1"] +hier2 [shape=plain label="2"] +} diff --git a/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__dot_module.snap b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__dot_module.snap new file mode 100644 index 000000000..37691fa9c --- /dev/null +++ b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__dot_module.snap @@ -0,0 +1,11 @@ +--- +source: hugr-core/src/hugr/views/tests.rs +expression: h.dot_string() +--- +digraph { +0 [shape=plain label=<
(0) Module
>] +1 [shape=plain label=<
(1) FuncDecl: "test"
0: [[]+[]] -> [[]][[]+[]]
>] +hier0 [shape=plain label="0"] +hier0 -> hier1 [style = "dashed"] +hier1 [shape=plain label="1"] +} diff --git a/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__mmd_func.snap b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__mmd_func.snap new file mode 100644 index 000000000..45bf1a427 --- /dev/null +++ b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__mmd_func.snap @@ -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
[]+[]"-->2 + end diff --git a/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__mmd_module.snap b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__mmd_module.snap new file mode 100644 index 000000000..0bb2de60e --- /dev/null +++ b/hugr-core/src/hugr/views/snapshots/hugr_core__hugr__views__tests__mmd_module.snap @@ -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 diff --git a/hugr-core/src/hugr/views/tests.rs b/hugr-core/src/hugr/views/tests.rs index 04004decd..c52957b2c 100644 --- a/hugr-core/src/hugr/views/tests.rs +++ b/hugr-core/src/hugr/views/tests.rs @@ -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()); @@ -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()); diff --git a/hugr-core/src/types/poly_func.rs b/hugr-core/src/types/poly_func.rs index 837a4e22d..b168556bf 100644 --- a/hugr-core/src/types/poly_func.rs +++ b/hugr-core/src/types/poly_func.rs @@ -1,5 +1,7 @@ //! Polymorphic Function Types +use itertools::Itertools; + use crate::extension::{ExtensionRegistry, SignatureError}; #[cfg(test)] use { @@ -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 { /// The declared type parameters, i.e., these must be instantiated with /// the same number of [TypeArg]s before the function can be called. This @@ -136,6 +134,17 @@ impl PolyFuncTypeBase { // 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)]