Skip to content

Commit 28cba40

Browse files
committed
Add link_name to FuncDefn
Note minimal fix to serial_upgrade test - this doesn't look like an upgrade though?!
1 parent cca66d9 commit 28cba40

File tree

13 files changed

+192
-127
lines changed

13 files changed

+192
-127
lines changed

hugr-core/src/builder.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,7 @@ pub(crate) mod test {
289289

290290
#[fixture]
291291
pub(crate) fn simple_funcdef_hugr() -> Hugr {
292-
let fn_builder =
293-
FunctionBuilder::new("test", Signature::new(vec![bool_t()], vec![bool_t()])).unwrap();
292+
let fn_builder = FunctionBuilder::new("test", Signature::new_endo(bool_t())).unwrap();
294293
let [i1] = fn_builder.input_wires_arr();
295294
fn_builder.finish_hugr_with_outputs([i1]).unwrap()
296295
}

hugr-core/src/builder/build_traits.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ pub trait Container {
8383
}
8484

8585
/// Add a [`ops::FuncDefn`] node and returns a builder to define the function
86-
/// body graph.
86+
/// body graph. The function has an appropriate [ops::FuncDefn::link_name] for the parent
87+
/// (`None` for most containers / with the default impl.)
8788
///
8889
/// # Errors
8990
///
@@ -94,22 +95,7 @@ pub trait Container {
9495
name: impl Into<String>,
9596
signature: impl Into<PolyFuncType>,
9697
) -> Result<FunctionBuilder<&mut Hugr>, BuildError> {
97-
let signature: PolyFuncType = signature.into();
98-
let body = signature.body().clone();
99-
let f_node = self.add_child_node(ops::FuncDefn {
100-
name: name.into(),
101-
signature,
102-
});
103-
104-
// Add the extensions used by the function types.
105-
self.use_extensions(
106-
body.used_extensions().unwrap_or_else(|e| {
107-
panic!("Build-time signatures should have valid extensions. {e}")
108-
}),
109-
);
110-
111-
let db = DFGBuilder::create_with_io(self.hugr_mut(), f_node, body)?;
112-
Ok(FunctionBuilder::from_dfg_builder(db))
98+
define_function_link_name(self, name, signature, None)
11399
}
114100

115101
/// Insert a HUGR as a child of the container.
@@ -157,6 +143,26 @@ pub trait Container {
157143
}
158144
}
159145

