hugr_core/ops/
module.rs

1//! Module-level operations
2
3use std::borrow::Cow;
4
5use smol_str::SmolStr;
6#[cfg(test)]
7use {
8    crate::proptest::{any_nonempty_smolstr, any_nonempty_string},
9    ::proptest_derive::Arbitrary,
10};
11
12use crate::types::{EdgeKind, PolyFuncType, Signature};
13use crate::types::{Type, TypeBound};
14
15use super::StaticTag;
16use super::dataflow::DataflowParent;
17use super::{OpTag, OpTrait, impl_op_name};
18
19/// The root of a module, parent of all other `OpType`s.
20#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
21#[cfg_attr(test, derive(Arbitrary))]
22pub struct Module {
23    // can't be simple unit struct due to flattened serialization issues
24    // see https://github.com/CQCL/hugr/issues/1270
25}
26
27impl Module {
28    /// Construct a new Module.
29    #[must_use]
30    pub const fn new() -> Self {
31        Self {}
32    }
33}
34
35impl_op_name!(Module);
36
37impl StaticTag for Module {
38    const TAG: OpTag = OpTag::ModuleRoot;
39}
40
41impl OpTrait for Module {
42    fn description(&self) -> &'static str {
43        "The root of a module, parent of all other `OpType`s"
44    }
45
46    fn tag(&self) -> super::OpTag {
47        <Self as StaticTag>::TAG
48    }
49}
50
51/// A function definition.
52///
53/// Children nodes are the body of the definition.
54#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
55#[cfg_attr(test, derive(Arbitrary))]
56pub struct FuncDefn {
57    #[cfg_attr(test, proptest(strategy = "any_nonempty_string()"))]
58    name: String,
59    signature: PolyFuncType,
60}
61
62impl FuncDefn {
63    /// Create a new instance with the given name and signature
64    pub fn new(name: impl Into<String>, signature: impl Into<PolyFuncType>) -> Self {
65        Self {
66            name: name.into(),
67            signature: signature.into(),
68        }
69    }
70
71    /// The name of the function (not the name of the Op)
72    pub fn func_name(&self) -> &String {
73        &self.name
74    }
75
76    /// Allows mutating the name of the function (as per [Self::func_name])
77    pub fn func_name_mut(&mut self) -> &mut String {
78        &mut self.name
79    }
80
81    /// Gets the signature of the function
82    pub fn signature(&self) -> &PolyFuncType {
83        &self.signature
84    }
85
86    /// Allows mutating the signature of the function
87    pub fn signature_mut(&mut self) -> &mut PolyFuncType {
88        &mut self.signature
89    }
90}
91
92impl_op_name!(FuncDefn);
93impl StaticTag for FuncDefn {
94    const TAG: OpTag = OpTag::FuncDefn;
95}
96
97impl DataflowParent for FuncDefn {
98    fn inner_signature(&self) -> Cow<'_, Signature> {
99        Cow::Borrowed(self.signature.body())
100    }
101}
102
103impl OpTrait for FuncDefn {
104    fn description(&self) -> &'static str {
105        "A function definition"
106    }
107
108    fn tag(&self) -> OpTag {
109        <Self as StaticTag>::TAG
110    }
111
112    fn static_output(&self) -> Option<EdgeKind> {
113        Some(EdgeKind::Function(self.signature.clone()))
114    }
115
116    // Cannot refer to TypeArgs of enclosing Hugr (it binds its own), so no substitute()
117}
118
119/// External function declaration, linked at runtime.
120#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
121#[cfg_attr(test, derive(Arbitrary))]
122pub struct FuncDecl {
123    #[cfg_attr(test, proptest(strategy = "any_nonempty_string()"))]
124    name: String,
125    signature: PolyFuncType,
126}
127
128impl FuncDecl {
129    /// Create a new instance with the given name and signature
130    pub fn new(name: impl Into<String>, signature: impl Into<PolyFuncType>) -> Self {
131        Self {
132            name: name.into(),
133            signature: signature.into(),
134        }
135    }
136
137    /// The name of the function (not the name of the Op)
138    pub fn func_name(&self) -> &String {
139        &self.name
140    }
141
142    /// Allows mutating the name of the function (as per [Self::func_name])
143    pub fn func_name_mut(&mut self) -> &mut String {
144        &mut self.name
145    }
146
147    /// Gets the signature of the function
148    pub fn signature(&self) -> &PolyFuncType {
149        &self.signature
150    }
151
152    /// Allows mutating the signature of the function
153    pub fn signature_mut(&mut self) -> &mut PolyFuncType {
154        &mut self.signature
155    }
156}
157
158impl_op_name!(FuncDecl);
159impl StaticTag for FuncDecl {
160    const TAG: OpTag = OpTag::Function;
161}
162
163impl OpTrait for FuncDecl {
164    fn description(&self) -> &'static str {
165        "External function declaration, linked at runtime"
166    }
167
168    fn tag(&self) -> OpTag {
169        <Self as StaticTag>::TAG
170    }
171
172    fn static_output(&self) -> Option<EdgeKind> {
173        Some(EdgeKind::Function(self.signature.clone()))
174    }
175
176    // Cannot refer to TypeArgs of enclosing Hugr (the type binds its own), so no substitute()
177}
178
179/// A type alias definition, used only for debug/metadata.
180#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
181#[cfg_attr(test, derive(Arbitrary))]
182pub struct AliasDefn {
183    /// Alias name
184    #[cfg_attr(test, proptest(strategy = "any_nonempty_smolstr()"))]
185    pub name: SmolStr,
186    /// Aliased type
187    pub definition: Type,
188}
189impl_op_name!(AliasDefn);
190impl StaticTag for AliasDefn {
191    const TAG: OpTag = OpTag::Alias;
192}
193impl OpTrait for AliasDefn {
194    fn description(&self) -> &'static str {
195        "A type alias definition"
196    }
197
198    fn tag(&self) -> OpTag {
199        <Self as StaticTag>::TAG
200    }
201
202    // Cannot refer to TypeArgs of enclosing Hugr (? - we planned to make this
203    // polymorphic so it binds its own, and we never combine binders), so no substitute()
204}
205
206/// A type alias declaration. Resolved at link time.
207#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
208#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
209pub struct AliasDecl {
210    /// Alias name
211    #[cfg_attr(test, proptest(strategy = "any_nonempty_smolstr()"))]
212    pub name: SmolStr,
213    /// Flag to signify type is classical
214    pub bound: TypeBound,
215}
216
217impl AliasDecl {
218    /// Construct a new Alias declaration.
219    pub fn new(name: impl Into<SmolStr>, bound: TypeBound) -> Self {
220        Self {
221            name: name.into(),
222            bound,
223        }
224    }
225
226    /// Returns a reference to the name of this [`AliasDecl`].
227    #[must_use]
228    pub fn name(&self) -> &str {
229        self.name.as_ref()
230    }
231}
232
233impl_op_name!(AliasDecl);
234impl StaticTag for AliasDecl {
235    const TAG: OpTag = OpTag::Alias;
236}
237impl OpTrait for AliasDecl {
238    fn description(&self) -> &'static str {
239        "A type alias declaration"
240    }
241
242    fn tag(&self) -> OpTag {
243        <Self as StaticTag>::TAG
244    }
245
246    // Cannot refer to TypeArgs of enclosing Hugr (? - we planned to make this
247    // polymorphic so it binds its own, and we never combine binders), so no substitute()
248}