conjure_cp_core/ast/
model.rs1#![allow(clippy::arc_with_non_send_sync)] use std::cell::RefCell;
3use std::collections::{HashMap, VecDeque};
4use std::fmt::{Debug, Display};
5use std::rc::Rc;
6use std::sync::{Arc, RwLock};
7
8use derivative::Derivative;
9use serde::{Deserialize, Serialize};
10use uniplate::{Biplate, Tree, Uniplate};
11
12use crate::ast::{Expression, Typeable};
13use crate::context::Context;
14
15use super::serde::{HasId, ObjId};
16use super::{DeclarationPtr, Name, SubModel};
17use super::{ReturnType, SymbolTable};
18
19#[derive(Derivative, Clone, Debug)]
27#[derivative(PartialEq, Eq)]
28pub struct Model {
29 submodel: SubModel,
30 pub search_order: Option<Vec<Name>>,
31 pub dominance: Option<Expression>,
32 #[derivative(PartialEq = "ignore")]
33 pub context: Arc<RwLock<Context<'static>>>,
34}
35
36impl Model {
37 pub fn from_submodel(submodel: SubModel) -> Model {
38 Model {
39 submodel,
40 ..Default::default()
41 }
42 }
43
44 pub fn new(context: Arc<RwLock<Context<'static>>>) -> Model {
46 Model {
47 submodel: SubModel::new_top_level(),
48 dominance: None,
49 context,
50 search_order: None,
51 }
52 }
53
54 pub fn as_submodel(&self) -> &SubModel {
56 &self.submodel
57 }
58
59 pub fn as_submodel_mut(&mut self) -> &mut SubModel {
61 &mut self.submodel
62 }
63
64 pub fn replace_submodel(&mut self, new_submodel: SubModel) -> SubModel {
66 std::mem::replace(self.as_submodel_mut(), new_submodel)
67 }
68}
69
70impl Default for Model {
71 fn default() -> Self {
72 Model {
73 submodel: SubModel::new_top_level(),
74 dominance: None,
75 context: Arc::new(RwLock::new(Context::default())),
76 search_order: None,
77 }
78 }
79}
80
81impl Typeable for Model {
82 fn return_type(&self) -> ReturnType {
83 ReturnType::Bool
84 }
85}
86
87impl Uniplate for Model {
90 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
91 let self2 = self.clone();
93 (Tree::Zero, Box::new(move |_| self2.clone()))
94 }
95}
96
97impl Biplate<Expression> for Model {
98 fn biplate(&self) -> (Tree<Expression>, Box<dyn Fn(Tree<Expression>) -> Self>) {
99 let submodel = self.as_submodel();
101 let (expr_tree, expr_ctx) = <SubModel as Biplate<Expression>>::biplate(submodel);
102
103 let dom_tree = match &self.dominance {
105 Some(expr) => Tree::One(expr.clone()),
106 None => Tree::Zero,
107 };
108 let tree = Tree::<Expression>::Many(VecDeque::from([expr_tree, dom_tree]));
109
110 let self2 = self.clone();
111 let ctx = Box::new(move |x| match x {
112 Tree::Many(xs) => {
113 if xs.len() != 2 {
114 panic!("Expected a tree with two children");
115 }
116 let submodel_tree = xs[0].clone();
117 let dom_tree = xs[1].clone();
118
119 let submodel = expr_ctx(submodel_tree);
121 let dominance = match dom_tree {
123 Tree::One(expr) => Some(expr),
124 Tree::Zero => None,
125 _ => panic!("Expected a tree with two children"),
126 };
127
128 let mut self3 = self2.clone();
129 self3.replace_submodel(submodel);
130 self3.dominance = dominance;
131 self3
132 }
133 _ => {
134 panic!("Expected a tree with two children");
135 }
136 });
137
138 (tree, ctx)
139 }
140}
141
142impl Biplate<SubModel> for Model {
143 fn biplate(&self) -> (Tree<SubModel>, Box<dyn Fn(Tree<SubModel>) -> Self>) {
144 let submodel = self.as_submodel().clone();
145
146 let self2 = self.clone();
147 let ctx = Box::new(move |x| {
148 let Tree::One(submodel) = x else {
149 panic!();
150 };
151
152 let mut self3 = self2.clone();
153 self3.replace_submodel(submodel);
154 self3
155 });
156
157 (Tree::One(submodel), ctx)
158 }
159}
160
161impl Display for Model {
162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 std::fmt::Display::fmt(self.as_submodel(), f)
164 }
165}
166
167#[derive(Clone, Debug, Serialize, Deserialize)]
173pub struct SerdeModel {
174 #[serde(flatten)]
175 submodel: SubModel,
176 search_order: Option<Vec<Name>>, dominance: Option<Expression>,
178}
179
180impl SerdeModel {
181 pub fn initialise(mut self, context: Arc<RwLock<Context<'static>>>) -> Option<Model> {
185 let mut tables: HashMap<ObjId, Rc<RefCell<SymbolTable>>> = HashMap::new();
194
195 for submodel in self.submodel.universe() {
197 let id = submodel.symbols().id();
198
199 assert_eq!(
201 tables.insert(id, submodel.symbols_ptr_unchecked().clone()),
202 None
203 );
204 }
205
206 for table in tables.clone().into_values() {
208 let mut table_mut = table.borrow_mut();
209 let parent_mut = table_mut.parent_mut_unchecked();
210
211 #[allow(clippy::unwrap_used)]
212 if let Some(parent) = parent_mut {
213 let parent_id = parent.borrow().id();
214
215 *parent = tables.get(&parent_id).unwrap().clone();
216 }
217 }
218
219 let mut all_declarations: HashMap<ObjId, DeclarationPtr> = HashMap::new();
224 for table in tables.values() {
225 for (_, decl) in table.as_ref().borrow().clone().into_iter_local() {
226 let id = decl.id();
227 all_declarations.insert(id, decl);
228 }
229 }
230
231 *self.submodel.constraints_mut() = self.submodel.constraints().transform_bi(&move |decl: DeclarationPtr| {
233 let id = decl.id();
234 all_declarations
235 .get(&id)
236 .unwrap_or_else(|| panic!("A declaration used in the expression tree should exist in the symbol table. The missing declaration has id {id}."))
237 .clone()
238 });
239
240 Some(Model {
241 submodel: self.submodel,
242 dominance: self.dominance,
243 context,
244 search_order: self.search_order,
245 })
246 }
247}
248
249impl From<Model> for SerdeModel {
250 fn from(val: Model) -> Self {
251 SerdeModel {
252 submodel: val.submodel,
253 dominance: val.dominance,
254 search_order: val.search_order,
255 }
256 }
257}
258
259impl Display for SerdeModel {
260 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
261 std::fmt::Display::fmt(&self.submodel, f)
262 }
263}
264
265impl SerdeModel {
266 pub fn collect_stable_id_mapping(&self) -> HashMap<ObjId, ObjId> {
276 let mut id_list: Vec<ObjId> = Vec::new();
277
278 for submodel in self.submodel.universe() {
280 let symbol_table_id = submodel.symbols().id();
281 if !id_list.contains(&symbol_table_id) {
282 id_list.push(symbol_table_id);
283 }
284 }
285
286 for decl_ptr in Biplate::<DeclarationPtr>::universe_bi(self.submodel.constraints()) {
288 let decl_id = decl_ptr.id();
289 if !id_list.contains(&decl_id) {
290 id_list.push(decl_id);
291 }
292 }
293
294 let mut id_map = HashMap::new();
296 for (stable_id, &original_id) in id_list.iter().enumerate() {
297 id_map.insert(original_id, stable_id as ObjId);
298 }
299
300 id_map
301 }
302}