146+
pub(super) fn define_function_link_name<C: Container + ?Sized>(
147+
ctr: &mut C,
148+
name: impl Into<String>,
149+
signature: impl Into<PolyFuncType>,
150+
link_name: impl Into<Option<String>>,
151+
) -> Result<FunctionBuilder<&mut Hugr>, BuildError> {
152+
let signature = signature.into();
153+
let body = signature.body().clone();
154+
let f_node = ctr.add_child_node(ops::FuncDefn::new(name.into(), signature, link_name));
155+
156+
// Add the extensions used by the function types.
157+
ctr.use_extensions(
158+
body.used_extensions()
159+
.unwrap_or_else(|e| panic!("Build-time signatures should have valid extensions. {e}")),
160+
);
161+
162+
let db = DFGBuilder::create_with_io(ctr.hugr_mut(), f_node, body)?;
163+
Ok(FunctionBuilder::from_dfg_builder(db))
164+
}
165+
160166
/// Types implementing this trait can be used to build complete HUGRs
161167
/// (with varying root node types)
162168
pub trait HugrBuilder: Container {

hugr-core/src/builder/dataflow.rs

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -152,20 +152,46 @@ impl<B, T> DFGWrapper<B, T> {
152152
pub type FunctionBuilder<B> = DFGWrapper<B, BuildHandle<FuncID<true>>>;
153153

154154
impl FunctionBuilder<Hugr> {
155-
/// Initialize a builder for a FuncDefn rooted HUGR
155+
/// Initialize a builder for a FuncDefn-rooted HUGR; the function will be private.
156+
/// (See also [Self::new_pub], [Self::new_link_name].)
157+
///
156158
/// # Errors
157159
///
158160
/// Error in adding DFG child nodes.
159161
pub fn new(
160162
name: impl Into<String>,
161163
signature: impl Into<PolyFuncType>,
162164
) -> Result<Self, BuildError> {
163-
let signature: PolyFuncType = signature.into();
164-
let body = signature.body().clone();
165-
let op = ops::FuncDefn {
166-
signature,
167-
name: name.into(),
168-
};
165+
Self::new_link_name(name, signature, None)
166+
}
167+
168+
/// Initialize a builder for a FuncDefn-rooted HUGR; the function will be public
169+
/// with the same name (see also [Self::new_link_name]).
170+
///
171+
/// # Errors
172+
///
173+
/// Error in adding DFG child nodes.
174+
pub fn new_pub(
175+
name: impl Into<String>,
176+
signature: impl Into<PolyFuncType>,
177+
) -> Result<Self, BuildError> {
178+
let name = name.into();
179+
Self::new_link_name(name.clone(), signature, Some(name))
180+
}
181+
182+
/// Initialize a builder for a FuncDefn-rooted HUGR, with the specified
183+
/// [link_name](ops::FuncDefn::link_name).
184+
///
185+
/// # Errors
186+
///
187+
/// Error in adding DFG child nodes.
188+
pub fn new_link_name(
189+
name: impl Into<String>,
190+
signature: impl Into<PolyFuncType>,
191+
link_name: impl Into<Option<String>>,
192+
) -> Result<Self, BuildError> {
193+
let op = ops::FuncDefn::new(name.into(), signature.into(), link_name);
194+
let body = op.signature.body().clone();
169195

170196
let base = Hugr::new_with_entrypoint(op).expect("FuncDefn entrypoint should be valid");
171197
let root = base.entrypoint();
@@ -253,22 +279,12 @@ impl FunctionBuilder<Hugr> {
253279
/// Returns a reference to the new optype.
254280
fn update_fn_signature(&mut self, f: impl FnOnce(Signature) -> Signature) -> &ops::FuncDefn {
255281
let parent = self.container_node();
256-
let old_optype = self
257-
.hugr()
258-
.get_optype(parent)
259-
.as_func_defn()
260-
.expect("FunctionBuilder node must be a FuncDefn");
261-
let signature = old_optype.inner_signature().into_owned();
262-
let name = old_optype.name.clone();
263-
self.hugr_mut().replace_op(
264-
parent,
265-
ops::FuncDefn {
266-
signature: f(signature).into(),
267-
name,
268-
},
269-
);
270282

271-
self.hugr().get_optype(parent).as_func_defn().unwrap()
283+
let ops::OpType::FuncDefn(fd) = self.hugr_mut().optype_mut(parent) else {
284+
panic!("FunctionBuilder node must be a FuncDefn")
285+
};
286+
fd.signature = f(fd.inner_signature().into_owned()).into();
287+
&*fd
272288
}
273289
}
274290

@@ -531,8 +547,8 @@ pub(crate) mod test {
531547
let mut module_builder = ModuleBuilder::new();
532548

533549
let (dfg_node, f_node) = {
534-
let mut f_build = module_builder
535-
.define_function("main", Signature::new(vec![bool_t()], vec![bool_t()]))?;
550+
let mut f_build =
551+
module_builder.define_function("main", Signature::new_endo(bool_t()))?;
536552

537553
let [i1] = f_build.input_wires_arr();
538554
let dfg = f_build.add_hugr_with_wires(dfg_hugr, [i1])?;

hugr-core/src/builder/module.rs

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{
2-
build_traits::HugrBuilder,
2+
build_traits::{define_function_link_name, HugrBuilder},
33
dataflow::{DFGBuilder, FunctionBuilder},
44
BuildError, Container,
55
};
@@ -8,9 +8,8 @@ use crate::hugr::internal::HugrMutInternals;
88
use crate::hugr::views::HugrView;
99
use crate::hugr::ValidationError;
1010
use crate::ops;
11-
use crate::types::{PolyFuncType, Type, TypeBound};
12-
1311
use crate::ops::handle::{AliasID, FuncID, NodeHandle};
12+
use crate::types::{PolyFuncType, Type, TypeBound};
1413

1514
use crate::{Hugr, Node};
1615
use smol_str::SmolStr;
@@ -33,6 +32,23 @@ impl<T: AsMut<Hugr> + AsRef<Hugr>> Container for ModuleBuilder<T> {
3332
fn hugr(&self) -> &Hugr {
3433
self.0.as_ref()
3534
}
35+
36+
/// Override the default to make the function public, with [link_name](ops::FuncDefn::link_name)
37+
/// the same as `name`. (See also [Self::define_function_link_name].)
38+
/// Returns a builder to define the function body graph.
39+
///
40+
/// # Errors
41+
///
42+
/// This function will return an error if there is an error in adding the
43+
/// [`ops::FuncDefn`] node.
44+
fn define_function(
45+
&mut self,
46+
name: impl Into<String>,
47+
signature: impl Into<PolyFuncType>,
48+
) -> Result<FunctionBuilder<&mut Hugr>, BuildError> {
49+
let name = name.into();
50+
define_function_link_name(self, name.clone(), signature, Some(name))
51+
}
3652
}
3753

3854
impl ModuleBuilder<Hugr> {
@@ -57,7 +73,7 @@ impl HugrBuilder for ModuleBuilder<Hugr> {
5773
}
5874

5975
impl<T: AsMut<Hugr> + AsRef<Hugr>> ModuleBuilder<T> {
60-
/// Replace a [`ops::FuncDecl`] with [`ops::FuncDefn`] and return a builder for
76+
/// Replace a [`ops::FuncDecl`] with public [`ops::FuncDefn`] and return a builder for
6177
/// the defining graph.
6278
///
6379
/// # Errors
@@ -69,23 +85,37 @@ impl<T: AsMut<Hugr> + AsRef<Hugr>> ModuleBuilder<T> {
6985
f_id: &FuncID<false>,
7086
) -> Result<FunctionBuilder<&mut Hugr>, BuildError> {
7187
let f_node = f_id.node();
72-
let ops::FuncDecl { signature, name } = self
73-
.hugr()
74-
.get_optype(f_node)
75-
.as_func_decl()
76-
.ok_or(BuildError::UnexpectedType {
88+
let opty = self.hugr_mut().optype_mut(f_node);
89+
let ops::OpType::FuncDecl(ops::FuncDecl { signature, name }) = opty else {
90+
return Err(BuildError::UnexpectedType {
7791
node: f_node,
7892
op_desc: "crate::ops::OpType::FuncDecl",
79-
})?
80-
.clone();
93+
});
94+
};
95+
8196
let body = signature.body().clone();
82-
self.hugr_mut()
83-
.replace_op(f_node, ops::FuncDefn { name, signature });
97+
*opty = ops::FuncDefn::new_public(name, signature.clone()).into();
8498

8599
let db = DFGBuilder::create_with_io(self.hugr_mut(), f_node, body)?;
86100
Ok(FunctionBuilder::from_dfg_builder(db))
87101
}
88102

103+
/// Add a [`ops::FuncDefn`] node, with both `name` and `link_name` explicitly specified.
104+
/// Returns a builder to define the function body graph.
105+
///
106+
/// # Errors
107+
///
108+
/// This function will return an error if there is an error in adding the
109+
/// [`ops::FuncDefn`] node.
110+
pub fn define_function_link_name(
111+
&mut self,
112+
name: impl Into<String>,
113+
signature: impl Into<PolyFuncType>,
114+
link_name: impl Into<Option<String>>,
115+
) -> Result<FunctionBuilder<&mut Hugr>, BuildError> {
116+
define_function_link_name(self, name, signature, link_name)
117+
}
118+
89119
/// Declare a function with `signature` and return a handle to the declaration.
90120
///
91121
/// # Errors
@@ -199,10 +229,7 @@ mod test {
199229

200230
let f_build = module_builder.define_function(
201231
"main",
202-
Signature::new(
203-
vec![qubit_state_type.get_alias_type()],
204-
vec![qubit_state_type.get_alias_type()],
205-
),
232+
Signature::new_endo(qubit_state_type.get_alias_type()),
206233
)?;
207234
n_identity(f_build)?;
208235
module_builder.finish_hugr()

hugr-core/src/hugr.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -440,13 +440,8 @@ fn make_module_hugr(root_op: OpType, nodes: usize, ports: usize) -> Option<Hugr>
440440
let dataflow_inputs = signature.input_count();
441441
let dataflow_outputs = signature.output_count();
442442

443-
let func = hugr.add_node_with_parent(
444-
module,
445-
ops::FuncDefn {
446-
name: "main".into(),
447-
signature: signature.clone().into(),
448-
},
449-
);
443+
let func =
444+
hugr.add_node_with_parent(module, ops::FuncDefn::new_public("main", signature.clone()));
450445
let inp = hugr.add_node_with_parent(
451446
func,
452447
ops::Input {

hugr-core/src/hugr/hugrmut.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -631,10 +631,10 @@ mod test {
631631
// Start a main function with two nat inputs.
632632
let f: Node = hugr.add_node_with_parent(
633633
module,
634-
ops::FuncDefn {
635-
name: "main".into(),
636-
signature: Signature::new(vec![usize_t()], vec![usize_t(), usize_t()]).into(),
637-
},
634+
ops::FuncDefn::new_public(
635+
"main",
636+
Signature::new(usize_t(), vec![usize_t(), usize_t()]),
637+
),
638638
);
639639

640640
{
@@ -679,10 +679,7 @@ mod test {
679679
let [foo, bar] = ["foo", "bar"].map(|name| {
680680
let fd = hugr.add_node_with_parent(
681681
root,
682-
FuncDefn {
683-
name: name.to_string(),
684-
signature: Signature::new_endo(usize_t()).into(),
685-
},
682+
FuncDefn::new_private(name, Signature::new_endo(usize_t())),
686683
);
687684
let inp = hugr.add_node_with_parent(fd, Input::new(usize_t()));
688685
let out = hugr.add_node_with_parent(fd, Output::new(usize_t()));

hugr-core/src/hugr/serialize/test.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,16 +219,16 @@ pub fn check_hugr(lhs: &Hugr, rhs: &Hugr) {
219219

220220
// Extension operations may have been downgraded to opaque operations.
221221
for node in rhs.nodes() {
222-
let new_op = rhs.get_optype(node);
223-
let old_op = h_canon.get_optype(node);
224-
if !new_op.is_const() {
225-
match (new_op, old_op) {
222+
let rhs_op = rhs.get_optype(node);
223+
let lhs_op = h_canon.get_optype(node);
224+
if !rhs_op.is_const() {
225+
match (rhs_op, lhs_op) {
226226
(OpType::ExtensionOp(ext), OpType::OpaqueOp(opaque))
227227
| (OpType::OpaqueOp(opaque), OpType::ExtensionOp(ext)) => {
228228
let ext_opaque: OpaqueOp = ext.clone().into();
229229
assert_eq!(ext_opaque, opaque.clone());
230230
}
231-
_ => assert_eq!(new_op, old_op),
231+
_ => assert_eq!(lhs_op, rhs_op),
232232
}
233233
}
234234
}
@@ -551,7 +551,8 @@ fn roundtrip_polyfunctype_varlen(#[case] poly_func_type: PolyFuncTypeRV) {
551551

552552
#[rstest]
553553
#[case(ops::Module::new())]
554-
#[case(ops::FuncDefn { name: "polyfunc1".into(), signature: polyfunctype1()})]
554+
#[case(ops::FuncDefn::new("polyfunc1", polyfunctype1(), "pf1".to_string()))]
555+
#[case(ops::FuncDefn { name: "polyfunc1".into(), signature: polyfunctype1(), link_name: None})]
555556
#[case(ops::FuncDecl { name: "polyfunc2".into(), signature: polyfunctype1()})]
556557
#[case(ops::AliasDefn { name: "aliasdefn".into(), definition: Type::new_unit_sum(4)})]
557558
#[case(ops::AliasDecl { name: "aliasdecl".into(), bound: TypeBound::Any})]

hugr-core/src/hugr/serialize/upgrade/testcases/hugr_with_named_op.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
}
3333
]
3434
}
35-
}
35+
},
36+
"link_name": "main"
3637
},
3738
{
3839
"parent": 1,
@@ -217,4 +218,4 @@
217218
],
218219
"encoder": "hugr-rs v0.15.4",
219220
"entrypoint": 4
220-
}
221+
}

0 commit comments

Comments
 (0)