LLR: used typed index for vectors in the LLR

type-safety+=1

This would avoid for example using a sub-component index in an array of
instances or items.
It also self-document what the index is for.

There are still a couple of cast from repeater-index to u32 because we
do some hack with the repeater-index number for component containers
We also cast back to numbers in order to convert it to string in the
generated code.
This commit is contained in:
Olivier Goffart 2025-01-26 10:51:15 +01:00
parent 1aeeba7d6b
commit 6c7a50bd3d
10 changed files with 307 additions and 298 deletions

View file

@ -54,6 +54,7 @@ by_address = { workspace = true }
itertools = { workspace = true }
url = "2.2.1"
linked_hash_set = "0.1.4"
typed-index-collections = "3.2"
# for processing and embedding the rendered image (texture)
image = { workspace = true, optional = true, features = ["default"] }

View file

@ -95,7 +95,7 @@ fn access_item_rc(pr: &llr::PropertyReference, ctx: &EvaluationContext) -> Strin
component_access += &sub_compo_path;
}
let component_rc = format!("{component_access}self_weak.lock()->into_dyn()");
let item_index_in_tree = sub_component.items[*item_index as usize].index_in_tree;
let item_index_in_tree = sub_component.items[*item_index].index_in_tree;
let item_index = if item_index_in_tree == 0 {
format!("{component_access}tree_index")
} else {
@ -794,7 +794,7 @@ pub fn generate(
}),
));
for (idx, glob) in llr.globals.iter().enumerate() {
for (idx, glob) in llr.globals.iter_enumerated() {
let ty = if glob.is_builtin {
format_smolstr!("slint::cbindgen_private::{}", glob.name)
} else if glob.must_generate() {
@ -1293,7 +1293,7 @@ fn generate_public_component(
fn add_friends(
friends: &mut Vec<SmolStr>,
unit: &llr::CompilationUnit,
c: llr::SubComponentIndex,
c: llr::SubComponentIdx,
is_root: bool,
) {
let sc = &unit.sub_components[c];
@ -1344,49 +1344,55 @@ fn generate_item_tree(
sub_tree.tree.visit_in_array(&mut |node, children_offset, parent_index| {
let parent_index = parent_index as u32;
if node.repeated {
assert_eq!(node.children.len(), 0);
let mut repeater_index = node.item_index;
let mut sub_component = &root.sub_components[sub_tree.root];
for i in &node.sub_component_path {
repeater_index += sub_component.sub_components[*i].repeater_offset;
sub_component = &root.sub_components[sub_component.sub_components[*i].ty];
match node.item_index {
Either::Right(mut repeater_index) => {
assert_eq!(node.children.len(), 0);
let mut sub_component = &root.sub_components[sub_tree.root];
for i in &node.sub_component_path {
repeater_index += sub_component.sub_components[*i].repeater_offset;
sub_component = &root.sub_components[sub_component.sub_components[*i].ty];
}
item_tree_array.push(format!(
"slint::private_api::make_dyn_node({}, {})",
repeater_index, parent_index
));
}
item_tree_array.push(format!(
"slint::private_api::make_dyn_node({}, {})",
repeater_index, parent_index
));
} else {
let mut compo_offset = String::new();
let mut sub_component = &root.sub_components[sub_tree.root];
for i in &node.sub_component_path {
let next_sub_component_name = ident(&sub_component.sub_components[*i].name);
write!(
Either::Left(item_index) => {
let mut compo_offset = String::new();
let mut sub_component = &root.sub_components[sub_tree.root];
for i in &node.sub_component_path {
let next_sub_component_name = ident(&sub_component.sub_components[*i].name);
write!(
compo_offset,
"offsetof({}, {}) + ",
ident(&sub_component.name),
next_sub_component_name
)
.unwrap();
sub_component = &root.sub_components[sub_component.sub_components[*i].ty];
}
let item = &sub_component.items[item_index];
let children_count = node.children.len() as u32;
let children_index = children_offset as u32;
let item_array_index = item_array.len() as u32;
item_tree_array.push(format!(
"slint::private_api::make_item_node({}, {}, {}, {}, {})",
children_count,
children_index,
parent_index,
item_array_index,
node.is_accessible
));
item_array.push(format!(
"{{ {}, {} offsetof({}, {}) }}",
item.ty.cpp_vtable_getter,
compo_offset,
"offsetof({}, {}) + ",
ident(&sub_component.name),
next_sub_component_name
)
.unwrap();
sub_component = &root.sub_components[sub_component.sub_components[*i].ty];
&ident(&sub_component.name),
ident(&item.name),
));
}
let item = &sub_component.items[node.item_index as usize];
let children_count = node.children.len() as u32;
let children_index = children_offset as u32;
let item_array_index = item_array.len() as u32;
item_tree_array.push(format!(
"slint::private_api::make_item_node({}, {}, {}, {}, {})",
children_count, children_index, parent_index, item_array_index, node.is_accessible
));
item_array.push(format!(
"{{ {}, {} offsetof({}, {}) }}",
item.ty.cpp_vtable_getter,
compo_offset,
&ident(&sub_component.name),
ident(&item.name),
));
}
});
@ -1482,7 +1488,7 @@ fn generate_item_tree(
.and_then(|parent| {
parent
.repeater_index
.map(|idx| parent.ctx.current_sub_component().unwrap().repeated[idx as usize].index_in_tree)
.map(|idx| parent.ctx.current_sub_component().unwrap().repeated[idx].index_in_tree)
}).map(|parent_index|
vec![
format!(
@ -1814,7 +1820,7 @@ fn generate_item_tree(
fn generate_sub_component(
target_struct: &mut Struct,
component: llr::SubComponentIndex,
component: llr::SubComponentIdx,
root: &llr::CompilationUnit,
parent_ctx: Option<ParentCtx>,
field_access: Access,
@ -2062,8 +2068,7 @@ fn generate_sub_component(
));
}
for (idx, repeated) in component.repeated.iter().enumerate() {
let idx = idx as u32;
for (idx, repeated) in component.repeated.iter_enumerated() {
let sc = &root.sub_components[repeated.sub_tree.root];
let data_type = if let Some(data_prop) = repeated.data_prop {
sc.properties[data_prop].ty.clone()
@ -2080,6 +2085,7 @@ fn generate_sub_component(
conditional_includes,
);
let idx = usize::from(idx);
let repeater_id = format_smolstr!("repeater_{}", idx);
let mut model = compile_expression(&repeated.model.borrow(), &ctx);
@ -2200,9 +2206,9 @@ fn generate_sub_component(
));
}
target_struct
.members
.extend(generate_functions(&component.functions, &ctx).map(|x| (Access::Public, x)));
target_struct.members.extend(
generate_functions(&component.functions.as_ref(), &ctx).map(|x| (Access::Public, x)),
);
target_struct.members.push((
field_access,
@ -2555,7 +2561,7 @@ fn generate_repeated_component(
fn generate_global(
file: &mut File,
conditional_includes: &ConditionalIncludes,
global_idx: llr::GlobalIndex,
global_idx: llr::GlobalIdx,
global: &llr::GlobalComponent,
root: &llr::CompilationUnit,
) {
@ -2592,7 +2598,7 @@ fn generate_global(
CppGeneratorContext { global_access: "this->globals".into(), conditional_includes },
);
for (property_index, expression) in global.init_values.iter().enumerate() {
for (property_index, expression) in global.init_values.iter_enumerated() {
if global.properties[property_index].use_count.get() == 0 {
continue;
}
@ -2612,7 +2618,7 @@ fn generate_global(
Access::Private,
Declaration::Var(Var {
ty: "slint::private_api::ChangeTracker".into(),
name: format_smolstr!("change_tracker{}", i),
name: format_smolstr!("change_tracker{}", usize::from(*i)),
..Default::default()
}),
));
@ -2620,7 +2626,7 @@ fn generate_global(
init.extend(global.change_callbacks.iter().map(|(p, e)| {
let code = compile_expression(&e.borrow(), &ctx);
let prop = access_member(&llr::PropertyReference::Local { sub_component_path: vec![], property_index: *p }, &ctx);
format!("this->change_tracker{p}.init(this, [this]([[maybe_unused]] auto self) {{ return {prop}.get(); }}, [this]([[maybe_unused]] auto self, auto) {{ {code}; }});")
format!("this->change_tracker{}.init(this, [this]([[maybe_unused]] auto self) {{ return {prop}.get(); }}, [this]([[maybe_unused]] auto self, auto) {{ {code}; }});", usize::from(*p))
}));
global_struct.members.push((
@ -2651,7 +2657,7 @@ fn generate_global(
);
global_struct
.members
.extend(generate_functions(&global.functions, &ctx).map(|x| (Access::Public, x)));
.extend(generate_functions(global.functions.as_ref(), &ctx).map(|x| (Access::Public, x)));
file.definitions.extend(global_struct.extract_definitions().collect::<Vec<_>>());
file.declarations.push(Declaration::Struct(global_struct));
@ -2856,8 +2862,8 @@ fn generate_public_api_for_properties(
fn follow_sub_component_path<'a>(
compilation_unit: &'a llr::CompilationUnit,
root: llr::SubComponentIndex,
sub_component_path: &[usize],
root: llr::SubComponentIdx,
sub_component_path: &[llr::SubComponentInstanceIdx],
) -> (String, &'a llr::SubComponent) {
let mut compo_path = String::new();
let mut sub_component = &compilation_unit.sub_components[root];
@ -2888,8 +2894,8 @@ fn access_window_field(ctx: &EvaluationContext) -> String {
fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) -> String {
fn in_native_item(
ctx: &EvaluationContext,
sub_component_path: &[usize],
item_index: u32,
sub_component_path: &[llr::SubComponentInstanceIdx],
item_index: llr::ItemInstanceIdx,
prop_name: &str,
path: &str,
) -> String {
@ -2898,7 +2904,7 @@ fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) ->
ctx.current_sub_component.unwrap(),
sub_component_path,
);
let item_name = ident(&sub_component.items[item_index as usize].name);
let item_name = ident(&sub_component.items[item_index].name);
if prop_name.is_empty() {
// then this is actually a reference to the element itself
format!("{}->{}{}", path, compo_path, item_name)
@ -3018,7 +3024,7 @@ fn native_item<'a>(
ctx.current_sub_component.unwrap(),
sub_component_path,
);
&sub_component.items[*item_index as usize].ty
&sub_component.items[*item_index].ty
}
llr::PropertyReference::InParent { level, parent_reference } => {
let mut ctx = ctx;
@ -3224,7 +3230,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
let repeater_index = repeater_index.unwrap();
let mut index_prop = llr::PropertyReference::Local {
sub_component_path: vec![],
property_index: ctx2.current_sub_component().unwrap().repeated[repeater_index as usize]
property_index: ctx2.current_sub_component().unwrap().repeated[repeater_index]
.index_prop
.unwrap(),
};
@ -3233,7 +3239,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
llr::PropertyReference::InParent { level, parent_reference: index_prop.into() };
}
let index_access = access_member(&index_prop, ctx);
write!(path, "->repeater_{}", repeater_index).unwrap();
write!(path, "->repeater_{}", usize::from(repeater_index)).unwrap();
format!("{}.model_set_row_data({}.get(), {})", path, index_access, value)
}
Expression::ArrayIndexAssignment { array, index, value } => {
@ -3415,7 +3421,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
} => box_layout_function(
cells_variable,
repeater_indices.as_ref().map(SmolStr::as_str),
elements,
elements.as_ref(),
*orientation,
sub_expression,
ctx,
@ -3890,7 +3896,7 @@ fn compile_builtin_function_call(
fn box_layout_function(
cells_variable: &str,
repeated_indices: Option<&str>,
elements: &[Either<llr::Expression, u32>],
elements: &[Either<llr::Expression, llr::RepeatedElementIdx>],
orientation: Orientation,
sub_expression: &llr::Expression,
ctx: &llr_EvaluationContext<CppGeneratorContext>,
@ -3911,6 +3917,7 @@ fn box_layout_function(
.unwrap();
}
Either::Right(repeater) => {
let repeater = usize::from(*repeater);
write!(push_code, "self->repeater_{}.ensure_updated(self);", repeater).unwrap();
if let Some(ri) = &repeated_indices {

View file

@ -198,8 +198,7 @@ pub fn generate(
let globals = llr
.globals
.iter()
.enumerate()
.iter_enumerated()
.filter(|(_, glob)| glob.must_generate())
.map(|(idx, glob)| generate_global(idx, glob, &llr));
let shared_globals = generate_shared_globals(&llr, &compiler_config);
@ -669,10 +668,10 @@ fn public_api(
/// Generate the rust code for the given component.
fn generate_sub_component(
component_idx: llr::SubComponentIndex,
component_idx: llr::SubComponentIdx,
root: &llr::CompilationUnit,
parent_ctx: Option<ParentCtx>,
index_property: Option<llr::PropertyIndex>,
index_property: Option<llr::PropertyIdx>,
pinned_drop: bool,
) -> TokenStream {
let component = &root.sub_components[component_idx];
@ -726,7 +725,7 @@ fn generate_sub_component(
.enumerate()
.map(|(idx, _)| format_ident!("change_tracker{idx}"));
let declared_functions = generate_functions(&component.functions, &ctx);
let declared_functions = generate_functions(component.functions.as_ref(), &ctx);
let mut init = vec![];
let mut item_names = vec![];
@ -769,13 +768,13 @@ fn generate_sub_component(
let mut repeated_subtree_ranges: Vec<TokenStream> = vec![];
let mut repeated_subtree_components: Vec<TokenStream> = vec![];
for (idx, repeated) in component.repeated.iter().enumerate() {
let idx = idx as u32;
for (idx, repeated) in component.repeated.iter_enumerated() {
extra_components.push(generate_repeated_component(
repeated,
root,
ParentCtx::new(&ctx, Some(idx)),
));
let idx = usize::from(idx) as u32;
let repeater_id = format_ident!("repeater{}", idx);
let rep_inner_component_id =
self::inner_component_id(&root.sub_components[repeated.sub_tree.root]);
@ -1329,7 +1328,7 @@ fn generate_functions(functions: &[llr::Function], ctx: &EvaluationContext) -> V
}
fn generate_global(
global_idx: llr::GlobalIndex,
global_idx: llr::GlobalIdx,
global: &llr::GlobalComponent,
root: &llr::CompilationUnit,
) -> TokenStream {
@ -1372,9 +1371,9 @@ fn generate_global(
},
);
let declared_functions = generate_functions(&global.functions, &ctx);
let declared_functions = generate_functions(global.functions.as_ref(), &ctx);
for (property_index, expression) in global.init_values.iter().enumerate() {
for (property_index, expression) in global.init_values.iter_enumerated() {
if global.properties[property_index].use_count.get() == 0 {
continue;
}
@ -1387,7 +1386,7 @@ fn generate_global(
)
}
}
for (property_index, cst) in global.const_properties.iter().enumerate() {
for (property_index, cst) in global.const_properties.iter_enumerated() {
if global.properties[property_index].use_count.get() == 0 {
continue;
}
@ -1404,8 +1403,10 @@ fn generate_global(
let public_component_id = ident(&global.name);
let global_id = format_ident!("global_{}", public_component_id);
let change_tracker_names =
global.change_callbacks.iter().map(|(idx, _)| format_ident!("change_tracker{idx}"));
let change_tracker_names = global
.change_callbacks
.iter()
.map(|(idx, _)| format_ident!("change_tracker{}", usize::from(*idx)));
init.extend(global.change_callbacks.iter().map(|(p, e)| {
let code = compile_expression(&e.borrow(), &ctx);
let prop = access_member(
@ -1413,7 +1414,7 @@ fn generate_global(
&ctx,
)
.unwrap();
let change_tracker = format_ident!("change_tracker{p}");
let change_tracker = format_ident!("change_tracker{}", usize::from(*p));
quote! {
#[allow(dead_code, unused)]
_self.#change_tracker.init(
@ -1498,7 +1499,7 @@ fn generate_item_tree(
sub_tree: &llr::ItemTree,
root: &llr::CompilationUnit,
parent_ctx: Option<ParentCtx>,
index_property: Option<llr::PropertyIndex>,
index_property: Option<llr::PropertyIdx>,
is_popup_menu: bool,
) -> TokenStream {
let sub_comp = generate_sub_component(sub_tree.root, root, parent_ctx, index_property, true);
@ -1529,7 +1530,7 @@ fn generate_item_tree(
let parent_item_expression = parent_ctx.and_then(|parent| {
parent.repeater_index.map(|idx| {
let sub_component_offset = parent.ctx.current_sub_component().unwrap().repeated[idx as usize].index_in_tree;
let sub_component_offset = parent.ctx.current_sub_component().unwrap().repeated[idx].index_in_tree;
quote!(if let Some((parent_component, parent_index)) = self
.parent
@ -1548,41 +1549,43 @@ fn generate_item_tree(
let parent_index = parent_index as u32;
let (path, component) =
follow_sub_component_path(root, sub_tree.root, &node.sub_component_path);
if node.repeated || node.component_container {
assert_eq!(node.children.len(), 0);
let mut repeater_index = node.item_index;
let mut sub_component = &root.sub_components[sub_tree.root];
for i in &node.sub_component_path {
repeater_index += sub_component.sub_components[*i].repeater_offset;
sub_component = &root.sub_components[sub_component.sub_components[*i].ty];
match node.item_index {
Either::Right(mut repeater_index) => {
assert_eq!(node.children.len(), 0);
let mut sub_component = &root.sub_components[sub_tree.root];
for i in &node.sub_component_path {
repeater_index += sub_component.sub_components[*i].repeater_offset;
sub_component = &root.sub_components[sub_component.sub_components[*i].ty];
}
item_tree_array.push(quote!(
sp::ItemTreeNode::DynamicTree {
index: #repeater_index,
parent_index: #parent_index,
}
));
}
item_tree_array.push(quote!(
sp::ItemTreeNode::DynamicTree {
index: #repeater_index,
parent_index: #parent_index,
}
));
} else {
let item = &component.items[node.item_index as usize];
let field = access_component_field_offset(
&self::inner_component_id(component),
&ident(&item.name),
);
Either::Left(item_index) => {
let item = &component.items[item_index];
let field = access_component_field_offset(
&self::inner_component_id(component),
&ident(&item.name),
);
let children_count = node.children.len() as u32;
let children_index = children_offset as u32;
let item_array_len = item_array.len() as u32;
let is_accessible = node.is_accessible;
item_tree_array.push(quote!(
sp::ItemTreeNode::Item {
is_accessible: #is_accessible,
children_count: #children_count,
children_index: #children_index,
parent_index: #parent_index,
item_array_index: #item_array_len,
}
));
item_array.push(quote!(sp::VOffset::new(#path #field)));
let children_count = node.children.len() as u32;
let children_index = children_offset as u32;
let item_array_len = item_array.len() as u32;
let is_accessible = node.is_accessible;
item_tree_array.push(quote!(
sp::ItemTreeNode::Item {
is_accessible: #is_accessible,
children_count: #children_count,
children_index: #children_index,
parent_index: #parent_index,
item_array_index: #item_array_len,
}
));
item_array.push(quote!(sp::VOffset::new(#path #field)));
}
}
});
@ -1889,8 +1892,8 @@ fn property_set_value_tokens(
fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) -> MemberAccess {
fn in_native_item(
ctx: &EvaluationContext,
sub_component_path: &[usize],
item_index: u32,
sub_component_path: &[llr::SubComponentInstanceIdx],
item_index: llr::ItemInstanceIdx,
prop_name: &str,
path: TokenStream,
) -> TokenStream {
@ -1900,14 +1903,14 @@ fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) ->
sub_component_path,
);
let component_id = inner_component_id(sub_component);
let item_name = ident(&sub_component.items[item_index as usize].name);
let item_name = ident(&sub_component.items[item_index].name);
let item_field = access_component_field_offset(&component_id, &item_name);
if prop_name.is_empty() {
// then this is actually a reference to the element itself
quote!((#compo_path #item_field).apply_pin(#path))
} else {
let property_name = ident(prop_name);
let item_ty = ident(&sub_component.items[item_index as usize].ty.class_name);
let item_ty = ident(&sub_component.items[item_index].ty.class_name);
quote!((#compo_path #item_field + sp::#item_ty::FIELD_OFFSETS.#property_name).apply_pin(#path))
}
}
@ -2109,8 +2112,8 @@ impl MemberAccess {
fn follow_sub_component_path<'a>(
compilation_unit: &'a llr::CompilationUnit,
root: llr::SubComponentIndex,
sub_component_path: &[usize],
root: llr::SubComponentIdx,
sub_component_path: &[llr::SubComponentInstanceIdx],
) -> (TokenStream, &'a llr::SubComponent) {
let mut compo_path = quote!();
let mut sub_component = &compilation_unit.sub_components[root];
@ -2159,7 +2162,7 @@ fn access_item_rc(pr: &llr::PropertyReference, ctx: &EvaluationContext) -> Token
&ctx.compilation_unit.sub_components[sub_component.sub_components[*i].ty];
}
let component_rc_tokens = quote!(sp::VRcMapped::origin(&#component_access_tokens.self_weak.get().unwrap().upgrade().unwrap()));
let item_index_in_tree = sub_component.items[*item_index as usize].index_in_tree;
let item_index_in_tree = sub_component.items[*item_index].index_in_tree;
let item_index_tokens = if item_index_in_tree == 0 {
quote!(#component_access_tokens.tree_index.get())
} else {
@ -2348,10 +2351,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
let repeater_index = repeater_index.unwrap();
let mut index_prop = llr::PropertyReference::Local {
sub_component_path: vec![],
property_index: ctx2.current_sub_component().unwrap().repeated
[repeater_index as usize]
.index_prop
.unwrap(),
property_index: ctx2.current_sub_component().unwrap().repeated[repeater_index].index_prop.unwrap(),
};
if let Some(level) = NonZeroUsize::new(*level) {
index_prop =
@ -2360,7 +2360,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
let index_access = access_member(&index_prop, ctx).get_property();
let repeater = access_component_field_offset(
&inner_component_id(ctx2.current_sub_component().unwrap()),
&format_ident!("repeater{}", repeater_index),
&format_ident!("repeater{}", usize::from(repeater_index)),
);
quote!(#repeater.apply_pin(#path.as_pin_ref()).model_set_row_data(#index_access as _, #value as _))
}
@ -2598,7 +2598,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
} => box_layout_function(
cells_variable,
repeater_indices.as_ref().map(SmolStr::as_str),
elements,
elements.as_ref(),
*orientation,
sub_expression,
ctx,
@ -3126,7 +3126,7 @@ fn struct_name_to_tokens(name: &str) -> TokenStream {
fn box_layout_function(
cells_variable: &str,
repeated_indices: Option<&str>,
elements: &[Either<Expression, u32>],
elements: &[Either<Expression, llr::RepeatedElementIdx>],
orientation: Orientation,
sub_expression: &Expression,
ctx: &EvaluationContext,
@ -3145,14 +3145,10 @@ fn box_layout_function(
push_code.push(quote!(items_vec.push(#value);))
}
Either::Right(repeater) => {
let repeater_id = format_ident!("repeater{}", repeater);
let repeater_id = format_ident!("repeater{}", usize::from(*repeater));
let rep_inner_component_id = self::inner_component_id(
&ctx.compilation_unit.sub_components[ctx
.current_sub_component()
.unwrap()
.repeated[*repeater as usize]
.sub_tree
.root],
&ctx.compilation_unit.sub_components
[ctx.current_sub_component().unwrap().repeated[*repeater].sub_tree.root],
);
repeated_count = quote!(#repeated_count + _self.#repeater_id.len());
let ri = repeated_indices.as_ref().map(|ri| {

View file

@ -1,7 +1,9 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
use super::{GlobalIndex, PropertyReference, SubComponentIndex};
use super::{
GlobalIdx, PropertyReference, RepeatedElementIdx, SubComponentIdx, SubComponentInstanceIdx,
};
use crate::expression_tree::{BuiltinFunction, MinMaxOp, OperatorClass};
use crate::langtype::Type;
use crate::layout::Orientation;
@ -169,7 +171,7 @@ pub enum Expression {
/// The name for the local variable that contains the repeater indices
repeater_indices: Option<SmolStr>,
/// Either an expression of type BoxLayoutCellData, or an index to the repeater
elements: Vec<Either<Expression, u32>>,
elements: Vec<Either<Expression, RepeatedElementIdx>>,
orientation: Orientation,
sub_expression: Box<Expression>,
},
@ -462,7 +464,7 @@ pub trait TypeResolutionContext {
pub struct ParentCtx<'a, T = ()> {
pub ctx: &'a EvaluationContext<'a, T>,
// Index of the repeater within the ctx.current_sub_component
pub repeater_index: Option<u32>,
pub repeater_index: Option<RepeatedElementIdx>,
}
impl<'a, T> Clone for ParentCtx<'a, T> {
@ -473,7 +475,10 @@ impl<'a, T> Clone for ParentCtx<'a, T> {
impl<'a, T> Copy for ParentCtx<'a, T> {}
impl<'a, T> ParentCtx<'a, T> {
pub fn new(ctx: &'a EvaluationContext<'a, T>, repeater_index: Option<u32>) -> Self {
pub fn new(
ctx: &'a EvaluationContext<'a, T>,
repeater_index: Option<RepeatedElementIdx>,
) -> Self {
Self { ctx, repeater_index }
}
}
@ -481,8 +486,8 @@ impl<'a, T> ParentCtx<'a, T> {
#[derive(Clone)]
pub struct EvaluationContext<'a, T = ()> {
pub compilation_unit: &'a super::CompilationUnit,
pub current_sub_component: Option<SubComponentIndex>,
pub current_global: Option<GlobalIndex>,
pub current_sub_component: Option<SubComponentIdx>,
pub current_global: Option<GlobalIdx>,
pub generator_state: T,
/// The repeater parent
pub parent: Option<ParentCtx<'a, T>>,
@ -494,7 +499,7 @@ pub struct EvaluationContext<'a, T = ()> {
impl<'a, T> EvaluationContext<'a, T> {
pub fn new_sub_component(
compilation_unit: &'a super::CompilationUnit,
sub_component: SubComponentIndex,
sub_component: SubComponentIdx,
generator_state: T,
parent: Option<ParentCtx<'a, T>>,
) -> Self {
@ -510,7 +515,7 @@ impl<'a, T> EvaluationContext<'a, T> {
pub fn new_global(
compilation_unit: &'a super::CompilationUnit,
global: GlobalIndex,
global: GlobalIdx,
generator_state: T,
) -> Self {
Self {
@ -708,7 +713,7 @@ impl<'a, T> TypeResolutionContext for EvaluationContext<'a, T> {
&self.compilation_unit.sub_components[sub_component.sub_components[*i].ty];
}
sub_component.items[*item_index as usize].ty.lookup_property(prop_name).unwrap()
sub_component.items[*item_index].ty.lookup_property(prop_name).unwrap()
}
PropertyReference::InParent { level, parent_reference } => {
let mut ctx = self;
@ -758,12 +763,12 @@ pub(crate) struct PropertyInfoResult<'a> {
#[derive(Debug, Clone)]
pub(crate) enum ContextMap {
Identity,
InSubElement { path: Vec<usize>, parent: usize },
InGlobal(GlobalIndex),
InSubElement { path: Vec<SubComponentInstanceIdx>, parent: usize },
InGlobal(GlobalIdx),
}
impl ContextMap {
fn deeper_in_sub_component(self, sub: usize) -> Self {
fn deeper_in_sub_component(self, sub: SubComponentInstanceIdx) -> Self {
match self {
ContextMap::Identity => ContextMap::InSubElement { parent: 0, path: vec![sub] },
ContextMap::InSubElement { mut path, parent } => {
@ -778,7 +783,7 @@ impl ContextMap {
match self {
ContextMap::Identity => p.clone(),
ContextMap::InSubElement { path, parent } => {
let map_sub_path = |sub_component_path: &[usize]| -> Vec<usize> {
let map_sub_path = |sub_component_path: &[SubComponentInstanceIdx]| -> Vec<SubComponentInstanceIdx> {
path.iter().chain(sub_component_path.iter()).copied().collect()
};

View file

@ -8,13 +8,24 @@ use std::cell::{Cell, RefCell};
use std::collections::{BTreeMap, HashMap};
use std::num::NonZeroUsize;
use std::rc::Rc;
use typed_index_collections::TiVec;
// Index in the `SubComponent::properties`
pub type PropertyIndex = usize;
// Index in CompilationUint::sub_components
pub type SubComponentIndex = usize;
// Index in CompilationUnit::globas
pub type GlobalIndex = usize;
#[derive(
Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq, PartialOrd, Ord,
)]
pub struct PropertyIdx(usize);
#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
pub struct FunctionIdx(usize);
#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From)]
pub struct SubComponentIdx(usize);
#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
pub struct GlobalIdx(usize);
#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
pub struct SubComponentInstanceIdx(usize);
#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
pub struct ItemInstanceIdx(usize);
#[derive(Debug, Clone, Copy, derive_more::Into, derive_more::From, Hash, PartialEq, Eq)]
pub struct RepeatedElementIdx(usize);
#[derive(Debug, Clone, derive_more::Deref)]
pub struct MutExpression(RefCell<Expression>);
@ -56,13 +67,13 @@ pub struct BindingExpression {
#[derive(Debug)]
pub struct GlobalComponent {
pub name: SmolStr,
pub properties: Vec<Property>,
pub functions: Vec<Function>,
pub properties: TiVec<PropertyIdx, Property>,
pub functions: TiVec<FunctionIdx, Function>,
/// One entry per property
pub init_values: Vec<Option<BindingExpression>>,
pub init_values: TiVec<PropertyIdx, Option<BindingExpression>>,
// maps property to its changed callback
pub change_callbacks: BTreeMap<usize, MutExpression>,
pub const_properties: Vec<bool>,
pub change_callbacks: BTreeMap<PropertyIdx, MutExpression>,
pub const_properties: TiVec<PropertyIdx, bool>,
pub public_properties: PublicProperties,
pub private_properties: PrivateProperties,
/// true if we should expose the global in the generated API
@ -74,7 +85,7 @@ pub struct GlobalComponent {
pub is_builtin: bool,
/// Analysis for each properties
pub prop_analysis: Vec<crate::object_tree::PropertyAnalysis>,
pub prop_analysis: TiVec<PropertyIdx, crate::object_tree::PropertyAnalysis>,
}
impl GlobalComponent {
@ -90,18 +101,22 @@ impl GlobalComponent {
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum PropertyReference {
/// A property relative to this SubComponent
Local { sub_component_path: Vec<usize>, property_index: PropertyIndex },
Local { sub_component_path: Vec<SubComponentInstanceIdx>, property_index: PropertyIdx },
/// A property in a Native item
InNativeItem { sub_component_path: Vec<usize>, item_index: u32, prop_name: String },
InNativeItem {
sub_component_path: Vec<SubComponentInstanceIdx>,
item_index: ItemInstanceIdx,
prop_name: String,
},
/// The properties is a property relative to a parent ItemTree (`level` level deep)
InParent { level: NonZeroUsize, parent_reference: Box<PropertyReference> },
/// The property within a GlobalComponent
Global { global_index: GlobalIndex, property_index: usize },
Global { global_index: GlobalIdx, property_index: PropertyIdx },
/// A function in a sub component.
Function { sub_component_path: Vec<usize>, function_index: usize },
Function { sub_component_path: Vec<SubComponentInstanceIdx>, function_index: FunctionIdx },
/// A function in a global.
GlobalFunction { global_index: GlobalIndex, function_index: usize },
GlobalFunction { global_index: GlobalIdx, function_index: FunctionIdx },
}
#[derive(Debug, Default)]
@ -143,9 +158,9 @@ pub struct ListViewInfo {
pub struct RepeatedElement {
pub model: MutExpression,
/// Within the sub_tree's root component
pub index_prop: Option<PropertyIndex>,
pub index_prop: Option<PropertyIdx>,
/// Within the sub_tree's root component
pub data_prop: Option<PropertyIndex>,
pub data_prop: Option<PropertyIdx>,
pub sub_tree: ItemTree,
/// The index of the item node in the parent tree
pub index_in_tree: u32,
@ -158,7 +173,7 @@ pub struct ComponentContainerElement {
/// The index of the `ComponentContainer` in the enclosing components `item_tree` array
pub component_container_item_tree_index: u32,
/// The index of the `ComponentContainer` item in the enclosing components `items` array
pub component_container_items_index: u32,
pub component_container_items_index: ItemInstanceIdx,
/// The index to a dynamic tree node where the component is supposed to be embedded at
pub component_placeholder_item_tree_index: u32,
}
@ -182,11 +197,9 @@ impl std::fmt::Debug for Item {
#[derive(Debug)]
pub struct TreeNode {
pub sub_component_path: Vec<usize>,
/// Either an index in the items or repeater, depending on (repeated || component_container)
pub item_index: u32,
pub repeated: bool,
pub component_container: bool,
pub sub_component_path: Vec<SubComponentInstanceIdx>,
/// Either an index in the items, or the local dynamic index for repeater or component container
pub item_index: itertools::Either<ItemInstanceIdx, u32>,
pub children: Vec<TreeNode>,
pub is_accessible: bool,
}
@ -237,14 +250,14 @@ impl TreeNode {
#[derive(Debug)]
pub struct SubComponent {
pub name: SmolStr,
pub properties: Vec<Property>,
pub functions: Vec<Function>,
pub items: Vec<Item>,
pub repeated: Vec<RepeatedElement>,
pub properties: TiVec<PropertyIdx, Property>,
pub functions: TiVec<FunctionIdx, Function>,
pub items: TiVec<ItemInstanceIdx, Item>,
pub repeated: TiVec<RepeatedElementIdx, RepeatedElement>,
pub component_containers: Vec<ComponentContainerElement>,
pub popup_windows: Vec<PopupWindow>,
pub timers: Vec<Timer>,
pub sub_components: Vec<SubComponentInstance>,
pub sub_components: TiVec<SubComponentInstanceIdx, SubComponentInstance>,
/// The initial value or binding for properties.
/// This is ordered in the order they must be set.
pub property_init: Vec<(PropertyReference, BindingExpression)>,
@ -335,7 +348,7 @@ impl SubComponent {
#[derive(Debug)]
pub struct SubComponentInstance {
pub ty: SubComponentIndex,
pub ty: SubComponentIdx,
pub name: SmolStr,
pub index_in_tree: u32,
pub index_of_first_child_in_tree: u32,
@ -344,7 +357,7 @@ pub struct SubComponentInstance {
#[derive(Debug)]
pub struct ItemTree {
pub root: SubComponentIndex,
pub root: SubComponentIdx,
pub tree: TreeNode,
/// This tree has a parent. e.g: it is a Repeater or a PopupWindow whose property can access
/// the parent ItemTree.
@ -364,10 +377,10 @@ pub struct PublicComponent {
pub struct CompilationUnit {
pub public_components: Vec<PublicComponent>,
/// Storage for all sub-components
pub sub_components: Vec<SubComponent>,
pub sub_components: TiVec<SubComponentIdx, SubComponent>,
/// The sub-components that are not item-tree root
pub used_sub_components: Vec<SubComponentIndex>,
pub globals: Vec<GlobalComponent>,
pub used_sub_components: Vec<SubComponentIdx>,
pub globals: TiVec<GlobalIdx, GlobalComponent>,
pub popup_menu: Option<PopupMenu>,
pub has_debug_info: bool,
#[cfg(feature = "bundle-translations")]
@ -381,19 +394,19 @@ impl CompilationUnit {
) {
fn visit_component<'a>(
root: &'a CompilationUnit,
c: SubComponentIndex,
c: SubComponentIdx,
visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
parent: Option<ParentCtx<'_>>,
) {
let ctx = EvaluationContext::new_sub_component(root, c, (), parent);
let sc = &root.sub_components[c];
visitor(sc, &ctx);
for (idx, r) in sc.repeated.iter().enumerate() {
for (idx, r) in sc.repeated.iter_enumerated() {
visit_component(
root,
r.sub_tree.root,
visitor,
Some(ParentCtx::new(&ctx, Some(idx as u32))),
Some(ParentCtx::new(&ctx, Some(idx))),
);
}
for popup in &sc.popup_windows {
@ -439,7 +452,7 @@ impl CompilationUnit {
visitor(e, ctx);
}
});
for (idx, g) in self.globals.iter().enumerate() {
for (idx, g) in self.globals.iter_enumerated() {
let ctx = EvaluationContext::new_global(self, idx, ());
for e in g.init_values.iter().filter_map(|x| x.as_ref()) {
visitor(&e.expression, &ctx)

View file

@ -11,7 +11,7 @@ use itertools::Either;
use smol_str::{format_smolstr, SmolStr};
use super::lower_to_item_tree::{LoweredElement, LoweredSubComponentMapping, LoweringState};
use super::{Animation, PropertyReference};
use super::{Animation, PropertyIdx, PropertyReference, RepeatedElementIdx};
use crate::expression_tree::{BuiltinFunction, Callable, Expression as tree_Expression};
use crate::langtype::{EnumerationValue, Struct, Type};
use crate::layout::Orientation;
@ -88,10 +88,10 @@ pub fn lower_expression(
)))
}
tree_Expression::RepeaterIndexReference { element } => {
repeater_special_property(element, ctx.component, 1)
repeater_special_property(element, ctx.component, 1usize.into())
}
tree_Expression::RepeaterModelReference { element } => {
repeater_special_property(element, ctx.component, 0)
repeater_special_property(element, ctx.component, 0usize.into())
}
tree_Expression::FunctionParameterReference { index, .. } => {
llr_Expression::FunctionParameterReference { index: *index }
@ -288,7 +288,7 @@ fn lower_assignment(
}
tree_Expression::RepeaterModelReference { element } => {
let rhs = lower_expression(rhs, ctx);
let prop = repeater_special_property(element, ctx.component, 0);
let prop = repeater_special_property(element, ctx.component, 0usize.into());
let level = match &prop {
llr_Expression::PropertyReference(PropertyReference::InParent {
@ -331,7 +331,7 @@ fn lower_assignment(
fn repeater_special_property(
element: &Weak<RefCell<Element>>,
component: &Rc<crate::object_tree::Component>,
property_index: usize,
property_index: PropertyIdx,
) -> llr_Expression {
let mut r = PropertyReference::Local { sub_component_path: vec![], property_index };
let enclosing = element.upgrade().unwrap().borrow().enclosing_component.upgrade().unwrap();
@ -695,7 +695,7 @@ struct BoxLayoutDataResult {
cells: llr_Expression,
/// When there are repeater involved, we need to do a BoxLayoutFunction with the
/// given cell variable and elements
compute_cells: Option<(String, Vec<Either<llr_Expression, u32>>)>,
compute_cells: Option<(String, Vec<Either<llr_Expression, RepeatedElementIdx>>)>,
}
fn box_layout_data(

View file

@ -13,6 +13,7 @@ use crate::CompilerConfiguration;
use smol_str::{format_smolstr, SmolStr};
use std::collections::{BTreeMap, HashMap};
use std::rc::Rc;
use typed_index_collections::TiVec;
pub fn lower_to_item_tree(
document: &crate::object_tree::Document,
@ -31,9 +32,9 @@ pub fn lower_to_item_tree(
);
}
let mut globals = Vec::new();
let mut globals = TiVec::new();
for g in &document.used_types.borrow().globals {
let count = globals.len();
let count = globals.next_key();
globals.push(lower_global(g, count, &mut state));
}
for (g, l) in document.used_types.borrow().globals.iter().zip(&mut globals) {
@ -42,8 +43,8 @@ pub fn lower_to_item_tree(
for c in &document.used_types.borrow().sub_components {
let sc = lower_sub_component(c, &mut state, None, compiler_config);
state.sub_component_mapping.insert(ByAddress(c.clone()), state.sub_components.len());
state.sub_components.push(sc);
let idx = state.sub_components.push_and_get_key(sc);
state.sub_component_mapping.insert(ByAddress(c.clone()), idx);
}
let public_components = document
@ -51,13 +52,12 @@ pub fn lower_to_item_tree(
.map(|component| {
let mut sc = lower_sub_component(&component, &mut state, None, compiler_config);
let public_properties = public_properties(&component, &sc.mapping, &state);
sc.sub_component.name = component.id.clone();
let item_tree = ItemTree {
tree: make_tree(&state, &component.root_element, &sc, &[]),
root: state.sub_components.len(),
root: state.sub_components.push_and_get_key(sc),
parent_context: None,
};
sc.sub_component.name = component.id.clone();
state.sub_components.push(sc);
// For C++ codegen, the root component must have the same name as the public component
PublicComponent {
item_tree,
@ -70,11 +70,6 @@ pub fn lower_to_item_tree(
let popup_menu = document.popup_menu_impl.as_ref().map(|c| {
let sc = lower_sub_component(&c, &mut state, None, compiler_config);
let item_tree = ItemTree {
tree: make_tree(&state, &c.root_element, &sc, &[]),
root: state.sub_components.len(),
parent_context: None,
};
let sub_menu = sc.mapping.map_property_reference(
&NamedReference::new(&c.root_element, SmolStr::new_static("sub-menu")),
&state,
@ -87,7 +82,11 @@ pub fn lower_to_item_tree(
&NamedReference::new(&c.root_element, SmolStr::new_static("entries")),
&state,
);
state.sub_components.push(sc);
let item_tree = ItemTree {
tree: make_tree(&state, &c.root_element, &sc, &[]),
root: state.sub_components.push_and_get_key(sc),
parent_context: None,
};
PopupMenu { item_tree, sub_menu, activated, entries }
});
@ -113,9 +112,9 @@ pub fn lower_to_item_tree(
#[derive(Debug, Clone)]
pub enum LoweredElement {
SubComponent { sub_component_index: usize },
NativeItem { item_index: u32 },
Repeated { repeated_index: u32 },
SubComponent { sub_component_index: SubComponentInstanceIdx },
NativeItem { item_index: ItemInstanceIdx },
Repeated { repeated_index: RepeatedElementIdx },
ComponentPlaceholder { repeated_index: u32 },
}
@ -182,8 +181,8 @@ pub struct LoweredSubComponent {
#[derive(Default)]
pub struct LoweringState {
global_properties: HashMap<NamedReference, PropertyReference>,
sub_components: Vec<LoweredSubComponent>,
sub_component_mapping: HashMap<ByAddress<Rc<Component>>, SubComponentIndex>,
sub_components: TiVec<SubComponentIdx, LoweredSubComponent>,
sub_component_mapping: HashMap<ByAddress<Rc<Component>>, SubComponentIdx>,
#[cfg(feature = "bundle-translations")]
pub translation_builder: Option<super::translations::TranslationsBuilder>,
}
@ -203,20 +202,19 @@ impl LoweringState {
&self.sub_components[self.sub_component_idx(component)]
}
fn sub_component_idx(&self, component: &Rc<Component>) -> usize {
fn sub_component_idx(&self, component: &Rc<Component>) -> SubComponentIdx {
self.sub_component_mapping[&ByAddress(component.clone())]
}
fn push_sub_component(&mut self, sc: LoweredSubComponent) -> SubComponentIndex {
self.sub_components.push(sc);
self.sub_components.len() - 1
fn push_sub_component(&mut self, sc: LoweredSubComponent) -> SubComponentIdx {
self.sub_components.push_and_get_key(sc)
}
}
// Map a PropertyReference within a `sub_component` to a PropertyReference to the component containing it
fn property_reference_within_sub_component(
mut prop_ref: PropertyReference,
sub_component: usize,
sub_component: SubComponentInstanceIdx,
) -> PropertyReference {
match &mut prop_ref {
PropertyReference::Local { sub_component_path, .. }
@ -271,7 +269,7 @@ fn lower_sub_component(
prop_analysis: Default::default(),
};
let mut mapping = LoweredSubComponentMapping::default();
let mut repeated = vec![];
let mut repeated = TiVec::new();
let mut component_container_data = vec![];
let mut accessible_prop = Vec::new();
let mut change_callbacks = Vec::new();
@ -304,32 +302,30 @@ fn lower_sub_component(
continue;
}
if let Type::Function(function) = &x.property_type {
let function_index = sub_component.functions.len();
mapping.property_mapping.insert(
NamedReference::new(element, p.clone()),
PropertyReference::Function { sub_component_path: vec![], function_index },
);
// TODO: Function could wrap the Rc<langtype::Function>
// instead of cloning the return type and args?
sub_component.functions.push(Function {
let function_index = sub_component.functions.push_and_get_key(Function {
name: p.clone(),
ret_ty: function.return_type.clone(),
args: function.args.clone(),
// will be replaced later
code: super::Expression::CodeBlock(vec![]),
});
mapping.property_mapping.insert(
NamedReference::new(element, p.clone()),
PropertyReference::Function { sub_component_path: vec![], function_index },
);
continue;
}
let property_index = sub_component.properties.len();
mapping.property_mapping.insert(
NamedReference::new(element, p.clone()),
PropertyReference::Local { sub_component_path: vec![], property_index },
);
sub_component.properties.push(Property {
let property_index = sub_component.properties.push_and_get_key(Property {
name: format_smolstr!("{}_{}", elem.id, p),
ty: x.property_type.clone(),
..Property::default()
});
mapping.property_mapping.insert(
NamedReference::new(element, p.clone()),
PropertyReference::Local { sub_component_path: vec![], property_index },
);
}
if elem.is_component_placeholder {
mapping.element_mapping.insert(
@ -345,40 +341,43 @@ fn lower_sub_component(
if elem.repeated.is_some() {
mapping.element_mapping.insert(
element.clone().into(),
LoweredElement::Repeated { repeated_index: repeated.len() as u32 },
LoweredElement::Repeated {
repeated_index: repeated.push_and_get_key(element.clone()),
},
);
repeated.push(element.clone());
mapping.repeater_count += 1;
return None;
}
match &elem.base_type {
ElementType::Component(comp) => {
let ty = state.sub_component_idx(comp);
let sub_component_index = sub_component.sub_components.len();
let sub_component_index =
sub_component.sub_components.push_and_get_key(SubComponentInstance {
ty: ty.clone(),
name: elem.id.clone(),
index_in_tree: *elem.item_index.get().unwrap(),
index_of_first_child_in_tree: *elem
.item_index_of_first_children
.get()
.unwrap(),
repeater_offset,
});
mapping.element_mapping.insert(
element.clone().into(),
LoweredElement::SubComponent { sub_component_index },
);
sub_component.sub_components.push(SubComponentInstance {
ty: ty.clone(),
name: elem.id.clone(),
index_in_tree: *elem.item_index.get().unwrap(),
index_of_first_child_in_tree: *elem.item_index_of_first_children.get().unwrap(),
repeater_offset,
});
repeater_offset += comp.repeater_count();
}
ElementType::Native(n) => {
let item_index = sub_component.items.len() as u32;
mapping
.element_mapping
.insert(element.clone().into(), LoweredElement::NativeItem { item_index });
sub_component.items.push(Item {
let item_index = sub_component.items.push_and_get_key(Item {
ty: n.clone(),
name: elem.id.clone(),
index_in_tree: *elem.item_index.get().unwrap(),
})
});
mapping
.element_mapping
.insert(element.clone().into(), LoweredElement::NativeItem { item_index });
}
_ => unreachable!(),
};
@ -671,8 +670,8 @@ fn lower_repeated_component(
root: ctx.state.push_sub_component(sc),
parent_context: Some(e.enclosing_component.upgrade().unwrap().id.clone()),
},
index_prop: (!repeated.is_conditional_element).then_some(1),
data_prop: (!repeated.is_conditional_element).then_some(0),
index_prop: (!repeated.is_conditional_element).then_some(1usize.into()),
data_prop: (!repeated.is_conditional_element).then_some(0usize.into()),
index_in_tree: *e.item_index.get().unwrap(),
listview,
}
@ -686,11 +685,8 @@ fn lower_component_container(
let c = container.borrow();
let component_container_index = *c.item_index.get().unwrap();
let component_container_items_index = sub_component
.items
.iter()
.position(|i| i.index_in_tree == component_container_index)
.unwrap() as u32;
let component_container_items_index =
sub_component.items.position(|i| i.index_in_tree == component_container_index).unwrap();
ComponentContainerElement {
component_container_item_tree_index: component_container_index,
@ -752,39 +748,37 @@ fn lower_timer(timer: &object_tree::Timer, ctx: &ExpressionLoweringCtx) -> Timer
/// Lower the globals (but not their expressions as we first need to lower all the global to get proper mapping in the state)
fn lower_global(
global: &Rc<Component>,
global_index: usize,
global_index: GlobalIdx,
state: &mut LoweringState,
) -> GlobalComponent {
let mut properties = vec![];
let mut const_properties = vec![];
let mut prop_analysis = vec![];
let mut functions = vec![];
let mut properties = TiVec::new();
let mut const_properties = TiVec::new();
let mut prop_analysis = TiVec::new();
let mut functions = TiVec::new();
for (p, x) in &global.root_element.borrow().property_declarations {
if x.is_alias.is_some() {
continue;
}
let property_index = properties.len();
let nr = NamedReference::new(&global.root_element, p.clone());
if let Type::Function(function) = &x.property_type {
let function_index = functions.len();
state.global_properties.insert(
nr.clone(),
PropertyReference::GlobalFunction { global_index, function_index },
);
// TODO: wrap the Rc<langtype::Function> instead of cloning
functions.push(Function {
let function_index = functions.push_and_get_key(Function {
name: p.clone(),
ret_ty: function.return_type.clone(),
args: function.args.clone(),
// will be replaced later
code: super::Expression::CodeBlock(vec![]),
});
state.global_properties.insert(
nr.clone(),
PropertyReference::GlobalFunction { global_index, function_index },
);
continue;
}
properties.push(Property {
let property_index = properties.push_and_get_key(Property {
name: p.clone(),
ty: x.property_type.clone(),
..Property::default()
@ -812,8 +806,11 @@ fn lower_global(
let is_builtin = if let Some(builtin) = global.root_element.borrow().native_class() {
// We just generate the property so we know how to address them
for (p, x) in &builtin.properties {
let property_index = properties.len();
properties.push(Property { name: p.clone(), ty: x.ty.clone(), ..Property::default() });
let property_index = properties.push_and_get_key(Property {
name: p.clone(),
ty: x.ty.clone(),
..Property::default()
});
let nr = NamedReference::new(&global.root_element, p.clone());
state
.global_properties
@ -838,7 +835,7 @@ fn lower_global(
GlobalComponent {
name: global.root_element.borrow().id.clone(),
init_values: vec![None; properties.len()],
init_values: typed_index_collections::ti_vec![None; properties.len()],
properties,
functions,
change_callbacks: BTreeMap::new(),
@ -907,7 +904,7 @@ fn make_tree(
state: &LoweringState,
element: &ElementRc,
component: &LoweredSubComponent,
sub_component_path: &[usize],
sub_component_path: &[SubComponentInstanceIdx],
) -> TreeNode {
let e = element.borrow();
let children = e.children.iter().map(|c| make_tree(state, c, component, sub_component_path));
@ -933,26 +930,20 @@ fn make_tree(
LoweredElement::NativeItem { item_index } => TreeNode {
is_accessible: !e.accessibility_props.0.is_empty(),
sub_component_path: sub_component_path.into(),
item_index: *item_index,
item_index: itertools::Either::Left(*item_index),
children: children.collect(),
repeated: false,
component_container: false,
},
LoweredElement::Repeated { repeated_index } => TreeNode {
is_accessible: false,
sub_component_path: sub_component_path.into(),
item_index: *repeated_index,
item_index: itertools::Either::Right(usize::from(*repeated_index) as u32),
children: vec![],
repeated: true,
component_container: false,
},
LoweredElement::ComponentPlaceholder { repeated_index } => TreeNode {
is_accessible: false,
sub_component_path: sub_component_path.into(),
item_index: *repeated_index + repeater_count,
item_index: itertools::Either::Right(*repeated_index + repeater_count),
children: vec![],
repeated: false,
component_container: true,
},
}
}

View file

@ -24,7 +24,7 @@ pub fn count_property_use(root: &CompilationUnit) {
visit_property(&p.prop, &root_ctx);
}
}
for (idx, g) in root.globals.iter().enumerate().filter(|(_, g)| g.exported) {
for (idx, g) in root.globals.iter_enumerated().filter(|(_, g)| g.exported) {
let ctx = EvaluationContext::new_global(root, idx, ());
for p in g.public_properties.iter().filter(|p| {
!matches!(
@ -63,7 +63,7 @@ pub fn count_property_use(root: &CompilationUnit) {
expr.borrow().visit_property_references(ctx, &mut visit_property);
}
// 4. the models
for (idx, r) in sc.repeated.iter().enumerate() {
for (idx, r) in sc.repeated.iter_enumerated() {
r.model.borrow().visit_property_references(ctx, &mut visit_property);
if let Some(lv) = &r.listview {
visit_property(&lv.viewport_y, ctx);
@ -76,7 +76,7 @@ pub fn count_property_use(root: &CompilationUnit) {
root,
r.sub_tree.root,
(),
Some(ParentCtx::new(ctx, Some(idx as u32))),
Some(ParentCtx::new(ctx, Some(idx))),
);
visit_property(&lv.prop_y, &rep_ctx);
visit_property(&lv.prop_height, &rep_ctx);
@ -136,7 +136,7 @@ pub fn count_property_use(root: &CompilationUnit) {
});
// TODO: only visit used function
for (idx, g) in root.globals.iter().enumerate() {
for (idx, g) in root.globals.iter_enumerated() {
let ctx = EvaluationContext::new_global(root, idx, ());
for f in &g.functions {
f.code.visit_property_references(&ctx, &mut visit_property);

View file

@ -8,7 +8,7 @@ use itertools::Itertools;
use crate::expression_tree::MinMaxOp;
use super::{
CompilationUnit, EvaluationContext, Expression, ParentCtx, PropertyReference, SubComponentIndex,
CompilationUnit, EvaluationContext, Expression, ParentCtx, PropertyReference, SubComponentIdx,
};
pub fn pretty_print(root: &CompilationUnit, writer: &mut dyn Write) -> Result {
@ -22,12 +22,12 @@ struct PrettyPrinter<'a> {
impl<'a> PrettyPrinter<'a> {
fn print_root(&mut self, root: &CompilationUnit) -> Result {
for (idx, g) in root.globals.iter().enumerate() {
for (idx, g) in root.globals.iter_enumerated() {
if !g.is_builtin {
self.print_global(root, idx, g)?;
}
}
for c in 0..root.sub_components.len() {
for c in root.sub_components.keys() {
self.print_component(root, c, None)?
}
@ -37,7 +37,7 @@ impl<'a> PrettyPrinter<'a> {
fn print_component(
&mut self,
root: &CompilationUnit,
sc_idx: SubComponentIndex,
sc_idx: SubComponentIdx,
parent: Option<ParentCtx<'_>>,
) -> Result {
let ctx = EvaluationContext::new_sub_component(root, sc_idx, (), parent);
@ -98,14 +98,10 @@ impl<'a> PrettyPrinter<'a> {
});
writeln!(self.writer, "{} := {} {{ {geometry} }};", item.name, item.ty.class_name)?;
}
for (idx, r) in sc.repeated.iter().enumerate() {
for (idx, r) in sc.repeated.iter_enumerated() {
self.indent()?;
write!(self.writer, "for in {} : ", DisplayExpression(&r.model.borrow(), &ctx))?;
self.print_component(
root,
r.sub_tree.root,
Some(ParentCtx::new(&ctx, Some(idx as u32))),
)?
self.print_component(root, r.sub_tree.root, Some(ParentCtx::new(&ctx, Some(idx))))?
}
for w in &sc.popup_windows {
self.indent()?;
@ -119,7 +115,7 @@ impl<'a> PrettyPrinter<'a> {
fn print_global(
&mut self,
root: &CompilationUnit,
idx: super::GlobalIndex,
idx: super::GlobalIdx,
global: &super::GlobalComponent,
) -> Result {
let ctx = EvaluationContext::new_global(root, idx, ());
@ -206,7 +202,7 @@ impl<T> Display for DisplayPropertyRef<'_, T> {
write!(f, "{}.", sc.sub_components[*i].name)?;
sc = &ctx.compilation_unit.sub_components[sc.sub_components[*i].ty];
}
let i = &sc.items[*item_index as usize];
let i = &sc.items[*item_index];
write!(f, "{}.{}", i.name, prop_name)
}
PropertyReference::InParent { level, parent_reference } => {

View file

@ -385,10 +385,10 @@ mod plural_rule_parser {
fn p(string: &str) -> String {
let ctx = crate::llr::EvaluationContext {
compilation_unit: &crate::llr::CompilationUnit {
public_components: Vec::new(),
sub_components: Vec::new(),
used_sub_components: Vec::new(),
globals: Vec::new(),
public_components: Default::default(),
sub_components: Default::default(),
used_sub_components: Default::default(),
globals: Default::default(),
has_debug_info: false,
translations: None,
popup_menu: None,