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;
33
34use crate::{
35 diag::WriteToFile, rc::RcMut, src_ref::SrcReferrer, syntax::Identifier, tree_display::*,
36 value::Value,
37};
38
39#[derive(Clone, Deref, DerefMut)]
41pub struct Model(RcMut<ModelInner>);
42
43impl Model {
44 pub fn new(inner: RcMut<ModelInner>) -> Self {
46 Self(inner)
47 }
48
49 pub fn depth(&self) -> usize {
51 self.parents().count()
52 }
53
54 pub fn is_operation(&self) -> bool {
56 self.borrow().element.is_operation()
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.borrow().is_empty()
62 }
63
64 pub fn is_empty_model(&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 detach(&self) {
101 match self.0.borrow_mut().parent {
102 Some(ref mut parent) => {
103 parent.remove_child(self);
104 }
105 None => return,
106 }
107
108 self.0.borrow_mut().parent = None;
109 }
110
111 pub fn append(&self, model: Model) -> Model {
115 model.borrow_mut().parent = Some(self.clone());
116
117 let mut self_ = self.0.borrow_mut();
118 self_.children.push(model.clone());
119
120 model
121 }
122
123 pub fn append_children(&self, models: Models) -> Self {
127 for model in models.iter() {
128 self.append(model.clone());
129 }
130 self.clone()
131 }
132
133 pub fn boolean_op(self, op: BooleanOp, other: Model) -> Model {
135 assert!(self != other, "lhs and rhs must be distinct.");
136 Models::from(vec![self.clone(), other]).boolean_op(op)
137 }
138
139 pub fn replace_input_placeholders(&self, input_model: &Model) -> Self {
141 self.descendants().for_each(|model| {
142 let mut model_ = model.borrow_mut();
143 if model_.id.is_none() && matches!(model_.element.value, Element::InputPlaceholder) {
144 let mut input_model_ = input_model.borrow_mut();
145 input_model_.parent = Some(self.clone());
146 *model_ = input_model_.clone_content();
147 model_.children = input_model_.children.clone();
148 }
149 });
150 self.clone()
151 }
152
153 pub fn deduce_output_type(&self) -> OutputType {
155 let self_ = self.borrow();
156 let mut output_type = self_.element.output_type();
157 if output_type == OutputType::NotDetermined {
158 let children = &self_.children;
159 output_type = children.deduce_output_type();
160 }
161
162 output_type
163 }
164
165 pub fn into_group(&self) -> Option<Model> {
170 let children = &self.borrow().children;
171 if children.len() != 1 {
172 return None;
173 }
174
175 children.first().and_then(|n| {
176 if let Element::Group = *n.0.borrow().element {
177 Some(n.clone())
178 } else {
179 None
180 }
181 })
182 }
183}
184
185impl Model {
187 pub fn descendants(&self) -> Descendants {
191 Descendants::new(self.clone())
192 }
193
194 pub fn source_file_descendants(&self) -> SourceFileDescendants {
196 SourceFileDescendants::new(self.clone())
197 }
198
199 pub fn parents(&self) -> Parents {
201 Parents::new(self.clone())
202 }
203
204 pub fn ancestors(&self) -> Ancestors {
206 Ancestors::new(self.clone())
207 }
208
209 pub fn get_property(&self, id: &Identifier) -> Option<Value> {
211 self.borrow().element.get_property(id).cloned()
212 }
213
214 pub fn set_property(&mut self, id: Identifier, value: Value) -> Option<Value> {
216 self.borrow_mut().element.set_property(id, value)
217 }
218
219 pub fn add_property(&self, id: Identifier, value: Value) {
221 self.borrow_mut()
222 .element
223 .add_properties([(id, value)].into_iter().collect())
224 }
225}
226
227impl AttributesAccess for Model {
228 fn get_attributes_by_id(&self, id: &Identifier) -> Vec<Attribute> {
229 self.borrow().attributes.get_attributes_by_id(id)
230 }
231}
232
233impl PartialEq for Model {
234 fn eq(&self, other: &Self) -> bool {
235 self.addr() == other.addr()
236 }
237}
238
239impl SrcReferrer for Model {
240 fn src_ref(&self) -> crate::src_ref::SrcRef {
241 self.borrow().src_ref()
242 }
243}
244
245impl std::fmt::Display for Model {
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 write!(
248 f,
249 "{id}{element}{is_root} ->",
250 id = match &self.borrow().id {
251 Some(id) => format!("{id}: "),
252 None => String::new(),
253 },
254 element = *self.borrow().element,
255 is_root = if self.parents().next().is_some() {
256 ""
257 } else {
258 " (root)"
259 }
260 )
261 }
262}
263
264impl std::fmt::Debug for Model {
265 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266 write!(
267 f,
268 "{}",
269 crate::shorten!(format!(
270 "{id}{element}{is_root} ->",
271 id = match &self.borrow().id {
272 Some(id) => format!("{id:?}: "),
273 None => String::new(),
274 },
275 element = *self.borrow().element,
276 is_root = if self.parents().next().is_some() {
277 ""
278 } else {
279 " (root)"
280 }
281 ))
282 )
283 }
284}
285
286impl TreeDisplay for Model {
287 fn tree_print(
288 &self,
289 f: &mut std::fmt::Formatter,
290 mut tree_state: TreeState,
291 ) -> std::fmt::Result {
292 let signature = if tree_state.debug {
293 format!("{self:?}")
294 } else {
295 self.to_string()
296 };
297 let self_ = self.borrow();
298 if let Some(output) = &self_.output {
299 writeln!(f, "{:tree_state$}{signature} {output}", "",)?;
300 } else {
301 writeln!(f, "{:tree_state$}{signature}", "",)?;
302 }
303 tree_state.indent();
304 if let Some(props) = self_.get_properties() {
305 props.tree_print(f, tree_state)?;
306 }
307 self_.attributes.tree_print(f, tree_state)?;
308 self_.children.tree_print(f, tree_state)
309 }
310}
311
312impl WriteToFile for Model {}