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::dataflow::DataflowParent;
16use super::StaticTag;
17use super::{impl_op_name, OpTag, OpTrait};
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    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) -> &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    /// Name of function
57    #[cfg_attr(test, proptest(strategy = "any_nonempty_string()"))]
58    pub name: String,
59    /// Signature of the function
60    pub signature: PolyFuncType,
61}
62
63impl_op_name!(FuncDefn);
64impl StaticTag for FuncDefn {
65    const TAG: OpTag = OpTag::FuncDefn;
66}
67
68impl DataflowParent for FuncDefn {
69    fn inner_signature(&self) -> Cow<'_, Signature> {
70        Cow::Borrowed(self.signature.body())
71    }
72}
73
74impl OpTrait for FuncDefn {
75    fn description(&self) -> &str {
76        "A function definition"
77    }
78
79    fn tag(&self) -> OpTag {
80        <Self as StaticTag>::TAG
81    }
82
83    fn static_output(&self) -> Option<EdgeKind> {
84        Some(EdgeKind::Function(self.signature.clone()))
85    }
86
87    // Cannot refer to TypeArgs of enclosing Hugr (it binds its own), so no substitute()
88}
89
90/// External function declaration, linked at runtime.
91#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
92#[cfg_attr(test, derive(Arbitrary))]
93pub struct FuncDecl {
94    /// Name of function
95    #[cfg_attr(test, proptest(strategy = "any_nonempty_string()"))]
96    pub name: String,
97    /// Signature of the function
98    pub signature: PolyFuncType,
99}
100
101impl_op_name!(FuncDecl);
102impl StaticTag for FuncDecl {
103    const TAG: OpTag = OpTag::Function;
104}
105
106impl OpTrait for FuncDecl {
107    fn description(&self) -> &str {
108        "External function declaration, linked at runtime"
109    }
110
111    fn tag(&self) -> OpTag {
112        <Self as StaticTag>::TAG
113    }
114
115    fn static_output(&self) -> Option<EdgeKind> {
116        Some(EdgeKind::Function(self.signature.clone()))
117    }
118
119    // Cannot refer to TypeArgs of enclosing Hugr (the type binds its own), so no substitute()
120}
121
122/// A type alias definition, used only for debug/metadata.
123#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
124#[cfg_attr(test, derive(Arbitrary))]
125pub struct AliasDefn {
126    /// Alias name
127    #[cfg_attr(test, proptest(strategy = "any_nonempty_smolstr()"))]
128    pub name: SmolStr,
129    /// Aliased type
130    pub definition: Type,
131}
132impl_op_name!(AliasDefn);
133impl StaticTag for AliasDefn {
134    const TAG: OpTag = OpTag::Alias;
135}
136impl OpTrait for AliasDefn {
137    fn description(&self) -> &str {
138        "A type alias definition"
139    }
140
141    fn tag(&self) -> OpTag {
142        <Self as StaticTag>::TAG
143    }
144
145    // Cannot refer to TypeArgs of enclosing Hugr (? - we planned to make this
146    // polymorphic so it binds its own, and we never combine binders), so no substitute()
147}
148
149/// A type alias declaration. Resolved at link time.
150#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
151#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
152pub struct AliasDecl {
153    /// Alias name
154    #[cfg_attr(test, proptest(strategy = "any_nonempty_smolstr()"))]
155    pub name: SmolStr,
156    /// Flag to signify type is classical
157    pub bound: TypeBound,
158}
159
160impl AliasDecl {
161    /// Construct a new Alias declaration.
162    pub fn new(name: impl Into<SmolStr>, bound: TypeBound) -> Self {
163        Self {
164            name: name.into(),
165            bound,
166        }
167    }
168
169    /// Returns a reference to the name of this [`AliasDecl`].
170    pub fn name(&self) -> &str {
171        self.name.as_ref()
172    }
173}
174
175impl_op_name!(AliasDecl);
176impl StaticTag for AliasDecl {
177    const TAG: OpTag = OpTag::Alias;
178}
179impl OpTrait for AliasDecl {
180    fn description(&self) -> &str {
181        "A type alias declaration"
182    }
183
184    fn tag(&self) -> OpTag {
185        <Self as StaticTag>::TAG
186    }
187
188    // Cannot refer to TypeArgs of enclosing Hugr (? - we planned to make this
189    // polymorphic so it binds its own, and we never combine binders), so no substitute()
190}