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(Debug, 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 make_deep_copy(&self) -> Self {
62 let copy = Self(RcMut::new(self.0.borrow().clone_content()));
63 for child in self.borrow().children.iter() {
64 copy.append(child.make_deep_copy());
65 }
66 copy
67 }
68
69 pub fn addr(&self) -> usize {
71 self.0.as_ptr().addr()
72 }
73
74 pub fn is_same_as(&self, other: &Model) -> bool {
76 self.addr() == other.addr()
77 }
78
79 pub fn remove_child(&self, child: &Model) {
81 let mut s = self.0.borrow_mut();
82 s.children.retain(|model| !model.is_same_as(child));
83 }
84
85 pub fn detach(&self) {
87 match self.0.borrow_mut().parent {
88 Some(ref mut parent) => {
89 parent.remove_child(self);
90 }
91 None => return,
92 }
93
94 self.0.borrow_mut().parent = None;
95 }
96
97 pub fn append(&self, model: Model) -> Model {
101 model.borrow_mut().parent = Some(self.clone());
102
103 let mut self_ = self.0.borrow_mut();
104 self_.children.push(model.clone());
105
106 model
107 }
108
109 pub fn append_children(&self, models: Models) -> Self {
113 for model in models.iter() {
114 self.append(model.clone());
115 }
116 self.clone()
117 }
118
119 pub fn boolean_op(self, op: BooleanOp, other: Model) -> Model {
121 assert!(self != other, "lhs and rhs must be distinct.");
122 Models::from(vec![self.clone(), other]).boolean_op(op)
123 }
124
125 pub fn replace_input_placeholders(&self, input_model: &Model) -> Self {
127 self.descendants().for_each(|model| {
128 let mut model_ = model.borrow_mut();
129 if model_.id.is_none() && matches!(model_.element.value, Element::InputPlaceholder) {
130 let mut input_model_ = input_model.borrow_mut();
131 input_model_.parent = Some(self.clone());
132 *model_ = input_model_.clone_content();
133 model_.children = input_model_.children.clone();
134 }
135 });
136 self.clone()
137 }
138
139 pub fn deduce_output_type(&self) -> OutputType {
141 let self_ = self.borrow();
142 let mut output_type = self_.element.output_type();
143 if output_type == OutputType::NotDetermined {
144 let children = &self_.children;
145 output_type = children.deduce_output_type();
146 }
147
148 output_type
149 }
150
151 pub fn into_group(&self) -> Option<Model> {
156 let children = &self.borrow().children;
157 if children.len() != 1 {
158 return None;
159 }
160
161 children.first().and_then(|n| {
162 if let Element::Group = *n.0.borrow().element {
163 Some(n.clone())
164 } else {
165 None
166 }
167 })
168 }
169
170 pub fn signature(&self) -> String {
172 format!(
173 "{id}{element}{is_root} ->",
174 id = match &self.borrow().id {
175 Some(id) => format!("{id}: "),
176 None => String::new(),
177 },
178 element = *self.borrow().element,
179 is_root = if self.parents().next().is_some() {
180 ""
181 } else {
182 " (root)"
183 }
184 )
185 }
186}
187
188impl Model {
190 pub fn descendants(&self) -> Descendants {
194 Descendants::new(self.clone())
195 }
196
197 pub fn source_file_descendants(&self) -> SourceFileDescendants {
199 SourceFileDescendants::new(self.clone())
200 }
201
202 pub fn parents(&self) -> Parents {
204 Parents::new(self.clone())
205 }
206
207 pub fn ancestors(&self) -> Ancestors {
209 Ancestors::new(self.clone())
210 }
211
212 pub fn get_property(&self, id: &Identifier) -> Option<Value> {
214 self.borrow().element.get_property(id).cloned()
215 }
216
217 pub fn set_property(&mut self, id: Identifier, value: Value) -> Option<Value> {
219 self.borrow_mut().element.set_property(id, value)
220 }
221
222 pub fn add_property(&self, id: Identifier, value: Value) {
224 self.borrow_mut()
225 .element
226 .add_properties([(id, value)].into_iter().collect())
227 }
228}
229
230impl AttributesAccess for Model {
231 fn get_attributes_by_id(&self, id: &Identifier) -> Vec<Attribute> {
232 self.borrow().attributes.get_attributes_by_id(id)
233 }
234}
235
236impl PartialEq for Model {
237 fn eq(&self, other: &Self) -> bool {
238 self.addr() == other.addr()
239 }
240}
241
242impl SrcReferrer for Model {
243 fn src_ref(&self) -> crate::src_ref::SrcRef {
244 self.borrow().src_ref()
245 }
246}
247
248impl std::fmt::Display for Model {
259 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260 write!(
261 f,
262 "{signature}",
263 signature = crate::shorten!(self.signature())
264 )
265 }
266}
267
268impl TreeDisplay for Model {
269 fn tree_print(
270 &self,
271 f: &mut std::fmt::Formatter,
272 mut tree_state: TreeState,
273 ) -> std::fmt::Result {
274 let signature = crate::shorten!(self.signature(), tree_state.shorten);
275 let self_ = self.borrow();
276 if let Some(output) = &self_.output {
277 writeln!(f, "{:tree_state$}{signature} {output}", "",)?;
278 } else {
279 writeln!(f, "{:tree_state$}{signature}", "",)?;
280 }
281 tree_state.indent();
282 if let Some(props) = self_.get_properties() {
283 props.tree_print(f, tree_state)?;
284 }
285 self_.attributes.tree_print(f, tree_state)?;
286 self_.children.tree_print(f, tree_state)
287 }
288}
289
290impl WriteToFile for Model {}