Skip to main content

conjure_cp_core/ast/
name.rs

1use crate::representation::ReprId;
2use std::fmt::Display;
3
4use itertools::Itertools as _;
5use polyquine::Quine;
6use serde::{Deserialize, Serialize};
7use 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)]
12pub 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
41impl Name {
42    /// Creates a new `Name::User` from a `&str`.
43    pub fn user(name: &str) -> Self {
44        Name::User(Ustr::from(name))
45    }
46
47    /// Creates a name for an auxiliary variable introduced by a representation.
48    pub fn repr(src: Name, rule: ReprId, suffix: &str) -> Self {
49        Name::Represented(Box::new((src, rule, Ustr::from(suffix))))
50    }
51}
52
53impl Default for Name {
54    fn default() -> Self {
55        Name::User(Ustr::from(""))
56    }
57}
58
59uniplate::derive_unplateable!(Name);
60
61impl Display for Name {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        match self {
64            Name::User(s) => write!(f, "{s}"),
65            Name::Machine(i) => write!(f, "__{i}"),
66            Name::Represented(fields) => {
67                let (name, rule, suffix) = fields.as_ref();
68                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    }
76}
77
78impl From<&str> for Name {
79    fn from(s: &str) -> Self {
80        Name::User(Ustr::from(s))
81    }
82}
83
84impl From<i32> for Name {
85    fn from(i: i32) -> Self {
86        Name::Machine(i)
87    }
88}