1
use std::cell::RefCell;
2
use std::collections::{HashMap, VecDeque};
3
use std::fmt::{Debug, Display};
4
use std::rc::Rc;
5
use std::sync::{Arc, RwLock};
6

            
7
use derivative::Derivative;
8
use serde::{Deserialize, Serialize};
9
use uniplate::{Biplate, Tree, Uniplate};
10

            
11
use crate::ast::Expression;
12
use crate::context::Context;
13

            
14
use super::serde::{HasId, ObjId};
15
use super::types::Typeable;
16
use super::SubModel;
17
use super::{ReturnType, SymbolTable};
18

            
19
/// An Essence model.
20
///
21
/// - This type wraps a [`Submodel`] containing the top-level lexical scope. To manipulate the
22
///   model's constraints or symbols, first convert it to a [`Submodel`] using
23
///   [`as_submodel`](Model::as_submodel) / [`as_submodel_mut`](Model::as_submodel_mut).
24
///
25
/// - To de/serialise a model using `serde`, see [`SerdeModel`].
26
#[derive(Derivative, Clone, Debug)]
27
#[derivative(PartialEq, Eq)]
28
pub struct Model {
29
    submodel: SubModel,
30
    pub dominance: Option<Expression>,
31
    #[derivative(PartialEq = "ignore")]
32
    pub context: Arc<RwLock<Context<'static>>>,
33
}
34

            
35
impl Model {
36
    /// Creates a new model.
37
2034
    pub fn new(context: Arc<RwLock<Context<'static>>>) -> Model {
38
2034
        Model {
39
2034
            submodel: SubModel::new_top_level(),
40
2034
            dominance: None,
41
2034
            context,
42
2034
        }
43
2034
    }
44

            
45
    /// Returns this model as a [`Submodel`].
46
29718
    pub fn as_submodel(&self) -> &SubModel {
47
29718
        &self.submodel
48
29718
    }
49

            
50
    /// Returns this model as a mutable [`Submodel`].
51
25236
    pub fn as_submodel_mut(&mut self) -> &mut SubModel {
52
25236
        &mut self.submodel
53
25236
    }
54

            
55
    /// Replaces the model contents with `new_submodel`, returning the old contents.
56
17784
    pub fn replace_submodel(&mut self, new_submodel: SubModel) -> SubModel {
57
17784
        std::mem::replace(self.as_submodel_mut(), new_submodel)
58
17784
    }
59
}
60

            
61
impl Default for Model {
62
162
    fn default() -> Self {
63
162
        Model {
64
162
            submodel: SubModel::new_top_level(),
65
162
            dominance: None,
66
162
            context: Arc::new(RwLock::new(Context::default())),
67
162
        }
68
162
    }
69
}
70

            
71
impl Typeable for Model {
72
    fn return_type(&self) -> Option<ReturnType> {
73
        Some(ReturnType::Bool)
74
    }
75
}
76

            
77
// At time of writing (03/02/2025), the Uniplate derive macro doesn't like the lifetimes inside
78
// context, and we do not yet have a way of ignoring this field.
79
impl Uniplate for Model {
80
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
81
        // Model contains no sub-models.
82
        let self2 = self.clone();
83
        (Tree::Zero, Box::new(move |_| self2.clone()))
84
    }
