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 is_empty(&self) -> bool {
56 self.borrow().is_empty()
57 }
58
59 pub fn has_no_output(&self) -> bool {
61 let self_ = self.borrow();
62 match self_.element.value {
63 Element::BuiltinWorkpiece(_) | Element::InputPlaceholder => false,
64 _ => self_.is_empty(),
65 }
66 }
67
68 pub fn make_deep_copy(&self) -> Self {
70 let copy = Self(RcMut::new(self.0.borrow().clone_content()));
71 for child in self.borrow().children.iter() {
72 copy.append(child.make_deep_copy());
73 }
74 copy
75 }
76
77 pub fn addr(&self) -> usize {
79 self.0.as_ptr().addr()
80 }
81
82 pub fn append(&self, model: Model) -> Model {
86 model.borrow_mut().parent = Some(self.clone());
87
88 let mut self_ = self.0.borrow_mut();
89 self_.children.push(model.clone());
90
91 model
92 }
93
94 pub fn append_children(&self, models: Models) -> Self {
98 for model in models.iter() {
99 self.append(model.clone());
100 }
101 self.clone()
102 }
103
104 pub fn boolean_op(self, op: BooleanOp, other: Model) -> Model {
106 assert!(self != other, "lhs and rhs must be distinct.");
107 Models::from(vec![self.clone(), other]).boolean_op(op)
108 }
109
110 pub fn multiply(&self, n: Integer) -> Vec<Model> {
112 (0..n).map(|_| self.make_deep_copy()).collect()
113 }
114
115 pub fn replace_input_placeholders(&self, input_model: &Model) -> Self {
117 self.descendants().for_each(|model| {
118 let mut model_ = model.borrow_mut();
119 if model_.id.is_none() && matches!(model_.element.value, Element::InputPlaceholder) {
120 let input_model_ = input_model.borrow_mut();
121 *model_ = input_model_.clone_content();
122 model_.parent = Some(self.clone());
123 model_.children = input_model_.children.clone();
124 }
125 });
126 self.clone()
127 }
128
129 pub fn deduce_output_type(&self) -> OutputType {
131 let self_ = self.borrow();
132 let mut output_type = self_.element.output_type();
133 if output_type == OutputType::NotDetermined {
134 let children = &self_.children;
135 output_type = children.deduce_output_type();
136 }
137
138 output_type
139 }
140
141 pub fn render_output_type(&self) -> OutputType {
143 let self_ = self.borrow();
144 self_
145 .output
146 .as_ref()
147 .map(|output| output.output_type)
148 .unwrap_or(OutputType::InvalidMixed)
149 }
150
151 pub fn into_group(&self) -> Option<Model> {
156 self.borrow()
157 .children
158 .single_model()
159 .filter(|model| matches!(model.borrow().element.value, Element::Group))
160 }
161
162 pub fn set_id(&self, id: Identifier) {
166 self.borrow_mut().id = Some(id);
167 }
168}
169
170impl Model {
172 pub fn descendants(&self) -> Descendants {
176 Descendants::new(self.clone())
177 }
178
179 pub fn multiplicity_descendants(&self) -> MultiplicityDescendants {
181 MultiplicityDescendants::new(self.clone())
182 }
183
184 pub fn source_file_descendants(&self) -> SourceFileDescendants {
186 SourceFileDescendants::new(self.clone())
187 }
188
189 pub fn parents(&self) -> Parents {
191 Parents::new(self.clone())
192 }
193
194 pub fn ancestors(&self) -> Ancestors {
196 Ancestors::new(self.clone())
197 }
198
199 pub fn get_property(&self, id: &Identifier) -> Option<Value> {
201 self.borrow().element.get_property(id).cloned()
202 }
203
204 pub fn set_property(&mut self, id: Identifier, value: Value) -> Option<Value> {
206 self.borrow_mut().element.set_property(id, value)
207 }
208
209 pub fn add_property(&self, id: Identifier, value: Value) {
211 self.borrow_mut()
212 .element
213 .add_properties([(id, value)].into_iter().collect())
214 }
215}
216
217impl AttributesAccess for Model {
218 fn get_attributes_by_id(&self, id: &Identifier) -> Vec<Attribute> {
219 self.borrow().attributes.get_attributes_by_id(id)
220 }
221}
222
223impl PartialEq for Model {
224 fn eq(&self, other: &Self) -> bool {
225 self.addr() == other.addr()
226 }
227}
228
229impl SrcReferrer for Model {
230 fn src_ref(&self) -> crate::src_ref::SrcRef {
231 self.borrow().src_ref()
232 }
233}
234
235impl std::fmt::Display for Model {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 write!(
238 f,
239 "{id}{element}{is_root} ->",
240 id = match &self.borrow().id {
241 Some(id) => format!("{id}: "),
242 None => String::new(),
243 },
244 element = *self.borrow().element,
245 is_root = if self.parents().next().is_some() {
246 ""
247 } else {
248 " (root)"
249 }
250 )
251 }
252}
253
254impl std::fmt::Debug for Model {
255 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256 write!(
257 f,
258 "{}",
259 crate::shorten!(format!(
260 "{id}{element}{is_root} ->",
261 id = match &self.borrow().id {
262 Some(id) => format!("{id:?}: "),
263 None => String::new(),
264 },
265 element = *self.borrow().element,
266 is_root = if self.parents().next().is_some() {
267 ""
268 } else {
269 " (root)"
270 }
271 ))
272 )
273 }
274}
275
276impl TreeDisplay for Model {
277 fn tree_print(
278 &self,
279 f: &mut std::fmt::Formatter,
280 mut tree_state: TreeState,
281 ) -> std::fmt::Result {
282 let signature = if tree_state.debug {
283 format!("{self:?}")
284 } else {
285 self.to_string()
286 };
287 let self_ = self.borrow();
288 if let Some(output) = &self_.output {
289 writeln!(f, "{:tree_state$}{signature} {output}", "",)?;
290 } else {
291 writeln!(f, "{:tree_state$}{signature}", "",)?;
292 }
293 tree_state.indent();
294 if let Some(props) = self_.get_properties() {
295 props.tree_print(f, tree_state)?;
296 }
297 self_.attributes.tree_print(f, tree_state)?;
298 self_.children.tree_print(f, tree_state)
299 }
300}
301
302impl WriteToFile for Model {}
303
304impl std::hash::Hash for Model {
305 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
306 let self_ = self.borrow();
307 self_.element().hash(state);
308 self_.children().for_each(|child| child.hash(state));
309 }
310}
311
312impl ComputedHash for Model {
313 fn computed_hash(&self) -> HashId {
314 let self_ = self.borrow();
315 self_.output().computed_hash()
316 }
317}