1
use crate::representation::ReprId;
2
use std::fmt::Display;
3

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

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

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

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

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

            
47
    /// Creates a name for an auxiliary variable introduced by a representation.
48
52443019
    pub fn repr(src: Name, rule: ReprId, suffix: &str) -> Self {
49
52443019
        Name::Represented(Box::new((src, rule, Ustr::from(suffix))))
50
52443019
    }
51
}
52

            
53
impl Default for Name {
54
    fn default() -> Self {
55
        Name::User(Ustr::from(""))
56
    }
57
}
58

            
59
uniplate::derive_unplateable!(Name);
60

            
61
impl Display for Name {
62
490632686
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63
490632686
        match self {
64
280265152
            Name::User(s) => write!(f, "{s}"),
65
4154438
            Name::Machine(i) => write!(f, "__{i}"),
66
            Name::Represented(fields) => {
67
206213096
                let (name, rule, suffix) = fields.as_ref();
68
206213096
                write!(f, "{name}#{rule}_{suffix}")
69
            }
70
            Name::WithRepresentation(name, items) => {
71
                // TODO: what is the correct syntax for nested reprs?
72
                write!(f, "{name}#{}", items.iter().join("#"))
73
            }
74
        }
75
490632686
    }
76
}
77

            
78
impl From<&str> for Name {
79
946
    fn from(s: &str) -> Self {
80
946
        Name::User(Ustr::from(s))
81
946
    }
82
}
83

            
84
impl From<i32> for Name {
85
    fn from(i: i32) -> Self {
86
        Name::Machine(i)
87
    }
88
}