Skip to main content

conjure_cp_core/ast/
enumerated.rs

1use std::fmt::Display;
2
3use polyquine::Quine;
4use serde::{Deserialize, Serialize};
5
6use crate::ast::{Domain, DomainPtr, Moo, Name, Range};
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
9pub struct EnumeratedType {
10    pub name: Name,
11    pub variants: Vec<Name>,
12}
13
14impl EnumeratedType {
15    pub fn new(name: Name, variants: impl Into<Vec<Name>>) -> Self {
16        Self {
17            name,
18            variants: variants.into(),
19        }
20    }
21
22    pub fn is_empty(&self) -> bool {
23        self.variants.is_empty()
24    }
25
26    pub fn len(&self) -> usize {
27        self.variants.len()
28    }
29}
30
31impl Moo<EnumeratedType> {
32    pub fn to_domain(&self) -> DomainPtr {
33        Domain::enumerated_ground(self.clone(), vec![Range::Unbounded])
34    }
35}
36
37impl Display for EnumeratedType {
38    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39        let name = &self.name;
40        write!(f, "enum {name}")
41    }
42}
43
44#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
45pub struct EnumVariant {
46    pub ty: Moo<EnumeratedType>,
47    pub variant: u32,
48}
49
50impl EnumVariant {
51    pub fn new(ty: Moo<EnumeratedType>, variant: u32) -> Self {
52        Self { ty, variant }
53    }
54
55    pub fn name(&self) -> &Name {
56        &self.ty.variants[self.variant as usize]
57    }
58
59    pub fn pred(&self) -> Option<EnumVariant> {
60        if self.variant == 0 {
61            return None;
62        }
63
64        Some(Self::new(self.ty.clone(), self.variant - 1))
65    }
66
67    pub fn succ(&self) -> Option<EnumVariant> {
68        if self.variant as usize >= self.ty.variants.len().saturating_sub(1) {
69            return None;
70        }
71
72        Some(Self::new(self.ty.clone(), self.variant + 1))
73    }
74}