-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[2 of 4] Builder operates on any HugrMut #281
Changes from all commits
4bc534c
5dcb6c7
1dd1f1f
51701cc
65e02f1
e8c0d81
5e64b0a
8ac5c6b
42d5eef
46c35a9
0372837
630c216
6ae5516
1742bc9
2d6ebce
cc8f489
eee773c
f4cc4af
3cee27a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
#![allow(missing_docs)] | ||
use crate::hugr::validate::InterGraphEdgeError; | ||
use crate::hugr::view::HugrView; | ||
use crate::hugr::{Node, NodeMetadata, Port, ValidationError}; | ||
|
@@ -29,17 +30,40 @@ use crate::Hugr; | |
|
||
use crate::hugr::HugrMut; | ||
|
||
pub trait Buildable { | ||
type BaseMut<'a>: Buildable + HugrMut | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could avoid this |
||
where | ||
Self: 'a; | ||
type BaseView<'a>: HugrView | ||
where | ||
Self: 'a; | ||
/// The underlying [`Hugr`] being built | ||
fn hugr_mut(&mut self) -> Self::BaseMut<'_>; | ||
/// Immutable reference to HUGR being built | ||
fn hugr(&self) -> Self::BaseView<'_>; | ||
} | ||
|
||
impl<T: AsMut<Hugr> + AsRef<Hugr>> Buildable for T { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An interesting alternative (in that it illustrates what's going on) would be one |
||
type BaseMut<'a> = &'a mut Hugr where Self: 'a; | ||
|
||
type BaseView<'a> = &'a Hugr where Self: 'a; | ||
|
||
fn hugr_mut(&mut self) -> Self::BaseMut<'_> { | ||
self.as_mut() | ||
} | ||
|
||
fn hugr(&self) -> Self::BaseView<'_> { | ||
self.as_ref() | ||
} | ||
} | ||
|
||
/// Trait for HUGR container builders. | ||
/// Containers are nodes that are parents of sibling graphs. | ||
/// Implementations of this trait allow the child sibling graph to be added to | ||
/// the HUGR. | ||
pub trait Container { | ||
pub trait Container: Buildable { | ||
/// The container node. | ||
fn container_node(&self) -> Node; | ||
/// The underlying [`Hugr`] being built | ||
fn hugr_mut(&mut self) -> &mut Hugr; | ||
/// Immutable reference to HUGR being built | ||
fn hugr(&self) -> &Hugr; | ||
/// Add an [`OpType`] as the final child of the container. | ||
fn add_child_op(&mut self, op: impl Into<OpType>) -> Result<Node, BuildError> { | ||
let parent = self.container_node(); | ||
|
@@ -79,7 +103,7 @@ pub trait Container { | |
&mut self, | ||
name: impl Into<String>, | ||
signature: Signature, | ||
) -> Result<FunctionBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<FunctionBuilder<Self::BaseMut<'_>>, BuildError> { | ||
let f_node = self.add_child_op(ops::FuncDefn { | ||
name: name.into(), | ||
signature: signature.clone(), | ||
|
@@ -252,7 +276,7 @@ pub trait Dataflow: Container { | |
&mut self, | ||
signature: Signature, | ||
input_wires: impl IntoIterator<Item = Wire>, | ||
) -> Result<DFGBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<DFGBuilder<Self::BaseMut<'_>>, BuildError> { | ||
let (dfg_n, _) = add_op_with_wires( | ||
self, | ||
ops::DFG { | ||
|
@@ -278,7 +302,7 @@ pub trait Dataflow: Container { | |
&mut self, | ||
inputs: impl IntoIterator<Item = (SimpleType, Wire)>, | ||
output_types: SimpleRow, | ||
) -> Result<CFGBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<CFGBuilder<Self::BaseMut<'_>>, BuildError> { | ||
let (input_types, input_wires): (Vec<SimpleType>, Vec<Wire>) = inputs.into_iter().unzip(); | ||
|
||
let inputs: SimpleRow = input_types.into(); | ||
|
@@ -337,7 +361,7 @@ pub trait Dataflow: Container { | |
just_inputs: impl IntoIterator<Item = (ClassicType, Wire)>, | ||
inputs_outputs: impl IntoIterator<Item = (SimpleType, Wire)>, | ||
just_out_types: ClassicRow, | ||
) -> Result<TailLoopBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<TailLoopBuilder<Self::BaseMut<'_>>, BuildError> { | ||
let (input_types, mut input_wires): (Vec<ClassicType>, Vec<Wire>) = | ||
just_inputs.into_iter().unzip(); | ||
let (rest_types, rest_input_wires): (Vec<SimpleType>, Vec<Wire>) = | ||
|
@@ -371,7 +395,7 @@ pub trait Dataflow: Container { | |
(predicate_inputs, predicate_wire): (impl IntoIterator<Item = ClassicRow>, Wire), | ||
other_inputs: impl IntoIterator<Item = (SimpleType, Wire)>, | ||
output_types: SimpleRow, | ||
) -> Result<ConditionalBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<ConditionalBuilder<Self::BaseMut<'_>>, BuildError> { | ||
let mut input_wires = vec![predicate_wire]; | ||
let (input_types, rest_input_wires): (Vec<SimpleType>, Vec<Wire>) = | ||
other_inputs.into_iter().unzip(); | ||
|
@@ -526,9 +550,7 @@ pub trait Dataflow: Container { | |
function: &FuncID<DEFINED>, | ||
input_wires: impl IntoIterator<Item = Wire>, | ||
) -> Result<BuildHandle<DataflowOpID>, BuildError> { | ||
let hugr = self.hugr(); | ||
let def_op = hugr.get_optype(function.node()); | ||
let signature = match def_op { | ||
let signature = match self.hugr().get_optype(function.node()) { | ||
OpType::FuncDefn(ops::FuncDefn { signature, .. }) | ||
| OpType::FuncDecl(ops::FuncDecl { signature, .. }) => signature.clone(), | ||
_ => { | ||
|
@@ -540,7 +562,7 @@ pub trait Dataflow: Container { | |
}; | ||
let const_in_port = signature.output.len(); | ||
let op_id = self.add_dataflow_op(ops::Call { signature }, input_wires)?; | ||
let src_port = self.hugr_mut().num_outputs(function.node()) - 1; | ||
let src_port = self.hugr().num_outputs(function.node()) - 1; | ||
|
||
self.hugr_mut() | ||
.connect(function.node(), src_port, op_id.node(), const_in_port)?; | ||
|
@@ -586,9 +608,10 @@ fn wire_up_inputs<T: Dataflow + ?Sized>( | |
dst_port, | ||
)?; | ||
} | ||
let base = data_builder.hugr_mut(); | ||
let base = data_builder.hugr(); | ||
let op = base.get_optype(op_node); | ||
let some_df_outputs = !op.signature().output.is_empty(); | ||
drop(base); | ||
if !any_local_df_inputs && some_df_outputs { | ||
// If op has no inputs add a StateOrder edge from input to place in | ||
// causal cone of Input node | ||
|
@@ -605,7 +628,7 @@ fn wire_up<T: Dataflow + ?Sized>( | |
dst: Node, | ||
dst_port: usize, | ||
) -> Result<bool, BuildError> { | ||
let base = data_builder.hugr_mut(); | ||
let mut base = data_builder.hugr_mut(); | ||
let src_offset = Port::new_outgoing(src_port); | ||
|
||
let src_parent = base.get_parent(src); | ||
|
@@ -652,14 +675,10 @@ fn wire_up<T: Dataflow + ?Sized>( | |
} | ||
} | ||
|
||
data_builder | ||
.hugr_mut() | ||
.connect(src, src_port, dst, dst_port)?; | ||
base.connect(src, src_port, dst, dst_port)?; | ||
Ok(local_source | ||
&& matches!( | ||
data_builder | ||
.hugr_mut() | ||
.get_optype(dst) | ||
base.get_optype(dst) | ||
.port_kind(Port::new_incoming(dst_port)) | ||
.unwrap(), | ||
EdgeKind::Value(_) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
use itertools::Itertools; | ||
|
||
use super::{ | ||
build_traits::SubContainer, | ||
build_traits::{Buildable, SubContainer}, | ||
dataflow::{DFGBuilder, DFGWrapper}, | ||
handle::BuildHandle, | ||
BasicBlockID, BuildError, CfgID, Container, Dataflow, HugrBuilder, Wire, | ||
|
@@ -25,24 +25,28 @@ pub struct CFGBuilder<T> { | |
pub(super) n_out_wires: usize, | ||
} | ||
|
||
impl<B: AsMut<Hugr> + AsRef<Hugr>> Container for CFGBuilder<B> { | ||
impl<B: Buildable> Buildable for CFGBuilder<B> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are, indeed, a lot of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, if/presuming that works, one could have a macro implementing |
||
type BaseMut<'a> = B::BaseMut<'a> where Self: 'a; | ||
type BaseView<'a> = B::BaseView<'a> where Self: 'a; | ||
#[inline] | ||
fn container_node(&self) -> Node { | ||
self.cfg_node | ||
fn hugr_mut(&mut self) -> Self::BaseMut<'_> { | ||
self.base.hugr_mut() | ||
} | ||
|
||
#[inline] | ||
fn hugr_mut(&mut self) -> &mut Hugr { | ||
self.base.as_mut() | ||
fn hugr(&self) -> Self::BaseView<'_> { | ||
self.base.hugr() | ||
} | ||
} | ||
|
||
impl<B: Buildable + HugrMut> Container for CFGBuilder<B> { | ||
#[inline] | ||
fn hugr(&self) -> &Hugr { | ||
self.base.as_ref() | ||
fn container_node(&self) -> Node { | ||
self.cfg_node | ||
} | ||
} | ||
|
||
impl<H: AsMut<Hugr> + AsRef<Hugr>> SubContainer for CFGBuilder<H> { | ||
impl<B: Buildable + HugrMut> SubContainer for CFGBuilder<B> { | ||
type ContainerHandle = BuildHandle<CfgID>; | ||
#[inline] | ||
fn finish_sub_container(self) -> Result<Self::ContainerHandle, BuildError> { | ||
|
@@ -76,7 +80,7 @@ impl HugrBuilder for CFGBuilder<Hugr> { | |
} | ||
} | ||
|
||
impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | ||
impl<B: Buildable + HugrMut> CFGBuilder<B> { | ||
pub(super) fn create( | ||
mut base: B, | ||
cfg_node: Node, | ||
|
@@ -88,7 +92,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
cfg_outputs: output, | ||
}); | ||
let exit_node = base | ||
.as_mut() | ||
.hugr_mut() | ||
.add_op_with_parent(cfg_node, exit_block_type)?; | ||
Ok(Self { | ||
base, | ||
|
@@ -126,7 +130,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
inputs: SimpleRow, | ||
predicate_variants: Vec<ClassicRow>, | ||
other_outputs: SimpleRow, | ||
) -> Result<BlockBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<BlockBuilder<<Self as Buildable>::BaseMut<'_>>, BuildError> { | ||
self.any_block_builder(inputs, predicate_variants, other_outputs, false) | ||
} | ||
|
||
|
@@ -136,7 +140,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
predicate_variants: Vec<ClassicRow>, | ||
other_outputs: SimpleRow, | ||
entry: bool, | ||
) -> Result<BlockBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<BlockBuilder<<Self as Buildable>::BaseMut<'_>>, BuildError> { | ||
let op = OpType::BasicBlock(BasicBlock::DFB { | ||
inputs: inputs.clone(), | ||
other_outputs: other_outputs.clone(), | ||
|
@@ -170,7 +174,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
inputs: SimpleRow, | ||
outputs: SimpleRow, | ||
n_cases: usize, | ||
) -> Result<BlockBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<BlockBuilder<<Self as Buildable>::BaseMut<'_>>, BuildError> { | ||
self.block_builder(inputs, vec![type_row![]; n_cases], outputs) | ||
} | ||
|
||
|
@@ -185,7 +189,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
&mut self, | ||
predicate_variants: Vec<ClassicRow>, | ||
other_outputs: SimpleRow, | ||
) -> Result<BlockBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<BlockBuilder<<Self as Buildable>::BaseMut<'_>>, BuildError> { | ||
let inputs = self | ||
.inputs | ||
.take() | ||
|
@@ -203,7 +207,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
&mut self, | ||
outputs: SimpleRow, | ||
n_cases: usize, | ||
) -> Result<BlockBuilder<&mut Hugr>, BuildError> { | ||
) -> Result<BlockBuilder<<Self as Buildable>::BaseMut<'_>>, BuildError> { | ||
self.entry_builder(vec![type_row![]; n_cases], outputs) | ||
} | ||
|
||
|
@@ -232,7 +236,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> CFGBuilder<B> { | |
/// Builder for a [`BasicBlock::DFB`] child graph. | ||
pub type BlockBuilder<B> = DFGWrapper<B, BasicBlockID>; | ||
|
||
impl<B: AsMut<Hugr> + AsRef<Hugr>> BlockBuilder<B> { | ||
impl<B: Buildable + HugrMut> BlockBuilder<B> { | ||
/// Set the outputs of the block, with `branch_wire` being the value of the | ||
/// predicate. `outputs` are the remaining outputs. | ||
pub fn set_outputs( | ||
|
@@ -242,6 +246,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> BlockBuilder<B> { | |
) -> Result<(), BuildError> { | ||
Dataflow::set_outputs(self, [branch_wire].into_iter().chain(outputs.into_iter())) | ||
} | ||
|
||
fn create( | ||
base: B, | ||
block_n: Node, | ||
|
@@ -257,8 +262,7 @@ impl<B: AsMut<Hugr> + AsRef<Hugr>> BlockBuilder<B> { | |
let db = DFGBuilder::create_with_io(base, block_n, signature)?; | ||
Ok(BlockBuilder::from_dfg_builder(db)) | ||
} | ||
} | ||
impl<B: AsMut<Hugr> + AsRef<Hugr>> BlockBuilder<B> { | ||
|
||
/// [Set outputs](BlockBuilder::set_outputs) and [finish](`BlockBuilder::finish_sub_container`). | ||
pub fn finish_with_outputs( | ||
mut self, | ||
|
@@ -371,9 +375,12 @@ mod test { | |
Ok(()) | ||
} | ||
|
||
fn build_basic_cfg<T: AsMut<Hugr> + AsRef<Hugr>>( | ||
fn build_basic_cfg<T: Buildable + HugrMut>( | ||
cfg_builder: &mut CFGBuilder<T>, | ||
) -> Result<(), BuildError> { | ||
) -> Result<(), BuildError> | ||
where | ||
CFGBuilder<T>: Container, | ||
{ | ||
let sum2_variants = vec![ | ||
classic_row![ClassicType::i64()], | ||
classic_row![ClassicType::i64()], | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤨
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is not for submission, but good to flag up, sorry. If we decide to go this way then I'll take this out and put in docs, but at least it shows that the rest of CI passes