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 pub from_library: bool,
88 pub prop_analysis: TiVec<PropertyIdx, crate::object_tree::PropertyAnalysis>,
90}
91
92impl GlobalComponent {
93 pub fn must_generate(&self) -> bool {
94 !self.is_builtin
95 && !self.from_library
96 && (self.exported
97 || !self.functions.is_empty()
98 || self.properties.iter().any(|p| p.use_count.get() > 0))
99 }
100}
101
102#[derive(Clone, Debug, Hash, PartialEq, Eq)]
104pub enum PropertyReference {
105 Local { sub_component_path: Vec<SubComponentInstanceIdx>, property_index: PropertyIdx },
107 InNativeItem {
109 sub_component_path: Vec<SubComponentInstanceIdx>,
110 item_index: ItemInstanceIdx,
111 prop_name: String,
112 },
113 InParent { level: NonZeroUsize, parent_reference: Box<PropertyReference> },
115 Global { global_index: GlobalIdx, property_index: PropertyIdx },
117
118 Function { sub_component_path: Vec<SubComponentInstanceIdx>, function_index: FunctionIdx },
120 GlobalFunction { global_index: GlobalIdx, function_index: FunctionIdx },
122}
123
124#[derive(Debug, Default)]
125pub struct Property {
126 pub name: SmolStr,
127 pub ty: Type,
128 pub use_count: Cell<usize>,
131}
132
133#[derive(Debug)]
134pub struct Function {
135 pub name: SmolStr,
136 pub ret_ty: Type,
137 pub args: Vec<Type>,
138 pub code: Expression,
139}
140
141#[derive(Debug, Clone)]
142pub struct ListViewInfo {
145 pub viewport_y: PropertyReference,
146 pub viewport_height: PropertyReference,
147 pub viewport_width: PropertyReference,
148 pub listview_height: PropertyReference,
150 pub listview_width: PropertyReference,
152
153 pub prop_y: PropertyReference,
155 pub prop_height: PropertyReference,
157}
158
159#[derive(Debug)]
160pub struct RepeatedElement {
161 pub model: MutExpression,
162 pub index_prop: Option<PropertyIdx>,
164 pub data_prop: Option<PropertyIdx>,
166 pub sub_tree: ItemTree,
167 pub index_in_tree: u32,
169
170 pub listview: Option<ListViewInfo>,
171
172 pub container_item_index: Option<ItemInstanceIdx>,
174}
175
176#[derive(Debug)]
177pub struct ComponentContainerElement {
178 pub component_container_item_tree_index: u32,
180 pub component_container_items_index: ItemInstanceIdx,
182 pub component_placeholder_item_tree_index: u32,
184}
185
186pub struct Item {
187 pub ty: Rc<NativeClass>,
188 pub name: SmolStr,
189 pub index_in_tree: u32,
191}
192
193impl std::fmt::Debug for Item {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 f.debug_struct("Item")
196 .field("ty", &self.ty.class_name)
197 .field("name", &self.name)
198 .field("index_in_tree", &self.index_in_tree)
199 .finish()
200 }
201}
202
203#[derive(Debug)]
204pub struct TreeNode {
205 pub sub_component_path: Vec<SubComponentInstanceIdx>,
206 pub item_index: itertools::Either<ItemInstanceIdx, u32>,
208 pub children: Vec<TreeNode>,
209 pub is_accessible: bool,
210}
211
212impl TreeNode {
213 fn children_count(&self) -> usize {
214 let mut count = self.children.len();
215 for c in &self.children {
216 count += c.children_count();
217 }
218 count
219 }
220
221 pub fn visit_in_array(
224 &self,
225 visitor: &mut dyn FnMut(
226 &TreeNode,
227 usize,
228 usize,
229 ),
230 ) {
231 visitor(self, 1, 0);
232 visit_in_array_recursive(self, 1, 0, visitor);
233
234 fn visit_in_array_recursive(
235 node: &TreeNode,
236 children_offset: usize,
237 current_index: usize,
238 visitor: &mut dyn FnMut(&TreeNode, usize, usize),
239 ) {
240 let mut offset = children_offset + node.children.len();
241 for c in &node.children {
242 visitor(c, offset, current_index);
243 offset += c.children_count();
244 }
245
246 let mut offset = children_offset + node.children.len();
247 for (i, c) in node.children.iter().enumerate() {
248 visit_in_array_recursive(c, offset, children_offset + i, visitor);
249 offset += c.children_count();
250 }
251 }
252 }
253}
254
255#[derive(Debug)]
256pub struct SubComponent {
257 pub name: SmolStr,
258 pub properties: TiVec<PropertyIdx, Property>,
259 pub functions: TiVec<FunctionIdx, Function>,
260 pub items: TiVec<ItemInstanceIdx, Item>,
261 pub repeated: TiVec<RepeatedElementIdx, RepeatedElement>,
262 pub component_containers: Vec<ComponentContainerElement>,
263 pub popup_windows: Vec<PopupWindow>,
264 pub menu_item_trees: Vec<ItemTree>,
266 pub timers: Vec<Timer>,
267 pub sub_components: TiVec<SubComponentInstanceIdx, SubComponentInstance>,
268 pub property_init: Vec<(PropertyReference, BindingExpression)>,
271 pub change_callbacks: Vec<(PropertyReference, MutExpression)>,
272 pub animations: HashMap<PropertyReference, Expression>,
274 pub two_way_bindings: Vec<(PropertyReference, PropertyReference)>,
275 pub const_properties: Vec<PropertyReference>,
276 pub init_code: Vec<MutExpression>,
278
279 pub geometries: Vec<Option<MutExpression>>,
281
282 pub layout_info_h: MutExpression,
283 pub layout_info_v: MutExpression,
284
285 pub accessible_prop: BTreeMap<(u32, String), MutExpression>,
287
288 pub element_infos: BTreeMap<u32, String>,
290
291 pub prop_analysis: HashMap<PropertyReference, PropAnalysis>,
292}
293
294#[derive(Debug)]
295pub struct PopupWindow {
296 pub item_tree: ItemTree,
297 pub position: MutExpression,
298}
299
300#[derive(Debug)]
301pub struct PopupMenu {
302 pub item_tree: ItemTree,
303 pub sub_menu: PropertyReference,
304 pub activated: PropertyReference,
305 pub close: PropertyReference,
306 pub entries: PropertyReference,
307}
308
309#[derive(Debug)]
310pub struct Timer {
311 pub interval: MutExpression,
312 pub running: MutExpression,
313 pub triggered: MutExpression,
314}
315
316#[derive(Debug, Clone)]
317pub struct PropAnalysis {
318 pub property_init: Option<usize>,
320 pub analysis: crate::object_tree::PropertyAnalysis,
321}
322
323impl SubComponent {
324 pub fn repeater_count(&self, cu: &CompilationUnit) -> u32 {
326 let mut count = (self.repeated.len() + self.component_containers.len()) as u32;
327 for x in self.sub_components.iter() {
328 count += cu.sub_components[x.ty].repeater_count(cu);
329 }
330 count
331 }
332
333 pub fn child_item_count(&self, cu: &CompilationUnit) -> u32 {
335 let mut count = self.items.len() as u32;
336 for x in self.sub_components.iter() {
337 count += cu.sub_components[x.ty].child_item_count(cu);
338 }
339 count
340 }
341
342 pub fn prop_used(&self, prop: &PropertyReference, cu: &CompilationUnit) -> bool {
344 if let PropertyReference::Local { property_index, sub_component_path } = prop {
345 let mut sc = self;
346 for i in sub_component_path {
347 sc = &cu.sub_components[sc.sub_components[*i].ty];
348 }
349 if sc.properties[*property_index].use_count.get() == 0 {
350 return false;
351 }
352 }
353 true
354 }
355}
356
357#[derive(Debug)]
358pub struct SubComponentInstance {
359 pub ty: SubComponentIdx,
360 pub name: SmolStr,
361 pub index_in_tree: u32,
362 pub index_of_first_child_in_tree: u32,
363 pub repeater_offset: u32,
364}
365
366#[derive(Debug)]
367pub struct ItemTree {
368 pub root: SubComponentIdx,
369 pub tree: TreeNode,
370 pub parent_context: Option<SmolStr>,
374}
375
376#[derive(Debug)]
377pub struct PublicComponent {
378 pub public_properties: PublicProperties,
379 pub private_properties: PrivateProperties,
380 pub item_tree: ItemTree,
381 pub name: SmolStr,
382}
383
384#[derive(Debug)]
385pub struct CompilationUnit {
386 pub public_components: Vec<PublicComponent>,
387 pub sub_components: TiVec<SubComponentIdx, SubComponent>,
389 pub used_sub_components: Vec<SubComponentIdx>,
391 pub globals: TiVec<GlobalIdx, GlobalComponent>,
392 pub popup_menu: Option<PopupMenu>,
393 pub has_debug_info: bool,
394 #[cfg(feature = "bundle-translations")]
395 pub translations: Option<crate::translations::Translations>,
396}
397
398impl CompilationUnit {
399 pub fn for_each_sub_components<'a>(
400 &'a self,
401 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
402 ) {
403 fn visit_component<'a>(
404 root: &'a CompilationUnit,
405 c: SubComponentIdx,
406 visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
407 parent: Option<ParentCtx<'_>>,
408 ) {
409 let ctx = EvaluationContext::new_sub_component(root, c, (), parent);
410 let sc = &root.sub_components[c];
411 visitor(sc, &ctx);
412 for (idx, r) in sc.repeated.iter_enumerated() {
413 visit_component(
414 root,
415 r.sub_tree.root,
416 visitor,
417 Some(ParentCtx::new(&ctx, Some(idx))),
418 );
419 }
420 for popup in &sc.popup_windows {
421 visit_component(
422 root,
423 popup.item_tree.root,
424 visitor,
425 Some(ParentCtx::new(&ctx, None)),
426 );
427 }
428 for menu_tree in &sc.menu_item_trees {
429 visit_component(root, menu_tree.root, visitor, Some(ParentCtx::new(&ctx, None)));
430 }
431 }
432 for c in &self.used_sub_components {
433 visit_component(self, *c, visitor, None);
434 }
435 for p in &self.public_components {
436 visit_component(self, p.item_tree.root, visitor, None);
437 }
438 if let Some(p) = &self.popup_menu {
439 visit_component(self, p.item_tree.root, visitor, None);
440 }
441 }
442
443 pub fn for_each_expression<'a>(
444 &'a self,
445 visitor: &mut dyn FnMut(&'a super::MutExpression, &EvaluationContext<'_>),
446 ) {
447 self.for_each_sub_components(&mut |sc, ctx| {
448 for e in &sc.init_code {
449 visitor(e, ctx);
450 }
451 for (_, e) in &sc.property_init {
452 visitor(&e.expression, ctx);
453 }
454 visitor(&sc.layout_info_h, ctx);
455 visitor(&sc.layout_info_v, ctx);
456 for e in sc.accessible_prop.values() {
457 visitor(e, ctx);
458 }
459 for i in sc.geometries.iter().flatten() {
460 visitor(i, ctx);
461 }
462 for (_, e) in sc.change_callbacks.iter() {
463 visitor(e, ctx);
464 }
465 });
466 for (idx, g) in self.globals.iter_enumerated() {
467 let ctx = EvaluationContext::new_global(self, idx, ());
468 for e in g.init_values.iter().filter_map(|x| x.as_ref()) {
469 visitor(&e.expression, &ctx)
470 }
471 for e in g.change_callbacks.values() {
472 visitor(e, &ctx)
473 }
474 }
475 }
476}
477
478#[derive(Debug, Clone)]
479pub struct PublicProperty {
480 pub name: SmolStr,
481 pub ty: Type,
482 pub prop: PropertyReference,
483 pub read_only: bool,
484}
485pub type PublicProperties = Vec<PublicProperty>;
486pub type PrivateProperties = Vec<(SmolStr, Type)>;