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