mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Add the folded subject to LayoutMeta and derive reducer depth from it
This commit is contained in:
@@ -284,6 +284,10 @@ pub struct LayoutMeta {
|
||||
/// The depth change the node applies: `0` for elementwise and flip nodes,
|
||||
/// `+1` for a creator, `-1` for a reducer.
|
||||
pub level_delta: i8,
|
||||
/// The materialized subject a reducer folds, as `(input, levels)`: the
|
||||
/// output keeps the subject's levels above the folded ones, so the depth
|
||||
/// derives from its layout even though it contributes no fields.
|
||||
pub folded: Option<(u8, u8)>,
|
||||
}
|
||||
|
||||
/// The attributes a node reads from one input, recorded on [`LayoutMeta`] for
|
||||
@@ -314,6 +318,7 @@ impl LayoutMeta {
|
||||
writes: Vec::new(),
|
||||
removes: Vec::new(),
|
||||
level_delta: 0,
|
||||
folded: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +333,13 @@ impl LayoutMeta {
|
||||
sources => Layout::union(sources),
|
||||
}
|
||||
.without(&self.removes);
|
||||
let depth = (base.depth as i8 + self.level_delta).max(0) as u8;
|
||||
let depth = match self.folded {
|
||||
Some((input, levels)) => {
|
||||
let subject = inputs[input as usize].expect("layout fold folded input has no layout");
|
||||
(subject.depth.saturating_sub(levels) as i8 + self.level_delta).max(0) as u8
|
||||
}
|
||||
None => (base.depth as i8 + self.level_delta).max(0) as u8,
|
||||
};
|
||||
let element = match &self.element {
|
||||
ElementSpec::Concrete(element) => *element,
|
||||
ElementSpec::Carried => base.element,
|
||||
|
||||
@@ -236,6 +236,10 @@ pub(crate) fn layout_meta_tokens(node: &Node, element_spec: TokenStream2, core_t
|
||||
quote!((<#marker as #core_types::attribute::Attribute>::NAME, #level))
|
||||
});
|
||||
let level_delta = level_delta(node);
|
||||
let folded = match folded_subject(node) {
|
||||
Some((index, levels)) => quote!(::core::option::Option::Some((#index, #levels))),
|
||||
None => quote!(::core::option::Option::None),
|
||||
};
|
||||
quote! {
|
||||
#core_types::record::LayoutMeta {
|
||||
sources: ::std::vec![#(#sources),*],
|
||||
@@ -244,10 +248,20 @@ pub(crate) fn layout_meta_tokens(node: &Node, element_spec: TokenStream2, core_t
|
||||
writes: ::std::vec![#(#writes),*],
|
||||
removes: ::std::vec![#(#removes),*],
|
||||
level_delta: #level_delta,
|
||||
folded: #folded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The materialized subject a node folds, as `(input, levels)`.
|
||||
pub(crate) fn folded_subject(node: &Node) -> Option<(u8, u8)> {
|
||||
node.inputs
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(index, input)| input.subject && materialized_levels(node, *index) > 0)
|
||||
.map(|(index, _)| (index as u8, materialized_levels(node, index)))
|
||||
}
|
||||
|
||||
fn field_writes(attrs: &[LevelAttr], core_types: &TokenStream2) -> Vec<TokenStream2> {
|
||||
attrs
|
||||
.iter()
|
||||
|
||||
@@ -636,6 +636,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 1,
|
||||
folded: None,
|
||||
};
|
||||
let node = install(
|
||||
RepeatNode::new(RecordSource::new(bare_source(&base, 7.), &base, &base), count_edge, reverse_edge, &base, &count_layout, &reverse_layout),
|
||||
@@ -671,6 +672,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 1,
|
||||
folded: None,
|
||||
};
|
||||
let repeat = install(
|
||||
RepeatNode::new(RecordSource::new(IndexSourceNode { layout: base.clone() }, &base, &base), count_edge, reverse_edge, &base, &count_layout, &reverse_layout),
|
||||
@@ -712,6 +714,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 1,
|
||||
folded: None,
|
||||
};
|
||||
let repeat = install(
|
||||
RepeatNode::new(RecordSource::new(IndexSourceNode { layout: base.clone() }, &base, &base), count_edge, reverse_edge, &base, &count_layout, &reverse_layout),
|
||||
@@ -755,6 +758,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 1,
|
||||
folded: None,
|
||||
};
|
||||
let repeat = install(
|
||||
RepeatNode::new(RecordSource::new(content, &leveled_content, &leveled_content), count_edge, reverse_edge, &leveled_content, &count_layout, &reverse_layout),
|
||||
@@ -854,6 +858,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 0,
|
||||
folded: None,
|
||||
};
|
||||
let node = install(
|
||||
ExtendNode::new(RecordSource::new(base, &base_layout, &union), RecordSource::new(new, &new_layout, &union), &union),
|
||||
@@ -903,6 +908,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 0,
|
||||
folded: None,
|
||||
};
|
||||
let build = |index: f64| {
|
||||
let content = LeveledSourceNode {
|
||||
@@ -958,6 +964,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 0,
|
||||
folded: None,
|
||||
};
|
||||
install(
|
||||
IndexElementsNode::new(RecordSource::new(content, &layout, &layout), index_edge, &layout, &index_layout),
|
||||
@@ -1174,6 +1181,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 1,
|
||||
folded: None,
|
||||
};
|
||||
let nested = install(
|
||||
RepeatNode::new(RecordSource::new(content, &leveled_content, &leveled_content), count_edge, reverse_edge, &leveled_content, &count_layout, &reverse_layout),
|
||||
@@ -1234,6 +1242,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta: 1,
|
||||
folded: None,
|
||||
};
|
||||
let repeat = install(
|
||||
RepeatNode::new(RecordSource::new(IndexSourceNode { layout: base.clone() }, &base, &base), count_edge, reverse_edge, &base, &count_layout, &reverse_layout),
|
||||
|
||||
@@ -409,6 +409,7 @@ mod tests {
|
||||
writes: vec![],
|
||||
removes: vec![],
|
||||
level_delta,
|
||||
folded: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user