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::{OpTag, impl_op_name};
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    #[must_use]
25    pub fn new(tag: usize, variants: Vec<TypeRow>) -> Self {
26        Self { tag, variants }
27    }
28}
29
30impl_op_name!(Tag);
31
32impl DataflowOpTrait for Tag {
33    const TAG: OpTag = OpTag::Leaf;
34
35    /// A human-readable description of the operation.
36    fn description(&self) -> &'static str {
37        "Tag Sum operation"
38    }
39
40    /// The signature of the operation.
41    fn signature(&self) -> Cow<'_, Signature> {
42        // TODO: Store a cached signature
43        Cow::Owned(Signature::new(
44            self.variants
45                .get(self.tag)
46                .expect("Not a valid tag")
47                .clone(),
48            vec![Type::new_sum(self.variants.clone())],
49        ))
50    }
51
52    fn other_input(&self) -> Option<EdgeKind> {
53        Some(EdgeKind::StateOrder)
54    }
55
56    fn other_output(&self) -> Option<EdgeKind> {
57        Some(EdgeKind::StateOrder)
58    }
59
60    fn substitute(&self, subst: &crate::types::Substitution) -> Self {
61        Self {
62            variants: self.variants.iter().map(|r| r.substitute(subst)).collect(),
63            tag: self.tag,
64        }
65    }
66}