makepad_live_compiler/
live_expander.rs

1use std::cmp::Ordering;
2
3use {
4    std::sync::Arc,
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_eval::live_eval_value,
11        live_document::{LiveOriginal, LiveExpanded},
12        live_node::{LiveFont, LiveValue, LiveNode, LiveFieldKind, LivePropType, LiveNodeRoot},
13        live_node_vec::{LiveNodeSliceApi, LiveNodeVecApi},
14        live_registry::{LiveRegistry, LiveScopeTarget},
15    }
16};
17
18pub struct LiveExpander<'a> {
19    pub live_registry: &'a LiveRegistry,
20    pub in_crate: LiveId,
21    pub in_file_id: LiveFileId,
22    pub errors: &'a mut Vec<LiveError>,
23}
24
25impl<'a> LiveExpander<'a> {
26    pub fn is_baseclass(id: LiveId) -> bool {
27        id == live_id!(struct)
28    }
29    
30    pub fn shift_parent_stack(&self, parents: &mut Vec<(LiveId, usize)>, nodes: &[LiveNode], after_point: usize, old_size: usize, new_size: usize) {
31        for (live_id, item) in parents {
32            if *item > after_point {
33                match old_size.cmp(&new_size) {
34                    Ordering::Less => *item += new_size - old_size,
35                    Ordering::Greater => *item -= old_size - new_size,
36                    _ => (),
37                }
38                if nodes[*item].id != *live_id {
39                    panic!()
40                }
41                if !nodes[*item].is_open() {
42                    panic!()
43                }
44            }
45        }
46    }
47    
48    fn resolve_path(&self, file_id:LiveFileId, path:&str)->Option<Arc<String>>{
49        if let Some(path) = path.strip_prefix("crate://self/") {
50            let mut final_path = self.live_registry.file_id_to_cargo_manifest_path(file_id);
51            final_path.push('/');
52            final_path.push_str(path);
53            return Some(Arc::new(final_path))
54        } else if let Some(path) = path.strip_prefix("crate://") {
55            let mut split = path.split('/');
56            if let Some(crate_name) = split.next() {
57                if let Some(mut final_path) = self.live_registry.crate_name_to_cargo_manifest_path(crate_name) {
58                    for next in split {
59                        final_path.push('/');
60                        final_path.push_str(next);
61                    }
62                    return Some(Arc::new(final_path))
63                }
64            }
65        }
66        None
67    }
68    
69    pub fn expand(&mut self, in_doc: &LiveOriginal, out_doc: &mut LiveExpanded, generation: LiveFileGeneration) {
70        
71        let mut root = LiveNodeRoot::default();
72        
73        // lets build up the final local pointers from our imports
74        let resolved_imports = in_doc.resolved_imports.as_ref().unwrap();
75        for (ident, file_id) in resolved_imports{
76            let other = &self.live_registry.live_files[file_id.to_index()].expanded;
77            if let LiveValue::Root(root2) = &other.nodes[0].value {
78                let index = root2.exports.get(&ident).unwrap();
79                root.locals.insert(
80                    *ident,
81                    LiveScopeTarget::LivePtr(
82                        self.live_registry.file_id_index_to_live_ptr(*file_id, *index)
83                    )
84                );
85            }
86        }
87        
88        //out_doc.nodes.push(in_doc.nodes[0].clone());
89        out_doc.nodes.push(LiveNode {
90            origin: in_doc.nodes[0].origin,
91            id: LiveId(0),
92            value: LiveValue::Root(Box::new(root))
93        });
94        // alright lets build the locals from the import table
95        
96        let mut current_parent = vec![(LiveId(0), 0usize)];
97        let mut in_index = 1;
98        let mut lazy_define_value = None;
99        loop {
100            
101            if let Some((node_id, ptr)) = lazy_define_value.take() {
102                if let LiveValue::Root(root) = &mut out_doc.nodes[0].value {
103                    root.locals.insert(node_id, ptr);
104                }
105            }
106            
107            if in_index >= in_doc.nodes.len() - 1 {
108                break;
109            }
110            
111            let in_node = &in_doc.nodes[in_index];
112            let in_value = &in_node.value;
113            
114            match in_value {
115                
116                LiveValue::Close => {
117                    // inherit the close node origin so we can properly map to the original text range
118                    let close_index = out_doc.nodes.skip_node(current_parent.last().unwrap().1) - 1;
119                    let out_close = &mut out_doc.nodes[close_index];
120                    let mut origin = in_node.origin;
121                    origin.inherit_origin(out_close.origin);
122                    out_close.origin = origin;
123                    
124                    current_parent.pop();
125                    in_index += 1;
126                    continue;
127                }
128                LiveValue::Import(_live_import) => {
129                    /*
130                    // lets verify it points anywhere
131                    let mut found = false;
132                    let is_glob = in_node.id == LiveId::empty();
133                    
134                    if let Some(nodes) = self.live_registry.module_id_to_expanded_nodes(live_import.module_id) {
135                        let file_id = self.live_registry.module_id_to_file_id(live_import.module_id).unwrap();
136                        let mut node_iter = Some(1);
137                        while let Some(index) = node_iter {
138                            if is_glob{// its *
139                                if let LiveValue::Root(root) = &mut out_doc.nodes[0].value {
140                                    root.locals.insert(nodes[index].id, LiveScopeTarget::LivePtr(
141                                        self.live_registry.file_id_index_to_live_ptr(file_id, index)
142                                    ));
143                                }
144                                found = true;
145                            }
146                            else if nodes[index].id == live_import.import_id { 
147                                // ok so what do we store...
148                                if let LiveValue::Root(root) = &mut out_doc.nodes[0].value {
149                                    root.locals.insert(in_node.id , LiveScopeTarget::LivePtr(
150                                        self.live_registry.file_id_index_to_live_ptr(file_id, index)
151                                    ));
152                                }
153                                found = true;
154                            }
155                            node_iter = nodes.next_child(index);
156                        }
157                    }
158                    if !found {
159                        self.errors.push(LiveError {
160                            origin: live_error_origin!(),
161                            span: in_node.origin.token_id().unwrap().into(),
162                            message: format!("Import statement nothing found {}::{} as {}", live_import.module_id, live_import.import_id, in_node.id)
163                        });
164                    }*/
165                    in_index += 1;
166                    continue;
167                }
168                _ => ()
169            }
170            
171            //// determine node overwrite rules
172            let out_index = match out_doc.nodes.child_or_append_index_by_name(current_parent.last().unwrap().1, in_node.prop()) {
173                Ok(overwrite) => {
174                    if current_parent.len() == 1 {
175                        lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(overwrite)));
176                    }
177                    let out_value = &out_doc.nodes[overwrite].value;
178                    let out_origin = out_doc.nodes[overwrite].origin;
179                    
180                    if in_node.origin.edit_info().is_some() {
181                        self.errors.push(LiveError {
182                            origin: live_error_origin!(),
183                            span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
184                            message: format!("Cannot define edit info after first prop def of {}", in_node.id)
185                        });
186                    }
187                    
188                    if out_value.is_expr(){
189                        panic!("No expressions expected in out_value")
190                    }
191                    // object override
192                    if in_value.is_object() && (out_value.is_clone() || out_value.is_class() || out_value.is_object()) { // lets set the target ptr
193                        // do nothing
194                    }
195                    else if in_value.is_expr(){
196                        
197                        if !out_value.is_single_node(){
198                            panic!("overriding is_expr on not is_single_node in file {:?}", self.live_registry.file_id_to_file_name(self.in_file_id));
199                        }
200                        // lets expand it and output a single LiveValue instead
201                        let mut index = in_index;
202                        match live_eval_value(&self.live_registry, &mut index, &in_doc.nodes, &out_doc.nodes){
203                            Ok(v)=>{
204                                out_doc.nodes[overwrite] = in_node.clone();
205                                out_doc.nodes[overwrite].value = v;
206                            }
207                            Err(e)=>{ // output a None 
208                                out_doc.nodes[overwrite] = in_node.clone();
209                                out_doc.nodes[overwrite].value = LiveValue::None;
210                                self.errors.push(e);
211                            }
212                        }
213                        // lets skip the nodes
214                        out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
215                        in_index = in_doc.nodes.skip_node(in_index);
216                        continue;
217                    }
218                    else if out_value.is_open() && in_value.is_open() { // just replace the whole thing
219                        let next_index = out_doc.nodes.skip_node(overwrite);
220                        let old_len = out_doc.nodes.len();
221                        out_doc.nodes.drain(overwrite + 1..next_index - 1);
222                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
223                        out_doc.nodes[overwrite] = in_node.clone();
224                    }
225                    // replace object with single value
226                    else if out_value.is_open() {
227                        let next_index = out_doc.nodes.skip_node(overwrite);
228                        let old_len = out_doc.nodes.len();
229                        out_doc.nodes.drain(overwrite + 1..next_index);
230                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
231                        out_doc.nodes[overwrite] = in_node.clone();
232                    }
233                    // replace single value with object
234                    else if in_value.is_open() {
235                        let old_len = out_doc.nodes.len();
236                        out_doc.nodes[overwrite] = in_node.clone();
237                        out_doc.nodes.insert(overwrite + 1, in_node.clone());
238                        out_doc.nodes[overwrite + 1].value = LiveValue::Close;
239                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
240                    }
241                    else {
242                        out_doc.nodes[overwrite] = in_node.clone();
243                    };
244                    out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
245                    overwrite
246                }
247                Err(insert_point) => {
248                    if current_parent.len() == 1 {
249                        lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(insert_point)));
250                    }
251                    
252                    // ok so. if we are inserting an expression, just do the whole thing in one go.
253                    if in_node.is_expr() {
254                        
255                        // lets eval the expression
256                        let mut index = in_index;
257                        let old_len = out_doc.nodes.len();
258                                                
259                        match live_eval_value(&self.live_registry, &mut index, &in_doc.nodes, &out_doc.nodes){
260                            Ok(v)=>{
261                                out_doc.nodes.insert(insert_point, in_node.clone());
262                                out_doc.nodes[insert_point].value = v; 
263                            }
264                            Err(e)=>{
265                                out_doc.nodes.insert(insert_point, in_node.clone());
266                                out_doc.nodes[insert_point].value = LiveValue::None;
267                                self.errors.push(e);
268                            } 
269                        }
270                        self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
271                        // lets skip the nodes
272                        in_index = in_doc.nodes.skip_node(in_index);
273                        continue;
274                    }
275                    
276                    let old_len = out_doc.nodes.len();
277                    out_doc.nodes.insert(insert_point, in_node.clone());
278                    if in_node.is_open() {
279                        out_doc.nodes.insert(insert_point + 1, in_node.clone());
280                        out_doc.nodes[insert_point + 1].value = LiveValue::Close;
281                    }
282                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
283                    
284                    insert_point
285                }
286            };
287            
288            
289            // process stacks
290            match in_value {
291                LiveValue::Dependency(path) => {
292                     let file_id = in_node.origin.token_id().unwrap().file_id().unwrap();
293                    if let Some(final_path) = self.resolve_path(file_id, &path){
294                        out_doc.nodes[out_index].value = LiveValue::Dependency(final_path);
295                    }
296                },
297                LiveValue::Font(font) => {
298                    let file_id = in_node.origin.token_id().unwrap().file_id().unwrap();
299                    let mut paths = Vec::new();
300                    for path in &*font.paths{
301                        if let Some(final_path) = self.resolve_path(file_id, &path){
302                            paths.push(final_path);
303                        }
304                    }
305                    if paths.len()>0{
306                        out_doc.nodes[out_index].value = LiveValue::Font(LiveFont{
307                            paths: Arc::new(paths),
308                            ..*font
309                        });
310                    }
311                },
312                LiveValue::Clone{clone,..} | LiveValue::Deref{clone,..}=> {
313                    if let Some(target) = self.live_registry.find_scope_target(*clone, &out_doc.nodes) {
314                        match target {
315                            LiveScopeTarget::LocalPtr(local_ptr) => {
316                                
317                                let old_len = out_doc.nodes.len();
318                                
319                                out_doc.nodes.insert_children_from_self(local_ptr, out_index + 1);
320                                self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
321                                
322                                // we should overwrite our class live_type
323                                if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
324                                    out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
325                                    if let LiveValue::Class {live_type, ..} = &mut out_doc.nodes[out_index].value {
326                                        *live_type = *new_live_type
327                                    }
328                                }
329                                else{
330                                    if let LiveValue::Class {live_type: old_live_type, ..} = &out_doc.nodes[out_index].value {
331                                        if let LiveValue::Class {live_type, ..} = &out_doc.nodes[local_ptr].value {
332                                            if live_type != old_live_type {
333                                                self.errors.push(LiveError {
334                                                    origin: live_error_origin!(),
335                                                    span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
336                                                    message: format!("Class override with wrong type {}", in_node.id)
337                                                });
338                                            }
339                                        }
340                                    }
341                                    out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
342                                }
343                                
344                                if let LiveValue::Class {class_parent,..} = &mut out_doc.nodes[out_index].value {
345                                    //*class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
346                                    *class_parent = LivePtr {file_id: self.in_file_id, index: local_ptr as u32, generation};
347                                }
348                            }
349                            LiveScopeTarget::LivePtr(live_ptr) => {
350                                let doc = &self.live_registry.live_files[live_ptr.file_id.to_index()].expanded;
351                                
352                                let old_len = out_doc.nodes.len();
353                                out_doc.nodes.insert_children_from_other(live_ptr.node_index(), out_index + 1, &doc.nodes);
354                                self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
355                                
356                                out_doc.nodes[out_index].value = doc.nodes[live_ptr.node_index()].value.clone();
357                                
358                                if let LiveValue::Class {class_parent,live_type, ..} = &mut out_doc.nodes[out_index].value {
359                                    if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
360                                        *live_type = *new_live_type;
361                                    }
362                                    else{
363                                        *class_parent = live_ptr;
364                                    }
365                                    //*class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
366                                }
367                            }
368                        };
369                        //overwrite value, this copies the Class
370                    }
371                    else if !Self::is_baseclass(*clone) { //if !self.live_registry.ignore_no_dsl.contains(clone) {
372                        self.errors.push(LiveError {
373                            origin: live_error_origin!(),
374                            span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
375                            message: format!("Can't find live definition of {} did you forget to call live_design for it, put the definition above the place where you use it or if imported put pub before the definition?", clone)
376                        });
377                    }
378                    current_parent.push((out_doc.nodes[out_index].id, out_index));
379                },
380                LiveValue::Class {live_type, ..} => {
381                    
382                    // store the class context
383                    if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
384                        *class_parent = LivePtr {file_id: self.in_file_id, index: out_index as u32, generation};
385                    }
386                    
387                    let mut insert_point = out_index + 1;
388                    let live_type_info = self.live_registry.live_type_infos.get(live_type).unwrap();
389                    
390                    if let Some(field) = live_type_info.fields.iter().find( | f | f.live_field_kind == LiveFieldKind::Deref) {
391                        if !field.live_type_info.live_ignore {
392                            let live_type_info = &field.live_type_info;
393                            if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&live_type_info.module_id) {
394                                let doc = &self.live_registry.live_files[file_id.to_index()].expanded;
395                                
396                                let mut index = 1;
397                                let mut found = None;
398                                while index < doc.nodes.len() {
399                                    if let LiveValue::Class {live_type, ..} = &doc.nodes[index].value {
400                                        if *live_type == live_type_info.live_type {
401                                            found = Some(index);
402                                            break
403                                        }
404                                    }
405                                    index = doc.nodes.skip_node(index);
406                                }
407                                if let Some(index) = found {
408                                    let old_len = out_doc.nodes.len();
409                                    out_doc.nodes.insert_children_from_other(index, out_index + 1, &doc.nodes);
410                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
411                                }
412                            }
413                        }
414                    }
415                    // else {
416                    for field in &live_type_info.fields {
417                        if field.live_field_kind == LiveFieldKind::Deref {
418                            continue;
419                        }
420                        let lti = &field.live_type_info;
421                        if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&lti.module_id) {
422                            
423                            if *file_id == self.in_file_id { // clone on self
424                                let mut index = 1;
425                                let mut found = None;
426                                while index < out_doc.nodes.len() - 1 {
427                                    if let LiveValue::Class {live_type, ..} = &out_doc.nodes[index].value {
428                                        if *live_type == lti.live_type {
429                                            found = Some(index);
430                                            break
431                                        }
432                                    }
433                                    index = out_doc.nodes.skip_node(index);
434                                }
435                                if let Some(index) = found {
436                                    let node_insert_point = insert_point;
437                                    
438                                    let old_len = out_doc.nodes.len();
439                                    insert_point = out_doc.nodes.insert_node_from_self(index, insert_point);
440                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
441                                    
442                                    out_doc.nodes[node_insert_point].id = field.id;
443                                    out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
444                                    
445                                }
446                                else if !lti.live_ignore {
447                                    self.errors.push(LiveError {
448                                        origin: live_error_origin!(),
449                                        span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
450                                        message: format!("Can't find live definition of {} did you forget to call live_design for it, put the definition above the place where you use it or if imported put pub before the definition?", lti.type_name)
451                                    });
452                                }
453                            }
454                            else {
455                                let other_nodes = &self.live_registry.live_files[file_id.to_index()].expanded.nodes;
456                                if other_nodes.is_empty() {
457                                    panic!(
458                                        "Dependency order bug finding {}, file {} not registered before {}",
459                                        lti.type_name,
460                                        self.live_registry.file_id_to_file_name(*file_id),
461                                        self.live_registry.file_id_to_file_name(self.in_file_id),
462                                    );
463                                }
464                                let mut index = 1;
465                                let mut found = None;
466                                while index < other_nodes.len() - 1 {
467                                    if let LiveValue::Class {live_type, ..} = &other_nodes[index].value {
468                                        if *live_type == lti.live_type {
469                                            found = Some(index);
470                                            break
471                                        }
472                                    }
473                                    index = other_nodes.skip_node(index);
474                                }
475                                if let Some(index) = found {
476                                    let node_insert_point = insert_point;
477                                    
478                                    let old_len = out_doc.nodes.len();
479                                    insert_point = out_doc.nodes.insert_node_from_other(index, insert_point, other_nodes);
480                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
481                                    
482                                    out_doc.nodes[node_insert_point].id = field.id;
483                                    out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
484                                }
485                                else if !lti.live_ignore && lti.type_name != LiveId(0) {
486                                    self.errors.push(LiveError {
487                                        origin: live_error_origin!(),
488                                        span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
489                                        message: format!("Typename {}, not defined in file where it was expected", lti.type_name)
490                                    });
491                                }
492                            }
493                        }
494                        else if !lti.live_ignore {
495                            self.errors.push(LiveError {
496                                origin: live_error_origin!(),
497                                span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
498                                message: format!("Can't find live definition of {} did you forget to call live_design for it, put the definition above the place where you use it or if imported put pub before the definition?", lti.type_name)
499                            });
500                        }
501                    }
502                    //}
503                    
504                    current_parent.push((out_doc.nodes[out_index].id, out_index));
505                }
506                LiveValue::Expr {..} => {panic!()},
507                LiveValue::Array |
508                LiveValue::TupleEnum {..} |
509                LiveValue::NamedEnum {..} |
510                LiveValue::Object => { // lets check what we are overwriting
511                    current_parent.push((out_doc.nodes[out_index].id, out_index));
512                },
513                LiveValue::DSL {..} => {
514                    //println!("{}",std::mem::size_of::<TextSpan>());
515                },
516                _ => {}
517            }
518            
519            in_index += 1;
520        }
521        out_doc.nodes.push(in_doc.nodes.last().unwrap().clone());
522        // this stores the node index on nodes that don't have a node index
523        let mut level = 0;
524        
525        for i in 1..out_doc.nodes.len() {
526            // check if we have a prefix and its export
527            // store this pointer
528            //let exports: HashMap<LiveId, usize> = Default::default();
529            let node = &mut out_doc.nodes[i];
530            if node.value.is_dsl() {
531                node.value.set_dsl_expand_index_if_none(i);
532            }
533            if level == 0 && in_doc.exports.get(&node.id).is_some(){
534                let id = node.id;
535                if let LiveValue::Root(root) = &mut out_doc.nodes[0].value{
536                    root.exports.insert(id, i);
537                }
538            }
539            let node = &mut out_doc.nodes[i];
540            if node.value.is_open(){
541                level += 1
542            }
543            else if node.value.is_close() && level > 0{
544                level -= 1
545            }
546
547        }
548    }
549    
550}
551