microcad_lang/model/
mod.rs1pub mod attribute;
7pub mod builder;
8pub mod creator;
9pub mod element;
10mod inner;
11pub mod iter;
12pub mod models;
13pub mod operation;
14pub mod output_type;
15pub mod properties;
16pub mod workpiece;
17
18pub use attribute::*;
19pub use builder::*;
20pub use creator::*;
21pub use element::*;
22pub use inner::*;
23pub use iter::*;
24pub use models::*;
25pub use operation::*;
26pub use output_type::*;
27pub use properties::*;
28pub use workpiece::*;
29
30use derive_more::{Deref, DerefMut};
31
32use microcad_core::{BooleanOp, Integer};
33
34use crate::{
35 diag::WriteToFile,
36 rc::RcMut,
37 render::{ComputedHash, HashId},
38 src_ref::SrcReferrer,
39 syntax::Identifier,
40 tree_display::*,
41 value::Value,
42};
43
44#[derive(Clone, Deref, DerefMut)]
46pub struct Model(RcMut<ModelInner>);
47
48impl Model {
49 pub fn new(inner: RcMut<ModelInner>) -> Self {
51 Self(inner)
52 }
53
54 pub fn depth(&self) -> usize {
56 self.parents().count()
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.borrow().is_empty()
62 }
63
64 pub fn has_no_output(&self) -> bool {
66 let self_ = self.borrow();
67 match self_.element.value {
68 Element::BuiltinWorkpiece(_) | Element::InputPlaceholder => false,
69 _ => self_.is_empty(),
70 }
71 }
72
73 pub fn make_deep_copy(&self) -> Self {
76 let copy = Self(RcMut::new(self.0.borrow().clone_content()));
77 for child in self.borrow().children.iter() {
78 copy.append(child.make_deep_copy());
79 }
80 copy
81 }
82
83 pub fn addr(&self) -> usize {
85 self.0.as_ptr().addr()
86 }
87
88 pub fn is_same_as(&self, other: &Model) -> bool {
90 self.addr() == other.addr()
91 }
92
93 pub fn remove_child(&self, child: &Model) {
95 let mut s = self.0.borrow_mut();
96 s.children.retain(|model| !model.is_same_as(child));
97 }
98
99 pub fn append(&self, model: Model) -> Model {
103 model.borrow_mut().parent = Some(self.clone());
104
105 let mut self_ = self.0.borrow_mut();
106 self_.children.push(model.clone());
107
108 model
109 }
110
111 pub fn append_children(&self, models: Models) -> Self {
115 for model in models.iter() {
116 self.append(model.clone());
117 }
118 self.clone()
119 }
120
121 pub fn boolean_op(self, op: BooleanOp, other: Model) -> Model {
123 assert!(self != other, "lhs and rhs must be distinct.");
124 Models::from(vec![self.clone(), other]).boolean_op(op)
125 }
126
127 pub fn multiply(&self, n: Integer) -> Vec<Model> {
129 (0..n).map(|_| self.make_deep_copy()).collect()
130 }
131
132 pub fn replace_input_placeholders(&self, input_model: &Model) -> Self {
134 self.descendants().for_each(|model| {
135 let mut model_ = model.borrow_mut();
136 if model_.id.is_none() && matches!(model_.element.value, Element::InputPlaceholder) {
137 let input_model_ = input_model.borrow_mut();
138 *model_ = input_model_.clone_content();
139 model_.parent = Some(self.clone());
140 model_.children = input_model_.children.clone();
141 }
142 });
143 self.clone()
144 }
145
146 pub fn deduce_output_type(&self) -> OutputType {
148 let self_ = self.borrow();
149 let mut output_type = self_.element.output_type();
150 if output_type == OutputType::NotDetermined {
151 let children = &self_.children;
152 output_type = children.deduce_output_type();
153 }
154
155 output_type
156 }
157
158 pub fn render_output_type(&self) -> OutputType {
160 let self_ = self.borrow();
161 self_
162 .output
163 .as_ref()
164 .map(|output| output.output_type)
165 .unwrap_or(OutputType::InvalidMixed)
166 }
167
168 pub fn into_group(&self) -> Option<Model> {
173 self.borrow()
174 .children
175 .single_model()
176 .filter(|model| matches!(model.borrow().element.value, Element::Group))
177 }
178
179 pub fn set_id(&self, id: Identifier) {
183 self.borrow_mut().id = Some(id);
184 }
185}
186
187impl Model {
189 pub fn descendants(&self) -> Descendants {
193 Descendants::new(self.clone())
194 }
195
196 pub fn multiplicity_descendants(&self) -> MultiplicityDescendants {
198 MultiplicityDescendants::new(self.clone())
199 }
200
201 pub fn source_file_descendants(&self) -> SourceFileDescendants {
203 SourceFileDescendants::new(self.clone())
204 }
205
206 pub fn parents(&self) -> Parents {
208 Parents::new(self.clone())
209 }
210
211 pub fn ancestors(&self) -> Ancestors {
213 Ancestors::new(self.clone())
214 }
215
216 pub fn get_property(&self, id: &Identifier) -> Option<Value> {
218 self.borrow().element.get_property(id).cloned()
219 }
220
221 pub fn set_property(&mut self, id: Identifier, value: Value) -> Option<Value> {
223 self.borrow_mut().element.set_property(id, value)
224 }
225
226 pub fn add_property(&self, id: Identifier, value: Value) {
228 self.borrow_mut()
229 .element
230 .add_properties([(id, value)].into_iter().collect())
231 }
232}
233
234impl AttributesAccess for Model {
235 fn get_attributes_by_id(&self, id: &Identifier) -> Vec<Attribute> {
236 self.borrow().attributes.get_attributes_by_id(id)
237 }
238}
239
240impl PartialEq for Model {
241 fn eq(&self, other: &Self) -> bool {
242 self.addr() == other.addr()
243 }
244}
245
246impl SrcReferrer for Model {
247 fn src_ref(&self) -> crate::src_ref::SrcRef {
248 self.borrow().src_ref()
249 }
250}
251
252impl std::fmt::Display for Model {
253 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 write!(
255 f,
256 "{id}{element}{is_root} ->",
257 id = match &self.borrow().id {
258 Some(id) => format!("{id}: "),
259 None => String::new(),
260 },
261 element = *self.borrow().element,
262 is_root = if self.parents().next().is_some() {
263 ""
264 } else {
265 " (root)"
266 }
267 )
268 }
269}
270
271impl std::fmt::Debug for Model {
272 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
273 write!(
274 f,
275 "{}",
276 crate::shorten!(format!(
277 "{id}{element}{is_root} ->",
278 id = match &self.borrow().id {
279 Some(id) => format!("{id:?}: "),
280 None => String::new(),
281 },
282 element = *self.borrow().element,
283 is_root = if self.parents().next().is_some() {
284 ""
285 } else {
286 " (root)"
287 }
288 ))
289 )
290 }
291}
292
293impl TreeDisplay for Model {
294 fn tree_print(
295 &self,
296 f: &mut std::fmt::Formatter,
297 mut tree_state: TreeState,
298 ) -> std::fmt::Result {
299 let signature = if tree_state.debug {
300 format!("{self:?}")
301 } else {
302 self.to_string()
303 };
304 let self_ = self.borrow();
305 if let Some(output) = &self_.output {
306 writeln!(f, "{:tree_state$}{signature} {output}", "",)?;
307 } else {
308 writeln!(f, "{:tree_state$}{signature}", "",)?;
309 }
310 tree_state.indent();
311 if let Some(props) = self_.get_properties() {
312 props.tree_print(f, tree_state)?;
313 }
314 self_.attributes.tree_print(f, tree_state)?;
315 self_.children.tree_print(f, tree_state)
316 }
317}
318
319impl WriteToFile for Model {}
320
321impl std::hash::Hash for Model {
322 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
323 let self_ = self.borrow();
324 self_.element().hash(state);
325 self_.children().for_each(|child| child.hash(state));
326 }
327}
328
329impl ComputedHash for Model {
330 fn computed_hash(&self) -> HashId {
331 let self_ = self.borrow();
332 self_.output().computed_hash()
333 }
334}