mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 10:50:00 +00:00
LLR: peliminary support for multiple public components
There currently still can only be one because the passes expect that, but now the LLR and generator should be ready to accept multiple public component later
This commit is contained in:
parent
ffbd8a6bfb
commit
d0ed0438ce
10 changed files with 131 additions and 110 deletions
|
@ -94,10 +94,7 @@ pub fn generate(
|
|||
)); // Perhaps byte code in the future?
|
||||
}
|
||||
OutputFormat::Llr => {
|
||||
let root = crate::llr::lower_to_item_tree::lower_to_item_tree(
|
||||
&doc.root_component,
|
||||
compiler_config,
|
||||
);
|
||||
let root = crate::llr::lower_to_item_tree::lower_to_item_tree(&doc, compiler_config);
|
||||
let mut output = String::new();
|
||||
crate::llr::pretty_print::pretty_print(&root, &mut output).unwrap();
|
||||
write!(destination, "{output}")?;
|
||||
|
|
|
@ -769,12 +769,11 @@ pub fn generate(
|
|||
return file;
|
||||
}
|
||||
|
||||
let llr = llr::lower_to_item_tree::lower_to_item_tree(&doc.root_component, compiler_config);
|
||||
let llr = llr::lower_to_item_tree::lower_to_item_tree(&doc, compiler_config);
|
||||
|
||||
// Forward-declare the root so that sub-components can access singletons, the window, etc.
|
||||
file.declarations.push(Declaration::Struct(Struct {
|
||||
name: ident(&llr.item_tree.root.name),
|
||||
..Default::default()
|
||||
file.declarations.extend(llr.public_components.iter().map(|c| {
|
||||
Declaration::Struct(Struct { name: ident(&c.item_tree.root.name), ..Default::default() })
|
||||
}));
|
||||
|
||||
let conditional_includes = ConditionalIncludes::default();
|
||||
|
@ -861,7 +860,9 @@ pub fn generate(
|
|||
}
|
||||
file.declarations.push(Declaration::Struct(globals_struct));
|
||||
|
||||
generate_public_component(&mut file, &conditional_includes, &llr);
|
||||
for p in &llr.public_components {
|
||||
generate_public_component(&mut file, &conditional_includes, p, &llr);
|
||||
}
|
||||
|
||||
generate_type_aliases(&mut file, doc);
|
||||
|
||||
|
@ -943,6 +944,7 @@ fn generate_public_component(
|
|||
file: &mut File,
|
||||
conditional_includes: &ConditionalIncludes,
|
||||
component: &llr::PublicComponent,
|
||||
unit: &llr::CompilationUnit,
|
||||
) {
|
||||
let root_component = &component.item_tree.root;
|
||||
let component_id = ident(&root_component.name);
|
||||
|
@ -959,12 +961,12 @@ fn generate_public_component(
|
|||
}),
|
||||
));
|
||||
|
||||
for glob in component.globals.iter().filter(|glob| !glob.is_builtin) {
|
||||
for glob in unit.globals.iter().filter(|glob| !glob.is_builtin) {
|
||||
component_struct.friends.push(ident(&glob.name));
|
||||
}
|
||||
|
||||
let mut global_accessor_function_body = Vec::new();
|
||||
for glob in component.globals.iter().filter(|glob| glob.exported && !glob.is_builtin) {
|
||||
for glob in unit.globals.iter().filter(|glob| glob.exported && !glob.is_builtin) {
|
||||
let accessor_statement = format!(
|
||||
"{0}if constexpr(std::is_same_v<T, {1}>) {{ return *m_globals.global_{1}.get(); }}",
|
||||
if global_accessor_function_body.is_empty() { "" } else { "else " },
|
||||
|
@ -990,7 +992,7 @@ fn generate_public_component(
|
|||
}
|
||||
|
||||
let ctx = EvaluationContext {
|
||||
public_component: component,
|
||||
compilation_unit: unit,
|
||||
current_sub_component: Some(&component.item_tree.root),
|
||||
current_global: None,
|
||||
generator_state: CppGeneratorContext {
|
||||
|
@ -1006,7 +1008,7 @@ fn generate_public_component(
|
|||
generate_item_tree(
|
||||
&mut component_struct,
|
||||
&component.item_tree,
|
||||
component,
|
||||
unit,
|
||||
None,
|
||||
component_id,
|
||||
Access::Private, // Hide properties and other fields from the C++ API
|
||||
|
@ -1076,9 +1078,6 @@ fn generate_public_component(
|
|||
component_struct.friends.push("slint::private_api::WindowAdapterRc".into());
|
||||
|
||||
add_friends(&mut component_struct.friends, &component.item_tree.root, true);
|
||||
for sc in &component.sub_components {
|
||||
add_friends(&mut component_struct.friends, sc, false);
|
||||
}
|
||||
|
||||
fn add_friends(friends: &mut Vec<String>, sc: &llr::SubComponent, is_root: bool) {
|
||||
if !is_root {
|
||||
|
@ -1099,7 +1098,7 @@ fn generate_public_component(
|
|||
fn generate_item_tree(
|
||||
target_struct: &mut Struct,
|
||||
sub_tree: &llr::ItemTree,
|
||||
root: &llr::PublicComponent,
|
||||
root: &llr::CompilationUnit,
|
||||
parent_ctx: Option<ParentCtx>,
|
||||
item_tree_class_name: String,
|
||||
field_access: Access,
|
||||
|
@ -1568,7 +1567,7 @@ fn generate_item_tree(
|
|||
fn generate_sub_component(
|
||||
target_struct: &mut Struct,
|
||||
component: &llr::SubComponent,
|
||||
root: &llr::PublicComponent,
|
||||
root: &llr::CompilationUnit,
|
||||
parent_ctx: Option<ParentCtx>,
|
||||
field_access: Access,
|
||||
file: &mut File,
|
||||
|
@ -2134,7 +2133,7 @@ fn generate_sub_component(
|
|||
|
||||
fn generate_repeated_component(
|
||||
repeated: &llr::RepeatedElement,
|
||||
root: &llr::PublicComponent,
|
||||
root: &llr::CompilationUnit,
|
||||
parent_ctx: ParentCtx,
|
||||
model_data_type: &Type,
|
||||
file: &mut File,
|
||||
|
@ -2154,7 +2153,7 @@ fn generate_repeated_component(
|
|||
);
|
||||
|
||||
let ctx = EvaluationContext {
|
||||
public_component: root,
|
||||
compilation_unit: root,
|
||||
current_sub_component: Some(&repeated.sub_tree.root),
|
||||
current_global: None,
|
||||
generator_state: CppGeneratorContext { global_access: "self".into(), conditional_includes },
|
||||
|
@ -2263,7 +2262,7 @@ fn generate_global(
|
|||
file: &mut File,
|
||||
conditional_includes: &ConditionalIncludes,
|
||||
global: &llr::GlobalComponent,
|
||||
root: &llr::PublicComponent,
|
||||
root: &llr::CompilationUnit,
|
||||
) {
|
||||
let mut global_struct = Struct { name: ident(&global.name), ..Default::default() };
|
||||
|
||||
|
@ -2656,19 +2655,19 @@ fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) ->
|
|||
}
|
||||
llr::PropertyReference::Global { global_index, property_index } => {
|
||||
let global_access = &ctx.generator_state.global_access;
|
||||
let global = &ctx.public_component.globals[*global_index];
|
||||
let global = &ctx.compilation_unit.globals[*global_index];
|
||||
let global_id = format!("global_{}", ident(&global.name));
|
||||
let property_name = ident(
|
||||
&ctx.public_component.globals[*global_index].properties[*property_index].name,
|
||||
&ctx.compilation_unit.globals[*global_index].properties[*property_index].name,
|
||||
);
|
||||
format!("{}->{}->{}", global_access, global_id, property_name)
|
||||
}
|
||||
llr::PropertyReference::GlobalFunction { global_index, function_index } => {
|
||||
let global_access = &ctx.generator_state.global_access;
|
||||
let global = &ctx.public_component.globals[*global_index];
|
||||
let global = &ctx.compilation_unit.globals[*global_index];
|
||||
let global_id = format!("global_{}", ident(&global.name));
|
||||
let name =
|
||||
ident(&ctx.public_component.globals[*global_index].functions[*function_index].name);
|
||||
ident(&ctx.compilation_unit.globals[*global_index].functions[*function_index].name);
|
||||
format!("{global_access}->{global_id}->fn_{name}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -169,18 +169,16 @@ pub fn generate(doc: &Document, compiler_config: &CompilerConfiguration) -> Toke
|
|||
return TokenStream::default();
|
||||
}
|
||||
|
||||
let llr =
|
||||
crate::llr::lower_to_item_tree::lower_to_item_tree(&doc.root_component, &compiler_config);
|
||||
let llr = crate::llr::lower_to_item_tree::lower_to_item_tree(&doc, &compiler_config);
|
||||
|
||||
let sub_compos = llr
|
||||
.sub_components
|
||||
.iter()
|
||||
.map(|sub_compo| generate_sub_component(sub_compo, &llr, None, None, false))
|
||||
.collect::<Vec<_>>();
|
||||
let public_components =
|
||||
llr.public_components.iter().map(|p| generate_public_component(p, &llr));
|
||||
|
||||
let compo = generate_public_component(&llr);
|
||||
let compo_id = public_component_id(&llr.item_tree.root);
|
||||
let compo_module = format_ident!("slint_generated{}", compo_id);
|
||||
let version_check = format_ident!(
|
||||
"VersionCheck_{}_{}_{}",
|
||||
env!("CARGO_PKG_VERSION_MAJOR"),
|
||||
|
@ -190,9 +188,11 @@ pub fn generate(doc: &Document, compiler_config: &CompilerConfiguration) -> Toke
|
|||
|
||||
let globals =
|
||||
llr.globals.iter().filter(|glob| !glob.is_builtin).map(|glob| generate_global(glob, &llr));
|
||||
let shared_globals = generate_shared_globals(&llr);
|
||||
let globals_ids = llr.globals.iter().filter(|glob| glob.exported).flat_map(|glob| {
|
||||
std::iter::once(ident(&glob.name)).chain(glob.aliases.iter().map(|x| ident(x)))
|
||||
});
|
||||
let compo_ids = llr.public_components.iter().map(|c| public_component_id(&c.item_tree.root));
|
||||
|
||||
let resource_symbols = generate_resources(doc);
|
||||
let named_exports = generate_named_exports(doc);
|
||||
|
@ -201,32 +201,36 @@ pub fn generate(doc: &Document, compiler_config: &CompilerConfiguration) -> Toke
|
|||
#[allow(non_snake_case, non_camel_case_types)]
|
||||
#[allow(unused_braces, unused_parens)]
|
||||
#[allow(clippy::all)]
|
||||
mod #compo_module {
|
||||
mod slint_generated {
|
||||
use slint::private_unstable_api::re_exports as sp;
|
||||
#[allow(unused_imports)]
|
||||
use sp::{RepeatedItemTree as _, ModelExt as _, Model as _, Float as _};
|
||||
#(#structs_and_enum_def)*
|
||||
#(#globals)*
|
||||
#(#sub_compos)*
|
||||
#compo
|
||||
#(#public_components)*
|
||||
#shared_globals
|
||||
#(#resource_symbols)*
|
||||
const _THE_SAME_VERSION_MUST_BE_USED_FOR_THE_COMPILER_AND_THE_RUNTIME : slint::#version_check = slint::#version_check;
|
||||
}
|
||||
#[allow(unused_imports)]
|
||||
pub use #compo_module::{#compo_id #(,#structs_and_enums_ids)* #(,#globals_ids)* #(,#named_exports)*};
|
||||
pub use slint_generated::{#(#compo_ids),* #(,#structs_and_enums_ids)* #(,#globals_ids)* #(,#named_exports)*};
|
||||
#[allow(unused_imports)]
|
||||
pub use slint::{ComponentHandle as _, Global as _, ModelExt as _};
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
||||
fn generate_public_component(
|
||||
llr: &llr::PublicComponent,
|
||||
unit: &llr::CompilationUnit,
|
||||
) -> TokenStream {
|
||||
let public_component_id = public_component_id(&llr.item_tree.root);
|
||||
let inner_component_id = inner_component_id(&llr.item_tree.root);
|
||||
|
||||
let component = generate_item_tree(&llr.item_tree, llr, None, None);
|
||||
let component = generate_item_tree(&llr.item_tree, unit, None, None);
|
||||
|
||||
let ctx = EvaluationContext {
|
||||
public_component: llr,
|
||||
compilation_unit: unit,
|
||||
current_sub_component: Some(&llr.item_tree.root),
|
||||
current_global: None,
|
||||
generator_state: RustGeneratorContext {
|
||||
|
@ -243,10 +247,6 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
|||
&ctx,
|
||||
);
|
||||
|
||||
let global_names =
|
||||
llr.globals.iter().map(|g| format_ident!("global_{}", ident(&g.name))).collect::<Vec<_>>();
|
||||
let global_types = llr.globals.iter().map(global_inner_name).collect::<Vec<_>>();
|
||||
|
||||
quote!(
|
||||
#component
|
||||
pub struct #public_component_id(sp::VRc<sp::ItemTreeVTable, #inner_component_id>);
|
||||
|
@ -254,9 +254,7 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
|||
impl #public_component_id {
|
||||
pub fn new() -> core::result::Result<Self, slint::PlatformError> {
|
||||
let inner = #inner_component_id::new()?;
|
||||
#[allow(unused)]
|
||||
let globals = inner.globals.get().unwrap();
|
||||
#(globals.#global_names.clone().init(globals);)*
|
||||
inner.globals.get().unwrap().init();
|
||||
#inner_component_id::user_init(sp::VRc::map(inner.clone(), |x| x));
|
||||
core::result::Result::Ok(Self(inner))
|
||||
}
|
||||
|
@ -307,7 +305,15 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
|||
T::get(&self)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn generate_shared_globals(llr: &llr::CompilationUnit) -> TokenStream {
|
||||
let global_names =
|
||||
llr.globals.iter().map(|g| format_ident!("global_{}", ident(&g.name))).collect::<Vec<_>>();
|
||||
let global_types = llr.globals.iter().map(global_inner_name).collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
#[allow(dead_code)] // FIXME: some global are unused because of optimization, we should then remove them completely
|
||||
struct SharedGlobals {
|
||||
#(#global_names : ::core::pin::Pin<sp::Rc<#global_types>>,)*
|
||||
|
@ -323,6 +329,10 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
fn init(self: &sp::Rc<Self>) {
|
||||
#(self.#global_names.clone().init(self);)*
|
||||
}
|
||||
|
||||
fn window_adapter_impl(&self) -> sp::Rc<dyn sp::WindowAdapter> {
|
||||
sp::Rc::clone(self.window_adapter_ref().unwrap())
|
||||
}
|
||||
|
@ -341,7 +351,7 @@ fn generate_public_component(llr: &llr::PublicComponent) -> TokenStream {
|
|||
self.window_adapter.get().cloned()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_struct(
|
||||
|
@ -603,7 +613,7 @@ fn public_api(
|
|||
/// Generate the rust code for the given component.
|
||||
fn generate_sub_component(
|
||||
component: &llr::SubComponent,
|
||||
root: &llr::PublicComponent,
|
||||
root: &llr::CompilationUnit,
|
||||
parent_ctx: Option<ParentCtx>,
|
||||
index_property: Option<llr::PropertyIndex>,
|
||||
pinned_drop: bool,
|
||||
|
@ -1012,8 +1022,7 @@ fn generate_sub_component(
|
|||
let layout_info_v = compile_expression(&component.layout_info_v.borrow(), &ctx);
|
||||
|
||||
// FIXME! this is only public because of the ComponentHandle::Inner. we should find another way
|
||||
let visibility =
|
||||
core::ptr::eq(&root.item_tree.root as *const _, component as *const _).then(|| quote!(pub));
|
||||
let visibility = parent_ctx.is_none().then(|| quote!(pub));
|
||||
|
||||
let subtree_index_function = if let Some(property_index) = index_property {
|
||||
let prop = access_member(
|
||||
|
@ -1217,7 +1226,7 @@ fn generate_functions(functions: &[llr::Function], ctx: &EvaluationContext) -> V
|
|||
.collect()
|
||||
}
|
||||
|
||||
fn generate_global(global: &llr::GlobalComponent, root: &llr::PublicComponent) -> TokenStream {
|
||||
fn generate_global(global: &llr::GlobalComponent, root: &llr::CompilationUnit) -> TokenStream {
|
||||
let mut declared_property_vars = vec![];
|
||||
let mut declared_property_types = vec![];
|
||||
let mut declared_callbacks = vec![];
|
||||
|
@ -1294,10 +1303,19 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::PublicComponent) -
|
|||
&ctx,
|
||||
);
|
||||
let public_component_id = ident(&global.name);
|
||||
let root_component_id = self::public_component_id(&root.item_tree.root);
|
||||
let global_id = format_ident!("global_{}", public_component_id);
|
||||
|
||||
let aliases = global.aliases.iter().map(|name| ident(name));
|
||||
let getters = root.public_components.iter().map(|c| {
|
||||
let root_component_id = self::public_component_id(&c.item_tree.root);
|
||||
quote! {
|
||||
impl<'a> slint::Global<'a, #root_component_id> for #public_component_id<'a> {
|
||||
fn get(component: &'a #root_component_id) -> Self {
|
||||
Self(&component.0.globals.get().unwrap().#global_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote!(
|
||||
#[allow(unused)]
|
||||
pub struct #public_component_id<'a>(&'a ::core::pin::Pin<sp::Rc<#inner_component_id>>);
|
||||
|
@ -1305,14 +1323,8 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::PublicComponent) -
|
|||
impl<'a> #public_component_id<'a> {
|
||||
#property_and_callback_accessors
|
||||
}
|
||||
|
||||
#(pub type #aliases<'a> = #public_component_id<'a>;)*
|
||||
|
||||
impl<'a> slint::Global<'a, #root_component_id> for #public_component_id<'a> {
|
||||
fn get(component: &'a #root_component_id) -> Self {
|
||||
Self(&component.0.globals.get().unwrap().#global_id)
|
||||
}
|
||||
}
|
||||
#(#getters)*
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -1348,7 +1360,7 @@ fn generate_global(global: &llr::GlobalComponent, root: &llr::PublicComponent) -
|
|||
|
||||
fn generate_item_tree(
|
||||
sub_tree: &llr::ItemTree,
|
||||
root: &llr::PublicComponent,
|
||||
root: &llr::CompilationUnit,
|
||||
parent_ctx: Option<ParentCtx>,
|
||||
index_property: Option<llr::PropertyIndex>,
|
||||
) -> TokenStream {
|
||||
|
@ -1614,14 +1626,14 @@ fn generate_item_tree(
|
|||
|
||||
fn generate_repeated_component(
|
||||
repeated: &llr::RepeatedElement,
|
||||
root: &llr::PublicComponent,
|
||||
unit: &llr::CompilationUnit,
|
||||
parent_ctx: ParentCtx,
|
||||
) -> TokenStream {
|
||||
let component =
|
||||
generate_item_tree(&repeated.sub_tree, root, Some(parent_ctx), repeated.index_prop);
|
||||
generate_item_tree(&repeated.sub_tree, unit, Some(parent_ctx), repeated.index_prop);
|
||||
|
||||
let ctx = EvaluationContext {
|
||||
public_component: root,
|
||||
compilation_unit: unit,
|
||||
current_sub_component: Some(&repeated.sub_tree.root),
|
||||
current_global: None,
|
||||
generator_state: RustGeneratorContext { global_access: quote!(_self) },
|
||||
|
@ -1631,9 +1643,6 @@ fn generate_repeated_component(
|
|||
|
||||
let inner_component_id = self::inner_component_id(&repeated.sub_tree.root);
|
||||
|
||||
// let rep_inner_component_id = self::inner_component_id(&repeated.sub_tree.root.name);
|
||||
// let inner_component_id = self::inner_component_id(&parent_compo);
|
||||
|
||||
let extra_fn = if let Some(listview) = &repeated.listview {
|
||||
let p_y = access_member(&listview.prop_y, &ctx);
|
||||
let p_height = access_member(&listview.prop_height, &ctx);
|
||||
|
@ -1850,11 +1859,11 @@ fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) ->
|
|||
}
|
||||
llr::PropertyReference::Global { global_index, property_index } => {
|
||||
let global_access = &ctx.generator_state.global_access;
|
||||
let global = &ctx.public_component.globals[*global_index];
|
||||
let global = &ctx.compilation_unit.globals[*global_index];
|
||||
let global_id = format_ident!("global_{}", ident(&global.name));
|
||||
let global_name = global_inner_name(global);
|
||||
let property_name = ident(
|
||||
&ctx.public_component.globals[*global_index].properties[*property_index].name,
|
||||
&ctx.compilation_unit.globals[*global_index].properties[*property_index].name,
|
||||
);
|
||||
quote!(#global_name::FIELD_OFFSETS.#property_name.apply_pin(#global_access.#global_id.as_ref()))
|
||||
}
|
||||
|
@ -1879,11 +1888,11 @@ fn access_member(reference: &llr::PropertyReference, ctx: &EvaluationContext) ->
|
|||
}
|
||||
llr::PropertyReference::GlobalFunction { global_index, function_index } => {
|
||||
let global_access = &ctx.generator_state.global_access;
|
||||
let global = &ctx.public_component.globals[*global_index];
|
||||
let global = &ctx.compilation_unit.globals[*global_index];
|
||||
let global_id = format_ident!("global_{}", ident(&global.name));
|
||||
let fn_id = ident(&format!(
|
||||
"fn_{}",
|
||||
ctx.public_component.globals[*global_index].functions[*function_index].name
|
||||
ctx.compilation_unit.globals[*global_index].functions[*function_index].name
|
||||
));
|
||||
quote!(#global_access.#global_id.as_ref().#fn_id)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ pub mod optim_passes {
|
|||
pub mod count_property_use;
|
||||
mod inline_expressions;
|
||||
|
||||
pub fn run_passes(root: &super::PublicComponent) {
|
||||
pub fn run_passes(root: &super::CompilationUnit) {
|
||||
inline_expressions::inline_simple_expressions(root);
|
||||
count_property_use::count_property_use(root);
|
||||
}
|
||||
|
|
|
@ -436,7 +436,7 @@ impl<'a, T> ParentCtx<'a, T> {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct EvaluationContext<'a, T = ()> {
|
||||
pub public_component: &'a super::PublicComponent,
|
||||
pub compilation_unit: &'a super::CompilationUnit,
|
||||
pub current_sub_component: Option<&'a super::SubComponent>,
|
||||
pub current_global: Option<&'a super::GlobalComponent>,
|
||||
pub generator_state: T,
|
||||
|
@ -449,13 +449,13 @@ pub struct EvaluationContext<'a, T = ()> {
|
|||
|
||||
impl<'a, T> EvaluationContext<'a, T> {
|
||||
pub fn new_sub_component(
|
||||
public_component: &'a super::PublicComponent,
|
||||
compilation_unit: &'a super::CompilationUnit,
|
||||
sub_component: &'a super::SubComponent,
|
||||
generator_state: T,
|
||||
parent: Option<ParentCtx<'a, T>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
public_component,
|
||||
compilation_unit,
|
||||
current_sub_component: Some(sub_component),
|
||||
current_global: None,
|
||||
generator_state,
|
||||
|
@ -465,12 +465,12 @@ impl<'a, T> EvaluationContext<'a, T> {
|
|||
}
|
||||
|
||||
pub fn new_global(
|
||||
public_component: &'a super::PublicComponent,
|
||||
compilation_unit: &'a super::CompilationUnit,
|
||||
global: &'a super::GlobalComponent,
|
||||
generator_state: T,
|
||||
) -> Self {
|
||||
Self {
|
||||
public_component,
|
||||
compilation_unit,
|
||||
current_sub_component: None,
|
||||
current_global: Some(global),
|
||||
generator_state,
|
||||
|
@ -571,7 +571,7 @@ impl<'a, T> EvaluationContext<'a, T> {
|
|||
);
|
||||
}
|
||||
PropertyReference::Global { global_index, property_index } => {
|
||||
let g = &self.public_component.globals[*global_index];
|
||||
let g = &self.compilation_unit.globals[*global_index];
|
||||
return PropertyInfoResult {
|
||||
analysis: Some(&g.prop_analysis[*property_index]),
|
||||
animation: None,
|
||||
|
@ -645,7 +645,7 @@ impl<'a, T> TypeResolutionContext for EvaluationContext<'a, T> {
|
|||
ctx.property_ty(parent_reference)
|
||||
}
|
||||
PropertyReference::Global { global_index, property_index } => {
|
||||
&self.public_component.globals[*global_index].properties[*property_index].ty
|
||||
&self.compilation_unit.globals[*global_index].properties[*property_index].ty
|
||||
}
|
||||
PropertyReference::Function { sub_component_path, function_index } => {
|
||||
if let Some(mut sub_component) = self.current_sub_component {
|
||||
|
@ -660,7 +660,7 @@ impl<'a, T> TypeResolutionContext for EvaluationContext<'a, T> {
|
|||
}
|
||||
}
|
||||
PropertyReference::GlobalFunction { global_index, function_index } => {
|
||||
&self.public_component.globals[*global_index].functions[*function_index].ret_ty
|
||||
&self.compilation_unit.globals[*global_index].functions[*function_index].ret_ty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -788,12 +788,12 @@ impl ContextMap {
|
|||
for i in path {
|
||||
e = &e.sub_components[*i].ty;
|
||||
}
|
||||
EvaluationContext::new_sub_component(ctx.public_component, e, (), None)
|
||||
EvaluationContext::new_sub_component(ctx.compilation_unit, e, (), None)
|
||||
}
|
||||
}
|
||||
ContextMap::InGlobal(g) => EvaluationContext::new_global(
|
||||
ctx.public_component,
|
||||
&ctx.public_component.globals[*g],
|
||||
ctx.compilation_unit,
|
||||
&ctx.compilation_unit.globals[*g],
|
||||
(),
|
||||
),
|
||||
}
|
||||
|
|
|
@ -322,17 +322,22 @@ pub struct PublicComponent {
|
|||
pub public_properties: PublicProperties,
|
||||
pub private_properties: PrivateProperties,
|
||||
pub item_tree: ItemTree,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompilationUnit {
|
||||
pub public_components: Vec<PublicComponent>,
|
||||
pub sub_components: Vec<Rc<SubComponent>>,
|
||||
pub globals: Vec<GlobalComponent>,
|
||||
}
|
||||
|
||||
impl PublicComponent {
|
||||
impl CompilationUnit {
|
||||
pub fn for_each_sub_components<'a>(
|
||||
&'a self,
|
||||
visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
|
||||
) {
|
||||
fn visit_component<'a>(
|
||||
root: &'a PublicComponent,
|
||||
root: &'a CompilationUnit,
|
||||
c: &'a SubComponent,
|
||||
visitor: &mut dyn FnMut(&'a SubComponent, &EvaluationContext<'_>),
|
||||
parent: Option<ParentCtx<'_>>,
|
||||
|
@ -354,7 +359,9 @@ impl PublicComponent {
|
|||
for c in &self.sub_components {
|
||||
visit_component(self, c, visitor, None);
|
||||
}
|
||||
visit_component(self, &self.item_tree.root, visitor, None);
|
||||
for p in &self.public_components {
|
||||
visit_component(self, &p.item_tree.root, visitor, None);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_expression<'a>(
|
||||
|
|
|
@ -14,11 +14,13 @@ use std::collections::{BTreeMap, HashMap};
|
|||
use std::rc::Rc;
|
||||
|
||||
pub fn lower_to_item_tree(
|
||||
component: &Rc<Component>,
|
||||
document: &crate::object_tree::Document,
|
||||
compiler_config: &CompilerConfiguration,
|
||||
) -> PublicComponent {
|
||||
) -> CompilationUnit {
|
||||
let mut state = LoweringState::default();
|
||||
|
||||
let component = &document.root_component;
|
||||
|
||||
let mut globals = Vec::new();
|
||||
for g in &component.used_types.borrow().globals {
|
||||
let count = globals.len();
|
||||
|
@ -36,8 +38,12 @@ pub fn lower_to_item_tree(
|
|||
root: Rc::try_unwrap(sc.sub_component).unwrap(),
|
||||
parent_context: None,
|
||||
};
|
||||
let root = PublicComponent {
|
||||
item_tree,
|
||||
let root = CompilationUnit {
|
||||
public_components: vec![PublicComponent {
|
||||
item_tree,
|
||||
public_properties,
|
||||
private_properties: component.private_properties.borrow().clone(),
|
||||
}],
|
||||
globals,
|
||||
sub_components: component
|
||||
.used_types
|
||||
|
@ -48,8 +54,6 @@ pub fn lower_to_item_tree(
|
|||
state.sub_components[&ByAddress(tree_sub_compo.clone())].sub_component.clone()
|
||||
})
|
||||
.collect(),
|
||||
public_properties,
|
||||
private_properties: component.private_properties.borrow().clone(),
|
||||
};
|
||||
super::optim_passes::run_passes(&root);
|
||||
root
|
||||
|
|
|
@ -6,21 +6,23 @@
|
|||
//! This pass assume that use_count of all properties is zero
|
||||
|
||||
use crate::llr::{
|
||||
Animation, BindingExpression, EvaluationContext, Expression, ParentCtx, PropertyReference,
|
||||
PublicComponent,
|
||||
Animation, BindingExpression, CompilationUnit, EvaluationContext, Expression, ParentCtx,
|
||||
PropertyReference,
|
||||
};
|
||||
|
||||
pub fn count_property_use(root: &PublicComponent) {
|
||||
pub fn count_property_use(root: &CompilationUnit) {
|
||||
// Visit the root properties that are used.
|
||||
// 1. the public properties
|
||||
let root_ctx = EvaluationContext::new_sub_component(root, &root.item_tree.root, (), None);
|
||||
for p in root.public_properties.iter().filter(|p| {
|
||||
!matches!(
|
||||
p.prop,
|
||||
PropertyReference::Function { .. } | PropertyReference::GlobalFunction { .. }
|
||||
)
|
||||
}) {
|
||||
visit_property(&p.prop, &root_ctx);
|
||||
for c in &root.public_components {
|
||||
let root_ctx = EvaluationContext::new_sub_component(root, &c.item_tree.root, (), None);
|
||||
for p in c.public_properties.iter().filter(|p| {
|
||||
!matches!(
|
||||
p.prop,
|
||||
PropertyReference::Function { .. } | PropertyReference::GlobalFunction { .. }
|
||||
)
|
||||
}) {
|
||||
visit_property(&p.prop, &root_ctx);
|
||||
}
|
||||
}
|
||||
for g in root.globals.iter().filter(|g| g.exported) {
|
||||
let ctx = EvaluationContext::new_global(root, g, ());
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//! in the calling expression
|
||||
|
||||
use crate::expression_tree::BuiltinFunction;
|
||||
use crate::llr::{EvaluationContext, Expression, PropertyInfoResult, PublicComponent};
|
||||
use crate::llr::{CompilationUnit, EvaluationContext, Expression, PropertyInfoResult};
|
||||
|
||||
const PROPERTY_ACCESS_COST: isize = 1000;
|
||||
const ALLOC_COST: isize = 700;
|
||||
|
@ -119,7 +119,7 @@ fn builtin_function_cost(function: &BuiltinFunction) -> isize {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn inline_simple_expressions(root: &PublicComponent) {
|
||||
pub fn inline_simple_expressions(root: &CompilationUnit) {
|
||||
root.for_each_expression(&mut |e, ctx| {
|
||||
inline_simple_expressions_in_expression(&mut e.borrow_mut(), ctx)
|
||||
})
|
||||
|
|
|
@ -8,15 +8,15 @@ use itertools::Itertools;
|
|||
use crate::expression_tree::MinMaxOp;
|
||||
|
||||
use super::{
|
||||
EvaluationContext, Expression, ParentCtx, PropertyReference, PublicComponent, SubComponent,
|
||||
CompilationUnit, EvaluationContext, Expression, ParentCtx, PropertyReference, SubComponent,
|
||||
};
|
||||
|
||||
pub fn pretty_print(root: &PublicComponent, writer: &mut dyn Write) -> Result {
|
||||
pub fn pretty_print(root: &CompilationUnit, writer: &mut dyn Write) -> Result {
|
||||
PrettyPrinter { writer, indentation: 0 }.print_root(root)
|
||||
}
|
||||
|
||||
pub fn pretty_print_component(
|
||||
root: &PublicComponent,
|
||||
root: &CompilationUnit,
|
||||
component: &SubComponent,
|
||||
writer: &mut dyn Write,
|
||||
) -> Result {
|
||||
|
@ -29,16 +29,19 @@ struct PrettyPrinter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> PrettyPrinter<'a> {
|
||||
fn print_root(&mut self, root: &PublicComponent) -> Result {
|
||||
fn print_root(&mut self, root: &CompilationUnit) -> Result {
|
||||
for c in &root.sub_components {
|
||||
self.print_component(root, c, None)?
|
||||
}
|
||||
self.print_component(root, &root.item_tree.root, None)
|
||||
for p in &root.public_components {
|
||||
self.print_component(root, &p.item_tree.root, None)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_component(
|
||||
&mut self,
|
||||
root: &PublicComponent,
|
||||
root: &CompilationUnit,
|
||||
sc: &SubComponent,
|
||||
parent: Option<ParentCtx<'_>>,
|
||||
) -> Result {
|
||||
|
@ -137,7 +140,7 @@ impl<T> Display for DisplayPropertyRef<'_, T> {
|
|||
write!(f, "{}", Self(parent_reference, ctx))
|
||||
}
|
||||
PropertyReference::Global { global_index, property_index } => {
|
||||
let g = &ctx.public_component.globals[*global_index];
|
||||
let g = &ctx.compilation_unit.globals[*global_index];
|
||||
write!(f, "{}.{}", g.name, g.properties[*property_index].name)
|
||||
}
|
||||
PropertyReference::Function { sub_component_path, function_index } => {
|
||||
|
@ -153,7 +156,7 @@ impl<T> Display for DisplayPropertyRef<'_, T> {
|
|||
}
|
||||
}
|
||||
PropertyReference::GlobalFunction { global_index, function_index } => {
|
||||
let g = &ctx.public_component.globals[*global_index];
|
||||
let g = &ctx.compilation_unit.globals[*global_index];
|
||||
write!(f, "{}.{}", g.name, g.functions[*function_index].name)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue