Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
464 changes: 186 additions & 278 deletions internal/compiler/generator/cpp.rs

Large diffs are not rendered by default.

539 changes: 231 additions & 308 deletions internal/compiler/generator/rust.rs

Large diffs are not rendered by default.

431 changes: 182 additions & 249 deletions internal/compiler/llr/expression.rs

Large diffs are not rendered by default.

150 changes: 106 additions & 44 deletions internal/compiler/llr/item_tree.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// 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::{EvaluationContext, Expression, ParentCtx};
use super::{EvaluationContext, Expression, ParentScope};
use crate::langtype::{NativeClass, Type};
use smol_str::SmolStr;
use std::cell::{Cell, RefCell};
use std::collections::{BTreeMap, HashMap};
use std::num::NonZeroUsize;
use std::rc::Rc;
use typed_index_collections::TiVec;

Expand Down Expand Up @@ -104,26 +103,82 @@ impl GlobalComponent {
}
}

/// a Reference to a property, in the context of a SubComponent
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum PropertyReference {
/// A property relative to this SubComponent
Local { sub_component_path: Vec<SubComponentInstanceIdx>, property_index: PropertyIdx },
/// A property in a Native item
InNativeItem {
sub_component_path: Vec<SubComponentInstanceIdx>,
#[derive(Clone, Debug, Hash, PartialEq, Eq, derive_more::From)]
pub enum LocalMemberIndex {
#[from]
Property(PropertyIdx),
#[from]
Function(FunctionIdx),
Native {
item_index: ItemInstanceIdx,
prop_name: String,
prop_name: SmolStr,
},
}
impl LocalMemberIndex {
pub fn property(&self) -> Option<PropertyIdx> {
if let LocalMemberIndex::Property(p) = self {
Some(*p)
} else {
None
}
}
}

/// A reference to a property, callback, or function, in the context of a SubComponent
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum MemberReference {
/// The property or callback is withing a global
Global { global_index: GlobalIdx, member: LocalMemberIndex },

/// The reference is relative to the current SubComponent
Relative {
/// Go up so many level to reach the parent
parent_level: usize,
local_reference: LocalMemberReference,
},
/// 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: GlobalIdx, property_index: PropertyIdx },
}
impl MemberReference {
/// this is only valid for relative local reference
#[track_caller]
pub fn local(&self) -> LocalMemberReference {
match self {
MemberReference::Relative { parent_level: 0, local_reference, .. } => {
local_reference.clone()
}
_ => panic!("not a local reference"),
}
}

/// A function in a sub component.
Function { sub_component_path: Vec<SubComponentInstanceIdx>, function_index: FunctionIdx },
/// A function in a global.
GlobalFunction { global_index: GlobalIdx, function_index: FunctionIdx },
pub fn is_function(&self) -> bool {
match self {
MemberReference::Global { member: LocalMemberIndex::Function(..), .. }
| MemberReference::Relative {
local_reference:
LocalMemberReference { reference: LocalMemberIndex::Function(..), .. },
..
} => true,
_ => false,
}
}
}

impl From<LocalMemberReference> for MemberReference {
fn from(local_reference: LocalMemberReference) -> Self {
MemberReference::Relative { parent_level: 0, local_reference }
}
}

/// A reference to something within an ItemTree
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LocalMemberReference {
pub sub_component_path: Vec<SubComponentInstanceIdx>,
pub reference: LocalMemberIndex,
}

impl<T: Into<LocalMemberIndex>> From<T> for LocalMemberReference {
fn from(reference: T) -> Self {
Self { sub_component_path: vec![], reference: reference.into() }
}
}

#[derive(Debug, Default)]
Expand All @@ -147,18 +202,18 @@ pub struct Function {
/// The property references might be either in the parent context, or in the
/// repeated's component context
pub struct ListViewInfo {
pub viewport_y: PropertyReference,
pub viewport_height: PropertyReference,
pub viewport_width: PropertyReference,
pub viewport_y: LocalMemberReference,
pub viewport_height: LocalMemberReference,
pub viewport_width: LocalMemberReference,
/// The ListView's inner visible height (not counting eventual scrollbar)
pub listview_height: PropertyReference,
pub listview_height: LocalMemberReference,
/// The ListView's inner visible width (not counting eventual scrollbar)
pub listview_width: PropertyReference,
pub listview_width: LocalMemberReference,

// In the repeated component context
pub prop_y: PropertyReference,
pub prop_y: MemberReference,
// In the repeated component context
pub prop_height: PropertyReference,
pub prop_height: MemberReference,
}

#[derive(Debug)]
Expand Down Expand Up @@ -272,13 +327,13 @@ pub struct SubComponent {
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)>,
pub change_callbacks: Vec<(PropertyReference, MutExpression)>,
pub property_init: Vec<(MemberReference, BindingExpression)>,
pub change_callbacks: Vec<(MemberReference, MutExpression)>,
/// The animation for properties which are animated
pub animations: HashMap<PropertyReference, Expression>,
pub animations: HashMap<LocalMemberReference, Expression>,
/// The two way bindings that map the first property to the second wih optional field access
pub two_way_bindings: Vec<(PropertyReference, PropertyReference, Vec<SmolStr>)>,
pub const_properties: Vec<PropertyReference>,
pub two_way_bindings: Vec<(MemberReference, MemberReference, Vec<SmolStr>)>,
pub const_properties: Vec<LocalMemberReference>,
/// Code that is run in the sub component constructor, after property initializations
pub init_code: Vec<MutExpression>,

Expand All @@ -294,7 +349,7 @@ pub struct SubComponent {
/// Maps item index to a list of encoded element infos of the element (type name, qualified ids).
pub element_infos: BTreeMap<u32, String>,

pub prop_analysis: HashMap<PropertyReference, PropAnalysis>,
pub prop_analysis: HashMap<MemberReference, PropAnalysis>,
}

#[derive(Debug)]
Expand All @@ -306,10 +361,10 @@ pub struct PopupWindow {
#[derive(Debug)]
pub struct PopupMenu {
pub item_tree: ItemTree,
pub sub_menu: PropertyReference,
pub activated: PropertyReference,
pub close: PropertyReference,
pub entries: PropertyReference,
pub sub_menu: MemberReference,
pub activated: MemberReference,
pub close: MemberReference,
pub entries: MemberReference,
}

#[derive(Debug)]
Expand Down Expand Up @@ -346,10 +401,16 @@ impl SubComponent {
}

/// Return if a local property is used. (unused property shouldn't be generated)
pub fn prop_used(&self, prop: &PropertyReference, cu: &CompilationUnit) -> bool {
if let PropertyReference::Local { property_index, sub_component_path } = prop {
pub fn prop_used(&self, prop: &MemberReference, cu: &CompilationUnit) -> bool {
let MemberReference::Relative { parent_level, local_reference } = prop else {
return true;
};
if *parent_level != 0 {
return true;
}
if let LocalMemberIndex::Property(property_index) = &local_reference.reference {
let mut sc = self;
for i in sub_component_path {
for i in &local_reference.sub_component_path {
sc = &cu.sub_components[sc.sub_components[*i].ty];
}
if sc.properties[*property_index].use_count.get() == 0 {
Expand Down Expand Up @@ -410,7 +471,7 @@ impl CompilationUnit {
root: &'a CompilationUnit,
c: SubComponentIdx,
visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
parent: Option<ParentCtx<'_>>,
parent: Option<&ParentScope<'_>>,
) {
let ctx = EvaluationContext::new_sub_component(root, c, (), parent);
let sc = &root.sub_components[c];
Expand All @@ -420,19 +481,19 @@ impl CompilationUnit {
root,
r.sub_tree.root,
visitor,
Some(ParentCtx::new(&ctx, Some(idx))),
Some(&ParentScope::new(&ctx, Some(idx))),
);
}
for popup in &sc.popup_windows {
visit_component(
root,
popup.item_tree.root,
visitor,
Some(ParentCtx::new(&ctx, None)),
Some(&ParentScope::new(&ctx, None)),
);
}
for menu_tree in &sc.menu_item_trees {
visit_component(root, menu_tree.root, visitor, Some(ParentCtx::new(&ctx, None)));
visit_component(root, menu_tree.root, visitor, Some(&ParentScope::new(&ctx, None)));
}
}
for c in &self.used_sub_components {
Expand Down Expand Up @@ -481,11 +542,12 @@ impl CompilationUnit {
}
}

/// Depending on the type, this can also be a Callback or a Function
#[derive(Debug, Clone)]
pub struct PublicProperty {
pub name: SmolStr,
pub ty: Type,
pub prop: PropertyReference,
pub prop: MemberReference,
pub read_only: bool,
}
pub type PublicProperties = Vec<PublicProperty>;
Expand Down
45 changes: 21 additions & 24 deletions internal/compiler/llr/lower_expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@

use std::cell::RefCell;
use std::collections::{BTreeMap, HashMap};
use std::num::NonZeroUsize;
use std::rc::{Rc, Weak};

use itertools::Either;
use smol_str::{format_smolstr, SmolStr};

use super::lower_to_item_tree::{LoweredElement, LoweredSubComponentMapping, LoweringState};
use super::{Animation, PropertyIdx, PropertyReference, RepeatedElementIdx};
use super::{Animation, LocalMemberReference, MemberReference, PropertyIdx, RepeatedElementIdx};
use crate::expression_tree::{BuiltinFunction, Callable, Expression as tree_Expression};
use crate::langtype::{EnumerationValue, Struct, Type};
use crate::layout::Orientation;
Expand All @@ -33,32 +32,28 @@ pub struct ExpressionLoweringCtx<'a> {
}

impl ExpressionLoweringCtx<'_> {
pub fn map_property_reference(&self, from: &NamedReference) -> PropertyReference {
pub fn map_property_reference(&self, from: &NamedReference) -> MemberReference {
let element = from.element();
let enclosing = &element.borrow().enclosing_component.upgrade().unwrap();
let mut level = 0;
let mut map = &self.inner;
if !enclosing.is_global() {
let mut map = &self.inner;
let mut level = 0;
while !Rc::ptr_eq(enclosing, map.component) {
map = map.parent.unwrap();
level += 1;
}
if let Some(level) = NonZeroUsize::new(level) {
return PropertyReference::InParent {
level,
parent_reference: Box::new(
map.mapping.map_property_reference(from, self.state),
),
};
}
}
self.mapping.map_property_reference(from, self.state)
let mut r = map.mapping.map_property_reference(from, self.state);
if let MemberReference::Relative { parent_level, .. } = &mut r {
*parent_level += level;
}
r
}
}

impl super::TypeResolutionContext for ExpressionLoweringCtx<'_> {
fn property_ty(&self, _: &PropertyReference) -> &Type {
todo!()
fn property_ty(&self, _: &MemberReference) -> &Type {
unimplemented!()
}
}

Expand Down Expand Up @@ -334,7 +329,7 @@ fn lower_assignment(
repeater_special_property(element, ctx.component, PropertyIdx::REPEATER_DATA);

let level = match &prop {
PropertyReference::InParent { level, .. } => (*level).into(),
MemberReference::Relative { parent_level, .. } => *parent_level,
_ => 0,
};

Expand Down Expand Up @@ -377,10 +372,9 @@ pub fn repeater_special_property(
element: &Weak<RefCell<Element>>,
component: &Rc<crate::object_tree::Component>,
property_index: PropertyIdx,
) -> PropertyReference {
let mut r = PropertyReference::Local { sub_component_path: vec![], property_index };
) -> MemberReference {
let enclosing = element.upgrade().unwrap().borrow().enclosing_component.upgrade().unwrap();
let mut level = 0;
let mut parent_level = 0;
let mut component = component.clone();
while !Rc::ptr_eq(&enclosing, &component) {
component = component
Expand All @@ -391,12 +385,15 @@ pub fn repeater_special_property(
.enclosing_component
.upgrade()
.unwrap();
level += 1;
parent_level += 1;
}
if let Some(level) = NonZeroUsize::new(level - 1) {
r = PropertyReference::InParent { level, parent_reference: Box::new(r) };
MemberReference::Relative {
parent_level: parent_level - 1,
local_reference: LocalMemberReference {
sub_component_path: vec![],
reference: property_index.into(),
},
}
r
}

fn lower_restart_timer(args: &[tree_Expression]) -> llr_Expression {
Expand Down
Loading
Loading