1
use std::fmt::Display;
2

            
3
use polyquine::Quine;
4
use serde::{Deserialize, Serialize};
5

            
6
use crate::ast::{Domain, DomainPtr, Moo, Name, Range};
7

            
8
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
9
pub struct EnumeratedType {
10
    pub name: Name,
11
    pub variants: Vec<Name>,
12
}
13

            
14
impl EnumeratedType {
15
20
    pub fn new(name: Name, variants: impl Into<Vec<Name>>) -> Self {
16
20
        Self {
17
20
            name,
18
20
            variants: variants.into(),
19
20
        }
20
20
    }
21

            
22
    pub fn is_empty(&self) -> bool {
23
        self.variants.is_empty()
24
    }
25

            
26
16
    pub fn len(&self) -> usize {
27
16
        self.variants.len()
28
16
    }
29
}
30

            
31
impl Moo<EnumeratedType> {
32
60
    pub fn to_domain(&self) -> DomainPtr {
33
60
        Domain::enumerated_ground(self.clone(), vec![Range::Unbounded])
34
60
    }
35
}
36

            
37
impl 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)]
45
pub struct EnumVariant {
46
    pub ty: Moo<EnumeratedType>,
47
    pub variant: u32,
48
}
49

            
50
impl EnumVariant {
51
40
    pub fn new(ty: Moo<EnumeratedType>, variant: u32) -> Self {
52
40
        Self { ty, variant }
53
40
    }
54

            
55
100
    pub fn name(&self) -> &Name {
56
100
        &self.ty.variants[self.variant as usize]
57
100
    }
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
32
    pub fn succ(&self) -> Option<EnumVariant> {
68
32
        if self.variant as usize >= self.ty.variants.len().saturating_sub(1) {
69
32
            return None;
70
        }
71

            
72
        Some(Self::new(self.ty.clone(), self.variant + 1))
73
32
    }
74
}