mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 06:38:03 +08:00
Emit declarative LayoutMeta from the node macro into registry entries
This commit is contained in:
@@ -242,6 +242,52 @@ pub fn empty_layout() -> &'static Layout {
|
||||
EMPTY.get_or_init(Layout::default)
|
||||
}
|
||||
|
||||
/// Declarative record-io metadata for a node type, emitted by the macro into
|
||||
/// its registry entry so the compiler can fold each wire's layout without
|
||||
/// running the node's constructor. [`fold`](LayoutMeta::fold) reproduces the
|
||||
/// layout the constructor derives at wiring today; the compiler layout pass
|
||||
/// calls it over the proto graph instead.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LayoutMeta {
|
||||
/// Whether the node derives its layout from a carrier input; `false` writes
|
||||
/// a fresh record from `Layout::default`.
|
||||
pub carrier: bool,
|
||||
/// The output element: a concrete write, or carried through from the carrier.
|
||||
pub element: ElementSpec,
|
||||
/// The attributes the node writes at its acting level.
|
||||
pub writes: Vec<FieldWrite>,
|
||||
/// The attributes removed from the carrier's layout, as `(name, level)`.
|
||||
pub removes: Vec<(&'static str, u8)>,
|
||||
/// The depth change the node applies to its carrier: `0` for elementwise and
|
||||
/// flip nodes, `+1` for a creator, `-1` for a reducer.
|
||||
pub level_delta: i8,
|
||||
}
|
||||
|
||||
/// Where a node's output element comes from, for [`LayoutMeta`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ElementSpec {
|
||||
/// The node writes this concrete element.
|
||||
Concrete(ElementWrite),
|
||||
/// The node carries the carrier's element through unchanged.
|
||||
Carried,
|
||||
}
|
||||
|
||||
impl LayoutMeta {
|
||||
/// Folds the node's output layout from its carrier's, reproducing what the
|
||||
/// node's constructor derives at wiring. `carrier` is the carrier input's
|
||||
/// layout, or `None` when the node writes a fresh record.
|
||||
pub fn fold(&self, carrier: Option<&Layout>) -> Layout {
|
||||
let carrier = carrier.filter(|_| self.carrier);
|
||||
let base = carrier.map_or_else(Layout::default, |c| c.without(&self.removes));
|
||||
let depth = (carrier.map_or(0, |c| c.depth) as i8 + self.level_delta).max(0) as u8;
|
||||
let element = match &self.element {
|
||||
ElementSpec::Concrete(element) => *element,
|
||||
ElementSpec::Carried => carrier.map_or_else(ElementWrite::default, |c| c.element),
|
||||
};
|
||||
base.with_writes(depth, element, &self.writes)
|
||||
}
|
||||
}
|
||||
|
||||
/// A view of one record: a pointer whose layout is proven at wiring.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Rec(*const u8);
|
||||
|
||||
@@ -170,6 +170,11 @@ where
|
||||
unsafe { self.ptr.as_ref() }.extent(input)
|
||||
}
|
||||
|
||||
fn extent_at(&self, input: &Input, level: u8) -> crate::gpoll::GPoll<crate::gpoll::Extent> {
|
||||
// SAFETY: as in eval.
|
||||
unsafe { self.ptr.as_ref() }.extent_at(input, level)
|
||||
}
|
||||
|
||||
fn serialize(&self) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>> {
|
||||
// SAFETY: as in eval.
|
||||
unsafe { self.ptr.as_ref() }.serialize()
|
||||
@@ -278,6 +283,10 @@ pub type NodeConstructor = fn(Vec<EdgeHandle>) -> Result<EdgeHandle, Constructio
|
||||
pub struct RegistryEntry {
|
||||
pub io: NodeIOTypes,
|
||||
pub constructor: NodeConstructor,
|
||||
/// Declarative record-io metadata for the compiler layout pass; `None` for
|
||||
/// nodes whose layout the pass does not yet fold (routing/opaque, hand-written
|
||||
/// rows), which keep the construction-time path.
|
||||
pub layout_meta: Option<crate::record::LayoutMeta>,
|
||||
}
|
||||
|
||||
pub fn construct(entry: &RegistryEntry, inputs: Vec<EdgeHandle>) -> Result<EdgeHandle, ConstructionError> {
|
||||
@@ -502,6 +511,7 @@ mod tests {
|
||||
Ok(EdgeHandle::new(Arc::new(ValueNode(0u32)) as Arc<ErasedNode<u32>>))
|
||||
}
|
||||
let entry = RegistryEntry {
|
||||
layout_meta: None,
|
||||
io: NodeIOTypes::new(concrete!(Context), concrete!(u32), vec![edge_type::<String>()]),
|
||||
constructor: construct_strlen,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user