conjure_cp_core/ast/
enumerated.rs1use 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}