85
}
86

            
87
impl Biplate<Expression> for Model {
88
    fn biplate(&self) -> (Tree<Expression>, Box<dyn Fn(Tree<Expression>) -> Self>) {
89
        // walk into submodel
90
        let submodel = self.as_submodel();
91
        let (expr_tree, expr_ctx) = <SubModel as Biplate<Expression>>::biplate(submodel);
92

            
93
        // walk into dominance relation if it exists
94
        let dom_tree = match &self.dominance {
95
            Some(expr) => Tree::One(expr.clone()),
96
            None => Tree::Zero,
97
        };
98
        let tree = Tree::<Expression>::Many(VecDeque::from([expr_tree, dom_tree]));
99

            
100
        let self2 = self.clone();
101
        let ctx = Box::new(move |x| match x {
102
            Tree::Many(xs) => {
103
                if xs.len() != 2 {
104
                    panic!("Expected a tree with two children");
105
                }
106
                let submodel_tree = xs[0].clone();
107
                let dom_tree = xs[1].clone();
108

            
109
                // reconstruct the submodel
110
                let submodel = expr_ctx(submodel_tree);
111
                // reconstruct the dominance relation
112
                let dominance = match dom_tree {
113
                    Tree::One(expr) => Some(expr),
114
                    Tree::Zero => None,
115
                    _ => panic!("Expected a tree with two children"),
116
                };
117

            
118
                let mut self3 = self2.clone();
119
                self3.replace_submodel(submodel);
120
                self3.dominance = dominance;
121
                self3
122
            }
123
            _ => {
124
                panic!("Expected a tree with two children");
125
            }
126
        });
127

            
128
        (tree, ctx)
129
    }
130
}
131

            
132
impl Biplate<SubModel> for Model {
133
19602
    fn biplate(&self) -> (Tree<SubModel>, Box<dyn Fn(Tree<SubModel>) -> Self>) {
134
19602
        let submodel = self.as_submodel().clone();
135
19602

            
136
19602
        let self2 = self.clone();
137
19602
        let ctx = Box::new(move |x| {
138
17784
            let Tree::One(submodel) = x else {
139
                panic!();
140
            };
141

            
142
17784
            let mut self3 = self2.clone();
143
17784
            self3.replace_submodel(submodel);
144
17784
            self3
145
19602
        });
146
19602

            
147
19602
        (Tree::One(submodel), ctx)
148
19602
    }
149
}
150

            
151
impl Display for Model {
152
3564
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153
3564
        std::fmt::Display::fmt(self.as_submodel(), f)
154
3564
    }
155
}
156

            
157
/// A model that is de/serializable using `serde`.
158
///
159
/// To turn this into a rewritable model, it needs to be initialised using [`initialise`](SerdeModel::initialise).
160
///
161
/// To deserialise a [`Model`], use `.into()` to convert it into a `SerdeModel` first.
162
#[derive(Clone, Debug, Serialize, Deserialize)]
163
pub struct SerdeModel {
164
    #[serde(flatten)]
165
    submodel: SubModel,
166
    dominance: Option<Expression>,
167
}
168

            
169
impl SerdeModel {
170
    /// Initialises the model for rewriting.
171
5382
    pub fn initialise(self, context: Arc<RwLock<Context<'static>>>) -> Option<Model> {
172
5382
        // The definitive versions of each symbol table are stored in the submodels. Parent
173
5382
        // pointers store dummy values with the correct ids, but nothing else. We need to replace
174
5382
        // these dummy values with pointers to the actual parent symbol tables, using the ids to
175
5382
        // know which tables should be equal.
176
5382
        //
177
5382
        // See super::serde::RcRefCellToInner, super::serde::RcRefCellToId.
178
5382

            
179
5382
        // Store the definitive versions of all symbol tables by id.
180
5382
        let mut tables: HashMap<ObjId, Rc<RefCell<SymbolTable>>> = HashMap::new();
181

            
182
        // Find the definitive versions by traversing the sub-models.
183
5382
        for submodel in self.submodel.universe() {
184
5382
            let id = submodel.symbols().id();
185
5382

            
186
5382
            // ids should be unique!
187
5382
            assert_eq!(
188
5382
                tables.insert(id, submodel.symbols_ptr_unchecked().clone()),
189
5382
                None
190
5382
            );
191
        }
192

            
193
        // Restore parent pointers using `tables`.
194
5382
        for table in tables.clone().into_values() {
195
5382
            let mut table_mut = table.borrow_mut();
196
5382
            let parent_mut = table_mut.parent_mut_unchecked();
197

            
198
            #[allow(clippy::unwrap_used)]
199
5382
            if let Some(parent) = parent_mut {
200
                let parent_id = parent.borrow().id();
201

            
202
                *parent = tables.get(&parent_id).unwrap().clone();
203
5382
            }
204
        }
205

            
206
5382
        Some(Model {
207
5382
            submodel: self.submodel,
208
5382
            dominance: self.dominance,
209
5382
            context,
210
5382
        })
211
5382
    }
212
}
213

            
214
impl From<Model> for SerdeModel {
215
3582
    fn from(val: Model) -> Self {
216
3582
        SerdeModel {
217
3582
            submodel: val.submodel,
218
3582
            dominance: val.dominance,
219
3582
        }
220
3582
    }
221
}
222

            
223
impl Display for SerdeModel {
224
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225
        std::fmt::Display::fmt(&self.submodel, f)
226
    }
227
}