Skip to content

Commit a843ba2

Browse files
committed
llr: Split the EvaluationContext and the EvaluationScope
The idea is that we want to be able to get a scope without borrowing the llr::Compilation unit so we can have mutable borrow to the compilation unit
1 parent 075f387 commit a843ba2

File tree

7 files changed

+247
-252
lines changed

7 files changed

+247
-252
lines changed

internal/compiler/generator/cpp.rs

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ pub fn concatenate_ident(ident: &str) -> SmolStr {
6969
/// Given a property reference to a native item (eg, the property name is empty)
7070
/// return tokens to the `ItemRc`
7171
fn access_item_rc(pr: &llr::MemberReference, ctx: &EvaluationContext) -> String {
72-
let mut ctx = ctx;
7372
let mut component_access = "self->".into();
7473

7574
let llr::MemberReference::Relative { parent_level, local_reference } = pr else {
@@ -82,12 +81,11 @@ fn access_item_rc(pr: &llr::MemberReference, ctx: &EvaluationContext) -> String
8281

8382
for _ in 0..*parent_level {
8483
component_access = format!("{component_access}parent.lock().value()->");
85-
ctx = ctx.parent.as_ref().unwrap().ctx;
8684
}
8785

8886
let (sub_compo_path, sub_component) = follow_sub_component_path(
8987
ctx.compilation_unit,
90-
ctx.current_sub_component.unwrap(),
88+
ctx.parent_sub_component_idx(*parent_level).unwrap(),
9189
&local_reference.sub_component_path,
9290
);
9391
if !local_reference.sub_component_path.is_empty() {
@@ -467,7 +465,7 @@ use crate::expression_tree::{BuiltinFunction, EasingCurve, MinMaxOp};
467465
use crate::langtype::{Enumeration, EnumerationValue, NativeClass, Type};
468466
use crate::layout::Orientation;
469467
use crate::llr::{
470-
self, EvaluationContext as llr_EvaluationContext, ParentCtx as llr_ParentCtx,
468+
self, EvaluationContext as llr_EvaluationContext, EvaluationScope, ParentScope,
471469
TypeResolutionContext as _,
472470
};
473471
use crate::object_tree::Document;
@@ -494,7 +492,6 @@ struct CppGeneratorContext<'a> {
494492
}
495493

496494
type EvaluationContext<'a> = llr_EvaluationContext<'a, CppGeneratorContext<'a>>;
497-
type ParentCtx<'a> = llr_ParentCtx<'a, CppGeneratorContext<'a>>;
498495

499496
impl CppType for Type {
500497
fn cpp_type(&self) -> Option<SmolStr> {
@@ -607,7 +604,7 @@ fn handle_property_init(
607604
ctx: &EvaluationContext,
608605
) {
609606
let prop_access = access_local_member(prop, ctx);
610-
let prop_type = ctx.local_property_ty(prop);
607+
let prop_type = ctx.relative_property_ty(prop, 0);
611608
if let Type::Callback(callback) = &prop_type {
612609
let mut ctx2 = ctx.clone();
613610
ctx2.argument_types = &callback.args;
@@ -1239,13 +1236,11 @@ fn generate_public_component(
12391236

12401237
let ctx = EvaluationContext {
12411238
compilation_unit: unit,
1242-
current_sub_component: Some(component.item_tree.root),
1243-
current_global: None,
1239+
current_scope: EvaluationScope::SubComponent(component.item_tree.root, None),
12441240
generator_state: CppGeneratorContext {
12451241
global_access: "(&this->m_globals)".to_string(),
12461242
conditional_includes,
12471243
},
1248-
parent: None,
12491244
argument_types: &[],
12501245
};
12511246

@@ -1355,7 +1350,7 @@ fn generate_item_tree(
13551350
target_struct: &mut Struct,
13561351
sub_tree: &llr::ItemTree,
13571352
root: &llr::CompilationUnit,
1358-
parent_ctx: Option<ParentCtx>,
1353+
parent_ctx: Option<&ParentScope>,
13591354
is_popup_menu: bool,
13601355
item_tree_class_name: SmolStr,
13611356
field_access: Access,
@@ -1533,7 +1528,7 @@ fn generate_item_tree(
15331528
format!("*result = {{ parent->self_weak, 0 }};"),
15341529
]
15351530
}, |idx| {
1536-
let current_sub_component = parent.ctx.current_sub_component().unwrap();
1531+
let current_sub_component = &root.sub_components[parent.sub_component];
15371532
let parent_index = current_sub_component.repeated[idx].index_in_tree;
15381533
vec![
15391534
format!("auto self = reinterpret_cast<const {item_tree_class_name}*>(component.instance);"),
@@ -1768,7 +1763,7 @@ fn generate_item_tree(
17681763

17691764
if let Some(parent) = &parent_ctx {
17701765
let parent_type =
1771-
format!("class {} const *", ident(&parent.ctx.current_sub_component().unwrap().name));
1766+
format!("class {} const *", ident(&root.sub_components[parent.sub_component].name));
17721767
create_parameters.push(format!("{parent_type} parent"));
17731768

17741769
init_parent_parameters = ", parent";
@@ -1861,7 +1856,7 @@ fn generate_sub_component(
18611856
target_struct: &mut Struct,
18621857
component: llr::SubComponentIdx,
18631858
root: &llr::CompilationUnit,
1864-
parent_ctx: Option<ParentCtx>,
1859+
parent_ctx: Option<&ParentScope>,
18651860
field_access: Access,
18661861
file: &mut File,
18671862
conditional_includes: &ConditionalIncludes,
@@ -1918,7 +1913,7 @@ fn generate_sub_component(
19181913
init.push("self->tree_index = tree_index;".into());
19191914

19201915
if let Some(parent_ctx) = &parent_ctx {
1921-
let parent_type = ident(&parent_ctx.ctx.current_sub_component().unwrap().name);
1916+
let parent_type = ident(&root.sub_components[parent_ctx.sub_component].name);
19221917
init_parameters.push(format!("class {parent_type} const *parent"));
19231918

19241919
target_struct.members.push((
@@ -1944,14 +1939,16 @@ fn generate_sub_component(
19441939

19451940
let component = &root.sub_components[component];
19461941

1942+
let parent_ctx = ParentScope::new(&ctx, None);
1943+
19471944
component.popup_windows.iter().for_each(|popup| {
19481945
let component_id = ident(&root.sub_components[popup.item_tree.root].name);
19491946
let mut popup_struct = Struct { name: component_id.clone(), ..Default::default() };
19501947
generate_item_tree(
19511948
&mut popup_struct,
19521949
&popup.item_tree,
19531950
root,
1954-
Some(ParentCtx::new(&ctx, None)),
1951+
Some(&parent_ctx),
19551952
false,
19561953
component_id,
19571954
Access::Public,
@@ -1968,7 +1965,7 @@ fn generate_sub_component(
19681965
&mut menu_struct,
19691966
menu,
19701967
root,
1971-
Some(ParentCtx::new(&ctx, None)),
1968+
Some(&parent_ctx),
19721969
false,
19731970
component_id,
19741971
Access::Public,
@@ -2092,7 +2089,7 @@ fn generate_sub_component(
20922089

20932090
for (prop1, prop2, fields) in &component.two_way_bindings {
20942091
if fields.is_empty() {
2095-
let ty = ctx.local_property_ty(&prop1).cpp_type().unwrap();
2092+
let ty = ctx.relative_property_ty(&prop1, 0).cpp_type().unwrap();
20962093
let p1 = access_local_member(prop1, &ctx);
20972094
init.push(
20982095
access_member(prop2, &ctx).then(|p2| {
@@ -2152,7 +2149,7 @@ fn generate_sub_component(
21522149
generate_repeated_component(
21532150
repeated,
21542151
root,
2155-
ParentCtx::new(&ctx, Some(idx)),
2152+
ParentScope::new(&ctx, Some(idx)),
21562153
data_type.as_ref(),
21572154
file,
21582155
conditional_includes,
@@ -2498,7 +2495,7 @@ fn generate_sub_component(
24982495
fn generate_repeated_component(
24992496
repeated: &llr::RepeatedElement,
25002497
root: &llr::CompilationUnit,
2501-
parent_ctx: ParentCtx,
2498+
parent_ctx: ParentScope,
25022499
model_data_type: Option<&Type>,
25032500
file: &mut File,
25042501
conditional_includes: &ConditionalIncludes,
@@ -2509,7 +2506,7 @@ fn generate_repeated_component(
25092506
&mut repeater_struct,
25102507
&repeated.sub_tree,
25112508
root,
2512-
Some(parent_ctx),
2509+
Some(&parent_ctx),
25132510
false,
25142511
repeater_id.clone(),
25152512
Access::Public,
@@ -2519,10 +2516,8 @@ fn generate_repeated_component(
25192516

25202517
let ctx = EvaluationContext {
25212518
compilation_unit: root,
2522-
current_sub_component: Some(repeated.sub_tree.root),
2523-
current_global: None,
2519+
current_scope: EvaluationScope::SubComponent(repeated.sub_tree.root, Some(&parent_ctx)),
25242520
generator_state: CppGeneratorContext { global_access: "self".into(), conditional_includes },
2525-
parent: Some(parent_ctx),
25262521
argument_types: &[],
25272522
};
25282523

@@ -2965,13 +2960,11 @@ fn access_window_field(ctx: &EvaluationContext) -> String {
29652960
fn access_member(reference: &llr::MemberReference, ctx: &EvaluationContext) -> MemberAccess {
29662961
match reference {
29672962
llr::MemberReference::Relative { parent_level, local_reference } => {
2968-
let mut ctx = ctx;
29692963
let mut path = MemberAccess::Direct("self".to_string());
29702964
for _ in 0..*parent_level {
29712965
path = path.and_then(|x| format!("{x}->parent.lock()"));
2972-
ctx = ctx.parent.as_ref().unwrap().ctx;
29732966
}
2974-
if let Some(sub_component) = ctx.current_sub_component {
2967+
if let Some(sub_component) = ctx.parent_sub_component_idx(*parent_level) {
29752968
let (compo_path, sub_component) = follow_sub_component_path(
29762969
ctx.compilation_unit,
29772970
sub_component,
@@ -3141,14 +3134,9 @@ fn native_prop_info<'a, 'b>(
31413134
unreachable!()
31423135
};
31433136

3144-
let mut ctx = ctx;
3145-
for _ in 0..*parent_level {
3146-
ctx = ctx.parent.as_ref().unwrap().ctx;
3147-
}
3148-
31493137
let (_, sub_component) = follow_sub_component_path(
31503138
ctx.compilation_unit,
3151-
ctx.current_sub_component.unwrap(),
3139+
ctx.parent_sub_component_idx(*parent_level).unwrap(),
31523140
&local_reference.sub_component_path,
31533141
);
31543142
(&sub_component.items[*item_index].ty, prop_name)
@@ -3364,16 +3352,17 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
33643352
Expression::ModelDataAssignment { level, value } => {
33653353
let value = compile_expression(value, ctx);
33663354
let mut path = "self".to_string();
3367-
let mut ctx2 = ctx;
3355+
let EvaluationScope::SubComponent(mut sc, mut par) = ctx.current_scope else { unreachable!() };
33683356
let mut repeater_index = None;
33693357
for _ in 0..=*level {
3370-
let x = ctx2.parent.unwrap();
3371-
ctx2 = x.ctx;
3358+
let x = par.unwrap();
3359+
par = x.parent;
33723360
repeater_index = x.repeater_index;
3361+
sc = x.sub_component;
33733362
write!(path, "->parent.lock().value()").unwrap();
33743363
}
33753364
let repeater_index = repeater_index.unwrap();
3376-
let local_reference = ctx2.current_sub_component().unwrap().repeated[repeater_index].index_prop.unwrap().into();
3365+
let local_reference = ctx.compilation_unit.sub_components[sc].repeated[repeater_index].index_prop.unwrap().into();
33773366
let index_prop = llr::MemberReference::Relative { parent_level: *level, local_reference };
33783367
let index_access = access_member(&index_prop, ctx).get_property();
33793368
write!(path, "->repeater_{}", usize::from(repeater_index)).unwrap();
@@ -3902,26 +3891,24 @@ fn compile_builtin_function_call(
39023891
if let [llr::Expression::NumberLiteral(popup_index), close_policy, llr::Expression::PropertyReference(parent_ref)] =
39033892
arguments
39043893
{
3905-
let mut parent_ctx = ctx;
39063894
let mut component_access = MemberAccess::Direct("self".into());
3907-
if let llr::MemberReference::Relative { parent_level, .. } = parent_ref {
3908-
for _ in 0..*parent_level {
3909-
component_access = component_access.and_then(|x| format!("{x}->parent.lock()"));
3910-
parent_ctx = parent_ctx.parent.as_ref().unwrap().ctx;
3911-
}
3912-
};
3895+
let llr::MemberReference::Relative { parent_level, .. } = parent_ref else {unreachable!()};
3896+
for _ in 0..*parent_level {
3897+
component_access = component_access.and_then(|x| format!("{x}->parent.lock()"));
3898+
}
39133899

39143900
let window = access_window_field(ctx);
3915-
let current_sub_component = parent_ctx.current_sub_component().unwrap();
3901+
let current_sub_component = &ctx.compilation_unit.sub_components[ctx.parent_sub_component_idx(*parent_level).unwrap()];
39163902
let popup = &current_sub_component.popup_windows[*popup_index as usize];
39173903
let popup_window_id =
39183904
ident(&ctx.compilation_unit.sub_components[popup.item_tree.root].name);
39193905
let parent_component = access_item_rc(parent_ref, ctx);
3906+
let parent_ctx = ParentScope::new(ctx, None);
39203907
let popup_ctx = EvaluationContext::new_sub_component(
39213908
ctx.compilation_unit,
39223909
popup.item_tree.root,
39233910
CppGeneratorContext { global_access: "self->globals".into(), conditional_includes: ctx.generator_state.conditional_includes },
3924-
Some(ParentCtx::new(ctx, None)),
3911+
Some(&parent_ctx),
39253912
);
39263913
let position = compile_expression(&popup.position.borrow(), &popup_ctx);
39273914
let close_policy = compile_expression(close_policy, ctx);
@@ -3934,14 +3921,11 @@ fn compile_builtin_function_call(
39343921
}
39353922
BuiltinFunction::ClosePopupWindow => {
39363923
if let [llr::Expression::NumberLiteral(popup_index), llr::Expression::PropertyReference(parent_ref)] = arguments {
3937-
let mut parent_ctx = ctx;
39383924
let mut component_access = MemberAccess::Direct("self".into());
3939-
if let llr::MemberReference::Relative { parent_level, .. } = parent_ref {
3940-
for _ in 0..*parent_level {
3941-
component_access = component_access.and_then(|x| format!("{x}->parent.lock()"));
3942-
parent_ctx = parent_ctx.parent.as_ref().unwrap().ctx;
3943-
}
3944-
};
3925+
let llr::MemberReference::Relative { parent_level, .. } = parent_ref else {unreachable!()};
3926+
for _ in 0..*parent_level {
3927+
component_access = component_access.and_then(|x| format!("{x}->parent.lock()"));
3928+
}
39453929

39463930
let window = access_window_field(ctx);
39473931
component_access.then(|component_access| format!("{window}.close_popup({component_access}->popup_id_{popup_index})"))
@@ -4309,13 +4293,11 @@ fn generate_translation(
43094293

43104294
let ctx = EvaluationContext {
43114295
compilation_unit,
4312-
current_sub_component: None,
4313-
current_global: None,
4296+
current_scope: EvaluationScope::Global(0.into()),
43144297
generator_state: CppGeneratorContext {
43154298
global_access: "\n#error \"language rule can't access state\";".into(),
43164299
conditional_includes: &Default::default(),
43174300
},
4318-
parent: None,
43194301
argument_types: &[Type::Int32],
43204302
};
43214303
declarations.push(Declaration::Var(Var {

0 commit comments

Comments
 (0)