conjure_core/ast/
model.rs
1use std::cell::RefCell;
2use std::collections::{HashMap, VecDeque};
3use std::fmt::{Debug, Display};
4use std::rc::Rc;
5use std::sync::{Arc, RwLock};
6
7use derivative::Derivative;
8use serde::{Deserialize, Serialize};
9use uniplate::{Biplate, Tree, Uniplate};
10
11use crate::ast::Expression;
12use crate::context::Context;
13
14use super::serde::{HasId, ObjId};
15use super::types::Typeable;
16use super::{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) -> Option<ReturnType> {
83 Some(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(self, context: Arc<RwLock<Context<'static>>>) -> Option<Model> {
183 let mut tables: HashMap<ObjId, Rc<RefCell<SymbolTable>>> = HashMap::new();
192
193 for submodel in self.submodel.universe() {
195 let id = submodel.symbols().id();
196
197 assert_eq!(
199 tables.insert(id, submodel.symbols_ptr_unchecked().clone()),
200 None
201 );
202 }
203
204 for table in tables.clone().into_values() {
206 let mut table_mut = table.borrow_mut();
207 let parent_mut = table_mut.parent_mut_unchecked();
208
209 #[allow(clippy::unwrap_used)]
210 if let Some(parent) = parent_mut {
211 let parent_id = parent.borrow().id();
212
213 *parent = tables.get(&parent_id).unwrap().clone();
214 }
215 }
216
217 Some(Model {
218 submodel: self.submodel,
219 dominance: self.dominance,
220 context,
221 search_order: self.search_order,
222 })
223 }
224}
225
226impl From<Model> for SerdeModel {
227 fn from(val: Model) -> Self {
228 SerdeModel {
229 submodel: val.submodel,
230 dominance: val.dominance,
231 search_order: val.search_order,
232 }
233 }
234}
235
236impl Display for SerdeModel {
237 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 std::fmt::Display::fmt(&self.submodel, f)
239 }
240}