pax_manifest/
parsing.rs

1use crate::*;
2use pax_lang::interpreter::parse_pax_expression_from_pair;
3use pax_lang::{from_pax, parse_pax_expression, parse_pax_str, Pair, Pairs, Rule, Span};
4use pax_runtime_api::{Color, Fill, Size, Stroke};
5use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
6
7pub fn parse_template_from_component_definition_string(
8    ctx: &mut TemplateNodeParseContext,
9    pax: &str,
10    pax_component_definition: Pair<Rule>,
11) {
12    pax_component_definition
13        .into_inner()
14        .for_each(|pair| match pair.as_rule() {
15            Rule::root_tag_pair => {
16                recurse_visit_tag_pairs_for_template(
17                    ctx,
18                    pair.into_inner().next().unwrap(),
19                    pax,
20                    TreeLocation::Root,
21                );
22            }
23            _ => {}
24        });
25}
26
27pub struct TemplateNodeParseContext {
28    pub template: ComponentTemplate,
29    pub pascal_identifier_to_type_id_map: HashMap<String, TypeId>,
30}
31
32fn recurse_visit_tag_pairs_for_template(
33    ctx: &mut TemplateNodeParseContext,
34    any_tag_pair: Pair<Rule>,
35    pax: &str,
36    location: TreeLocation,
37) {
38    match any_tag_pair.as_rule() {
39        Rule::matched_tag => {
40            //matched_tag => open_tag > pascal_identifier
41            let matched_tag = any_tag_pair;
42            let mut open_tag = matched_tag
43                .clone()
44                .into_inner()
45                .next()
46                .unwrap()
47                .into_inner();
48            let pascal_identifier = open_tag.next().unwrap().as_str();
49
50            let template_node = TemplateNodeDefinition {
51                type_id: TypeId::build_singleton(
52                    &ctx.pascal_identifier_to_type_id_map
53                        .get(pascal_identifier)
54                        .expect(&format!("Template key not found {}", &pascal_identifier))
55                        .to_string(),
56                    Some(&pascal_identifier.to_string()),
57                ),
58                settings: parse_inline_attribute_from_final_pairs_of_tag(open_tag),
59                raw_comment_string: None,
60                control_flow_settings: None,
61            };
62
63            let id = match location {
64                TreeLocation::Root => ctx.template.add_root_node_back(template_node),
65                TreeLocation::Parent(id) => ctx.template.add_child_back(id, template_node),
66            };
67
68            //recurse into inner_nodes
69            let prospective_inner_nodes = matched_tag.into_inner().nth(1).unwrap();
70            match prospective_inner_nodes.as_rule() {
71                Rule::inner_nodes => {
72                    let inner_nodes = prospective_inner_nodes;
73                    inner_nodes.into_inner().for_each(|sub_tag_pair| {
74                        recurse_visit_tag_pairs_for_template(
75                            ctx,
76                            sub_tag_pair,
77                            pax,
78                            TreeLocation::Parent(id.clone().get_template_node_id()),
79                        );
80                    })
81                }
82                _ => {
83                    panic!("wrong prospective inner nodes (or nth)")
84                }
85            }
86        }
87        Rule::self_closing_tag => {
88            let mut tag_pairs = any_tag_pair.into_inner();
89            let pascal_identifier = tag_pairs.next().unwrap().as_str();
90
91            let type_id = if let Some(type_id) =
92                ctx.pascal_identifier_to_type_id_map.get(pascal_identifier)
93            {
94                type_id.clone()
95            } else {
96                TypeId::build_blank_component(pascal_identifier)
97            };
98            let template_node = TemplateNodeDefinition {
99                type_id,
100                settings: parse_inline_attribute_from_final_pairs_of_tag(tag_pairs),
101                raw_comment_string: None,
102                control_flow_settings: None,
103            };
104            let _ = match location {
105                TreeLocation::Root => ctx.template.add_root_node_back(template_node),
106                TreeLocation::Parent(id) => ctx.template.add_child_back(id, template_node),
107            };
108        }
109        Rule::statement_control_flow => {
110            /* statement_control_flow = {(statement_if | statement_for | statement_slot)} */
111
112            let any_tag_pair = any_tag_pair.into_inner().next().unwrap();
113            let _template_node_definition = match any_tag_pair.as_rule() {
114                Rule::statement_if => {
115                    let mut statement_if = any_tag_pair.into_inner();
116                    let expression_body = statement_if.next().unwrap();
117                    let condition_expression =
118                        parse_pax_expression(expression_body.as_str()).unwrap();
119                    let expression_info = ExpressionInfo::new(condition_expression);
120
121                    //`if` TemplateNodeDefinition
122                    let template_node = TemplateNodeDefinition {
123                        control_flow_settings: Some(ControlFlowSettingsDefinition {
124                            condition_expression: Some(expression_info),
125                            slot_index_expression: None,
126                            repeat_predicate_definition: None,
127                            repeat_source_expression: None,
128                        }),
129                        type_id: TypeId::build_if(),
130                        settings: None,
131                        raw_comment_string: None,
132                    };
133
134                    let id = match location {
135                        TreeLocation::Root => ctx.template.add_root_node_back(template_node),
136                        TreeLocation::Parent(id) => ctx.template.add_child_back(id, template_node),
137                    };
138
139                    let prospective_inner_nodes = statement_if.next();
140
141                    if let Some(inner_nodes) = prospective_inner_nodes {
142                        inner_nodes.into_inner().for_each(|sub_tag_pair| {
143                            recurse_visit_tag_pairs_for_template(
144                                ctx,
145                                sub_tag_pair,
146                                pax,
147                                TreeLocation::Parent(id.clone().get_template_node_id()),
148                            );
149                        })
150                    }
151                }
152                Rule::statement_for => {
153                    let mut cfavd = ControlFlowSettingsDefinition::default();
154                    let mut for_statement = any_tag_pair.clone().into_inner();
155                    let mut predicate_declaration = for_statement.next().unwrap().into_inner();
156                    let source = for_statement.next().unwrap();
157
158                    let prospective_inner_nodes = for_statement.next();
159
160                    if predicate_declaration.clone().count() > 1 {
161                        //tuple, like the `elem, i` in `for (elem, i) in self.some_list`
162                        let elem = predicate_declaration.next().unwrap();
163                        let index = predicate_declaration.next().unwrap();
164                        cfavd.repeat_predicate_definition =
165                            Some(ControlFlowRepeatPredicateDefinition::ElemIdIndexId(
166                                elem.as_str().to_owned(),
167                                index.as_str().to_owned(),
168                            ));
169                    } else {
170                        let elem = predicate_declaration.next().unwrap();
171                        //single identifier, like the `elem` in `for elem in self.some_list`
172                        cfavd.repeat_predicate_definition = Some(
173                            ControlFlowRepeatPredicateDefinition::ElemId(elem.as_str().to_owned()),
174                        );
175                    }
176
177                    let inner_source = source.into_inner().next().unwrap();
178                    /* statement_for_source = { xo_range | xo_symbol } */
179                    let repeat_source_definition =
180                        ExpressionInfo::new(parse_pax_expression(inner_source.as_str()).unwrap());
181                    cfavd.repeat_source_expression = Some(repeat_source_definition);
182
183                    //`for` TemplateNodeDefinition
184                    let template_node = TemplateNodeDefinition {
185                        type_id: TypeId::build_repeat(),
186                        control_flow_settings: Some(cfavd),
187                        settings: None,
188                        raw_comment_string: None,
189                    };
190
191                    let id = match location {
192                        TreeLocation::Root => ctx.template.add_root_node_back(template_node),
193                        TreeLocation::Parent(id) => ctx.template.add_child_back(id, template_node),
194                    };
195
196                    if let Some(inner_nodes) = prospective_inner_nodes {
197                        inner_nodes.into_inner().for_each(|sub_tag_pair| {
198                            recurse_visit_tag_pairs_for_template(
199                                ctx,
200                                sub_tag_pair,
201                                pax,
202                                TreeLocation::Parent(id.clone().get_template_node_id()),
203                            );
204                        })
205                    }
206                }
207                Rule::statement_slot => {
208                    let mut statement_slot = any_tag_pair.into_inner();
209                    let expression_body = statement_slot.next().unwrap();
210                    let slot_expression = ExpressionInfo::new(
211                        parse_pax_expression(expression_body.as_str()).unwrap(),
212                    );
213                    let template_node = TemplateNodeDefinition {
214                        control_flow_settings: Some(ControlFlowSettingsDefinition {
215                            condition_expression: None,
216                            slot_index_expression: Some(slot_expression),
217                            repeat_predicate_definition: None,
218                            repeat_source_expression: None,
219                        }),
220                        type_id: TypeId::build_slot(),
221                        settings: None,
222                        raw_comment_string: None,
223                    };
224
225                    let _ = match location {
226                        TreeLocation::Root => ctx.template.add_root_node_back(template_node),
227                        TreeLocation::Parent(id) => ctx.template.add_child_back(id, template_node),
228                    };
229                }
230                _ => {
231                    unreachable!("Parsing error: {:?}", any_tag_pair.as_rule());
232                }
233            };
234        }
235        Rule::comment => {
236            let template_node = TemplateNodeDefinition {
237                control_flow_settings: None,
238                type_id: TypeId::build_comment(),
239                settings: None,
240                raw_comment_string: Some(any_tag_pair.as_str().to_string()),
241            };
242            let _ = match location {
243                TreeLocation::Root => ctx.template.add_root_node_back(template_node),
244                TreeLocation::Parent(id) => ctx.template.add_child_back(id, template_node),
245            };
246        }
247        Rule::node_inner_content => {
248            //For example:  `<Text>"I am inner content"</Text>`
249            unimplemented!("Inner content not yet supported");
250        }
251        _ => {
252            unreachable!("Parsing error: {:?}", any_tag_pair.as_rule());
253        }
254    }
255}
256
257fn parse_literal_function(literal_function_full: Pair<Rule>) -> Token {
258    let literal_function = literal_function_full.clone().into_inner().next().unwrap();
259
260    let location_info = span_to_location(&literal_function.as_span());
261    let literal_function_token = Token::new(literal_function.as_str().to_string(), location_info);
262    literal_function_token
263}
264
265fn parse_event_id(event_id_full: Pair<Rule>) -> Token {
266    let event_id = event_id_full.clone().into_inner().next().unwrap();
267
268    let event_id_location = span_to_location(&event_id.as_span());
269    let event_id_token = Token::new(event_id.as_str().to_string(), event_id_location);
270    event_id_token
271}
272
273fn parse_inline_attribute_from_final_pairs_of_tag(
274    final_pairs_of_tag: Pairs<Rule>,
275) -> Option<Vec<SettingElement>> {
276    let vec: Vec<SettingElement> = final_pairs_of_tag
277        .map(|attribute_key_value_pair| {
278            match attribute_key_value_pair
279                .clone()
280                .into_inner()
281                .next()
282                .unwrap()
283                .as_rule()
284            {
285                Rule::double_binding => {
286                    let mut kv = attribute_key_value_pair.into_inner();
287                    let mut double_binding = kv.next().unwrap().into_inner();
288
289                    let setting: Pair<Rule> = double_binding.next().unwrap();
290                    let property = double_binding.next().unwrap();
291                    let setting_location = span_to_location(&setting.as_span());
292                    let setting_token = Token::new(setting.as_str().to_string(), setting_location);
293
294                    SettingElement::Setting(
295                        setting_token,
296                        ValueDefinition::DoubleBinding(PaxIdentifier::new(property.as_str())),
297                    )
298                }
299                Rule::attribute_event_binding => {
300                    // attribute_event_binding = {event_id ~ "=" ~ literal_function}
301                    let mut kv = attribute_key_value_pair.into_inner();
302                    let mut attribute_event_binding = kv.next().unwrap().into_inner();
303
304                    let event_id_token = parse_event_id(attribute_event_binding.next().unwrap());
305
306                    let literal_function = attribute_event_binding.next().unwrap().as_str();
307                    SettingElement::Setting(
308                        event_id_token,
309                        ValueDefinition::EventBindingTarget(PaxIdentifier::new(literal_function)),
310                    )
311                }
312                _ => {
313                    //Vanilla `key=value` setting pair
314
315                    let mut kv = attribute_key_value_pair.into_inner();
316                    let key = kv.next().unwrap();
317                    let key_location = span_to_location(&key.as_span());
318                    let key_token = Token::new(key.as_str().to_string(), key_location);
319                    let value_outer =
320                        kv.next()
321                            .expect(&format!("key: {}, kvs: {}", key.as_str(), kv));
322                    let value = value_outer.clone().into_inner().next().expect(&format!(
323                        "key: {}, value: {}",
324                        key.as_str(),
325                        value_outer.as_str()
326                    ));
327                    let value_definition = parse_value_definition(value);
328                    SettingElement::Setting(key_token, value_definition)
329                }
330            }
331        })
332        .collect();
333
334    if vec.len() > 0 {
335        Some(vec)
336    } else {
337        None
338    }
339}
340
341pub fn parse_value_definition(value: Pair<Rule>) -> ValueDefinition {
342    match value.as_rule() {
343        Rule::literal_value => {
344            let inner = value.into_inner().next().unwrap();
345            match inner.as_rule() {
346                Rule::literal_object => {
347                    let literal = from_pax(inner.as_str());
348                    match literal {
349                        Ok(value) => ValueDefinition::LiteralValue(value),
350                        Err(_) => ValueDefinition::Block(
351                            derive_value_definition_from_literal_object_pair(inner),
352                        ),
353                    }
354                }
355                _ => {
356                    let literal = from_pax(inner.as_str())
357                        .expect(&format!("Unable to parse literal: {:?}", inner));
358                    ValueDefinition::LiteralValue(literal)
359                }
360            }
361        }
362        Rule::expression_body => {
363            let expression =
364                parse_pax_expression_from_pair(value).expect("Unable to parse expression");
365            ValueDefinition::Expression(ExpressionInfo::new(expression))
366        }
367        Rule::identifier => {
368            let identifier = PaxIdentifier::new(value.as_str());
369            ValueDefinition::Identifier(identifier)
370        }
371        _ => {
372            unreachable!(
373                "Unexpected attribute value pair rule: {:?}",
374                value.as_rule()
375            );
376        }
377    }
378}
379
380fn derive_value_definition_from_literal_object_pair(
381    literal_object: Pair<Rule>,
382) -> LiteralBlockDefinition {
383    let mut literal_object_pairs = literal_object.into_inner();
384
385    if let None = literal_object_pairs.peek() {
386        return LiteralBlockDefinition {
387            explicit_type_pascal_identifier: None,
388            elements: vec![],
389        };
390    }
391
392    let explicit_type_pascal_identifier = match literal_object_pairs.peek().unwrap().as_rule() {
393        Rule::pascal_identifier => {
394            let raw_value = literal_object_pairs.next().unwrap();
395            let raw_value_location = span_to_location(&raw_value.as_span());
396            let token = Token::new(raw_value.as_str().to_string(), raw_value_location);
397            Some(token)
398        }
399        _ => None,
400    };
401
402    LiteralBlockDefinition {
403        explicit_type_pascal_identifier,
404        elements: literal_object_pairs
405            .map(
406                |settings_key_value_pair| match settings_key_value_pair.as_rule() {
407                    Rule::settings_key_value_pair => {
408                        let mut pairs = settings_key_value_pair.into_inner();
409
410                        let setting_key = pairs.next().unwrap().into_inner().next().unwrap();
411                        let setting_key_location = span_to_location(&setting_key.as_span());
412                        let setting_key_token =
413                            Token::new(setting_key.as_str().to_string(), setting_key_location);
414                        let value = pairs.next().unwrap().into_inner().next().unwrap();
415                        let setting_value_definition = parse_value_definition(value);
416
417                        SettingElement::Setting(setting_key_token, setting_value_definition)
418                    }
419                    Rule::comment => {
420                        let comment = settings_key_value_pair.as_str().to_string();
421                        SettingElement::Comment(comment)
422                    }
423                    _ => {
424                        unreachable!(
425                            "Parsing error 2314314145: {:?}",
426                            settings_key_value_pair.as_rule()
427                        );
428                    }
429                },
430            )
431            .collect(),
432    }
433}
434
435pub fn parse_settings_from_component_definition_string(
436    pax_component_definition: Pair<Rule>,
437) -> Vec<SettingsBlockElement> {
438    let mut settings: Vec<SettingsBlockElement> = vec![];
439
440    pax_component_definition
441        .into_inner()
442        .for_each(|top_level_pair| {
443            match top_level_pair.as_rule() {
444                Rule::settings_block_declaration => {
445                    top_level_pair
446                        .into_inner()
447                        .for_each(|top_level_settings_block_entity| {
448                            match top_level_settings_block_entity.as_rule() {
449                                Rule::settings_event_binding => {
450                                    //event handler binding in the form of `@pre_render: handle_pre_render`
451                                    let mut settings_event_binding_pairs =
452                                        top_level_settings_block_entity.into_inner();
453                                    let event_id_token = parse_event_id(
454                                        settings_event_binding_pairs.next().unwrap(),
455                                    );
456                                    let literal_function_token = parse_literal_function(
457                                        settings_event_binding_pairs.next().unwrap(),
458                                    );
459                                    let handler_element: SettingsBlockElement =
460                                        SettingsBlockElement::Handler(
461                                            event_id_token,
462                                            vec![literal_function_token],
463                                        );
464                                    settings.push(handler_element);
465                                }
466                                Rule::selector_block => {
467                                    //selector_block => settings_key_value_pair where v is a ValueDefinition
468                                    let mut selector_block_pairs =
469                                        top_level_settings_block_entity.into_inner();
470                                    //first pair is the selector itself
471                                    let raw_selector = selector_block_pairs.next().unwrap();
472                                    let raw_value_location =
473                                        span_to_location(&raw_selector.as_span());
474                                    let selector: String = raw_selector
475                                        .as_str()
476                                        .chars()
477                                        .filter(|c| !c.is_whitespace())
478                                        .collect();
479                                    let token = Token::new(selector, raw_value_location);
480                                    let literal_object = selector_block_pairs.next().unwrap();
481
482                                    settings.push(SettingsBlockElement::SelectorBlock(
483                                        token,
484                                        derive_value_definition_from_literal_object_pair(
485                                            literal_object,
486                                        ),
487                                    ));
488                                }
489                                Rule::comment => {
490                                    let comment =
491                                        top_level_settings_block_entity.as_str().to_string();
492                                    settings.push(SettingsBlockElement::Comment(comment));
493                                }
494                                _ => {
495                                    unreachable!(
496                                        "Parsing error: {:?}",
497                                        top_level_settings_block_entity.as_rule()
498                                    );
499                                }
500                            }
501                        });
502                }
503                _ => {}
504            }
505        });
506    settings
507}
508
509pub struct ParsingContext {
510    /// Used to track which files/sources have been visited during parsing,
511    /// to prevent duplicate parsing
512    pub visited_type_ids: HashSet<TypeId>,
513
514    pub main_component_type_id: TypeId,
515
516    pub component_definitions: BTreeMap<TypeId, ComponentDefinition>,
517
518    pub template_map: HashMap<String, TypeId>,
519
520    pub template_node_definitions: ComponentTemplate,
521
522    pub type_table: TypeTable,
523
524    pub assets_dirs: Vec<String>,
525}
526
527impl Default for ParsingContext {
528    fn default() -> Self {
529        Self {
530            main_component_type_id: TypeId::default(),
531            visited_type_ids: HashSet::new(),
532            component_definitions: BTreeMap::new(),
533            template_map: HashMap::new(),
534            type_table: get_primitive_type_table(),
535            template_node_definitions: ComponentTemplate::default(),
536            assets_dirs: vec![],
537        }
538    }
539}
540
541#[derive(Debug)]
542pub struct ParsingError {
543    pub error_name: String,
544    pub error_message: String,
545    pub matched_string: String,
546    pub start: (usize, usize),
547    pub end: (usize, usize),
548}
549
550/// From a raw string of Pax representing a single component, parse a complete ComponentDefinition
551pub fn assemble_component_definition(
552    mut ctx: ParsingContext,
553    pax: &str,
554    is_main_component: bool,
555    template_map: HashMap<String, TypeId>,
556    module_path: &str,
557    self_type_id: TypeId,
558    component_source_file_path: &str,
559) -> (ParsingContext, ComponentDefinition) {
560    let mut tpc = TemplateNodeParseContext {
561        pascal_identifier_to_type_id_map: template_map,
562        template: ComponentTemplate::new(
563            self_type_id.clone(),
564            Some(component_source_file_path.to_owned()),
565        ),
566    };
567
568    let ast = parse_pax_str(Rule::pax_component_definition, pax).expect("Unsuccessful parse");
569
570    parse_template_from_component_definition_string(&mut tpc, pax, ast.clone());
571    let modified_module_path = if module_path.starts_with("parser") {
572        module_path.replacen("parser", "crate", 1)
573    } else {
574        module_path.to_string()
575    };
576
577    //populate template_node_definitions vec, needed for traversing node tree at codegen-time
578    ctx.template_node_definitions = tpc.template.clone();
579
580    let settings = parse_settings_from_component_definition_string(ast);
581
582    let new_def = ComponentDefinition {
583        is_primitive: false,
584        is_struct_only_component: false,
585        is_main_component,
586        primitive_instance_import_path: None,
587        type_id: self_type_id,
588        template: Some(tpc.template),
589        settings: Some(settings),
590        module_path: modified_module_path,
591    };
592
593    (ctx, new_def)
594}
595
596pub fn clean_module_path(module_path: &str) -> String {
597    if module_path.starts_with("parser") {
598        module_path.replacen("parser", "crate", 1)
599    } else {
600        module_path.to_string()
601    }
602}
603
604pub fn assemble_struct_only_component_definition(
605    ctx: ParsingContext,
606    module_path: &str,
607    self_type_id: TypeId,
608) -> (ParsingContext, ComponentDefinition) {
609    let modified_module_path = clean_module_path(module_path);
610
611    let new_def = ComponentDefinition {
612        type_id: self_type_id,
613        is_main_component: false,
614        is_primitive: false,
615        is_struct_only_component: true,
616        module_path: modified_module_path,
617        primitive_instance_import_path: None,
618        template: None,
619        settings: None,
620    };
621    (ctx, new_def)
622}
623
624pub fn assemble_primitive_definition(
625    module_path: &str,
626    primitive_instance_import_path: String,
627    self_type_id: TypeId,
628) -> ComponentDefinition {
629    let modified_module_path = clean_module_path(module_path);
630
631    ComponentDefinition {
632        is_primitive: true,
633        is_struct_only_component: false,
634        primitive_instance_import_path: Some(primitive_instance_import_path),
635        is_main_component: false,
636        type_id: self_type_id,
637        template: None,
638        settings: None,
639        module_path: modified_module_path,
640    }
641}
642
643pub fn assemble_type_definition(
644    mut ctx: ParsingContext,
645    property_definitions: Vec<PropertyDefinition>,
646    inner_iterable_type_id: Option<TypeId>,
647    self_type_id: TypeId,
648) -> (ParsingContext, TypeDefinition) {
649    let new_def = TypeDefinition {
650        type_id: self_type_id.clone(),
651        inner_iterable_type_id,
652        property_definitions,
653    };
654
655    ctx.type_table.insert(self_type_id, new_def.clone());
656
657    (ctx, new_def)
658}
659
660/// Given a Pest Span returns starting and ending (line,col)
661fn span_to_location(span: &Span) -> LocationInfo {
662    let start = (
663        span.start_pos().line_col().0 - 1,
664        span.start_pos().line_col().1 - 1,
665    );
666    let end = (
667        span.end_pos().line_col().0 - 1,
668        span.end_pos().line_col().1 - 1,
669    );
670    LocationInfo {
671        start_line_col: start,
672        end_line_col: end,
673    }
674}
675
676/// This trait is used only to extend primitives like u64
677/// with the parser-time method `parse_to_manifest`.  This
678/// allows the parser binary to codegen calls to `::parse_to_manifest()` even
679/// on primitive types
680pub trait Reflectable {
681    fn parse_to_manifest(mut ctx: ParsingContext) -> (ParsingContext, Vec<PropertyDefinition>) {
682        //Default impl for primitives and pax_runtime_api
683        let type_id = Self::get_type_id();
684        let td = TypeDefinition {
685            type_id: type_id.clone(),
686            inner_iterable_type_id: None,
687            property_definitions: vec![],
688        };
689
690        if !ctx.type_table.contains_key(&type_id) {
691            ctx.type_table.insert(type_id, td);
692        }
693
694        (ctx, vec![])
695    }
696
697    ///The import path is the fully namespace-qualified path for a type, like `std::vec::Vec`
698    ///This is distinct from type_id ONLY when the type has generics, like Vec, where
699    ///the type_id is distinct across a Vec<Foo> and a Vec<Bar>.  In both cases of Vec,
700    ///the import_path will remain the same.
701    fn get_import_path() -> String {
702        //This default is used by primitives but expected to
703        //be overridden by userland Pax components / primitives
704        Self::get_self_pascal_identifier()
705    }
706
707    fn get_self_pascal_identifier() -> String;
708
709    fn get_type_id() -> TypeId;
710
711    fn get_iterable_type_id() -> Option<TypeId> {
712        //Most types do not have an iterable type (e.g. the T in Vec<T>) —
713        //it is the responsibility of iterable types to override this fn
714        None
715    }
716}
717
718impl Reflectable for () {
719    fn get_self_pascal_identifier() -> String {
720        "()".to_string()
721    }
722
723    fn get_type_id() -> TypeId {
724        TypeId::build_primitive(&Self::get_self_pascal_identifier())
725    }
726}
727
728impl Reflectable for usize {
729    fn get_self_pascal_identifier() -> String {
730        "usize".to_string()
731    }
732
733    fn get_type_id() -> TypeId {
734        TypeId::build_primitive(&Self::get_self_pascal_identifier())
735    }
736}
737impl Reflectable for isize {
738    fn get_self_pascal_identifier() -> String {
739        "isize".to_string()
740    }
741    fn get_type_id() -> TypeId {
742        TypeId::build_primitive(&Self::get_self_pascal_identifier())
743    }
744}
745impl Reflectable for i128 {
746    fn get_self_pascal_identifier() -> String {
747        "i128".to_string()
748    }
749    fn get_type_id() -> TypeId {
750        TypeId::build_primitive(&Self::get_self_pascal_identifier())
751    }
752}
753impl Reflectable for u128 {
754    fn get_self_pascal_identifier() -> String {
755        "u128".to_string()
756    }
757    fn get_type_id() -> TypeId {
758        TypeId::build_primitive(&Self::get_self_pascal_identifier())
759    }
760}
761impl Reflectable for i64 {
762    fn get_self_pascal_identifier() -> String {
763        "i64".to_string()
764    }
765    fn get_type_id() -> TypeId {
766        TypeId::build_primitive(&Self::get_self_pascal_identifier())
767    }
768}
769impl Reflectable for u64 {
770    fn get_self_pascal_identifier() -> String {
771        "u64".to_string()
772    }
773    fn get_type_id() -> TypeId {
774        TypeId::build_primitive(&Self::get_self_pascal_identifier())
775    }
776}
777impl Reflectable for i32 {
778    fn get_self_pascal_identifier() -> String {
779        "i32".to_string()
780    }
781    fn get_type_id() -> TypeId {
782        TypeId::build_primitive(&Self::get_self_pascal_identifier())
783    }
784}
785impl Reflectable for u32 {
786    fn get_self_pascal_identifier() -> String {
787        "u32".to_string()
788    }
789    fn get_type_id() -> TypeId {
790        TypeId::build_primitive(&Self::get_self_pascal_identifier())
791    }
792}
793impl Reflectable for i8 {
794    fn get_self_pascal_identifier() -> String {
795        "i8".to_string()
796    }
797    fn get_type_id() -> TypeId {
798        TypeId::build_primitive(&Self::get_self_pascal_identifier())
799    }
800}
801impl Reflectable for u8 {
802    fn get_self_pascal_identifier() -> String {
803        "u8".to_string()
804    }
805    fn get_type_id() -> TypeId {
806        TypeId::build_primitive(&Self::get_self_pascal_identifier())
807    }
808}
809impl Reflectable for f64 {
810    fn get_self_pascal_identifier() -> String {
811        "f64".to_string()
812    }
813    fn get_type_id() -> TypeId {
814        TypeId::build_primitive(&&Self::get_self_pascal_identifier())
815    }
816}
817impl Reflectable for f32 {
818    fn get_self_pascal_identifier() -> String {
819        "f32".to_string()
820    }
821    fn get_type_id() -> TypeId {
822        TypeId::build_primitive(&Self::get_self_pascal_identifier())
823    }
824}
825impl Reflectable for bool {
826    fn get_self_pascal_identifier() -> String {
827        "bool".to_string()
828    }
829    fn get_type_id() -> TypeId {
830        TypeId::build_primitive(&Self::get_self_pascal_identifier())
831    }
832}
833
834impl Reflectable for char {
835    fn get_self_pascal_identifier() -> String {
836        "char".to_string()
837    }
838    fn get_type_id() -> TypeId {
839        TypeId::build_primitive(&Self::get_self_pascal_identifier())
840    }
841}
842
843impl Reflectable for std::string::String {
844    fn get_import_path() -> String {
845        "std::string::String".to_string()
846    }
847    fn get_self_pascal_identifier() -> String {
848        "String".to_string()
849    }
850    fn get_type_id() -> TypeId {
851        TypeId::build_singleton(
852            &Self::get_import_path(),
853            Some(&Self::get_self_pascal_identifier()),
854        )
855    }
856}
857
858impl<T> Reflectable for std::rc::Rc<T> {
859    fn get_import_path() -> String {
860        "std::rc::Rc".to_string()
861    }
862    fn get_self_pascal_identifier() -> String {
863        "Rc".to_string()
864    }
865    fn get_type_id() -> TypeId {
866        TypeId::build_singleton(
867            &Self::get_import_path(),
868            Some(&Self::get_self_pascal_identifier()),
869        )
870    }
871}
872
873impl<T: Reflectable> Reflectable for std::option::Option<T> {
874    fn parse_to_manifest(mut ctx: ParsingContext) -> (ParsingContext, Vec<PropertyDefinition>) {
875        let type_id = Self::get_type_id();
876        let td = TypeDefinition {
877            type_id: type_id.clone(),
878            inner_iterable_type_id: None,
879            property_definitions: vec![],
880        };
881
882        if !ctx.type_table.contains_key(&type_id) {
883            ctx.type_table.insert(type_id, td);
884        }
885
886        let (ctx, _) = T::parse_to_manifest(ctx);
887        (ctx, vec![]) //Option itself has no PAXEL-addressable properties
888    }
889    fn get_import_path() -> String {
890        "std::option::Option".to_string()
891    }
892    fn get_self_pascal_identifier() -> String {
893        "Option".to_string()
894    }
895    fn get_type_id() -> TypeId {
896        TypeId::build_option(&format!("{}", &T::get_type_id()))
897    }
898}
899
900impl Reflectable for TypeId {
901    fn get_import_path() -> String {
902        "pax_manifest::TypeId".to_string()
903    }
904
905    fn get_self_pascal_identifier() -> String {
906        "TypeId".to_string()
907    }
908
909    fn get_type_id() -> TypeId {
910        TypeId::build_singleton(
911            &Self::get_import_path(),
912            Some(&Self::get_self_pascal_identifier()),
913        )
914    }
915}
916
917impl Reflectable for TemplateNodeId {
918    fn get_import_path() -> String {
919        "pax_manifest::TemplateNodeId".to_string()
920    }
921
922    fn get_self_pascal_identifier() -> String {
923        "TemplateNodeId".to_string()
924    }
925
926    fn get_type_id() -> TypeId {
927        TypeId::build_singleton(
928            &Self::get_import_path(),
929            Some(&Self::get_self_pascal_identifier()),
930        )
931    }
932}
933
934impl Reflectable for Fill {
935    fn get_import_path() -> String {
936        "pax_engine::api::Fill".to_string()
937    }
938
939    fn get_self_pascal_identifier() -> String {
940        "Fill".to_string()
941    }
942
943    fn get_type_id() -> TypeId {
944        TypeId::build_singleton(
945            &Self::get_import_path(),
946            Some(&Self::get_self_pascal_identifier()),
947        )
948    }
949}
950
951impl Reflectable for Stroke {
952    fn parse_to_manifest(mut ctx: ParsingContext) -> (ParsingContext, Vec<PropertyDefinition>) {
953        let type_id = Self::get_type_id();
954        let mut flags = PropertyDefinitionFlags::default();
955        flags.is_property_wrapped = true;
956        let td = TypeDefinition {
957            type_id: type_id.clone(),
958            inner_iterable_type_id: None,
959            property_definitions: vec![
960                PropertyDefinition {
961                    name: "color".to_string(),
962                    flags: flags.clone(),
963                    type_id: Color::get_type_id(),
964                },
965                PropertyDefinition {
966                    name: "width".to_string(),
967                    flags: flags,
968                    type_id: Size::get_type_id(),
969                },
970            ],
971        };
972
973        if !ctx.type_table.contains_key(&type_id) {
974            ctx.type_table.insert(type_id, td);
975        }
976        let color_type_id = Color::get_type_id();
977        if !ctx.type_table.contains_key(&color_type_id) {
978            ctx.type_table.insert(
979                color_type_id.clone(),
980                TypeDefinition {
981                    type_id: color_type_id,
982                    inner_iterable_type_id: None,
983                    property_definitions: vec![],
984                },
985            );
986        }
987        let size_type_id = Size::get_type_id();
988        if !ctx.type_table.contains_key(&size_type_id) {
989            ctx.type_table.insert(
990                size_type_id.clone(),
991                TypeDefinition {
992                    type_id: size_type_id,
993                    inner_iterable_type_id: None,
994                    property_definitions: vec![],
995                },
996            );
997        }
998
999        (ctx, vec![])
1000    }
1001
1002    fn get_import_path() -> String {
1003        "pax_engine::api::Stroke".to_string()
1004    }
1005
1006    fn get_self_pascal_identifier() -> String {
1007        "Stroke".to_string()
1008    }
1009
1010    fn get_type_id() -> TypeId {
1011        TypeId::build_singleton(
1012            &Self::get_import_path(),
1013            Some(&Self::get_self_pascal_identifier()),
1014        )
1015    }
1016}
1017
1018impl Reflectable for pax_runtime_api::Size {
1019    fn get_import_path() -> String {
1020        "pax_engine::api::Size".to_string()
1021    }
1022
1023    fn get_self_pascal_identifier() -> String {
1024        "Size".to_string()
1025    }
1026
1027    fn get_type_id() -> TypeId {
1028        TypeId::build_singleton(
1029            &Self::get_import_path(),
1030            Some(&Self::get_self_pascal_identifier()),
1031        )
1032    }
1033}
1034
1035impl Reflectable for pax_runtime_api::Color {
1036    fn get_import_path() -> String {
1037        "pax_engine::api::Color".to_string()
1038    }
1039
1040    fn get_self_pascal_identifier() -> String {
1041        "Color".to_string()
1042    }
1043
1044    fn get_type_id() -> TypeId {
1045        TypeId::build_singleton(
1046            &Self::get_import_path(),
1047            Some(&Self::get_self_pascal_identifier()),
1048        )
1049    }
1050}
1051
1052impl Reflectable for pax_runtime_api::PathElement {
1053    fn get_import_path() -> String {
1054        "pax_engine::api::PathElement".to_string()
1055    }
1056
1057    fn get_self_pascal_identifier() -> String {
1058        "PathElement".to_string()
1059    }
1060
1061    fn get_type_id() -> TypeId {
1062        TypeId::build_singleton(
1063            &Self::get_import_path(),
1064            Some(&Self::get_self_pascal_identifier()),
1065        )
1066    }
1067}
1068
1069impl Reflectable for pax_runtime_api::ColorChannel {
1070    fn get_import_path() -> String {
1071        "pax_engine::api::ColorChannel".to_string()
1072    }
1073
1074    fn get_self_pascal_identifier() -> String {
1075        "ColorChannel".to_string()
1076    }
1077
1078    fn get_type_id() -> TypeId {
1079        TypeId::build_singleton(
1080            &Self::get_import_path(),
1081            Some(&Self::get_self_pascal_identifier()),
1082        )
1083    }
1084}
1085
1086impl Reflectable for pax_runtime_api::Rotation {
1087    fn get_import_path() -> String {
1088        "pax_engine::api::Rotation".to_string()
1089    }
1090
1091    fn get_self_pascal_identifier() -> String {
1092        "Rotation".to_string()
1093    }
1094    fn get_type_id() -> TypeId {
1095        let type_id = TypeId::build_singleton(
1096            &Self::get_import_path(),
1097            Some(&Self::get_self_pascal_identifier()),
1098        );
1099
1100        type_id
1101    }
1102}
1103
1104impl Reflectable for pax_runtime_api::Numeric {
1105    fn get_import_path() -> String {
1106        "pax_engine::api::Numeric".to_string()
1107    }
1108
1109    fn get_self_pascal_identifier() -> String {
1110        "Numeric".to_string()
1111    }
1112    fn get_type_id() -> TypeId {
1113        TypeId::build_singleton(
1114            &Self::get_import_path(),
1115            Some(&Self::get_self_pascal_identifier()),
1116        )
1117    }
1118}
1119
1120impl Reflectable for kurbo::Point {
1121    fn get_import_path() -> String {
1122        "kurbo::Point".to_string()
1123    }
1124
1125    fn get_self_pascal_identifier() -> String {
1126        "Point".to_string()
1127    }
1128    fn get_type_id() -> TypeId {
1129        TypeId::build_singleton(
1130            &Self::get_import_path(),
1131            Some(&Self::get_self_pascal_identifier()),
1132        )
1133    }
1134}
1135
1136impl Reflectable for pax_runtime_api::Transform2D {
1137    fn get_import_path() -> String {
1138        "pax_engine::api::Transform2D".to_string()
1139    }
1140
1141    fn get_self_pascal_identifier() -> String {
1142        "Transform2D".to_string()
1143    }
1144    fn get_type_id() -> TypeId {
1145        TypeId::build_singleton(
1146            &Self::get_import_path(),
1147            Some(&Self::get_self_pascal_identifier()),
1148        )
1149    }
1150}
1151
1152impl<T: Reflectable> Reflectable for std::vec::Vec<T> {
1153    fn parse_to_manifest(mut ctx: ParsingContext) -> (ParsingContext, Vec<PropertyDefinition>) {
1154        let type_id = Self::get_type_id();
1155        let td = TypeDefinition {
1156            type_id: type_id.clone(),
1157            inner_iterable_type_id: Self::get_iterable_type_id(),
1158            property_definitions: vec![],
1159        };
1160
1161        if !ctx.type_table.contains_key(&type_id) {
1162            ctx.type_table.insert(type_id, td);
1163        }
1164
1165        // Also parse iterable type
1166        T::parse_to_manifest(ctx)
1167    }
1168    fn get_import_path() -> String {
1169        "std::vec::Vec".to_string()
1170    }
1171    fn get_self_pascal_identifier() -> String {
1172        "Vec".to_string()
1173    }
1174    fn get_type_id() -> TypeId {
1175        //Need to encode generics contents as part of unique id for iterables
1176        TypeId::build_vector(&format!("{}", &Self::get_iterable_type_id().unwrap()))
1177    }
1178    fn get_iterable_type_id() -> Option<TypeId> {
1179        Some(T::get_type_id())
1180    }
1181}
1182
1183impl<T: Reflectable> Reflectable for VecDeque<T> {
1184    fn parse_to_manifest(mut ctx: ParsingContext) -> (ParsingContext, Vec<PropertyDefinition>) {
1185        let type_id = Self::get_type_id();
1186        let td = TypeDefinition {
1187            type_id: type_id.clone(),
1188            inner_iterable_type_id: Self::get_iterable_type_id(),
1189            property_definitions: vec![],
1190        };
1191
1192        if !ctx.type_table.contains_key(&type_id) {
1193            ctx.type_table.insert(type_id, td);
1194        }
1195
1196        // Also parse iterable type
1197        T::parse_to_manifest(ctx)
1198    }
1199    fn get_import_path() -> String {
1200        "std::collections::VecDeque".to_string()
1201    }
1202    fn get_self_pascal_identifier() -> String {
1203        "VecDeque".to_string()
1204    }
1205    fn get_type_id() -> TypeId {
1206        //Need to encode generics contents as part of unique id for iterables
1207        TypeId::build_vector(&format!("{}", &Self::get_iterable_type_id().unwrap()))
1208    }
1209    fn get_iterable_type_id() -> Option<TypeId> {
1210        Some(T::get_type_id())
1211    }
1212}
1213
1214pub fn clean_and_split_symbols(possibly_nested_symbols: &str) -> Vec<String> {
1215    let entire_symbol = if possibly_nested_symbols.starts_with("self.") {
1216        possibly_nested_symbols.replacen("self.", "", 1)
1217    } else if possibly_nested_symbols.starts_with("this.") {
1218        possibly_nested_symbols.replacen("this.", "", 1)
1219    } else {
1220        possibly_nested_symbols.to_string()
1221    };
1222
1223    let trimmed_symbol = entire_symbol.trim();
1224
1225    trimmed_symbol
1226        .split(".")
1227        .map(|atomic_symbol| atomic_symbol.to_string())
1228        .collect::<Vec<_>>()
1229}