1
use std::fmt::Display;
2

            
3
use itertools::Itertools as _;
4
use polyquine::Quine;
5
use serde::{Deserialize, Serialize};
6
use ustr::Ustr;
7

            
8
/// A reference to an object stored in the [`SymbolTable`].
9
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize, Quine)]
10
#[path_prefix(conjure_cp::ast)]
11
pub enum Name {
12
    /// A name given in the input model.
13
    User(Ustr),
14
    /// A name generated by Conjure-Oxide.
15
    Machine(i32),
16

            
17
    /// An auxiliary variable which is part of a Representation of a larger one.
18
    /// See [crate::representation::Representation]
19
    Represented(
20
        // box these fields to make the size of name smaller
21
        // this in turn makes the size of atom, expression, domain, ... smaller
22
        Box<(
23
            // The source variable
24
            Name,
25
            // The representation rule used
26
            Ustr,
27
            // Additional, rule dependent, information
28
            Ustr,
29
        )>,
30
    ),
31

            
32
    /// A variable divided into several auxiliary ones through a Representation.
33
    WithRepresentation(
34
        Box<Name>,
35
        /// representations chosen
36
        Vec<Ustr>,
37
    ),
38
}
39

            
40
impl Name {
41
    /// Creates a new `Name::User` from a `&str`.
42
    pub fn user(name: &str) -> Self {
43
        Name::User(Ustr::from(name))
44
    }
45
}
46

            
47
impl Default for Name {
48
    fn default() -> Self {
49
        Name::User(Ustr::from(""))
50
    }
51
}
52

            
53
uniplate::derive_unplateable!(Name);
54

            
55
impl Display for Name {
56
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57
        match self {
58
            Name::User(s) => write!(f, "{s}"),
59
            Name::Machine(i) => write!(f, "__{i}"),
60
            Name::Represented(fields) => {
61
                let (name, rule_string, suffix) = fields.as_ref();
62
                write!(f, "{name}#{rule_string}_{suffix}")
63
            }
64
            Name::WithRepresentation(name, items) => {
65
                // TODO: what is the correct syntax for nested reprs?
66
                write!(f, "{name}#{}", items.iter().join("#"))
67
            }
68
        }
69
    }
70
}
71

            
72
impl From<&str> for Name {
73
    fn from(s: &str) -> Self {
74
        Name::User(Ustr::from(s))
75
    }
76
}
77

            
78
impl From<i32> for Name {
79
    fn from(i: i32) -> Self {
80
        Name::Machine(i)
81
    }
82
}