mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 05:08:11 +08:00
Emit layout metadata from the intent IR
This commit is contained in:
@@ -1743,35 +1743,14 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let layout_meta_fn = format_ident!("{}_layout_meta", fn_name);
|
let layout_meta_fn = format_ident!("{}_layout_meta", fn_name);
|
||||||
let carrier_present = !shape.skips_carrier();
|
|
||||||
let element_spec = match &shape.element_write {
|
let element_spec = match &shape.element_write {
|
||||||
Some(ty) => quote!(#core_types::record::ElementSpec::Concrete(#core_types::record::element_write::<#ty>())),
|
Some(ty) => quote!(#core_types::record::ElementSpec::Concrete(#core_types::record::element_write::<#ty>())),
|
||||||
None => quote!(#core_types::record::ElementSpec::Carried),
|
None => quote!(#core_types::record::ElementSpec::Carried),
|
||||||
};
|
};
|
||||||
let sources = if carrier_present { quote!(::std::vec![0u8]) } else { quote!(::std::vec![]) };
|
let layout_meta = crate::codegen::ir::layout_meta_tokens(&crate::codegen::ir::build(parsed), element_spec, core_types);
|
||||||
let reads_meta: Vec<TokenStream2> = regular_fields
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(_, field)| !field.attribute_reads.is_empty())
|
|
||||||
.map(|(index, field)| {
|
|
||||||
let descs = field.attribute_reads.iter().map(|read| {
|
|
||||||
let marker = &read.marker;
|
|
||||||
quote!(#core_types::record::FieldWrite::of::<#marker>(0))
|
|
||||||
});
|
|
||||||
let index = index as u8;
|
|
||||||
quote!(#core_types::record::InputReads { input: #index, reads: ::std::vec![#(#descs),*] })
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let layout_meta_def = quote! {
|
let layout_meta_def = quote! {
|
||||||
#vis fn #layout_meta_fn() -> #core_types::record::LayoutMeta {
|
#vis fn #layout_meta_fn() -> #core_types::record::LayoutMeta {
|
||||||
#core_types::record::LayoutMeta {
|
#layout_meta
|
||||||
sources: #sources,
|
|
||||||
reads: ::std::vec![#(#reads_meta),*],
|
|
||||||
element: #element_spec,
|
|
||||||
writes: ::std::vec![#(#write_descs),*],
|
|
||||||
removes: ::std::vec![#(#remove_pairs),*],
|
|
||||||
level_delta: 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let reading_secondaries = reading_secondary_indices(®ular_fields, shape);
|
let reading_secondaries = reading_secondary_indices(®ular_fields, shape);
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ fn flip_entries_tokens(parsed: &ParsedNodeFn, struct_name: &Ident, regular_field
|
|||||||
let arity = regular_fields.len();
|
let arity = regular_fields.len();
|
||||||
let names: Vec<&Ident> = regular_fields.iter().map(|field| &field.pat_ident.ident).collect();
|
let names: Vec<&Ident> = regular_fields.iter().map(|field| &field.pat_ident.ident).collect();
|
||||||
let node_underscores: Vec<TokenStream2> = regular_fields.iter().map(|_| quote!(_)).collect();
|
let node_underscores: Vec<TokenStream2> = regular_fields.iter().map(|_| quote!(_)).collect();
|
||||||
let carrier_present = flip_carrier(parsed);
|
let node = crate::codegen::ir::build(parsed);
|
||||||
let sources = if carrier_present { quote!(::std::vec![0u8]) } else { quote!(::std::vec![]) };
|
let core_types = quote!(gcore);
|
||||||
|
|
||||||
// Shorthand associated types in the output only resolve against the
|
// Shorthand associated types in the output only resolve against the
|
||||||
// generics' bounds, so rows name the output through a bounded alias. Only
|
// generics' bounds, so rows name the output through a bounded alias. Only
|
||||||
@@ -142,16 +142,11 @@ fn flip_entries_tokens(parsed: &ParsedNodeFn, struct_name: &Ident, regular_field
|
|||||||
let layout = format_ident!("__layout_{index}");
|
let layout = format_ident!("__layout_{index}");
|
||||||
quote!(&#layout,)
|
quote!(&#layout,)
|
||||||
});
|
});
|
||||||
|
let element_spec = quote!(gcore::record::ElementSpec::Concrete(gcore::record::element_write::<#row_output>()));
|
||||||
|
let layout_meta = crate::codegen::ir::layout_meta_tokens(&node, element_spec, &core_types);
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
gcore::registry::RegistryEntry {
|
gcore::registry::RegistryEntry {
|
||||||
layout_meta: Some(gcore::record::LayoutMeta {
|
layout_meta: Some(#layout_meta),
|
||||||
sources: #sources,
|
|
||||||
reads: ::std::vec::Vec::new(),
|
|
||||||
element: gcore::record::ElementSpec::Concrete(gcore::record::element_write::<#row_output>()),
|
|
||||||
writes: ::std::vec::Vec::new(),
|
|
||||||
removes: ::std::vec::Vec::new(),
|
|
||||||
level_delta: 0,
|
|
||||||
}),
|
|
||||||
io: gcore::registry::NodeIOTypes::new(
|
io: gcore::registry::NodeIOTypes::new(
|
||||||
gcore::concrete!(gcore::context::ContextImpl<'static>),
|
gcore::concrete!(gcore::context::ContextImpl<'static>),
|
||||||
gcore::registry::record_type::<#row_output>(),
|
gcore::registry::record_type::<#row_output>(),
|
||||||
@@ -325,18 +320,11 @@ fn single_row_entries(parsed: &ParsedNodeFn, class: &Class, struct_name: &Ident,
|
|||||||
quote!(&#layout,)
|
quote!(&#layout,)
|
||||||
});
|
});
|
||||||
|
|
||||||
let carried_meta = |sources: &[usize]| {
|
let node = crate::codegen::ir::build(parsed);
|
||||||
let sources = sources.iter().map(|index| *index as u8);
|
let core_types = quote!(gcore);
|
||||||
quote! {
|
let carried_meta = |_sources: &[usize]| {
|
||||||
Some(gcore::record::LayoutMeta {
|
let meta = crate::codegen::ir::layout_meta_tokens(&node, quote!(gcore::record::ElementSpec::Carried), &core_types);
|
||||||
sources: ::std::vec![#(#sources),*],
|
quote!(Some(#meta))
|
||||||
reads: ::std::vec::Vec::new(),
|
|
||||||
element: gcore::record::ElementSpec::Carried,
|
|
||||||
writes: ::std::vec::Vec::new(),
|
|
||||||
removes: ::std::vec::Vec::new(),
|
|
||||||
level_delta: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (io_output, wrap, prelude, new_layout_args, layout_meta) = match class {
|
let (io_output, wrap, prelude, new_layout_args, layout_meta) = match class {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ use crate::codegen::classify::{
|
|||||||
};
|
};
|
||||||
use crate::codegen::entries::implementation_rows;
|
use crate::codegen::entries::implementation_rows;
|
||||||
use crate::parsing::{AttributeRead, NodeParsedField, ParsedField, ParsedFieldType, ParsedNodeFn, RecordWrites, RegularParsedField, record_writes};
|
use crate::parsing::{AttributeRead, NodeParsedField, ParsedField, ParsedFieldType, ParsedNodeFn, RecordWrites, RegularParsedField, record_writes};
|
||||||
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
|
use quote::quote;
|
||||||
use syn::{GenericArgument, GenericParam, Ident, PathArguments, Type, TypeParamBound};
|
use syn::{GenericArgument, GenericParam, Ident, PathArguments, Type, TypeParamBound};
|
||||||
|
|
||||||
pub(crate) fn build(parsed: &ParsedNodeFn) -> Node {
|
pub(crate) fn build(parsed: &ParsedNodeFn) -> Node {
|
||||||
@@ -165,6 +167,52 @@ fn ilist_inner(ty: &Type) -> Option<Type> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits the `LayoutMeta` literal from the IR. `element_spec` is supplied by the
|
||||||
|
/// caller since it is the one row-dependent facet; the rest folds from the node.
|
||||||
|
pub(crate) fn layout_meta_tokens(node: &Node, element_spec: TokenStream2, core_types: &TokenStream2) -> TokenStream2 {
|
||||||
|
let sources = node.inputs.iter().enumerate().filter(|(_, input)| input.subject).map(|(index, _)| index as u8);
|
||||||
|
let reads = node.inputs.iter().enumerate().filter_map(|(index, input)| {
|
||||||
|
(!input.shape.attrs.is_empty()).then(|| {
|
||||||
|
let descs = field_writes(&input.shape.attrs, core_types);
|
||||||
|
let index = index as u8;
|
||||||
|
quote!(#core_types::record::InputReads { input: #index, reads: ::std::vec![#(#descs),*] })
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let writes = field_writes(&node.output.shape.attrs, core_types);
|
||||||
|
let removes = node.output.removes.iter().map(|attr| {
|
||||||
|
let marker = &attr.marker;
|
||||||
|
let level = attr.level;
|
||||||
|
quote!((<#marker as #core_types::attribute::Attribute>::NAME, #level))
|
||||||
|
});
|
||||||
|
let level_delta = level_delta(node);
|
||||||
|
quote! {
|
||||||
|
#core_types::record::LayoutMeta {
|
||||||
|
sources: ::std::vec![#(#sources),*],
|
||||||
|
reads: ::std::vec![#(#reads),*],
|
||||||
|
element: #element_spec,
|
||||||
|
writes: ::std::vec![#(#writes),*],
|
||||||
|
removes: ::std::vec![#(#removes),*],
|
||||||
|
level_delta: #level_delta,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn field_writes(attrs: &[LevelAttr], core_types: &TokenStream2) -> Vec<TokenStream2> {
|
||||||
|
attrs
|
||||||
|
.iter()
|
||||||
|
.map(|attr| {
|
||||||
|
let marker = &attr.marker;
|
||||||
|
let level = attr.level;
|
||||||
|
quote!(#core_types::record::FieldWrite::of::<#marker>(#level))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn level_delta(node: &Node) -> i8 {
|
||||||
|
let subject_depth = node.inputs.iter().find(|input| input.subject).map_or(0, |input| input.shape.depth as i8);
|
||||||
|
node.output.shape.depth as i8 - subject_depth
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Node {
|
pub(crate) struct Node {
|
||||||
pub(crate) kernel: Kernel,
|
pub(crate) kernel: Kernel,
|
||||||
pub(crate) generics: Vec<Generic>,
|
pub(crate) generics: Vec<Generic>,
|
||||||
|
|||||||
Reference in New Issue
Block a user