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                    if let Some(final_path) = self.resolve_path(file_id, &font.path){
300                        out_doc.nodes[out_index].value = LiveValue::Font(LiveFont{
301                            path:final_path,
302                            ..*font
303                        });
304                    }
305                },
306                LiveValue::Clone{clone,..} | LiveValue::Deref{clone,..}=> {
307                    if let Some(target) = self.live_registry.find_scope_target(*clone, &out_doc.nodes) {
308                        match target {
309                            LiveScopeTarget::LocalPtr(local_ptr) => {
310                                
311                                let old_len = out_doc.nodes.len();
312                                
313                                out_doc.nodes.insert_children_from_self(local_ptr, out_index + 1);
314                                self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
315                                
316                                // we should overwrite our class live_type
317                                if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
318                                    out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
319                                    if let LiveValue::Class {live_type, ..} = &mut out_doc.nodes[out_index].value {
320                                        *live_type = *new_live_type
321                                    }
322                                }
323                                else{
324                                    if let LiveValue::Class {live_type: old_live_type, ..} = &out_doc.nodes[out_index].value {
325                                        if let LiveValue::Class {live_type, ..} = &out_doc.nodes[local_ptr].value {
326                                            if live_type != old_live_type {
327                                                self.errors.push(LiveError {
328                                                    origin: live_error_origin!(),
329                                                    span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
330                                                    message: format!("Class override with wrong type {}", in_node.id)
331                                                });
332                                            }
333                                        }
334                                    }
335                                    out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
336                                }
337                                
338                                if let LiveValue::Class {class_parent,..} = &mut out_doc.nodes[out_index].value {
339                                    //*class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
340                                    *class_parent = LivePtr {file_id: self.in_file_id, index: local_ptr as u32, generation};
341                                }
342                            }
343                            LiveScopeTarget::LivePtr(live_ptr) => {
344                                let doc = &self.live_registry.live_files[live_ptr.file_id.to_index()].expanded;
345                                
346                                let old_len = out_doc.nodes.len();
347                                out_doc.nodes.insert_children_from_other(live_ptr.node_index(), out_index + 1, &doc.nodes);
348                                self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
349                                
350                                out_doc.nodes[out_index].value = doc.nodes[live_ptr.node_index()].value.clone();
351                                
352                                if let LiveValue::Class {class_parent,live_type, ..} = &mut out_doc.nodes[out_index].value {
353                                    if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
354                                        *live_type = *new_live_type;
355                                    }
356                                    else{
357                                        *class_parent = live_ptr;
358                                    }
359                                    //*class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
360                                }
361                            }
362                        };
363                        //overwrite value, this copies the Class
364                    }
365                    else if !Self::is_baseclass(*clone) { //if !self.live_registry.ignore_no_dsl.contains(clone) {
366                        self.errors.push(LiveError {
367                            origin: live_error_origin!(),
368                            span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
369                            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)
370                        });
371                    }
372                    current_parent.push((out_doc.nodes[out_index].id, out_index));
373                },
374                LiveValue::Class {live_type, ..} => {
375                    
376                    // store the class context
377                    if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
378                        *class_parent = LivePtr {file_id: self.in_file_id, index: out_index as u32, generation};
379                    }
380                    
381                    let mut insert_point = out_index + 1;
382                    let live_type_info = self.live_registry.live_type_infos.get(live_type).unwrap();
383                    
384                    if let Some(field) = live_type_info.fields.iter().find( | f | f.live_field_kind == LiveFieldKind::Deref) {
385                        if !field.live_type_info.live_ignore {
386                            let live_type_info = &field.live_type_info;
387                            if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&live_type_info.module_id) {
388                                let doc = &self.live_registry.live_files[file_id.to_index()].expanded;
389                                
390                                let mut index = 1;
391                                let mut found = None;
392                                while index < doc.nodes.len() {
393                                    if let LiveValue::Class {live_type, ..} = &doc.nodes[index].value {
394                                        if *live_type == live_type_info.live_type {
395                                            found = Some(index);
396                                            break
397                                        }
398                                    }
399                                    index = doc.nodes.skip_node(index);
400                                }
401                                if let Some(index) = found {
402                                    let old_len = out_doc.nodes.len();
403                                    out_doc.nodes.insert_children_from_other(index, out_index + 1, &doc.nodes);
404                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
405                                }
406                            }
407                        }
408                    }
409                    // else {
410                    for field in &live_type_info.fields {
411                        if field.live_field_kind == LiveFieldKind::Deref {
412                            continue;
413                        }
414                        let lti = &field.live_type_info;
415                        if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&lti.module_id) {
416                            
417                            if *file_id == self.in_file_id { // clone on self
418                                let mut index = 1;
419                                let mut found = None;
420                                while index < out_doc.nodes.len() - 1 {
421                                    if let LiveValue::Class {live_type, ..} = &out_doc.nodes[index].value {
422                                        if *live_type == lti.live_type {
423                                            found = Some(index);
424                                            break
425                                        }
426                                    }
427                                    index = out_doc.nodes.skip_node(index);
428                                }
429                                if let Some(index) = found {
430                                    let node_insert_point = insert_point;
431                                    
432                                    let old_len = out_doc.nodes.len();
433                                    insert_point = out_doc.nodes.insert_node_from_self(index, insert_point);
434                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
435                                    
436                                    out_doc.nodes[node_insert_point].id = field.id;
437                                    out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
438                                    
439                                }
440                                else if !lti.live_ignore {
441                                    self.errors.push(LiveError {
442                                        origin: live_error_origin!(),
443                                        span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
444                                        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)
445                                    });
446                                }
447                            }
448                            else {
449                                let other_nodes = &self.live_registry.live_files[file_id.to_index()].expanded.nodes;
450                                if other_nodes.is_empty() {
451                                    panic!(
452                                        "Dependency order bug finding {}, file {} not registered before {}",
453                                        lti.type_name,
454                                        self.live_registry.file_id_to_file_name(*file_id),
455                                        self.live_registry.file_id_to_file_name(self.in_file_id),
456                                    );
457                                }
458                                let mut index = 1;
459                                let mut found = None;
460                                while index < other_nodes.len() - 1 {
461                                    if let LiveValue::Class {live_type, ..} = &other_nodes[index].value {
462                                        if *live_type == lti.live_type {
463                                            found = Some(index);
464                                            break
465                                        }
466                                    }
467                                    index = other_nodes.skip_node(index);
468                                }
469                                if let Some(index) = found {
470                                    let node_insert_point = insert_point;
471                                    
472                                    let old_len = out_doc.nodes.len();
473                                    insert_point = out_doc.nodes.insert_node_from_other(index, insert_point, other_nodes);
474                                    self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
475                                    
476                                    out_doc.nodes[node_insert_point].id = field.id;
477                                    out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
478                                }
479                                else if !lti.live_ignore && lti.type_name != LiveId(0) {
480                                    self.errors.push(LiveError {
481                                        origin: live_error_origin!(),
482                                        span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
483                                        message: format!("Typename {}, not defined in file where it was expected", lti.type_name)
484                                    });
485                                }
486                            }
487                        }
488                        else if !lti.live_ignore {
489                            self.errors.push(LiveError {
490                                origin: live_error_origin!(),
491                                span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
492                                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)
493                            });
494                        }
495                    }
496                    //}
497                    
498                    current_parent.push((out_doc.nodes[out_index].id, out_index));
499                }
500                LiveValue::Expr {..} => {panic!()},
501                LiveValue::Array |
502                LiveValue::TupleEnum {..} |
503                LiveValue::NamedEnum {..} |
504                LiveValue::Object => { // lets check what we are overwriting
505                    current_parent.push((out_doc.nodes[out_index].id, out_index));
506                },
507                LiveValue::DSL {..} => {
508                    //println!("{}",std::mem::size_of::<TextSpan>());
509                },
510                _ => {}
511            }
512            
513            in_index += 1;
514        }
515        out_doc.nodes.push(in_doc.nodes.last().unwrap().clone());
516        // this stores the node index on nodes that don't have a node index
517        let mut level = 0;
518        
519        for i in 1..out_doc.nodes.len() {
520            // check if we have a prefix and its export
521            // store this pointer
522            //let exports: HashMap<LiveId, usize> = Default::default();
523            let node = &mut out_doc.nodes[i];
524            if node.value.is_dsl() {
525                node.value.set_dsl_expand_index_if_none(i);
526            }
527            if level == 0 && in_doc.exports.get(&node.id).is_some(){
528                let id = node.id;
529                if let LiveValue::Root(root) = &mut out_doc.nodes[0].value{
530                    root.exports.insert(id, i);
531                }
532            }
533            let node = &mut out_doc.nodes[i];
534            if node.value.is_open(){
535                level += 1
536            }
537            else if node.value.is_close() && level > 0{
538                level -= 1
539            }
540
541        }
542    }
543    
544}
545