hugr_core/ops/
sum.rs

1//! Definition of dataflow operations with no children.
2
3use std::borrow::Cow;
4
5use super::dataflow::DataflowOpTrait;
6use super::{impl_op_name, OpTag};
7use crate::types::{EdgeKind, Signature, Type, TypeRow};
8
9/// An operation that creates a tagged sum value from one of its variants.
10#[derive(Debug, Clone, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
11#[non_exhaustive]
12#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
13pub struct Tag {
14    /// The variant to create.
15    pub tag: usize,
16    /// The variants of the sum type.
17    /// TODO this allows *none* of the variants to contain row variables, but
18    /// we could allow variants *other than the tagged one* to contain rowvars.
19    pub variants: Vec<TypeRow>,
20}
21
22impl Tag {
23    /// Create a new Tag operation.
24    pub fn new(tag: usize, variants: Vec<TypeRow>) -> Self {
25        Self { tag, variants }
26    }
27}
28
29impl_op_name!(Tag);
30
31impl DataflowOpTrait for Tag {
32    const TAG: OpTag = OpTag::Leaf;
33
34    /// A human-readable description of the operation.
35    fn description(&self) -> &str {
36        "Tag Sum operation"
37    }
38
39    /// The signature of the operation.
40    fn signature(&self) -> Cow<'_, Signature> {
41        // TODO: Store a cached signature
42        Cow::Owned(Signature::new(
43            self.variants
44                .get(self.tag)
45                .expect("Not a valid tag")
46                .clone(),
47            vec![Type::new_sum(self.variants.clone())],
48        ))
49    }
50
51    fn other_input(&self) -> Option<EdgeKind> {
52        Some(EdgeKind::StateOrder)
53    }
54
55    fn other_output(&self) -> Option<EdgeKind> {
56        Some(EdgeKind::StateOrder)
57    }
58
59    fn substitute(&self, subst: &crate::types::Substitution) -> Self {
60        Self {
61            variants: self.variants.iter().map(|r| r.substitute(subst)).collect(),
62            tag: self.tag,
63        }
64    }
65}