makepad_live_compiler/
live_expander.rs

1use std::cmp::Ordering;
2
3use {
4    std::rc::Rc,
5    crate::{
6        makepad_live_id::*,
7        makepad_live_tokenizer::{live_error_origin, LiveErrorOrigin},
8        live_ptr::{LiveFileId, LivePtr, LiveFileGeneration},
9        live_error::{LiveError},
10        live_document::{LiveOriginal, LiveExpanded},
11        live_node::{LiveValue, LiveNode, LiveFieldKind, LivePropType},
12        live_node_vec::{LiveNodeSliceApi, LiveNodeVecApi},
13        live_registry::{LiveRegistry, LiveScopeTarget},
14    }
15};
16
17pub struct LiveExpander<'a> {
18    pub live_registry: &'a LiveRegistry,
19    pub in_crate: LiveId,
20    pub in_file_id: LiveFileId,
21    pub errors: &'a mut Vec<LiveError>,
22}
23
24impl<'a> LiveExpander<'a> {
25    pub fn is_baseclass(id: LiveId) -> bool {
26        id == live_id!(struct)
27    }
28    
29    pub fn shift_parent_stack(&self, parents: &mut Vec<(LiveId, usize)>, nodes: &[LiveNode], after_point: usize, old_size: usize, new_size: usize) {
30        for (live_id, item) in parents {
31            if *item > after_point {
32                match old_size.cmp(&new_size) {
33                    Ordering::Less => *item += new_size - old_size,
34                    Ordering::Greater => *item -= old_size - new_size,
35                    _ => (),
36                }
37                if nodes[*item].id != *live_id {
38                    panic!()
39                }
40                if !nodes[*item].is_open() {
41                    panic!()
42                }
43            }
44        }
45    }
46    
47    pub fn expand(&mut self, in_doc: &LiveOriginal, out_doc: &mut LiveExpanded, generation: LiveFileGeneration) {
48        
49        //out_doc.nodes.push(in_doc.nodes[0].clone());
50        out_doc.nodes.push(LiveNode {
51            origin: in_doc.nodes[0].origin,
52            id: LiveId(0),
53            value: LiveValue::Root {id_resolve: Box::default()}
54        });
55        let mut current_parent = vec![(LiveId(0), 0usize)];
56        let mut in_index = 1;
57        let mut lazy_define_value = None;
58        loop {
59            if let Some((node_id, ptr)) = lazy_define_value.take() {
60                if let LiveValue::Root {id_resolve} = &mut out_doc.nodes[0].value {
61                    id_resolve.insert(node_id, ptr);
62                }
63            }
64            
65            if in_index >= in_doc.nodes.len() - 1 {
66                break;
67            }
68            
69            let in_node = &in_doc.nodes[in_index];
70            let in_value = &in_node.value;
71            
72            match in_value {
73                
74                LiveValue::Close => {
75                    current_parent.pop();
76                    in_index += 1;
77                    continue;
78                }
79                LiveValue::Import(live_import) => {
80                    // lets verify it points anywhere
81                    let mut found = false;
82                    let is_glob = in_node.id == LiveId::empty();
83                    if let Some(nodes) = self.live_registry.module_id_to_expanded_nodes(live_import.module_id) {
84                        let file_id = self.live_registry.module_id_to_file_id(live_import.module_id).unwrap();
85                        let mut node_iter = Some(1);
86                        while let Some(index) = node_iter {
87                            if is_glob{
88                                if let LiveValue::Root {id_resolve} = &mut out_doc.nodes[0].value {
89                                    id_resolve.insert(nodes[index].id, LiveScopeTarget::LivePtr(
90                                        self.live_registry.file_id_index_to_live_ptr(file_id, index)
91                                    ));
92                                }
93                                found = true;
94                            }
95                            else if nodes[index].id == live_import.import_id { // its *
96                                // ok so what do we store...
97                                if let LiveValue::Root {id_resolve} = &mut out_doc.nodes[0].value {
98                                    id_resolve.insert(in_node.id , LiveScopeTarget::LivePtr(
99                                        self.live_registry.file_id_index_to_live_ptr(file_id, index)
100                                    ));
101                                }
102                                found = true;
103                            }
104                            node_iter = nodes.next_child(index);
105                        }
106                    }
107                    if !found {
108                        self.errors.push(LiveError {
109                            origin: live_error_origin!(),
110                            span: in_node.origin.token_id().unwrap().into(),
111                            message: format!("Import statement nothing found {}::{} as {}", live_import.module_id, live_import.import_id, in_node.id)
112                        });
113                    }
114                    in_index += 1;
115                    continue;
116                }
117                _ => ()
118            }
119            
120            //// determine node overwrite rules
121            let out_index = match out_doc.nodes.child_or_append_index_by_name(current_parent.last().unwrap().1, in_node.prop()) {
122                Ok(overwrite) => {
123                    if current_parent.len() == 1 {
124                        lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(overwrite)));
125                    }
126                    let out_value = &out_doc.nodes[overwrite].value;
127                    let out_origin = out_doc.nodes[overwrite].origin;
128                    
129                    if in_node.origin.edit_info().is_some() {
130                        self.errors.push(LiveError {
131                            origin: live_error_origin!(),
132                            span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
133                            message: format!("Cannot define edit info after first prop def of {}", in_node.id)
134                        });
135                    }
136                    // object override
137                    if in_value.is_object() && (out_value.is_clone() || out_value.is_class() || out_value.is_object()) { // lets set the target ptr
138                        // do nothing
139                    }
140                    // replacing object types
141                    else if out_value.is_expr() || in_value.is_expr() && out_value.is_single_node() {
142                        // replace range
143                        let next_index = out_doc.nodes.skip_node(overwrite);
144                        
145                        // POTENTIAL SHIFT
146                        let old_len = out_doc.nodes.len();
147                        out_doc.nodes.splice(overwrite..next_index, in_doc.nodes.node_slice(in_index).iter().cloned());
148                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
149                        
150                        in_index = in_doc.nodes.skip_node(in_index);
151                        out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
152                        continue;
153                    }
154                    else if out_value.is_open() && in_value.is_open() { // just replace the whole thing
155                        let next_index = out_doc.nodes.skip_node(overwrite);
156                        let old_len = out_doc.nodes.len();
157                        out_doc.nodes.drain(overwrite + 1..next_index - 1);
158                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
159                        out_doc.nodes[overwrite] = in_node.clone();
160                    }
161                    // replace object with single value
162                    else if out_value.is_open() {
163                        let next_index = out_doc.nodes.skip_node(overwrite);
164                        let old_len = out_doc.nodes.len();
165                        out_doc.nodes.drain(overwrite + 1..next_index);
166                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
167                        out_doc.nodes[overwrite] = in_node.clone();
168                    }
169                    // replace single value with object
170                    else if in_value.is_open() {
171                        let old_len = out_doc.nodes.len();
172                        out_doc.nodes[overwrite] = in_node.clone();
173                        out_doc.nodes.insert(overwrite + 1, in_node.clone());
174                        out_doc.nodes[overwrite + 1].value = LiveValue::Close;
175                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
176                    }
177                    else {
178                        out_doc.nodes[overwrite] = in_node.clone();
179                    };
180                    out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
181                    overwrite
182                }
183                Err(insert_point) => {
184                    if current_parent.len() == 1 {
185                        lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(insert_point)));
186                    }
187                    
188                    // ok so. if we are inserting an expression, just do the whole thing in one go.
189                    if in_node.is_expr() {
190                        // splice it in
191                        let old_len = out_doc.nodes.len();
192                        out_doc.nodes.splice(insert_point..insert_point, in_doc.nodes.node_slice(in_index).iter().cloned());
193                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
194                        
195                        in_index = in_doc.nodes.skip_node(in_index);
196                        continue;
197                    }
198                    
199                    let old_len = out_doc.nodes.len();
200                    out_doc.nodes.insert(insert_point, in_node.clone());
201                    if in_node.is_open() {
202                        out_doc.nodes.insert(insert_point + 1, in_node.clone());
203                        out_doc.nodes[insert_point + 1].value = LiveValue::Close;
204                    }
205                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
206                    
207                    insert_point
208                }
209            };
210            
211            
212            // process stacks
213            match in_value {
214                LiveValue::Dependency(path) => {
215                    if let Some(path) = path.strip_prefix("crate://self/") {
216                        let file_id = in_node.origin.token_id().unwrap().file_id().unwrap();
217                        let mut final_path = self.live_registry.file_id_to_cargo_manifest_path(file_id);
218                        final_path.push('/');
219                        final_path.push_str(path);
220                        out_doc.nodes[out_index].value = LiveValue::Dependency(Rc::new(final_path));
221                    } else if let Some(path) = path.strip_prefix("crate://") {
222                        let mut split = path.split('/');
223                        if let Some(crate_name) = split.next() {
224                            if let Some(mut final_path) = self.live_registry.crate_name_to_cargo_manifest_path(crate_name) {
225                                for next in split {
226                                    final_path.push('/');
227                                    final_path.push_str(next);
228                                }
229                                out_doc.nodes[out_index].value = LiveValue::Dependency(Rc::new(final_path));
230                            }
231                        }
232                    }
233                },
234                LiveValue::Clone(clone) => {
235                    if let Some(target) = self.live_registry.find_scope_target(*clone, &out_doc.nodes) {
236                        match target {
237                            LiveScopeTarget::LocalPtr(local_ptr) => {
238                                
239                                let old_len = out_doc.nodes.len();
240                                
241                                out_doc.nodes.insert_children_from_self(local_ptr, out_index + 1);
242                                self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
243                                
244                                // clone the value and store a parent pointer
245                                if let LiveValue::Class {live_type: old_live_type, ..} = &out_doc.nodes[out_index].value {
246                                    if let LiveValue::Class {live_type, ..} = &out_doc.nodes[local_ptr].value {
247                                        if live_type != old_live_type {
248                                            self.errors.push(LiveError {
249                                                origin: live_error_origin!(),
250                                                span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
251                                                message: format!("Class override with wrong type {}", in_node.id)
252                                            });
253                                        }
254                                    }
255                                }
256                                
257                                out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
258                                if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
259                                    //*class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
260                                    *class_parent = Some(LivePtr {file_id: self.in_file_id, index: local_ptr as u32, generation});
261                                }
262                            }
263                            LiveScopeTarget::LivePtr(live_ptr) => {
264                                let doc = &self.live_registry.live_files[live_ptr.file_id.to_index()].expanded;
265                                
266                                let old_len = out_doc.nodes.len();
267                                out_doc.nodes.insert_children_from_other(live_ptr.node_index(), out_index + 1, &doc.nodes);
268                                self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
269                                
270                                out_doc.nodes[out_index].value = doc.nodes[live_ptr.node_index()].value.clone();
271                                if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
272                                    *class_parent = Some(live_ptr);
273                                    //*class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
274                                }
275                            }
276                        };
277                        //overwrite value, this copies the Class
278                    }
279                    else if !Self::is_baseclass(*clone) { //if !self.live_registry.ignore_no_dsl.contains(clone) {
280                        self.errors.push(LiveError {
281                            origin: live_error_origin!(),
282                            span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
283                            message: format!("Can't find live definition of {} did you forget to call live_design for it?", clone)
284                        });
285                    }
286                    current_parent.push((out_doc.nodes[out_index].id, out_index));
287                },
288                LiveValue::Class {live_type, ..} => {
289                    // store the class context
290                    if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
291                        *class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
292                    }
293                    
294                    let mut insert_point = out_index + 1;
295                    let live_type_info = self.live_registry.live_type_infos.get(live_type).unwrap();
296                    
297                    if let Some(field) = live_type_info.fields.iter().find( | f | f.live_field_kind == LiveFieldKind::Deref) {
298                        if !field.live_type_info.live_ignore {
299                            let live_type_info = &field.live_type_info;
300                            if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&live_type_info.module_id) {
301                                let doc = &self.live_registry.live_files[file_id.to_index()].expanded;
302                                
303                                let mut index = 1;
304                                let mut found = None;
305                                while index < doc.nodes.len() - 1 {
306                                    if let LiveValue::Class {live_type, ..} = &doc.nodes[index].value {
307                                        if *live_type == live_type_info.live_type {
308                                            found = Some(index);
309                                            break
310                                        }
311                                    }
312                                    index = out_doc.nodes.skip_node(index);
313                                }
314                                if let Some(index) = found {
315                                    let old_len = out_doc.nodes.len();
316                                    out_doc.nodes.insert_children_from_other(index, out_index + 1, &doc.nodes);
317                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
318                                }
319                            }
320                        }
321                    }
322                    // else {
323                    for field in &live_type_info.fields {
324                        if field.live_field_kind == LiveFieldKind::Deref {
325                            continue;
326                        }
327                        let lti = &field.live_type_info;
328                        if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&lti.module_id) {
329                            
330                            if *file_id == self.in_file_id { // clone on self
331                                let mut index = 1;
332                                let mut found = None;
333                                while index < out_doc.nodes.len() - 1 {
334                                    if let LiveValue::Class {live_type, ..} = &out_doc.nodes[index].value {
335                                        if *live_type == lti.live_type {
336                                            found = Some(index);
337                                            break
338                                        }
339                                    }
340                                    index = out_doc.nodes.skip_node(index);
341                                }
342                                if let Some(index) = found {
343                                    let node_insert_point = insert_point;
344                                    
345                                    let old_len = out_doc.nodes.len();
346                                    insert_point = out_doc.nodes.insert_node_from_self(index, insert_point);
347                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
348                                    
349                                    out_doc.nodes[node_insert_point].id = field.id;
350                                    out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
351                                    
352                                }
353                                else if !lti.live_ignore {
354                                    self.errors.push(LiveError {
355                                        origin: live_error_origin!(),
356                                        span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
357                                        message: format!("Can't find live definition of {} did you forget to call live_design for it?", lti.type_name)
358                                    });
359                                }
360                            }
361                            else {
362                                let other_nodes = &self.live_registry.live_files[file_id.to_index()].expanded.nodes;
363                                if other_nodes.is_empty() {
364                                    panic!(
365                                        "Dependency order bug finding {}, file {} not registered before {}",
366                                        lti.type_name,
367                                        self.live_registry.file_id_to_file_name(*file_id),
368                                        self.live_registry.file_id_to_file_name(self.in_file_id),
369                                    );
370                                }
371                                let mut index = 1;
372                                let mut found = None;
373                                while index < other_nodes.len() - 1 {
374                                    if let LiveValue::Class {live_type, ..} = &other_nodes[index].value {
375                                        if *live_type == lti.live_type {
376                                            found = Some(index);
377                                            break
378                                        }
379                                    }
380                                    index = other_nodes.skip_node(index);
381                                }
382                                if let Some(index) = found {
383                                    let node_insert_point = insert_point;
384                                    
385                                    let old_len = out_doc.nodes.len();
386                                    insert_point = out_doc.nodes.insert_node_from_other(index, insert_point, other_nodes);
387                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
388                                    
389                                    out_doc.nodes[node_insert_point].id = field.id;
390                                    out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
391                                }
392                                else if !lti.live_ignore && lti.type_name != LiveId(0) {
393                                    self.errors.push(LiveError {
394                                        origin: live_error_origin!(),
395                                        span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
396                                        message: format!("Typename {}, not defined in file where it was expected", lti.type_name)
397                                    });
398                                }
399                            }
400                        }
401                        else if !lti.live_ignore {
402                            self.errors.push(LiveError {
403                                origin: live_error_origin!(),
404                                span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
405                                message: format!("Can't find live definition of {} did you forget to call live_design for it?", lti.type_name)
406                            });
407                        }
408                    }
409                    //}
410                    current_parent.push((out_doc.nodes[out_index].id, out_index));
411                }
412                LiveValue::Expr {..} => {panic!()},
413                LiveValue::Array |
414                LiveValue::TupleEnum {..} |
415                LiveValue::NamedEnum {..} |
416                LiveValue::Object => { // lets check what we are overwriting
417                    current_parent.push((out_doc.nodes[out_index].id, out_index));
418                },
419                LiveValue::DSL {..} => {
420                    //println!("{}",std::mem::size_of::<TextSpan>());
421                },
422                _ => {}
423            }
424            
425            in_index += 1;
426        }
427        out_doc.nodes.push(in_doc.nodes.last().unwrap().clone());
428        
429        // this stores the node index on nodes that don't have a node index
430        for i in 1..out_doc.nodes.len() {
431            if out_doc.nodes[i].value.is_dsl() {
432                out_doc.nodes[i].value.set_dsl_expand_index_if_none(i);
433            }
434            if out_doc.nodes[i].value.is_expr() {
435                out_doc.nodes[i].value.set_expr_expand_index_if_none(i);
436            }
437        }
438    }
439    
440}
441