mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 06:38:03 +08:00
Write an attribute under a name the graph supplies
`Named<X>` in parameter position declares where a placeholder's name is wired, and the macro gives that input constant text; `Attr<Named<X, V>>` in the return writes under it. The kernel is handed the bare placeholder, since the name is spent resolving the layout and a folded offset is all the write needs, so the hot path matches a marker node's exactly. A name-generic write names its value type through the wired generic, which only an implementations row resolves, so those nodes emit their layout meta per row rather than sharing one across rows. `write_attribute` is the catalog's set half, restoring the identifier master's documents carry with its input positions. Its name input is a constant, so those documents resolve without migration, and the reset marker that stood in for the missing node retires with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -193,7 +193,27 @@ pub const NAMED_PLACEHOLDER: &str = "";
|
||||
/// them takes two names; `V` fixes the value type. The name is absent by
|
||||
/// construction: it comes from the instance's constant text input, folded
|
||||
/// into the layout at graph compile time, so a computed name cannot exist.
|
||||
pub struct Named<X, V>(PhantomData<fn() -> (X, V)>);
|
||||
///
|
||||
/// Written `Named<X>` in parameter position, it declares where `X`'s name is
|
||||
/// wired: the macro gives that input constant text, and the kernel receives
|
||||
/// only the placeholder, since a folded name is a layout fact rather than a
|
||||
/// value the kernel needs.
|
||||
pub struct Named<X, V = Text>(PhantomData<fn() -> (X, V)>);
|
||||
|
||||
impl<X, V> Default for Named<X, V> {
|
||||
fn default() -> Self {
|
||||
Named(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// The placeholders a signature distinguishes its name-generic attributes by.
|
||||
/// A node writing one name uses [`Name0`]; a second name on the same node
|
||||
/// takes [`Name1`], and so on, which is all the placeholder has to do.
|
||||
pub struct Name0;
|
||||
/// The second name-generic attribute in one signature. See [`Name0`].
|
||||
pub struct Name1;
|
||||
/// The third name-generic attribute in one signature. See [`Name0`].
|
||||
pub struct Name2;
|
||||
|
||||
// SAFETY: every obligation is discharged by `V`, which carries the same
|
||||
// contract at the same value type; only the name differs, and the compiler
|
||||
@@ -214,6 +234,63 @@ unsafe impl<X: 'static, V: AttrValue> Attribute for Named<X, V> {
|
||||
const REPARK: Option<crate::list::ReparkFn> = V::REPARK;
|
||||
}
|
||||
|
||||
/// The value a name-generic write takes off the wire, and the row it lands
|
||||
/// in. A plain row is its own wire form; a reference row's wire form is the
|
||||
/// owned payload the kernel parks in the arena, so the field can carry a
|
||||
/// borrow of it for the evaluation.
|
||||
pub trait WireValue: 'static {
|
||||
/// The row this value is written at, fixing the field's value type.
|
||||
type Row: AttrValue;
|
||||
|
||||
/// Moves the value into `arena` where the row borrows it, or hands it back
|
||||
/// unchanged where the row stores it plainly. `None` reports exhaustion.
|
||||
fn park<'e>(self, arena: &'e crate::arena::Arena) -> Option<<Self::Row as AttrValue>::Value<'e>>;
|
||||
}
|
||||
|
||||
/// Declares [`WireValue`] rows. `for T` is a plain value, carried and stored
|
||||
/// as itself; `Wire => Row` parks `Wire`'s payload in the arena and stores the
|
||||
/// borrow `Row` names.
|
||||
#[macro_export]
|
||||
macro_rules! wire_value {
|
||||
() => {};
|
||||
(for $value:ty; $($rest:tt)*) => {
|
||||
impl $crate::attribute::WireValue for $value {
|
||||
type Row = $value;
|
||||
|
||||
fn park<'e>(self, _: &'e $crate::arena::Arena) -> ::core::option::Option<$value> {
|
||||
::core::option::Option::Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
$crate::wire_value!($($rest)*);
|
||||
};
|
||||
($wire:ty => $row:ty; $($rest:tt)*) => {
|
||||
impl $crate::attribute::WireValue for $wire {
|
||||
type Row = $row;
|
||||
|
||||
fn park<'e>(self, arena: &'e $crate::arena::Arena) -> ::core::option::Option<<$row as $crate::attribute::AttrValue>::Value<'e>> {
|
||||
let (parked, _) = arena.alloc(self)?;
|
||||
::core::option::Option::Some(::std::borrow::Borrow::borrow(parked))
|
||||
}
|
||||
}
|
||||
|
||||
$crate::wire_value!($($rest)*);
|
||||
};
|
||||
}
|
||||
|
||||
wire_value! {
|
||||
for f64;
|
||||
for u32;
|
||||
for u64;
|
||||
for bool;
|
||||
for DVec2;
|
||||
for DAffine2;
|
||||
for crate::Color;
|
||||
for crate::blending::BlendMode;
|
||||
::std::vec::Vec<crate::uuid::NodeId> => NodeIdPath;
|
||||
::std::string::String => Text;
|
||||
}
|
||||
|
||||
/// Interns a folded attribute name for the `&'static str` a layout field
|
||||
/// holds. Census names never reach here; a document's novel names are finite
|
||||
/// and repeat across instances, so the leak is one allocation per name.
|
||||
|
||||
@@ -25,7 +25,7 @@ pub use access::{Rec, RecordValue, apply_plan, borrow_element, erase_static, rea
|
||||
pub use frames::{FrameArena, FrameScope, Frames};
|
||||
pub use input::{DerivedLazyInput, DerivedRecordInput, ElementInput, ElementLazyInput, LevelStatus, RecordExtract, RecordInput, RecordLazyInput, fill_frames, materialize_batch, materialize_level};
|
||||
pub use layout::{
|
||||
ElToken, ElementSpec, ElementWrite, ElementWritePick, ElementWritePickHashed, ElementWritePickPlain, FieldDesc, FieldOffset, FieldWrite, InputReads, Layout, LayoutMeta, RecordLayout, copy_plan,
|
||||
ElToken, ElementSpec, ElementWrite, ElementWritePick, ElementWritePickHashed, ElementWritePickPlain, FieldDesc, FieldOffset, FieldWrite, InputReads, Layout, LayoutMeta, NamedWrite, RecordLayout, copy_plan,
|
||||
element_dims, element_parked, element_write, element_write_hashed, empty_layout,
|
||||
};
|
||||
pub use owned::{OwnedRecord, deepen_field_value, has_deep_element_glue, register_deep_element_clone, register_deep_field_value, replay_field_value};
|
||||
|
||||
Reference in New Issue
Block a user