1use crate::Node;
3use crate::core::HugrNode;
4use crate::types::TypeBound;
5
6use derive_more::From as DerFrom;
7use smol_str::SmolStr;
8
9use super::OpTag;
10
11pub trait NodeHandle<N = Node>: Clone {
14 const TAG: OpTag;
16
17 fn node(&self) -> N;
19
20 #[inline]
22 fn tag(&self) -> OpTag {
23 Self::TAG
24 }
25
26 fn try_cast<T: NodeHandle<N> + From<N>>(&self) -> Option<T> {
28 T::TAG.is_superset(Self::TAG).then(|| self.node().into())
29 }
30
31 #[must_use]
33 fn can_hold(tag: OpTag) -> bool {
34 Self::TAG.is_superset(tag)
35 }
36}
37
38pub trait ContainerHandle<N = Node>: NodeHandle<N> {
42 type ChildrenHandle: NodeHandle<N>;
44}
45
46#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
47pub struct DataflowOpID<N = Node>(N);
49
50#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
51pub struct DfgID<N = Node>(N);
53
54#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
55pub struct CfgID<N = Node>(N);
57
58#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
59pub struct ModuleRootID<N = Node>(N);
61
62#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
63pub struct ModuleID<N = Node>(N);
65
66#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
67pub struct FuncID<const DEF: bool, N = Node>(N);
73
74#[derive(Debug, Clone, PartialEq, Eq)]
75pub struct AliasID<const DEF: bool, N = Node> {
81 node: N,
82 name: SmolStr,
83 bound: TypeBound,
84}
85
86impl<const DEF: bool, N> AliasID<DEF, N> {
87 pub fn new(node: N, name: SmolStr, bound: TypeBound) -> Self {
89 Self { node, name, bound }
90 }
91
92 pub fn get_name(&self) -> &SmolStr {
94 &self.name
95 }
96}
97
98#[derive(DerFrom, Debug, Clone, PartialEq, Eq)]
99pub struct ConstID<N = Node>(N);
101
102#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
103pub struct BasicBlockID<N = Node>(N);
105
106#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
107pub struct CaseID<N = Node>(N);
109
110#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
111pub struct TailLoopID<N = Node>(N);
113
114#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
115pub struct ConditionalID<N = Node>(N);
117
118#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, DerFrom, Debug)]
119pub struct DataflowParentID<N = Node>(N);
121
122macro_rules! impl_nodehandle {
128 ($name:ident, $tag:expr) => {
129 impl_nodehandle!($name, $tag, 0);
130 };
131 ($name:ident, $tag:expr, $node_attr:tt) => {
132 impl<N: HugrNode> NodeHandle<N> for $name<N> {
133 const TAG: OpTag = $tag;
134
135 #[inline]
136 fn node(&self) -> N {
137 self.$node_attr
138 }
139 }
140 };
141}
142
143impl_nodehandle!(DataflowParentID, OpTag::DataflowParent);
144impl_nodehandle!(DataflowOpID, OpTag::DataflowChild);
145impl_nodehandle!(ConditionalID, OpTag::Conditional);
146impl_nodehandle!(CaseID, OpTag::Case);
147impl_nodehandle!(DfgID, OpTag::Dfg);
148impl_nodehandle!(TailLoopID, OpTag::TailLoop);
149impl_nodehandle!(CfgID, OpTag::Cfg);
150
151impl_nodehandle!(ModuleRootID, OpTag::ModuleRoot);
152impl_nodehandle!(ModuleID, OpTag::ModuleOp);
153impl_nodehandle!(ConstID, OpTag::Const);
154
155impl_nodehandle!(BasicBlockID, OpTag::DataflowBlock);
156
157impl<const DEF: bool, N: HugrNode> NodeHandle<N> for FuncID<DEF, N> {
158 const TAG: OpTag = OpTag::Function;
159 #[inline]
160 fn node(&self) -> N {
161 self.0
162 }
163}
164
165impl<const DEF: bool, N: HugrNode> NodeHandle<N> for AliasID<DEF, N> {
166 const TAG: OpTag = OpTag::Alias;
167 #[inline]
168 fn node(&self) -> N {
169 self.node
170 }
171}
172
173impl<N: HugrNode> NodeHandle<N> for N {
174 const TAG: OpTag = OpTag::Any;
175 #[inline]
176 fn node(&self) -> N {
177 *self
178 }
179}
180
181macro_rules! impl_containerHandle {
183 ($name:ident, $children:ident) => {
184 impl<N: HugrNode> ContainerHandle<N> for $name<N> {
185 type ChildrenHandle = $children<N>;
186 }
187 };
188}
189
190impl_containerHandle!(DataflowParentID, DataflowOpID);
191impl_containerHandle!(DfgID, DataflowOpID);
192impl_containerHandle!(TailLoopID, DataflowOpID);
193impl_containerHandle!(ConditionalID, CaseID);
194impl_containerHandle!(CaseID, DataflowOpID);
195impl_containerHandle!(ModuleRootID, ModuleID);
196impl_containerHandle!(CfgID, BasicBlockID);
197impl_containerHandle!(BasicBlockID, DataflowOpID);
198impl<N: HugrNode> ContainerHandle<N> for FuncID<true, N> {
199 type ChildrenHandle = DataflowOpID<N>;
200}
201impl<N: HugrNode> ContainerHandle<N> for AliasID<true, N> {
202 type ChildrenHandle = DataflowOpID<N>;
203}