1use super::{EvaluationContext, Expression, ParentScope};
5use crate::langtype::{NativeClass, Type};
6use derive_more::{From, Into};
7use smol_str::SmolStr;
8use std::cell::{Cell, RefCell};
9use std::collections::{BTreeMap, HashMap};
10use std::rc::Rc;
11use typed_index_collections::TiVec;
12
13#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
14pub struct PropertyIdx(usize);
15#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
16pub struct FunctionIdx(usize);
17#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
18pub struct CallbackIdx(usize);
19#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
20pub struct SubComponentIdx(usize);
21#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
22pub struct GlobalIdx(usize);
23#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
24pub struct SubComponentInstanceIdx(usize);
25#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq, PartialOrd, Ord)]
26pub struct ItemInstanceIdx(usize);
27#[derive(Debug, Clone, Copy, Into, From, Hash, PartialEq, Eq)]
28pub struct RepeatedElementIdx(usize);
29
30#[derive(Debug, Clone)]
31pub struct LayoutRepeatedElement {
32 pub repeater_index: RepeatedElementIdx,
33 pub repeated_children_count: Option<usize>,
36}
37
38#[derive(Debug, Clone)]
39pub struct GridLayoutRepeatedElement {
40 pub new_row: bool,
41 pub repeater_index: RepeatedElementIdx,
42 pub repeated_children_count: Option<usize>,
43}
44
45impl PropertyIdx {
46 pub const REPEATER_DATA: Self = Self(0);
47 pub const REPEATER_INDEX: Self = Self(1);
48}
49
50#[derive(Debug, Clone)]
53pub struct GridLayoutChildLayoutInfo {
54 pub layout_info_h: MutExpression,
55 pub layout_info_v: MutExpression,
56}
57
58#[derive(Debug, Clone, derive_more::Deref, derive_more::DerefMut)]
59pub struct MutExpression(RefCell<Expression>);
60
61impl From<Expression> for MutExpression {
62 fn from(e: Expression) -> Self {
63 Self(e.into())
64 }
65}
66
67impl MutExpression {
68 pub fn ty(&self, ctx: &dyn super::TypeResolutionContext) -> Type {
69 self.0.borrow().ty(ctx)
70 }
71}
72
73#[derive(Debug, Clone)]
74pub enum Animation {
75 Static(Expression),
77 Transition(Expression),
78}
79
80#[derive(Debug, Clone)]
81pub struct BindingExpression {
82 pub expression: MutExpression,
83 pub animation: Option<Animation>,
84 pub is_constant: bool,
86 pub is_state_info: bool,
89
90 pub use_count: Cell<usize>,
93}
94
95#[derive(Debug)]
96pub struct GlobalComponent {
97 pub name: SmolStr,
98 pub properties: TiVec<PropertyIdx, Property>,
99 pub callbacks: TiVec<CallbackIdx, Callback>,
100 pub functions: TiVec<FunctionIdx, Function>,
101 pub init_values: BTreeMap<LocalMemberIndex, BindingExpression>,
103 pub change_callbacks: BTreeMap<PropertyIdx, MutExpression>,
105 pub const_properties: TiVec<PropertyIdx, bool>,
106 pub public_properties: PublicProperties,
107 pub private_properties: PrivateProperties,
108 pub exported: bool,
110 pub aliases: Vec<SmolStr>,
113 pub is_builtin: bool,
115 pub from_library: bool,
117 pub prop_analysis: TiVec<PropertyIdx, crate::object_tree::PropertyAnalysis>,
119}
120
121impl GlobalComponent {
122 pub fn must_generate(&self) -> bool {
123 !self.from_library
124 && (self.exported
125 || !self.functions.is_empty()
126 || self.properties.iter().any(|p| p.use_count.get() > 0)
127 || self.callbacks.iter().any(|c| c.use_count.get() > 0))
128 }
129}
130
131#[derive(Clone, Debug, Hash, PartialEq, Eq, From, PartialOrd, Ord)]
132pub enum LocalMemberIndex {
133 #[from]
134 Property(PropertyIdx),
135 #[from]
136 Function(FunctionIdx),
137 #[from]
138 Callback(CallbackIdx),
139 Native {
140 item_index: ItemInstanceIdx,
141 prop_name: SmolStr,
142 },
143}
144impl LocalMemberIndex {
145 pub fn property(&self) -> Option<PropertyIdx> {
146 if let LocalMemberIndex::Property(p) = self { Some(*p) } else { None }
147 }
148}
149
150#[derive(Clone, Debug, Hash, PartialEq, Eq)]
152pub enum MemberReference {
153 Global { global_index: GlobalIdx, member: LocalMemberIndex },
155
156 Relative {
158 parent_level: usize,
160 local_reference: LocalMemberReference,
161 },
162}
163impl MemberReference {
164 #[track_caller]
166 pub fn local(&self) -> LocalMemberReference {
167 match self {
168 MemberReference::Relative { parent_level: 0, local_reference, .. } => {
169 local_reference.clone()
170 }
171 _ => panic!("not a local reference"),
172 }
173 }
174
175 pub fn is_function(&self) -> bool {
176 match self {
177 MemberReference::Global { member: LocalMemberIndex::Function(..), .. }
178 | MemberReference::Relative {
179 local_reference:
180 LocalMemberReference { reference: LocalMemberIndex::Function(..), .. },
181 ..
182 } => true,
183 _ => false,
184 }
185 }
186}
187
188impl From<LocalMemberReference> for MemberReference {
189 fn from(local_reference: LocalMemberReference) -> Self {
190 MemberReference::Relative { parent_level: 0, local_reference }
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Hash)]
196pub struct LocalMemberReference {
197 pub sub_component_path: Vec<SubComponentInstanceIdx>,
198 pub reference: LocalMemberIndex,
199}
200
201impl<T: Into<LocalMemberIndex>> From<T> for LocalMemberReference {
202 fn from(reference: T) -> Self {
203 Self { sub_component_path: Vec::new(), reference: reference.into() }
204 }
205}
206
207#[derive(Debug, Default)]
208pub struct Property {
209 pub name: SmolStr,
210 pub ty: Type,
211 pub use_count: Cell<usize>,
214}
215
216#[derive(Debug, Default)]
217pub struct Callback {
218 pub name: SmolStr,
219 pub ret_ty: Type,
220 pub args: Vec<Type>,
221
222 pub ty: Type,
225
226 pub use_count: Cell<usize>,
228}
229
230#[derive(Debug)]
231pub struct Function {
232 pub name: SmolStr,
233 pub ret_ty: Type,
234 pub args: Vec<Type>,
235 pub code: Expression,
236}
237
238#[derive(Debug, Clone)]
239pub struct ListViewInfo {
242 pub viewport_y: LocalMemberReference,
243 pub viewport_height: LocalMemberReference,
244 pub viewport_width: LocalMemberReference,
245 pub listview_height: LocalMemberReference,
247 pub listview_width: LocalMemberReference,
249
250 pub prop_y: MemberReference,
252 pub prop_height: MemberReference,
254}
255
256#[derive(Debug)]
257pub struct RepeatedElement {
258 pub model: MutExpression,
259 pub index_prop: Option<PropertyIdx>,
261 pub data_prop: Option<PropertyIdx>,
263 pub sub_tree: ItemTree,
264 pub index_in_tree: u32,
266
267 pub listview: Option<ListViewInfo>,
268
269 pub container_item_index: Option<ItemInstanceIdx>,
271}
272
273#[derive(Debug)]
274pub struct ComponentContainerElement {
275 pub component_container_item_tree_index: u32,
277 pub component_container_items_index: ItemInstanceIdx,
279 pub component_placeholder_item_tree_index: u32,
281}
282
283pub struct Item {
284 pub ty: Rc<NativeClass>,
285 pub name: SmolStr,
286 pub index_in_tree: u32,
288}
289
290impl std::fmt::Debug for Item {
291 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
292 f.debug_struct("Item")
293 .field("ty", &self.ty.class_name)
294 .field("name", &self.name)
295 .field("index_in_tree", &self.index_in_tree)
296 .finish()
297 }
298}
299
300#[derive(Debug)]
301pub struct TreeNode {
302 pub sub_component_path: Vec<SubComponentInstanceIdx>,
303 pub item_index: itertools::Either<ItemInstanceIdx, u32>,
305 pub children: Vec<TreeNode>,
306 pub is_accessible: bool,
307}
308
309impl TreeNode {
310 fn children_count(&self) -> usize {
311 let mut count = self.children.len();
312 for c in &self.children {
313 count += c.children_count();
314 }
315 count
316 }
317
318 pub fn visit_in_array(
321 &self,
322 visitor: &mut dyn FnMut(
323 &TreeNode,
324 usize,
325 usize,
326 ),
327 ) {
328 visitor(self, 1, 0);
329 visit_in_array_recursive(self, 1, 0, visitor);
330
331 fn visit_in_array_recursive(
332 node: &TreeNode,
333 children_offset: usize,
334 current_index: usize,
335 visitor: &mut dyn FnMut(&TreeNode, usize, usize),
336 ) {
337 let mut offset = children_offset + node.children.len();
338 for c in &node.children {
339 visitor(c, offset, current_index);
340 offset += c.children_count();
341 }
342
343 let mut offset = children_offset + node.children.len();
344 for (i, c) in node.children.iter().enumerate() {
345 visit_in_array_recursive(c, offset, children_offset + i, visitor);
346 offset += c.children_count();
347 }
348 }
349 }
350}
351
352#[derive(Debug)]
353pub struct SubComponent {
354 pub name: SmolStr,
355 pub properties: TiVec<PropertyIdx, Property>,
356 pub callbacks: TiVec<CallbackIdx, Callback>,
357 pub functions: TiVec<FunctionIdx, Function>,
358 pub items: TiVec<ItemInstanceIdx, Item>,
359 pub repeated: TiVec<RepeatedElementIdx, RepeatedElement>,
360 pub component_containers: Vec<ComponentContainerElement>,
361 pub popup_windows: Vec<PopupWindow>,
362 pub menu_item_trees: Vec<ItemTree>,
364 pub timers: Vec<Timer>,
365 pub sub_components: TiVec<SubComponentInstanceIdx, SubComponentInstance>,
366 pub property_init: Vec<(MemberReference, BindingExpression)>,
369 pub change_callbacks: Vec<(MemberReference, MutExpression)>,
370 pub animations: HashMap<LocalMemberReference, Expression>,
372 pub two_way_bindings: Vec<(MemberReference, MemberReference, Vec<SmolStr>)>,
374 pub const_properties: Vec<LocalMemberReference>,
375 pub init_code: Vec<MutExpression>,
377
378 pub geometries: Vec<Option<MutExpression>>,
380
381 pub layout_info_h: MutExpression,
382 pub layout_info_v: MutExpression,
383 pub child_of_layout: bool,
384 pub grid_layout_input_for_repeated: Option<MutExpression>,
385 pub is_repeated_row: bool,
388 pub grid_layout_children: Vec<GridLayoutChildLayoutInfo>,
391
392 pub accessible_prop: BTreeMap<(u32, String), MutExpression>,
394
395 pub element_infos: BTreeMap<u32, String>,
397
398 pub prop_analysis: HashMap<MemberReference, PropAnalysis>,
399}
400
401#[derive(Debug)]
402pub struct PopupWindow {
403 pub item_tree: ItemTree,
404 pub position: MutExpression,
405}
406
407#[derive(Debug)]
408pub struct PopupMenu {
409 pub item_tree: ItemTree,
410 pub sub_menu: MemberReference,
411 pub activated: MemberReference,
412 pub close: MemberReference,
413 pub entries: MemberReference,
414}
415
416#[derive(Debug)]
417pub struct Timer {
418 pub interval: MutExpression,
419 pub running: MutExpression,
420 pub triggered: MutExpression,
421}
422
423#[derive(Debug, Clone)]
424pub struct PropAnalysis {
425 pub property_init: Option<usize>,
427 pub analysis: crate::object_tree::PropertyAnalysis,
428}
429
430impl SubComponent {
431 pub fn repeater_count(&self, cu: &CompilationUnit) -> u32 {
433 let mut count = (self.repeated.len() + self.component_containers.len()) as u32;
434 for x in self.sub_components.iter() {
435 count += cu.sub_components[x.ty].repeater_count(cu);
436 }
437 count
438 }
439
440 pub fn child_item_count(&self, cu: &CompilationUnit) -> u32 {
442 let mut count = self.items.len() as u32;
443 for x in self.sub_components.iter() {
444 count += cu.sub_components[x.ty].child_item_count(cu);
445 }
446 count
447 }
448}
449
450#[derive(Debug)]
451pub struct SubComponentInstance {
452 pub ty: SubComponentIdx,
453 pub name: SmolStr,
454 pub index_in_tree: u32,
455 pub index_of_first_child_in_tree: u32,
456 pub repeater_offset: u32,
457}
458
459#[derive(Debug)]
460pub struct ItemTree {
461 pub root: SubComponentIdx,
462 pub tree: TreeNode,
463}
464
465#[derive(Debug)]
466pub struct PublicComponent {
467 pub public_properties: PublicProperties,
468 pub private_properties: PrivateProperties,
469 pub item_tree: ItemTree,
470 pub name: SmolStr,
471}
472
473#[derive(Debug)]
474pub struct CompilationUnit {
475 pub public_components: Vec<PublicComponent>,
476 pub sub_components: TiVec<SubComponentIdx, SubComponent>,
478 pub used_sub_components: Vec<SubComponentIdx>,
480 pub globals: TiVec<GlobalIdx, GlobalComponent>,
481 pub popup_menu: Option<PopupMenu>,
482 pub has_debug_info: bool,
483 #[cfg(feature = "bundle-translations")]
484 pub translations: Option<crate::translations::Translations>,
485}
486
487impl CompilationUnit {
488 pub fn for_each_sub_components<'a>(
489 &'a self,
490 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
491 ) {
492 fn visit_component<'a>(
493 root: &'a CompilationUnit,
494 c: SubComponentIdx,
495 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
496 parent: Option<&ParentScope<'_>>,
497 ) {
498 let ctx = EvaluationContext::new_sub_component(root, c, (), parent);
499 let sc = &root.sub_components[c];
500 visitor(sc, &ctx);
501 for (idx, r) in sc.repeated.iter_enumerated() {
502 visit_component(
503 root,
504 r.sub_tree.root,
505 visitor,
506 Some(&ParentScope::new(&ctx, Some(idx))),
507 );
508 }
509 for popup in &sc.popup_windows {
510 visit_component(
511 root,
512 popup.item_tree.root,
513 visitor,
514 Some(&ParentScope::new(&ctx, None)),
515 );
516 }
517 for menu_tree in &sc.menu_item_trees {
518 visit_component(root, menu_tree.root, visitor, Some(&ParentScope::new(&ctx, None)));
519 }
520 }
521 for c in &self.used_sub_components {
522 visit_component(self, *c, visitor, None);
523 }
524 for p in &self.public_components {
525 visit_component(self, p.item_tree.root, visitor, None);
526 }
527 if let Some(p) = &self.popup_menu {
528 visit_component(self, p.item_tree.root, visitor, None);
529 }
530 }
531
532 pub fn for_each_expression<'a>(
533 &'a self,
534 visitor: &mut dyn FnMut(&'a super::MutExpression, &EvaluationContext<'_>),
535 ) {
536 self.for_each_sub_components(&mut |sc, ctx| {
537 for e in &sc.init_code {
538 visitor(e, ctx);
539 }
540 for (_, e) in &sc.property_init {
541 visitor(&e.expression, ctx);
542 }
543 visitor(&sc.layout_info_h, ctx);
544 visitor(&sc.layout_info_v, ctx);
545 if let Some(e) = &sc.grid_layout_input_for_repeated {
546 visitor(e, ctx);
547 }
548 for e in sc.accessible_prop.values() {
549 visitor(e, ctx);
550 }
551 for i in sc.geometries.iter().flatten() {
552 visitor(i, ctx);
553 }
554 for (_, e) in sc.change_callbacks.iter() {
555 visitor(e, ctx);
556 }
557 });
558 for (idx, g) in self.globals.iter_enumerated() {
559 let ctx = EvaluationContext::new_global(self, idx, ());
560 for e in g.init_values.values() {
561 visitor(&e.expression, &ctx)
562 }
563 for e in g.change_callbacks.values() {
564 visitor(e, &ctx)
565 }
566 }
567 }
568}
569
570#[derive(Debug, Clone)]
572pub struct PublicProperty {
573 pub name: SmolStr,
574 pub ty: Type,
575 pub prop: MemberReference,
576 pub read_only: bool,
577}
578pub type PublicProperties = Vec<PublicProperty>;
579pub type PrivateProperties = Vec<(SmolStr, Type)>;