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;
13use crate::context::Context;
14
15use super::serde::{HasId, ObjId};
16use super::types::Typeable;
17use super::{DeclarationPtr, Name, SubModel};
18use super::{ReturnType, SymbolTable};
19
20#[derive(Derivative, Clone, Debug)]
28#[derivative(PartialEq, Eq)]
29pub struct Model {
30 submodel: SubModel,
31 pub search_order: Option<Vec<Name>>,
32 pub dominance: Option<Expression>,
33 #[derivative(PartialEq = "ignore")]
34 pub context: Arc<RwLock<Context<'static>>>,
35}
36
37impl Model {
38 pub fn from_submodel(submodel: SubModel) -> Model {
39 Model {
40 submodel,
41 ..Default::default()
42 }
43 }
44
45 pub fn new(context: Arc<RwLock<Context<'static>>>) -> Model {
47 Model {
48 submodel: SubModel::new_top_level(),
49 dominance: None,
50 context,
51 search_order: None,
52 }
53 }
54
55 pub fn as_submodel(&self) -> &SubModel {
57 &self.submodel
58 }
59
60 pub fn as_submodel_mut(&mut self) -> &mut SubModel {
62 &mut self.submodel
63 }
64
65 pub fn replace_submodel(&mut self, new_submodel: SubModel) -> SubModel {
67 std::mem::replace(self.as_submodel_mut(), new_submodel)
68 }
69}
70
71impl Default for Model {
72 fn default() -> Self {
73 Model {
74 submodel: SubModel::new_top_level(),
75 dominance: None,
76 context: Arc::new(RwLock::new(Context::default())),
77 search_order: None,
78 }
79 }
80}
81
82impl Typeable for Model {
83 fn return_type(&self) -> Option<ReturnType> {
84 Some(ReturnType::Bool)
85 }
86}
87
88impl Uniplate for Model {
91 fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
92 let self2 = self.clone();
94 (Tree::Zero, Box::new(move |_| self2.clone()))
95 }
96}
97
98impl Biplate<Expression> for Model {
99 fn biplate(&self) -> (Tree<Expression>, Box<dyn Fn(Tree<Expression>) -> Self>) {
100 let submodel = self.as_submodel();
102 let (expr_tree, expr_ctx) = <SubModel as Biplate<Expression>>::biplate(submodel);
103
104 let dom_tree = match &self.dominance {
106 Some(expr) => Tree::One(expr.clone()),
107 None => Tree::Zero,
108 };
109 let tree = Tree::<Expression>::Many(VecDeque::from([expr_tree, dom_tree]));
110
111 let self2 = self.clone();
112 let ctx = Box::new(move |x| match x {
113 Tree::Many(xs) => {
114 if xs.len() != 2 {
115 panic!("Expected a tree with two children");
116 }
117 let submodel_tree = xs[0].clone();
118 let dom_tree = xs[1].clone();
119
120 let submodel = expr_ctx(submodel_tree);
122 let dominance = match dom_tree {
124 Tree::One(expr) => Some(expr),
125 Tree::Zero => None,
126 _ => panic!("Expected a tree with two children"),
127 };
128
129 let mut self3 = self2.clone();
130 self3.replace_submodel(submodel);
131 self3.dominance = dominance;
132 self3
133 }
134 _ => {
135 panic!("Expected a tree with two children");
136 }
137 });
138
139 (tree, ctx)
140 }
141}
142
143impl Biplate<SubModel> for Model {
144 fn biplate(&self) -> (Tree<SubModel>, Box<dyn Fn(Tree<SubModel>) -> Self>) {
145 let submodel = self.as_submodel().clone();
146
147 let self2 = self.clone();
148 let ctx = Box::new(move |x| {
149 let Tree::One(submodel) = x else {
150 panic!();
151 };
152
153 let mut self3 = self2.clone();
154 self3.replace_submodel(submodel);
155 self3
156 });
157
158 (Tree::One(submodel), ctx)
159 }
160}
161
162impl Display for Model {
163 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164 std::fmt::Display::fmt(self.as_submodel(), f)
165 }
166}
167
168#[derive(Clone, Debug, Serialize, Deserialize)]
174pub struct SerdeModel {
175 #[serde(flatten)]
176 submodel: SubModel,
177 search_order: Option<Vec<Name>>, dominance: Option<Expression>,
179}
180
181impl SerdeModel {
182 pub fn initialise(mut self, context: Arc<RwLock<Context<'static>>>) -> Option<Model> {
186 let mut tables: HashMap<ObjId, Rc<RefCell<SymbolTable>>> = HashMap::new();
195
196 for submodel in self.submodel.universe() {
198 let id = submodel.symbols().id();
199
200 assert_eq!(
202 tables.insert(id, submodel.symbols_ptr_unchecked().clone()),
203 None
204 );
205 }
206
207 for table in tables.clone().into_values() {
209 let mut table_mut = table.borrow_mut();
210 let parent_mut = table_mut.parent_mut_unchecked();
211
212 #[allow(clippy::unwrap_used)]
213 if let Some(parent) = parent_mut {
214 let parent_id = parent.borrow().id();
215
216 *parent = tables.get(&parent_id).unwrap().clone();
217 }
218 }
219
220 let mut all_declarations: HashMap<ObjId, DeclarationPtr> = HashMap::new();
225 for table in tables.values() {
226 for (_, decl) in table.as_ref().borrow().clone().into_iter_local() {
227 let id = decl.id();
228 all_declarations.insert(id, decl);
229 }
230 }
231
232 *self.submodel.constraints_mut() = self.submodel.constraints().transform_bi(&move |decl: DeclarationPtr| {
234 let id = decl.id();
235 all_declarations
236 .get(&id)
237 .unwrap_or_else(|| panic!("A declaration used in the expression tree should exist in the symbol table. The missing declaration has id {id}."))
238 .clone()
239 });
240
241 Some(Model {
242 submodel: self.submodel,
243 dominance: self.dominance,
244 context,
245 search_order: self.search_order,
246 })
247 }
248}
249
250impl From<Model> for SerdeModel {
251 fn from(val: Model) -> Self {
252 SerdeModel {
253 submodel: val.submodel,
254 dominance: val.dominance,
255 search_order: val.search_order,
256 }
257 }
258}
259
260impl Display for SerdeModel {
261 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
262 std::fmt::Display::fmt(&self.submodel, f)
263 }
264}