1use super::{EvaluationContext, Expression, ParentCtx};
5use crate::langtype::{NativeClass, Type};
6use smol_str::SmolStr;
7use std::cell::{Cell, RefCell};
8use std::collections::{BTreeMap, HashMap};
9use std::num::NonZeroUsize;
10use std::rc::Rc;
11use typed_index_collections::TiVec;
12
13#[derive(
14 Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq, PartialOrd, Ord,
15)]
16pub struct PropertyIdx(usize);
17#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
18pub struct FunctionIdx(usize);
19#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From)]
20pub struct SubComponentIdx(usize);
21#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
22pub struct GlobalIdx(usize);
23#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
24pub struct SubComponentInstanceIdx(usize);
25#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
26pub struct ItemInstanceIdx(usize);
27#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
28pub struct RepeatedElementIdx(usize);
29
30#[derive(Debug, Clone, derive_more::Deref)]
31pub struct MutExpression(RefCell<Expression>);
32
33impl From<Expression> for MutExpression {
34 fn from(e: Expression) -> Self {
35 Self(e.into())
36 }
37}
38
39impl MutExpression {
40 pub fn ty(&self, ctx: &dyn super::TypeResolutionContext) -> Type {
41 self.0.borrow().ty(ctx)
42 }
43}
44
45#[derive(Debug, Clone)]
46pub enum Animation {
47 Static(Expression),
49 Transition(Expression),
50}
51
52#[derive(Debug, Clone)]
53pub struct BindingExpression {
54 pub expression: MutExpression,
55 pub animation: Option<Animation>,
56 pub is_constant: bool,
58 pub is_state_info: bool,
61
62 pub use_count: Cell<usize>,
65}
66
67#[derive(Debug)]
68pub struct GlobalComponent {
69 pub name: SmolStr,
70 pub properties: TiVec<PropertyIdx, Property>,
71 pub functions: TiVec<FunctionIdx, Function>,
72 pub init_values: TiVec<PropertyIdx, Option<BindingExpression>>,
74 pub change_callbacks: BTreeMap<PropertyIdx, MutExpression>,
76 pub const_properties: TiVec<PropertyIdx, bool>,
77 pub public_properties: PublicProperties,
78 pub private_properties: PrivateProperties,
79 pub exported: bool,
81 pub aliases: Vec<SmolStr>,
84 pub is_builtin: bool,
86
87 pub prop_analysis: TiVec<PropertyIdx, crate::object_tree::PropertyAnalysis>,
89}
90
91impl GlobalComponent {
92 pub fn must_generate(&self) -> bool {
93 !self.is_builtin
94 && (self.exported
95 || !self.functions.is_empty()
96 || self.properties.iter().any(|p| p.use_count.get() > 0))
97 }
98}
99
100#[derive(Clone, Debug, Hash, PartialEq, Eq)]
102pub enum PropertyReference {
103 Local { sub_component_path: Vec<SubComponentInstanceIdx>, property_index: PropertyIdx },
105 InNativeItem {
107 sub_component_path: Vec<SubComponentInstanceIdx>,
108 item_index: ItemInstanceIdx,
109 prop_name: String,
110 },
111 InParent { level: NonZeroUsize, parent_reference: Box<PropertyReference> },
113 Global { global_index: GlobalIdx, property_index: PropertyIdx },
115
116 Function { sub_component_path: Vec<SubComponentInstanceIdx>, function_index: FunctionIdx },
118 GlobalFunction { global_index: GlobalIdx, function_index: FunctionIdx },
120}
121
122#[derive(Debug, Default)]
123pub struct Property {
124 pub name: SmolStr,
125 pub ty: Type,
126 pub use_count: Cell<usize>,
129}
130
131#[derive(Debug)]
132pub struct Function {
133 pub name: SmolStr,
134 pub ret_ty: Type,
135 pub args: Vec<Type>,
136 pub code: Expression,
137}
138
139#[derive(Debug, Clone)]
140pub struct ListViewInfo {
143 pub viewport_y: PropertyReference,
144 pub viewport_height: PropertyReference,
145 pub viewport_width: PropertyReference,
146 pub listview_height: PropertyReference,
148 pub listview_width: PropertyReference,
150
151 pub prop_y: PropertyReference,
153 pub prop_height: PropertyReference,
155}
156
157#[derive(Debug)]
158pub struct RepeatedElement {
159 pub model: MutExpression,
160 pub index_prop: Option<PropertyIdx>,
162 pub data_prop: Option<PropertyIdx>,
164 pub sub_tree: ItemTree,
165 pub index_in_tree: u32,
167
168 pub listview: Option<ListViewInfo>,
169
170 pub container_item_index: Option<ItemInstanceIdx>,
172}
173
174#[derive(Debug)]
175pub struct ComponentContainerElement {
176 pub component_container_item_tree_index: u32,
178 pub component_container_items_index: ItemInstanceIdx,
180 pub component_placeholder_item_tree_index: u32,
182}
183
184pub struct Item {
185 pub ty: Rc<NativeClass>,
186 pub name: SmolStr,
187 pub index_in_tree: u32,
189}
190
191impl std::fmt::Debug for Item {
192 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
193 f.debug_struct("Item")
194 .field("ty", &self.ty.class_name)
195 .field("name", &self.name)
196 .field("index_in_tree", &self.index_in_tree)
197 .finish()
198 }
199}
200
201#[derive(Debug)]
202pub struct TreeNode {
203 pub sub_component_path: Vec<SubComponentInstanceIdx>,
204 pub item_index: itertools::Either<ItemInstanceIdx, u32>,
206 pub children: Vec<TreeNode>,
207 pub is_accessible: bool,
208}
209
210impl TreeNode {
211 fn children_count(&self) -> usize {
212 let mut count = self.children.len();
213 for c in &self.children {
214 count += c.children_count();
215 }
216 count
217 }
218
219 pub fn visit_in_array(
222 &self,
223 visitor: &mut dyn FnMut(
224 &TreeNode,
225 usize,
226 usize,
227 ),
228 ) {
229 visitor(self, 1, 0);
230 visit_in_array_recursive(self, 1, 0, visitor);
231
232 fn visit_in_array_recursive(
233 node: &TreeNode,
234 children_offset: usize,
235 current_index: usize,
236 visitor: &mut dyn FnMut(&TreeNode, usize, usize),
237 ) {
238 let mut offset = children_offset + node.children.len();
239 for c in &node.children {
240 visitor(c, offset, current_index);
241 offset += c.children_count();
242 }
243
244 let mut offset = children_offset + node.children.len();
245 for (i, c) in node.children.iter().enumerate() {
246 visit_in_array_recursive(c, offset, children_offset + i, visitor);
247 offset += c.children_count();
248 }
249 }
250 }
251}
252
253#[derive(Debug)]
254pub struct SubComponent {
255 pub name: SmolStr,
256 pub properties: TiVec<PropertyIdx, Property>,
257 pub functions: TiVec<FunctionIdx, Function>,
258 pub items: TiVec<ItemInstanceIdx, Item>,
259 pub repeated: TiVec<RepeatedElementIdx, RepeatedElement>,
260 pub component_containers: Vec<ComponentContainerElement>,
261 pub popup_windows: Vec<PopupWindow>,
262 pub menu_item_trees: Vec<ItemTree>,
264 pub timers: Vec<Timer>,
265 pub sub_components: TiVec<SubComponentInstanceIdx, SubComponentInstance>,
266 pub property_init: Vec<(PropertyReference, BindingExpression)>,
269 pub change_callbacks: Vec<(PropertyReference, MutExpression)>,
270 pub animations: HashMap<PropertyReference, Expression>,
272 pub two_way_bindings: Vec<(PropertyReference, PropertyReference)>,
273 pub const_properties: Vec<PropertyReference>,
274 pub init_code: Vec<MutExpression>,
276
277 pub geometries: Vec<Option<MutExpression>>,
279
280 pub layout_info_h: MutExpression,
281 pub layout_info_v: MutExpression,
282
283 pub accessible_prop: BTreeMap<(u32, String), MutExpression>,
285
286 pub element_infos: BTreeMap<u32, String>,
288
289 pub prop_analysis: HashMap<PropertyReference, PropAnalysis>,
290}
291
292#[derive(Debug)]
293pub struct PopupWindow {
294 pub item_tree: ItemTree,
295 pub position: MutExpression,
296}
297
298#[derive(Debug)]
299pub struct PopupMenu {
300 pub item_tree: ItemTree,
301 pub sub_menu: PropertyReference,
302 pub activated: PropertyReference,
303 pub close: PropertyReference,
304 pub entries: PropertyReference,
305}
306
307#[derive(Debug)]
308pub struct Timer {
309 pub interval: MutExpression,
310 pub running: MutExpression,
311 pub triggered: MutExpression,
312}
313
314#[derive(Debug, Clone)]
315pub struct PropAnalysis {
316 pub property_init: Option<usize>,
318 pub analysis: crate::object_tree::PropertyAnalysis,
319}
320
321impl SubComponent {
322 pub fn repeater_count(&self, cu: &CompilationUnit) -> u32 {
324 let mut count = (self.repeated.len() + self.component_containers.len()) as u32;
325 for x in self.sub_components.iter() {
326 count += cu.sub_components[x.ty].repeater_count(cu);
327 }
328 count
329 }
330
331 pub fn child_item_count(&self, cu: &CompilationUnit) -> u32 {
333 let mut count = self.items.len() as u32;
334 for x in self.sub_components.iter() {
335 count += cu.sub_components[x.ty].child_item_count(cu);
336 }
337 count
338 }
339
340 pub fn prop_used(&self, prop: &PropertyReference, cu: &CompilationUnit) -> bool {
342 if let PropertyReference::Local { property_index, sub_component_path } = prop {
343 let mut sc = self;
344 for i in sub_component_path {
345 sc = &cu.sub_components[sc.sub_components[*i].ty];
346 }
347 if sc.properties[*property_index].use_count.get() == 0 {
348 return false;
349 }
350 }
351 true
352 }
353}
354
355#[derive(Debug)]
356pub struct SubComponentInstance {
357 pub ty: SubComponentIdx,
358 pub name: SmolStr,
359 pub index_in_tree: u32,
360 pub index_of_first_child_in_tree: u32,
361 pub repeater_offset: u32,
362}
363
364#[derive(Debug)]
365pub struct ItemTree {
366 pub root: SubComponentIdx,
367 pub tree: TreeNode,
368 pub parent_context: Option<SmolStr>,
372}
373
374#[derive(Debug)]
375pub struct PublicComponent {
376 pub public_properties: PublicProperties,
377 pub private_properties: PrivateProperties,
378 pub item_tree: ItemTree,
379 pub name: SmolStr,
380}
381
382#[derive(Debug)]
383pub struct CompilationUnit {
384 pub public_components: Vec<PublicComponent>,
385 pub sub_components: TiVec<SubComponentIdx, SubComponent>,
387 pub used_sub_components: Vec<SubComponentIdx>,
389 pub globals: TiVec<GlobalIdx, GlobalComponent>,
390 pub popup_menu: Option<PopupMenu>,
391 pub has_debug_info: bool,
392 #[cfg(feature = "bundle-translations")]
393 pub translations: Option<crate::translations::Translations>,
394}
395
396impl CompilationUnit {
397 pub fn for_each_sub_components<'a>(
398 &'a self,
399 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
400 ) {
401 fn visit_component<'a>(
402 root: &'a CompilationUnit,
403 c: SubComponentIdx,
404 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
405 parent: Option<ParentCtx<'_>>,
406 ) {
407 let ctx = EvaluationContext::new_sub_component(root, c, (), parent);
408 let sc = &root.sub_components[c];
409 visitor(sc, &ctx);
410 for (idx, r) in sc.repeated.iter_enumerated() {
411 visit_component(
412 root,
413 r.sub_tree.root,
414 visitor,
415 Some(ParentCtx::new(&ctx, Some(idx))),
416 );
417 }
418 for popup in &sc.popup_windows {
419 visit_component(
420 root,
421 popup.item_tree.root,
422 visitor,
423 Some(ParentCtx::new(&ctx, None)),
424 );
425 }
426 for menu_tree in &sc.menu_item_trees {
427 visit_component(root, menu_tree.root, visitor, Some(ParentCtx::new(&ctx, None)));
428 }
429 }
430 for c in &self.used_sub_components {
431 visit_component(self, *c, visitor, None);
432 }
433 for p in &self.public_components {
434 visit_component(self, p.item_tree.root, visitor, None);
435 }
436 if let Some(p) = &self.popup_menu {
437 visit_component(self, p.item_tree.root, visitor, None);
438 }
439 }
440
441 pub fn for_each_expression<'a>(
442 &'a self,
443 visitor: &mut dyn FnMut(&'a super::MutExpression, &EvaluationContext<'_>),
444 ) {
445 self.for_each_sub_components(&mut |sc, ctx| {
446 for e in &sc.init_code {
447 visitor(e, ctx);
448 }
449 for (_, e) in &sc.property_init {
450 visitor(&e.expression, ctx);
451 }
452 visitor(&sc.layout_info_h, ctx);
453 visitor(&sc.layout_info_v, ctx);
454 for e in sc.accessible_prop.values() {
455 visitor(e, ctx);
456 }
457 for i in sc.geometries.iter().flatten() {
458 visitor(i, ctx);
459 }
460 for (_, e) in sc.change_callbacks.iter() {
461 visitor(e, ctx);
462 }
463 });
464 for (idx, g) in self.globals.iter_enumerated() {
465 let ctx = EvaluationContext::new_global(self, idx, ());
466 for e in g.init_values.iter().filter_map(|x| x.as_ref()) {
467 visitor(&e.expression, &ctx)
468 }
469 for e in g.change_callbacks.values() {
470 visitor(e, &ctx)
471 }
472 }
473 }
474}
475
476#[derive(Debug, Clone)]
477pub struct PublicProperty {
478 pub name: SmolStr,
479 pub ty: Type,
480 pub prop: PropertyReference,
481 pub read_only: bool,
482}
483pub type PublicProperties = Vec<PublicProperty>;
484pub type PrivateProperties = Vec<(SmolStr, Type)>;