Sweep the data-flow wire and edge wording to input and source

This commit is contained in:
Dennis Kobert
2026-09-06 15:14:55 +00:00
parent 96521333d6
commit 9d3abe385f
34 changed files with 156 additions and 156 deletions

View File

@@ -266,7 +266,7 @@ macro_rules! tagged_value {
}
}
/// The record layout of this value's edge: leveled for the list-carrying
/// The record layout of this value's source: leveled for the list-carrying
/// variants, element-only at rank 0 otherwise. `None` for a
/// [`Self::TypeDefault`] whose named type is outside `for_each_type_default!`.
pub fn value_layout(&self) -> Option<core_types::record::Layout> {
@@ -309,7 +309,7 @@ macro_rules! tagged_value {
}
}
/// Materializes the value as [`Self::to_dynany`] does, wrapped in a value edge typed by [`Self::ty`].
/// Materializes the value as [`Self::to_dynany`] does, wrapped in a value source typed by [`Self::ty`].
pub fn to_edge(self) -> Result<EdgeHandle, String> {
match self {
// ===============
@@ -358,7 +358,7 @@ macro_rules! tagged_value {
}
}
/// Evaluates a typed edge and converts the landed value into a tagged value, with the coverage of [`Self::try_from_any`].
/// Evaluates a typed source and converts the landed value into a tagged value, with the coverage of [`Self::try_from_any`].
pub fn from_edge<'f>(handle: EdgeHandle, ctx: &Context<'f>, frames: &core_types::record::Frames<'f>) -> Result<GPoll<Self>, String> {
let ty = handle.ty().clone();
// =======================
@@ -447,7 +447,7 @@ macro_rules! tagged_value {
$( if name == core_types::normalize_type_name(std::any::type_name::<$ty>()) { return Some(TaggedValue::$identifier(Default::default())) } )*
if name == core_types::normalize_type_name(std::any::type_name::<List<f64>>()) { return Some(TaggedValue::F64Array(Vec::new())) }
if name == core_types::normalize_type_name(std::any::type_name::<List<BrushStroke>>()) { return Some(TaggedValue::BrushStrokes(Vec::new())) }
// Leveled wires type by their element; each element name maps to the
// Leveled inputs type by their element; each element name maps to the
// same tagged default as its legacy list form.
if name == core_types::normalize_type_name(std::any::type_name::<Color>()) { return Some(TaggedValue::Color(Some(Color::default()))) }
if name == core_types::normalize_type_name(std::any::type_name::<GradientStops>()) { return Some(TaggedValue::Gradient(GradientStops::default())) }
@@ -705,7 +705,7 @@ impl TaggedValue {
match ty {
Type::Generic(_) => None,
// A leveled wire's default is its element's default, as in `from_type`.
// A leveled input's default is its element's default, as in `from_type`.
Type::Record(inner) => TaggedValue::from_primitive_string(string, inner),
Type::Concrete(concrete_type) => {
let ty = concrete_type.id?;

View File

@@ -1041,8 +1041,8 @@ fn valid_type(from: &Type, to: &Type) -> bool {
// Graphite doesn't have subtyping currently, but it used to have it, and may do so again, so we make sure to compare types in this way to make things easier.
// More details explained here: <https://github.com/GraphiteEditor/Graphite/issues/1741>
(Type::Fn(in1, out1), Type::Fn(in2, out2)) => valid_type(out2, out1) && valid_type(in1, in2),
// A lend edge is substitutable exactly when the lent values are.
// A record edge is substitutable exactly when the elements are.
// A lend input is substitutable exactly when the lent values are.
// A record input is substitutable exactly when the elements are.
(Type::Record(in1), Type::Record(in2)) => valid_type(in1, in2),
// If either the proposed input or the allowed input are generic, we allow the substitution (meaning this is a valid subtype).
// TODO: Add proper generic counting which is not based on the name

View File

@@ -173,7 +173,7 @@ impl DynamicExecutor {
/// Calls the `Node::serialize` for that specific node. A monitor serializes
/// its stored context snapshot, and this entry recreates the monitored
/// value from it as the legacy value the editor's downcasts expect: a
/// rank-0 wire yields its element and a leveled wire its legacy list.
/// rank-0 input yields its element and a leveled input its legacy list.
pub fn introspect(&self, node_path: &[NodeId]) -> Result<Arc<dyn std::any::Any + Send + Sync + 'static>, IntrospectError> {
let result = self.tree.introspect(node_path)?;
if result.downcast_ref::<core_types::context::CtxSnapshot>().is_some() {
@@ -184,7 +184,7 @@ impl DynamicExecutor {
Ok(result)
}
/// Re-evaluates the monitored edge at `node_path` with its stored context
/// Re-evaluates the monitored input at `node_path` with its stored context
/// snapshot and hands the resulting resident batch to `read`, inside the
/// introspection window. The monitor stores only the context; the value is
/// recreated against current source data, so a read right after an
@@ -222,7 +222,7 @@ impl DynamicExecutor {
match core_types::record::serve_input(&edge, &ctx, &frames) {
GPoll::Final(value) | GPoll::Partial(value) => {
let rec = layout.rec(&value);
// SAFETY: the serve produced one live record of the edge's layout.
// SAFETY: the serve produced one live record of the input's layout.
let batch = unsafe { core_types::node::RecordBatch::new(rec.ptr(), 1, layout) };
read(layout, batch, &arena)
}

View File

@@ -128,7 +128,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, Vec<RegistryEntry>> {
.into_iter()
.map(|entry| (graphene_std::graphic::to_graphic::IDENTIFIER.clone(), entry)),
);
// The transitional level bridge: a leveled wire materializes into the legacy
// The transitional level bridge: a leveled input materializes into the legacy
// list an unconverted consumer expects. The rows are keyed under the legacy
// convert identifiers and die with the last legacy consumer.
node_types.extend(
@@ -367,7 +367,7 @@ mod tests {
}
}
/// One wire kind: every row consumes and produces record wires. A plain
/// One input kind: every row consumes and produces records. A plain
/// io type here would need a bridge adapter, and those are gone.
#[test]
fn every_registry_row_is_record_typed() {

View File

@@ -244,7 +244,7 @@ impl IndexLevels {
self.0 == u32::MAX
}
/// The same requirement seen from outside an edge whose innermost `supplied`
/// The same requirement seen from outside an input whose innermost `supplied`
/// levels the reading node drives itself, and whose chain sits `delta`
/// deeper than that node's. A supplied level leaves no requirement behind;
/// the rest renumber by the depth difference. An all-levels mask stays

View File

@@ -6,7 +6,7 @@
use crate::gpoll::{Extent, GPoll};
/// A wired value input; `get` evaluates the edge and yields the typed element.
/// A wired value input; `get` evaluates the input and yields the typed element.
pub struct ValueIn<'a, T> {
read: &'a dyn Fn() -> GPoll<T>,
}
@@ -21,9 +21,9 @@ impl<'a, T> ValueIn<'a, T> {
}
}
/// An upstream edge's extents. For derived (per-copy) content the query runs
/// An upstream input's extents. For derived (per-copy) content the query runs
/// at the given copy's promoted context; `at` queries copy 0, the uniform
/// default. For ordinary edges the copy is ignored.
/// default. For ordinary inputs the copy is ignored.
pub struct ExtentIn<'a> {
query: &'a dyn Fn(u64, u8) -> GPoll<Extent>,
}
@@ -62,7 +62,7 @@ impl<'a, T> ListIn<'a, T> {
(self.get)()
}
/// The subject wire's total flat extent as a plain query.
/// The subject input's total flat extent as a plain query.
pub fn total(&self) -> GPoll<crate::gpoll::Extent> {
(self.total)()
}

View File

@@ -208,7 +208,7 @@ impl Extent {
}
/// The sum of two extents, used to concatenate a level; a free operand
/// counts as one lane, so a scalar edge joins a concat as a single item,
/// counts as one lane, so a scalar input joins a concat as a single item,
/// and a lower-bound operand keeps the sum a lower bound.
pub fn sum(a: GPoll<Extent>, b: GPoll<Extent>) -> GPoll<Extent> {
let lanes = |extent| match extent {

View File

@@ -16,7 +16,7 @@ pub enum BatchStatus<'a> {
/// mutate the lanes or reclaim the buffer for in-place reuse. The extent
/// hint is as for `Lent`.
Filled(RecordBatchMut<'a>, Finality, Extent),
/// No batch implementation behind this edge; a driver answers with the
/// No batch implementation behind this input; a driver answers with the
/// per-lane serve and copy-out loop ([`crate::record::fill_frames`]).
Unbatched,
Pending,
@@ -519,9 +519,9 @@ impl StatusCell {
Self { no_partial: true, ..Self::new() }
}
/// Claims the edge's own frame out of `frames`, serves through it, and
/// Claims the input's own frame out of `frames`, serves through it, and
/// folds the poll's status into the cell. The claim is the caller's, so
/// the edge's frame is claimed exactly once per evaluation.
/// the input's frame is claimed exactly once per evaluation.
#[inline(always)]
pub fn eval_input<'e, Input, N: Node<Input> + ?Sized>(&self, input_index: usize, node: &N, input: &Input, frames: &crate::record::Frames<'e>) -> Result<crate::record::RecordValue<'e>, Interrupt>
where
@@ -612,7 +612,7 @@ impl<'a, 'f, N> LazyInput<'a, 'f, N> {
self.node.eval_derived(self.cell, self.input_index, ctx, self.frames)
}
/// The edge's composite extent, for kernels that split or shift indices
/// The input's composite extent, for kernels that split or shift indices
/// over their sources.
#[inline(always)]
pub fn extent<'e, Input>(&self, ctx: &Input, at: Level) -> GPoll<Extent>

View File

@@ -44,7 +44,7 @@ impl<U, T: ListConvert<U> + Send> Convert<List<U>, ()> for List<T> {
/// Wraps each row's element into a type-erased attribute. Lets nodes that accept a source attribute
/// from any `List<U>` express their signature as `AttributeDyn` and avoid monomorphizing
/// over `U`; the compiler inserts this convert to bridge concrete-typed graph wires to the dyn input.
/// over `U`; the compiler inserts this convert to bridge concrete-typed graph sources to the dyn input.
impl<T: Clone + Send + Sync + Default + std::fmt::Debug + PartialEq + CacheHash + 'static> Convert<AttributeDyn, ()> for List<T> {
fn convert(self, _: Footprint, _: ()) -> AttributeDyn {
let values: Vec<T> = self.into_iter().map(|row| row.into_element()).collect();
@@ -54,7 +54,7 @@ impl<T: Clone + Send + Sync + Default + std::fmt::Debug + PartialEq + CacheHash
/// Wraps a value into a type-erased attribute value. Lets nodes that take a per-item value source
/// (such as `write_attribute`'s value-producing input) be generic over the destination list type
/// alone, with the compiler-inserted convert handling each concrete value type at the wire level.
/// alone, with the compiler-inserted convert handling each concrete value type at the input level.
impl<T: Clone + Send + Sync + Default + std::fmt::Debug + PartialEq + CacheHash + 'static> Convert<AttributeValueDyn, ()> for T {
fn convert(self, _: Footprint, _: ()) -> AttributeValueDyn {
AttributeValueDyn(Box::new(self))

View File

@@ -45,7 +45,7 @@ impl FrameArena {
/// node's inputs claim beyond its frame, one after another, and the space they
/// used is free again once the claim dies: the release is the claim's
/// lifetime, not a rewind contract. The cursor is shared through `&self` so
/// the lazy edges a kernel holds claim beyond each other rather than over each
/// the lazy inputs a kernel holds claim beyond each other rather than over each
/// other. Covariant in `'e`, so a claim minted at the evaluation shortens onto
/// a derived context's arena lifetime.
pub struct Frames<'e> {

View File

@@ -7,7 +7,7 @@ use super::serve::{FrameClaim, Served, serve_input};
use crate::gpoll::GPoll;
use crate::node::Node;
/// A record edge evaluable at a derived context, yielding the record at that
/// A record input evaluable at a derived context, yielding the record at that
/// context's lifetime. The lifetime is a trait parameter because a bound like
/// `for<'d> Node<Derived<'d, C>>` cannot also say the derived context's arena
/// is at `'d`: the equality binding `ExtractArena<ArenaRef = &'d Arena>` is an
@@ -31,7 +31,7 @@ where
}
}
/// Fills caller scratch with one frame per lane of `range`: the edge serves
/// Fills caller scratch with one frame per lane of `range`: the input serves
/// into the lane's own region of the slab, and the lane's own frame space is
/// free again at the next lane, so the frame peak stays at one lane's need and
/// every lane's bytes are distinct.
@@ -78,9 +78,9 @@ where
BatchStatus::Filled(run.finish(), finality, hint)
}
/// The driver a consumer runs on a record edge: a resident batch returns with
/// The driver a consumer runs on a record input: a resident batch returns with
/// no allocation, a node's own batch impl gets `n * frame_bytes` of arena
/// scratch, and an unbatched edge falls back to the [`fill_frames`] loop.
/// scratch, and an unbatched input falls back to the [`fill_frames`] loop.
pub fn materialize_batch<'a, 'e, C, N>(node: &'a N, input: &'a C, range: std::ops::Range<u64>, arena: &'a crate::arena::Arena, frames: &Frames<'e>) -> crate::node::BatchStatus<'a>
where
C: crate::context::InjectIndex + Copy + crate::context::ExtractArena<ArenaRef = &'e crate::arena::Arena>,
@@ -110,14 +110,14 @@ where
}
}
/// The outcome of materializing a leveled edge's whole flat span.
/// The outcome of materializing a leveled input's whole flat span.
pub enum LevelStatus<'a> {
Batch(crate::node::RecordBatch<'a>, crate::gpoll::Finality),
Pending,
Error(crate::gpoll::GraphError),
}
/// Evaluates a leveled edge's whole flat span into one batch: an exact total
/// Evaluates a leveled input's whole flat span into one batch: an exact total
/// fills once, a lower bound drains by guess-and-double until a short fill,
/// each reply's hint seeding the next guess. The boundary consumers' driver;
/// reducers inline the same protocol with their span offsets.
@@ -167,10 +167,10 @@ where
}
}
/// The raw lazy record edge handed to a record-opaque kernel: the wire plus
/// The raw lazy record input handed to a record-opaque kernel: the input plus
/// its wiring-proven layout, the pairing the kernel's unsafe record
/// operations rely on. The kernel must only pair the layout with values this
/// edge produced.
/// input produced.
pub struct RecordInput<'a, 'e, N> {
node: &'a N,
layout: &'a Layout,
@@ -186,8 +186,8 @@ impl<'a, 'e, N> RecordInput<'a, 'e, N> {
self.layout
}
/// Serves the edge through the kernel's own claim: the kernel's output
/// layout is the edge's, so the claim it was handed is the edge's frame.
/// Serves the input through the kernel's own claim: the kernel's output
/// layout is the input's, so the claim it was handed is the input's frame.
pub fn serve<'l, C>(&self, ctx: &C, slot: FrameClaim<'e, 'l>) -> GPoll<Served<'e>>
where
N: Node<C>,
@@ -196,7 +196,7 @@ impl<'a, 'e, N> RecordInput<'a, 'e, N> {
self.node.serve(ctx, slot)
}
/// [`materialize_level`] over the edge: the wire's whole flat span as one
/// [`materialize_level`] over the input: the input's whole flat span as one
/// batch.
pub fn materialize_level<'b, C>(&'b self, ctx: &'b C, arena: &'b crate::arena::Arena) -> LevelStatus<'b>
where
@@ -207,7 +207,7 @@ impl<'a, 'e, N> RecordInput<'a, 'e, N> {
}
}
/// The raw lazy edge handed to a poll kernel whose wire rides records while
/// The raw lazy input handed to a poll kernel whose input rides records while
/// the kernel consumes the plain element.
/// # Safety
/// `rec` must be a record of the layout the offsets were resolved against
@@ -243,7 +243,7 @@ impl<'a, 'e, Out, N> ElementInput<'a, 'e, Out, N> {
Self { node, layout, reads, read, frames }
}
/// The edge's element at `ctx`, read out of a record claimed beyond the
/// The input's element at `ctx`, read out of a record claimed beyond the
/// kernel's own frame; the claim dies with the call, so the record is free
/// again at the next one.
pub fn eval<'d, C>(&self, ctx: &C) -> GPoll<Out>
@@ -254,14 +254,14 @@ impl<'a, 'e, Out, N> ElementInput<'a, 'e, Out, N> {
let cell = crate::node::StatusCell::new();
let scope = self.frames.scope();
match self.node.eval_derived(&cell, 0, ctx, &scope) {
// SAFETY: the read copies out by value against the edge's own layout.
// SAFETY: the read copies out by value against the input's own layout.
Ok(value) => cell.finish(unsafe { (self.read)(self.layout.rec(&value), self.reads) }),
Err(interrupt) => interrupt.into(),
}
}
}
/// The lazy input handed to a kernel whose edge rides a record wire while
/// The lazy input handed to a kernel whose input rides a record while
/// the kernel consumes the plain element, or the element beside its declared
/// attribute reads.
#[derive(Clone, Copy)]
@@ -321,12 +321,12 @@ impl<'a, 'e, Out, N> ElementLazyInput<'a, 'e, Out, N> {
{
let scope = self.frames.scope();
let value = self.node.eval_derived(self.cell, self.input_index, ctx, &scope)?;
// SAFETY: the reads are the edge's own layout's, resolved at wiring.
// SAFETY: the reads are the input's own layout's, resolved at wiring.
Ok(unsafe { (self.read)(self.layout.rec(&value), self.reads) })
}
}
/// The lazy record input handed to a kernel that evaluates its edges under
/// The lazy record input handed to a kernel that evaluates its inputs under
/// derived contexts: evaluating rebinds the record to the kernel's routing
/// lifetime, so the value escapes the derivation scope.
#[derive(Clone, Copy)]
@@ -357,7 +357,7 @@ impl<'a, 'e, N> RecordLazyInput<'a, 'e, N> {
Ok(self.node.eval_derived(self.cell, self.input_index, ctx, self.frames)?.rebind())
}
/// The flat lane count of one copy: the product of the edge's inner-level
/// The flat lane count of one copy: the product of the input's inner-level
/// extents, queried uniform across copies (at copy 0). The dividend of a
/// structure node's decompose-and-promote.
pub fn inner_extent<B>(&self, ctx: &B) -> Result<u64, crate::gpoll::Interrupt>
@@ -368,7 +368,7 @@ impl<'a, 'e, N> RecordLazyInput<'a, 'e, N> {
inner_extent_of(self.node, ctx, 0, self.inner_levels, self.input_index, self.frames)
}
/// The flat lane count of the copy at `copy`, for edges whose inner
/// The flat lane count of the copy at `copy`, for inputs whose inner
/// extents vary per copy.
pub fn inner_extent_at<B>(&self, ctx: &B, copy: u64) -> Result<u64, crate::gpoll::Interrupt>
where
@@ -399,7 +399,7 @@ where
Ok(inner)
}
/// The flat lane count of one copy of a lower-bound edge, probed by
/// The flat lane count of one copy of a lower-bound input, probed by
/// evaluating lanes to the past-end signal. The probed records are
/// discarded, and their statuses land in a scratch cell.
fn probed_inner<B, N>(node: &N, ctx: &B, copy: u64, input_index: usize, frames: &Frames<'_>) -> Result<u64, crate::gpoll::Interrupt>
@@ -483,9 +483,9 @@ impl<'a, 'e, Out, N> DerivedLazyInput<'a, 'e, Out, N> {
}
}
/// A plain probe over a record wire, cloning the element out of the parked
/// A plain probe over a record input, cloning the element out of the parked
/// reference when it carries drop glue. Registry constructors wrap a record
/// edge in one to feed a node's plain value input, keeping the wire kind
/// input in one to feed a node's plain value input, keeping the input kind
/// uniform.
pub struct RecordExtract<El, N> {
edge: N,
@@ -504,13 +504,13 @@ impl<El, N> RecordExtract<El, N> {
}
impl<El: Clone + 'static, N> RecordExtract<El, N> {
/// The edge's element, copied out of its record.
/// The input's element, copied out of its record.
pub fn eval<'e, C>(&self, input: &C, frames: &Frames<'e>) -> GPoll<El>
where
N: Node<C>,
C: crate::context::ExtractArena<ArenaRef = &'e crate::arena::Arena>,
{
// The element copies out by value, so the edge's claim dies with
// The element copies out by value, so the input's claim dies with
// the scope.
let scope = frames.scope();
serve_input(&self.edge, input, &scope).map(|value| unsafe { read_element::<El>(self.layout.rec(&value)) })

View File

@@ -347,7 +347,7 @@ pub struct RecordLayout {
pub lane_invariant: u32,
}
/// its registry entry so the compiler can fold each wire's layout without
/// its registry entry so the compiler can fold each input'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.
@@ -371,7 +371,7 @@ pub struct LayoutMeta {
/// `+1` for a creator, `-1` for a reducer.
pub level_delta: i8,
/// The materialized subject a reducer folds, as `(input, levels)`. The fold
/// consumes the whole subject wire, so only the node's own levels remain.
/// consumes the whole subject input, so only the node's own levels remain.
pub folded: Option<(u8, u8)>,
}
@@ -419,7 +419,7 @@ impl LayoutMeta {
}
.without(&self.removes);
let depth = match self.folded {
// A fold consumes the whole subject wire (a deeper wire folds its
// A fold consumes the whole subject input (a deeper input folds its
// total flat span), so only the node's own levels remain.
Some(_) => self.level_delta.max(0) as u8,
None => (base.depth as i8 + self.level_delta).max(0) as u8,
@@ -484,7 +484,7 @@ pub const fn element_parked<T>() -> bool {
std::mem::needs_drop::<T>()
}
/// The element (size, align) a record wire of `T` carries.
/// The element (size, align) a record input of `T` carries.
pub fn element_dims<T>() -> (usize, usize) {
match element_parked::<T>() {
true => (size_of::<*const u8>(), align_of::<*const u8>()),
@@ -492,7 +492,7 @@ pub fn element_dims<T>() -> (usize, usize) {
}
}
/// The element slot a record wire of `T` carries, its erased glue bound at
/// The element slot a record input of `T` carries, its erased glue bound at
/// the statically-known type.
pub fn element_write<T: Clone + Send + Sync + dyn_any::StaticTypeSized>() -> ElementWrite
where

View File

@@ -61,7 +61,7 @@ impl SourcePlan {
}
}
/// A routing input's claimed edge plus its wiring-resolved [`SourcePlan`].
/// A routing input's claimed source plus its wiring-resolved [`SourcePlan`].
/// Evaluating it yields the source's record translated to the union layout
/// (or forwarded untouched when the layouts already agree), so the kernel
/// holds and returns record values without ever seeing the representation.
@@ -99,7 +99,7 @@ where
};
match serve_input(&self.edge, input, &mut slot.frames().reborrow()) {
GPoll::Final(value) => {
// SAFETY: the value came from this edge, so it carries the
// SAFETY: the value came from this source, so it carries the
// plan's source layout.
unsafe { slot.translate(plan.source.rec(&value), plan) };
// SAFETY: the translation completes the union record.

View File

@@ -179,7 +179,7 @@ impl<'e, 'l> FrameClaim<'e, 'l> {
Served { value: unsafe { self.finish() } }
}
/// Fills the frame from a record a forwarded wire already served, and
/// Fills the frame from a record a forwarded input already served, and
/// closes it: the source's frame sits above this claim and dies with its
/// drop, so the served record is this claim's own.
///

View File

@@ -90,8 +90,8 @@ where
}
/// Law-test scaffolding: a kernel closure served onto an element-only record
/// wire (the element lands at offset 0, parked when it carries drop glue). No
/// production path constructs one; value edges are
/// input (the element lands at offset 0, parked when it carries drop glue). No
/// production path constructs one; value sources are
/// [`crate::value::ValueSource`].
pub struct LiftedSource<El, F> {
kernel: F,

View File

@@ -72,7 +72,7 @@ pub static NODE_METADATA: LazyLock<Mutex<HashMap<ProtoNodeIdentifier, NodeMetada
pub use crate::NodeIOTypes;
/// Element-independent by erasure; the wire's `Type::Record(El)` keeps element reads proven at wiring.
/// Element-independent by erasure; the input's `Type::Record(El)` keeps element reads proven at wiring.
#[cfg(not(target_family = "wasm"))]
pub type ErasedRecordNode = dyn for<'c> Node<ContextImpl<'c>> + Send + Sync;
#[cfg(target_family = "wasm")]
@@ -133,7 +133,7 @@ impl<N: ?Sized> SharedSource<N> {
}
}
// SAFETY: `ptr` is derived from the owned Arc and never mutated through, so the edge is exactly as
// SAFETY: `ptr` is derived from the owned Arc and never mutated through, so the source is exactly as
// thread safe as the payload it shares.
unsafe impl<N: ?Sized + Send + Sync> Send for SharedSource<N> {}
// SAFETY: as in Send.

View File

@@ -232,7 +232,7 @@ pub enum Type {
Fn(Box<Type>, Box<Type>),
/// Represents a future which promises to return the inner type.
Future(Box<Type>),
/// A packed record wire over the element type; the layout stays node-resident metadata.
/// A packed record input over the element type; the layout stays node-resident metadata.
Record(Box<Type>),
}

View File

@@ -1,5 +1,5 @@
/// The node behind every value edge: clones its constant onto the record
/// wire per evaluation.
/// The node behind every value source: clones its constant onto the record
/// input per evaluation.
pub struct ValueSource<T> {
value: T,
layout: crate::record::Layout,
@@ -41,7 +41,7 @@ where
crate::registry::EdgeHandle::new_record::<T>(std::sync::Arc::new(ValueSource::new(value)) as std::sync::Arc<crate::registry::ErasedRecordNode>)
}
/// The node behind a leveled value edge: a constant list served as one level,
/// The node behind a leveled value source: a constant list served as one level,
/// one lane per item, with the list's length as the exact extent.
pub struct LeveledValueSource<T> {
values: Vec<T>,

View File

@@ -431,8 +431,8 @@ pub(crate) fn generate_node_code(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
register_metadata();
}
};
// Record nodes construct through the generated `wire` fn, which resolves
// offsets from the carrier layout; `new` cannot fill that state.
// Record nodes construct through `new` with the carrier layout, which
// resolves the offsets their reads and writes address.
let routing_layout_param = (routing_generic.is_some() || opaque).then(|| quote!(__layout: &gcore::record::Layout,)).into_iter();
let routing_layout_init = (routing_generic.is_some() || opaque).then(|| quote!(__layout: __layout.clone(),)).into_iter();
// The lane-invariance mask arrives with the resolved layout, so `new` starts
@@ -878,7 +878,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
})
});
let derive_routing = derives && routing_generic.is_some();
// A kernel that holds records (a forwarded routing wire, or a lazy edge it
// A kernel that holds records (a forwarded routing source, or a lazy input it
// serves itself) names the record lifetime; unless it declared a serving
// lifetime of its own, the context binds the arena at that lifetime.
let kernel_lazy = parsed.fields.iter().any(|field| !field.is_data_field && matches!(field.ty, ParsedFieldType::Node(_)));
@@ -935,7 +935,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
})
.map(|param| match param {
// Flipped kernels clone bare-typed elements out of their records,
// so those generics carry the bound wire values satisfy; a
// so those generics carry the bound input values satisfy; a
// generic only nested in a field's type stays as declared.
GenericParam::Type(type_param)
if flip
@@ -1044,7 +1044,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
}
}
}
// The record lifetime the kernel's wire types and arena bound name; the
// The record lifetime the kernel's input types and arena bound name; the
// impl infers it from the serving lifetime at every call.
if wants_record_lifetime {
generics.insert(0, quote!('__record));
@@ -1156,7 +1156,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let node_bounds = regular_fields.iter().enumerate().zip(&node_generics).map(|((index, field), node_generic)| {
let plain = quote!(#node_generic: #core_types::node::Node<#ctx_ident>);
// A lazy edge the kernel evaluates at derived contexts needs the
// A lazy input the kernel evaluates at derived contexts needs the
// derived form: the derived context's arena binding is unnameable
// under a higher rank.
let derived = quote!(#node_generic: #derived_edge);
@@ -1173,7 +1173,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
true => derived,
false => plain,
},
// An element-consuming lazy secondary rides a record edge, derivable
// An element-consuming lazy secondary rides a record input, derivable
// when the kernel evaluates it at derived contexts.
ParsedFieldType::Node(_) if record_io && matches!(ir::lazy_binding(&node, index), LazyBinding::Element) => match derives {
true => derived_plus,
@@ -1188,8 +1188,8 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let bound = lazy_bound();
quote!(#node_generic: #bound)
}
// Every wire is a record edge; a value input's element copies out of
// the record its edge serves.
// Every input is a record input; a value input's element copies out of
// the record its source serves.
ParsedFieldType::Regular(_) => plain,
}
});
@@ -1202,7 +1202,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
lend_outlives.push(quote!(#inner: #lifetime));
}
// The slot persists the plain value even on record wires, so the Clone
// The slot persists the plain value even on record inputs, so the Clone
// bound targets the slot type, not the (possibly lifted) trait output.
let slot_ty = crate::codegen::classify::slot_static_type(&parsed.output_type);
let mut async_bounds = match (async_fn, future_kernel) {
@@ -1263,8 +1263,8 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
#[allow(unused_mut, unused_variables)]
let mut __frame = __run.slot(__lane, &__lane_frames);
};
// A lazy edge claims beyond every input frame this node holds, and its
// cursor is shared, so the edges a kernel drives claim past each other.
// A lazy input claims beyond every input frame this node holds, and its
// cursor is shared, so the inputs a kernel drives claim past each other.
let lazy_frames_entry = quote! {
let __lazy_frames = __frame.frames().reborrow();
};
@@ -1296,7 +1296,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let non_exact = fail(quote!(#core_types::gpoll::GraphError::new(::std::concat!("reduce over a non-exact extent in ", ::std::stringify!(#fn_name)))));
let batch_error = fail(quote!(__error));
let batch_failed = fail(quote!(#core_types::gpoll::GraphError::new("reduce batch failed")));
// A fold consumes the whole subject wire: a deeper wire's
// A fold consumes the whole subject input: a deeper input's
// total flat span, sized under the evaluation context, so a
// fold inside a pushed level covers that copy's span. The
// span caches per (lane-normalized context, generation):
@@ -1369,7 +1369,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let #name = unsafe { #core_types::node::List::<#ty>::new(__batch) };
}
}
// A reading secondary input claims a record edge: the element and
// A reading secondary input claims a record input: the element and
// the declared reads copy out right after its eval.
ValueBinding::ReadingSecondary => {
let slot = format_ident!("__in_{index}");
@@ -1398,7 +1398,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let #name = unsafe { #core_types::record::borrow_element::<#ty>(self.#slot.rec(&#record_local)) };
}
}
// A flip value or a routing non-source value rides a record edge; the
// A flip value or a routing non-source value rides a record input; the
// element copies out into `name`. The mark/rewind that reclaims the
// record's frame is applied by the step lowering (see `reads_out`).
ValueBinding::RecordElement => {
@@ -1411,8 +1411,8 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let #name: #ty = unsafe { #core_types::record::read_element(self.#slot.rec(&#name)) };
}
}
// A plain value rides a record edge like every other input; the
// element copies out against the edge's own layout, except for a
// A plain value rides a record input like every other input; the
// element copies out against the input's own layout, except for a
// routing source, whose record is what the kernel forwards.
ValueBinding::Plain => {
let read = (!routing_source(ty)).then(|| {
@@ -1432,7 +1432,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
}
},
ParsedFieldType::Node(NodeParsedField { output_type, .. }) => match (ir::lazy_binding(&node, index), raw_lazy) {
// A raw poll edge is threaded straight through, so it does not bind here.
// A raw poll input is threaded straight through, so it does not bind here.
(LazyBinding::Generic, true) => quote!(),
(LazyBinding::DeriveRouting, _) => quote! {
let #name = #core_types::record::RecordLazyInput::new(&self.#name, &__cell, #index, self.__layout.depth.saturating_sub(#pushed_levels), &__lazy_frames);
@@ -1493,7 +1493,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
}
};
// A bind whose element copies out reclaims the edge's frame; a forwarded
// A bind whose element copies out reclaims the input's frame; a forwarded
// record must outlive the bind, so its frame stays.
let _reads_out_at = |index: usize| match &regular_fields[index].ty {
ParsedFieldType::Regular(RegularParsedField { ty, .. }) => !routing_source(ty) && ir::value_binding(&node, index).reads_out(),
@@ -1518,7 +1518,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let call_args = regular_fields.iter().enumerate().filter(|(_, field)| !injected_name(&field.pat_ident.ident)).map(|(index, field)| {
let name = &field.pat_ident.ident;
match &field.ty {
// A lend param binds an owned edge; the kernel borrows the
// A lend param binds an owned input; the kernel borrows the
// evaluated value.
ParsedFieldType::Regular(RegularParsedField { lend: Some(_), .. }) if !flip => quote!(&#name),
ParsedFieldType::Regular(_) => quote!(#name),
@@ -1534,7 +1534,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
// composite `extent(ctx, Level)`, which the trait derives from it. A node
// without `extent = fn` keeps the scalar default (one item at every level).
// The typed extent surface: the node's inputs in declaration order (values
// readable without unsafe, edges as per-level extent queries, derived
// readable without unsafe, inputs as per-level extent queries, derived
// content promoted per copy), then the level paired with the node's depth.
let extent_impl = if let Some(path) = &parsed.attributes.extent {
let mut arg_decls: Vec<TokenStream2> = Vec::new();
@@ -1565,7 +1565,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
_ => extent_edge(&query, &arg),
},
ParsedFieldType::Regular(RegularParsedField { ty, .. }) => match ir::value_binding(&node, index) {
// A ranked input materializes whole (the wire's total flat
// A ranked input materializes whole (the input's total flat
// span, as in eval), so a data-dependent extent can walk
// its lanes.
ValueBinding::Materialized => {
@@ -1603,7 +1603,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
};
quote! {
let #query = || {
// The element copies out by value, so the edge's
// The element copies out by value, so the input's
// claim dies with the query.
let __scope = __frames.scope();
#core_types::record::serve_input(&self.#name, __input, &__scope)
@@ -1613,7 +1613,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
}
}
// A carrier, lent, or materialized ranked input is a record
// edge; its extents are the queryable quantity.
// input; its extents are the queryable quantity.
_ => extent_edge(&query, &arg),
},
};
@@ -1853,7 +1853,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
})
});
// Async slots persist plain values across evaluations; the source lifts
// the slot value onto its record wire at every merge point, into the
// the slot value onto its record input at every merge point, into the
// carried frame when the node has a carrier.
// A writing source stores the kernel's whole tuple as that plain value:
// the lift writes the attributes through the claim, then lifts the
@@ -1961,7 +1961,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
let value_args = regular_fields.iter().skip(if skips_carrier { 0 } else { 1 }).map(|field| {
let name = &field.pat_ident.ident;
match &field.ty {
// A lend param binds an owned edge; the kernel borrows the
// A lend param binds an owned input; the kernel borrows the
// evaluated value.
ParsedFieldType::Regular(RegularParsedField { lend: Some(_), .. }) => quote!(&#name),
_ => tuple_arg(field, quote!(#name)),
@@ -2230,7 +2230,7 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
&lazy_frames_entry,
);
// The rebind path with nothing hoisted: every non-carrier input binds
// fresh per lane, so an index-dependent edge reaches its own lane.
// fresh per lane, so an index-dependent input reaches its own lane.
let rebound_lane_binds: Vec<TokenStream2> = lazy_last(
regular_fields
.iter()

View File

@@ -131,7 +131,7 @@ pub(crate) fn lazy_read_fields<'a>(regular_fields: &[&'a ParsedField]) -> Vec<(u
}
/// The indices (into the unit-skipped regular fields) of value inputs whose
/// reads resolve against their own wire rather than the carrier's.
/// reads resolve against their own input rather than the carrier's.
pub(crate) fn reading_secondary_indices(regular_fields: &[&ParsedField], skips_carrier: bool) -> Vec<usize> {
regular_fields
.iter()
@@ -177,7 +177,7 @@ pub(crate) fn substitute_ident_types(ty: &Type, assignments: &[(Ident, Type)]) -
}
/// Replaces the routing generic in a derive-routing kernel's return type with
/// the routing record value, since the kernel's edges rebind to '__record.
/// the routing record value, since the kernel's inputs rebind to '__record.
pub(crate) fn substitute_routing_record(output: &Type, generic: &Ident, core_types: &TokenStream2) -> Type {
struct Subst<'a> {
generic: &'a Ident,
@@ -295,7 +295,7 @@ pub(crate) fn record_shape(parsed: &ParsedNodeFn) -> Option<RecordShape> {
return None;
}
// An async source's slot stores the kernel's plain tuple; the per-eval lift
// writes it through the claim, and the reads have no wire to bind against.
// writes it through the claim, and the reads have no input to bind against.
if source && (has_reads || writes.is_none()) {
return None;
}
@@ -306,7 +306,7 @@ pub(crate) fn record_shape(parsed: &ParsedNodeFn) -> Option<RecordShape> {
// A first-field lazy carrier: the kernel evaluates the derived content
// itself and returns its opaque row token beside the write set.
let lazy_carrier = matches!(&carrier_field.ty, ParsedFieldType::Node(_));
// Lazy secondaries are consumed as plain elements; raw record edges and
// Lazy secondaries are consumed as plain elements; raw record inputs and
// ranked outputs have no element binding here.
let unsupported_lazy_secondary = |field: &ParsedField| match &field.ty {
ParsedFieldType::Node(NodeParsedField { output_type, .. }) => is_served(output_type) || crate::codegen::ir::strip_ilist(output_type).1 > 0 || !field.attribute_reads.is_empty(),
@@ -423,7 +423,7 @@ pub(crate) fn flip_carrier(parsed: &ParsedNodeFn) -> bool {
!(async_kernel && lend.is_some())
}
/// Whether a plain node's lowering flips onto record wires: sync,
/// Whether a plain node's lowering flips onto record inputs: sync,
/// fully-concrete value-input nodes in this cut; batch, shader, async, lend,
/// lazy, and generic nodes keep the plain lowering until their record forms
/// land.
@@ -467,7 +467,7 @@ pub(crate) fn record_flip(parsed: &ParsedNodeFn) -> bool {
return false;
}
}
// A named lifetime is the serving lifetime: wire types substitute
// A named lifetime is the serving lifetime: input types substitute
// its erased projection in registry and layout contexts.
GenericParam::Lifetime(_) => {}
GenericParam::Const(_) => return false,
@@ -520,7 +520,7 @@ pub(crate) fn is_served(ty: &Type) -> bool {
}
/// Whether a kernel operates on whole records: it serves through the claim it
/// was handed, receives raw record edges paired with the node's layout, and
/// was handed, receives raw record inputs paired with the node's layout, and
/// takes on the record APIs' unsafe contracts itself.
pub(crate) fn record_opaque(parsed: &ParsedNodeFn) -> bool {
is_served(&slot_value_type(&parsed.output_type))
@@ -723,7 +723,7 @@ pub(crate) fn type_disqualifies(ty: &Type) -> bool {
visitor.found
}
/// The wire type with every named serving lifetime replaced: `'static` for
/// The input type with every named serving lifetime replaced: `'static` for
/// registry, layout, and declaration contexts (the erased projection shares
/// its type id and layout), `'_` for eval bindings, where inference recovers
/// the serving lifetime.
@@ -749,7 +749,7 @@ pub(crate) fn substitute_lifetimes(ty: &Type, replacement: &str) -> Type {
ty
}
/// The serving lifetime a wire type names, so a materialized binding can tie
/// The serving lifetime an input type names, so a materialized binding can tie
/// the list view to the element's own region.
pub(crate) fn named_serving_lifetime(ty: &Type) -> Option<Lifetime> {
struct Find {

View File

@@ -15,7 +15,7 @@ pub(crate) fn entries_tokens(parsed: &ParsedNodeFn, struct_name: &Ident, data_fi
}
}
/// The registry rows of a flipped plain node: every wire is a record wire,
/// The registry rows of a flipped plain node: every input is a record input,
/// inputs resolve their layouts off the claimed handles, and the output is an
/// element-only record of the kernel's return type.
fn flip_entries_tokens(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields: &[&ParsedField]) -> TokenStream2 {
@@ -179,20 +179,20 @@ fn flip_entries_tokens(parsed: &ParsedNodeFn, struct_name: &Ident, regular_field
}
}
/// Which record wire an input claims and how its value is recovered. Base slots
/// are the record edges whose layouts form the output; value slots are record
/// edges read for their layout.
/// Which record an input claims and how its value is recovered. Base slots
/// are the record inputs whose layouts form the output; value slots are record
/// inputs read for their layout.
enum SlotKind {
/// A generic record edge whose element is only known at runtime; the runtime
/// A generic record input whose element is only known at runtime; the runtime
/// type is captured for the output wrap or the union.
BaseGeneric(String),
/// A concrete record carrier read for its layout.
BaseConcrete(Type),
/// A concrete record edge read for its layout only.
/// A concrete record input read for its layout only.
Value(Type),
/// A record edge whose element extracts to the node's plain value input.
/// A record input whose element extracts to the node's plain value input.
Extracted(Type),
/// A ranked record edge consumed whole; no layout rides to the constructor.
/// A ranked record input consumed whole; no layout rides to the constructor.
Ranked(Type),
}
@@ -203,7 +203,7 @@ impl SlotKind {
}
/// The single registry row shared by record-io, routing, and opaque nodes: one
/// instance covers the wire, each input's edge type and downcast follow its
/// instance covers the input, each input's type and downcast follow its
/// slot, and the output layout folds from the base slots.
fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields: &[&ParsedField]) -> TokenStream2 {
use crate::codegen::ir;
@@ -212,8 +212,8 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
let core_types = quote!(gcore);
let lend = |field: &ParsedField| matches!(&field.ty, ParsedFieldType::Regular(RegularParsedField { lend: Some(_), .. }));
// A subject is its record edge (concrete carrier or erased generic); a
// non-subject value rides a record edge when it reads its layout.
// A subject is its record input (concrete carrier or erased generic); a
// non-subject value rides a record input when it reads its layout.
let slots: Option<Vec<SlotKind>> = regular_fields
.iter()
.enumerate()
@@ -228,7 +228,7 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
}
match &field.ty {
// An element-consuming lazy secondary of a record node rides a
// record edge with a layout slot, like a reading secondary.
// record input with a layout slot, like a reading secondary.
ParsedFieldType::Node(NodeParsedField { output_type, .. })
if matches!(ir::node_kind(&node), ir::NodeKind::RecordIo) && matches!(ir::lazy_binding(&node, index), ir::LazyBinding::Element) =>
{
@@ -241,8 +241,8 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
ParsedFieldType::Regular(RegularParsedField { ty, .. }) => match ir::value_binding(&node, index) {
ir::ValueBinding::Materialized => Some(SlotKind::Ranked(ty.clone())),
ir::ValueBinding::ReadingSecondary | ir::ValueBinding::RecordElement => Some(SlotKind::Value(ty.clone())),
// One wire kind: a record node's plain value still rides a
// record edge, extracted to its element at construction.
// One input kind: a record node's plain value still rides a
// record input, extracted to its element at construction.
_ if matches!(ir::node_kind(&node), ir::NodeKind::RecordIo) => Some(SlotKind::Extracted(ty.clone())),
_ => {
emit_error!(field.pat_ident.span(), "plain (non-record) io is unsupported: this value input needs a record edge");
@@ -359,7 +359,7 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
let #layout = #handle.layout().clone();
let #name = #handle.downcast_record::<#value_ty>()?;
},
// The node reads the element off the edge's own layout, so
// The node reads the element off the input's own layout, so
// neither slot rides a layout to the constructor.
SlotKind::Extracted(value_ty) | SlotKind::Ranked(value_ty) => quote! {
let #name = inputs.next().unwrap().downcast_record::<#value_ty>()?;
@@ -382,7 +382,7 @@ fn single_row_entries(parsed: &ParsedNodeFn, struct_name: &Ident, regular_fields
quote!(Some(#meta))
};
// The output wire and node wrap follow the output element: a concrete (or
// The output type and node wrap follow the output element: a concrete (or
// row-assigned) element is a typed record; a generic or opaque element is
// an erased record carrying the first base slot's runtime type.
let output_element = match &node.output.shape.element {

View File

@@ -388,13 +388,13 @@ pub(crate) enum LazyBinding {
}
impl ValueBinding {
/// Copies an element out of a record edge, so the frame is reclaimed after.
/// Copies an element out of a record input, so the frame is reclaimed after.
pub(crate) fn reads_out(&self) -> bool {
matches!(self, ValueBinding::ReadingSecondary | ValueBinding::RecordElement | ValueBinding::Plain)
}
}
/// A record node's lazy inputs consumed as plain elements: their record edges
/// A record node's lazy inputs consumed as plain elements: their record inputs
/// need a layout slot at wiring, like the reading secondaries.
pub(crate) fn element_lazy_indices(regular_fields: &[&ParsedField], node: &Node) -> Vec<usize> {
if !matches!(node_kind(node), NodeKind::RecordIo) {
@@ -454,7 +454,7 @@ fn has_attr_io(node: &Node) -> bool {
pub(crate) fn materialized_levels(node: &Node, index: usize) -> u8 {
let input = &node.inputs[index];
// An eager input's declared `IList` nesting IS its materialization count,
// independent of the rank delta; lazy edges never materialize.
// independent of the rank delta; lazy inputs never materialize.
match input.evaluation {
Evaluation::Eager => input.shape.depth,
Evaluation::Lazy => 0,

View File

@@ -44,7 +44,7 @@ pub(crate) struct ParsedNodeFn {
}
/// An `Attr<Marker>` slot in a parameter's read tuple: a declared attribute
/// read on that input's wire, not a wired input of its own.
/// read on that input, not a wired input of its own.
#[derive(Clone, Debug)]
pub(crate) struct AttributeRead {
pub(crate) pat_ident: PatIdent,
@@ -152,7 +152,7 @@ pub(crate) struct NodeFnAttributes {
pub(crate) batch: Option<Path>,
/// Whether partial upstream values are mapped to `Pending` instead of flowing into this node
pub(crate) no_partial: bool,
/// Whether this node keeps the plain-wire lowering during the record transition
/// Whether this node keeps the plain-input lowering during the record transition
pub(crate) plain: bool,
}
@@ -218,7 +218,7 @@ pub struct ParsedField {
pub unit: Option<LitStr>,
pub is_data_field: bool,
/// The attribute reads destructured from this input's tuple, resolved
/// against this input's wire.
/// against this input.
pub(crate) attribute_reads: Vec<AttributeRead>,
}
@@ -829,7 +829,7 @@ fn is_frame_claim(ty: &Type) -> bool {
}
/// Splits a lazy input's `Output = (T, Attr<..>..)` tuple into the element
/// type (the wire type) and the declared reads on that edge. A tuple without
/// type (the input type) and the declared reads on that input. A tuple without
/// `Attr` slots is an ordinary tuple output and passes through untouched.
fn split_lazy_reads(output_type: Type) -> syn::Result<(Type, Vec<AttributeRead>)> {
let Type::Tuple(tuple) = &output_type else {
@@ -865,7 +865,7 @@ fn split_lazy_reads(output_type: Type) -> syn::Result<(Type, Vec<AttributeRead>)
/// Parses a `(value, reads..): (T, Attr<..>..)` parameter: the value component
/// is an ordinary field of the value type, each `Attr` component a read bound
/// to this input's wire.
/// to this input.
fn parse_read_tuple(pat_tuple: &syn::PatTuple, ty: &Type, attrs: &[Attribute], index: usize) -> syn::Result<ParsedField> {
let spelling = "an input with attribute reads destructures as `(value, Attr<..>)` over `(T, Attr<..>)`";
let Type::Tuple(ty_tuple) = ty else {
@@ -1031,7 +1031,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
// Data fields act as internal state, using interior mutability to cache data between node evaluations.
//
// Normally, an input parameter is a construction argument to the node that is stored as a field on the node struct.
// Specifically, its struct field stores the connected upstream node (an evaluatable lambda that returns data of the connection wire's type).
// Specifically, its struct field stores the connected upstream node (an evaluatable lambda that returns data of the connection's type).
// By comparison, a data field is also stored as a field on the node struct, allowing it to persist state between evaluations.
// But it acts as internal state only, not exposed as a parameter in the UI or able to be wired to another node.
//
@@ -1166,7 +1166,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
}
let input_type = node_input_type.ok_or_else(|| Error::new_spanned(&ty, "Invalid Node type. Expected `impl Node<Input>` or `impl Node<Input, Output = OutputType>`"))?;
// A subject named without an output is a whole-record wire: the kernel
// A subject named without an output is a whole-record input: the kernel
// serves it through its own claim rather than reading an element.
let output_type = node_output_type.unwrap_or_else(|| syn::parse_quote!(Served<'_>));
if !matches!(&value_source, ParsedValueSource::None) {

View File

@@ -54,7 +54,7 @@ fn validate_record_io(parsed: &ParsedNodeFn) {
for field in parsed.fields.iter().skip(1) {
if let ParsedFieldType::Node(NodeParsedField { output_type, .. }) = &field.ty {
// Lazy secondaries are consumed as plain elements through the wire.
// Lazy secondaries are consumed as plain elements through the input.
if crate::codegen::classify::is_served(output_type) || crate::codegen::ir::strip_ilist(output_type).1 > 0 {
emit_error!(field.pat_ident.span(), "a record node's lazy inputs consume plain elements, not record or ranked wires");
}

View File

@@ -147,7 +147,7 @@ fn read_index(
/// In programming terms: inside the double loop `i { j { ... } }`, *Loop Level* 0 = `j` and 1 = `i`. After inserting a third loop `k { ... }`, inside it, levels would be 0 = `k`, 1 = `j`, and 2 = `i`.
loop_level: u32,
) -> f64 {
// The chain's innermost entry is the consuming wire's own lane from the
// The chain's innermost entry is the consuming input's own lane from the
// decompose-and-promote split; the loops the reader counts sit above it.
ctx.try_index().and_then(|mut iter| iter.nth(loop_level as usize + 1)).unwrap_or(0) as f64
}

View File

@@ -28,7 +28,7 @@ fn unwrap_option<T: Default>(_: impl Ctx, #[implementations(Option<f64>, Option<
input.unwrap_or_default()
}
/// Clones the element out of its record wire.
/// Clones the element out of its record input.
#[node_macro::node(category("Debug"))]
fn clone<T: Clone>(_: impl Ctx, #[implementations(Raster<CPU>, f64)] value: &T) -> T {
value.clone()

View File

@@ -21,11 +21,11 @@ pub struct MemoLevel {
/// Helps speed up repeated renders in a computationally-heavy part of the node graph.
///
/// Stores a deep copy of the last record (a scalar wire) or the last whole
/// level (a leveled wire) that flowed through this node and replays it on
/// Stores a deep copy of the last record (a scalar input) or the last whole
/// level (a leveled input) that flowed through this node and replays it on
/// subsequent renders if the context has not changed. The owned copies survive
/// a persistent flush, so this is the memo for content whose recomputation is
/// expensive. A leveled wire's cache key normalizes the addressed lane away,
/// expensive. A leveled input's cache key normalizes the addressed lane away,
/// so per-lane pulls share one materialization of the content instead of
/// re-evaluating it per lane.
#[node_macro::node(category("General"), path(graphene_core::memo))]
@@ -35,8 +35,8 @@ fn memoize<'e, 'l>(
content: impl Node<Context<'_>>,
slot: FrameClaim<'e, 'l>,
) -> GPoll<Served<'e>> {
// A scalar wire's value may depend on the consuming lane (index readers),
// so only a leveled wire, whose level covers every lane by construction,
// A scalar input's value may depend on the consuming lane (index readers),
// so only a leveled input, whose level covers every lane by construction,
// keys with the lane normalized away.
let leveled = content.layout().depth > 0;
let lane = match leveled {
@@ -89,7 +89,7 @@ fn memoize<'e, 'l>(
return match content.materialize_level(&ctx, ctx.arena()) {
LevelStatus::Batch(batch, finality) => {
let layout = content.layout();
// SAFETY: the batch came from this edge, so it carries the edge's layout.
// SAFETY: the batch came from this input, so it carries the input's layout.
let lanes: Vec<OwnedRecord> = (0..batch.len()).map(|index| unsafe { OwnedRecord::copy_out(layout, batch.get(index).rec()) }).collect();
let entry = MemoLevel {
key,
@@ -115,7 +115,7 @@ fn memoize<'e, 'l>(
};
if let Some((value, finality)) = publishable {
let layout = content.layout();
// SAFETY: the value came from this edge, so it carries the edge's
// SAFETY: the value came from this input, so it carries the input's
// layout, and one record of it is a batch of one lane.
let batch = unsafe { core_types::node::RecordBatch::new(layout.rec(value).ptr(), 1, layout) };
// SAFETY: as above.
@@ -151,8 +151,8 @@ fn frame_memo<'e, 'l>(
content: impl Node<Context<'_>>,
slot: FrameClaim<'e, 'l>,
) -> GPoll<Served<'e>> {
// A scalar wire's value may depend on the consuming lane (index readers),
// so only a leveled wire, whose level covers every lane by construction,
// A scalar input's value may depend on the consuming lane (index readers),
// so only a leveled input, whose level covers every lane by construction,
// keys with the lane normalized away.
let leveled = content.layout().depth > 0;
let lane = match leveled {
@@ -198,7 +198,7 @@ fn frame_memo<'e, 'l>(
if leveled {
return match content.materialize_level(&ctx, ctx.arena()) {
LevelStatus::Batch(batch, finality) => {
// SAFETY: the batch came from this edge, so it carries the edge's layout.
// SAFETY: the batch came from this input, so it carries the input's layout.
let span = unsafe { MaterializedSpan::to_persistent(&batch, &promotion) };
*cache.lock().unwrap() = span.map(|span| SpanLevel { key, span, finality });
match lane < batch.len() {
@@ -220,7 +220,7 @@ fn frame_memo<'e, 'l>(
};
if let Some((value, finality)) = publishable {
let layout = content.layout();
// SAFETY: the value came from this edge, so it carries the edge's
// SAFETY: the value came from this input, so it carries the input's
// layout, and one record of it is a batch of one lane.
let batch = unsafe { core_types::node::RecordBatch::new(layout.rec(value).ptr(), 1, layout) };
// SAFETY: as above.
@@ -235,7 +235,7 @@ type MonitorValue = Arc<Mutex<Option<CtxSnapshot>>>;
/// The Monitor node is used by the editor to access the data flowing through
/// it. It stores only the evaluation context: the output is pure over
/// (context, source generations), so introspection recreates it by
/// re-evaluating this edge with the rehydrated snapshot.
/// re-evaluating this input with the rehydrated snapshot.
#[node_macro::node(category(""), path(graphene_core::memo), serialize(serialize_monitor), properties("monitor_properties"))]
fn monitor<'e, 'l>(
ctx: impl Ctx + DeriveCtx + ExtractAll + ExtractArena<'e> + ModifyIndex + Copy,

View File

@@ -1,5 +1,5 @@
//! Pilot record nodes exercising the macro's record-tier attribute io:
//! per-input tuple reads resolved against each input's wire, offset writes,
//! per-input tuple reads resolved against each input, offset writes,
//! `RemoveAttr` layout subtraction, the ElToken byte-carry for passthrough
//! elements, and the `_: ()` no-carrier form. These are the flat-wave law
//! tests; the node forms are the production authoring surface, and the
@@ -1494,8 +1494,8 @@ mod tests {
}
}
/// The compiler clears an input's bit when its edge reads the addressed
/// lane; the batch must then re-evaluate that edge per lane, since hoisting
/// The compiler clears an input's bit when its source reads the addressed
/// lane; the batch must then re-evaluate that source per lane, since hoisting
/// a lane-varying value serves the range's first lane to all of them.
#[test]
fn batch_rebinds_an_eager_input_the_compiler_cannot_prove_invariant() {

View File

@@ -372,9 +372,9 @@ pub fn stamp_layer_path<'e, T>(ctx: impl Ctx + ExtractArena<'e>, element: T, pat
#[node_macro::node(category("General"), extent(extend_extent))]
pub fn extend<T>(
ctx: impl Ctx + ExtractIndex + InjectIndex + Copy,
/// The wire whose lanes appear at the start of the extended level.
/// The input whose lanes appear at the start of the extended level.
base: impl Node<Context<'_>, Output = T>,
/// The wire whose lanes appear at the end of the extended level.
/// The input whose lanes appear at the end of the extended level.
#[expose]
new: impl Node<Context<'_>, Output = T>,
) -> Result<T, Interrupt> {
@@ -488,7 +488,7 @@ pub fn to_graphic<'e, T: graphic_types::graphic::IntoGraphicElement>(
}
/// The elementwise `Graphic` coercion the compiler-inserted converts use: each
/// lane's element converts on its own, so a typed wire feeds a graphic input
/// lane's element converts on its own, so a typed source feeds a graphic input
/// without changing the level's shape. Registered under the convert identifier.
#[node_macro::node(category(""))]
pub fn to_graphic_element<'e, T: graphic_types::graphic::IntoGraphicElement>(
@@ -537,7 +537,7 @@ fn to_graphic_unit_extent(_content: core_types::extent::ValueIn<'_, ()>, _level:
GPoll::Final(Extent::Exactly(0))
}
/// The transitional level bridge: the wire's records as the legacy list an
/// The transitional level bridge: the input's records as the legacy list an
/// unconverted consumer expects, attributes copied through their erased
/// reads and content kept in its native form. Registered under the legacy
/// convert identifiers; the rows die with the last legacy consumer.

View File

@@ -178,7 +178,7 @@ fn flat_map<Row: Clone + Send + Sync + core_types::CacheHash + 'static, T>(
}
/// Rank-model level collapse: two nested levels become one flat level. The
/// flat index already spans the edge's depth, so the eval forwards it.
/// flat index already spans the input's depth, so the eval forwards it.
#[node_macro::node(category("Test"), extent(flatten_levels_extent))]
fn flatten_levels<T>(ctx: impl Ctx + DeriveCtx + ExtractIndex, content: impl Node<Context<'_>, Output = IList<IList<T>>>) -> Result<IList<T>, Interrupt> {
let head = ctx.index_head();

View File

@@ -75,7 +75,7 @@ fn render_intermediate<T: dyn_any::StaticTypeSized + 'static + Render + WasmNotS
Ok(intermediate_of(&data, render_params))
}
/// The leveled form of `render_intermediate`: the wire's records materialize
/// The leveled form of `render_intermediate`: the input's records materialize
/// into a run, which renders directly.
#[node_macro::node(category(""))]
fn render_intermediate_leveled<T: Clone + Send + Sync + core_types::CacheHash + dyn_any::StaticTypeSized + 'static>(

View File

@@ -1027,7 +1027,7 @@ mod graphene_test {
core_types::record::test_frames(layouts.iter().map(|layout| layout.frame_bytes()).sum::<usize>().max(1 << 12))
}
/// Lifts a plain-element test source onto a record wire, returned beside its
/// Lifts a plain-element test source onto a record input, returned beside its
/// element-only layout for the generated node's constructor.
fn lifted<T, F>(kernel: F) -> (LiftedSource<T, F>, Layout)
where

View File

@@ -102,7 +102,7 @@ fn boolean_core<'e>(
#[node_macro::node(category("Vector: Modifier"), memoize)]
fn boolean_operation<'e>(
ctx: impl Ctx + ExtractArena<'e> + core_types::InjectIndex + Copy,
/// The wire of vector paths to perform the boolean operation on. Nested groups are automatically flattened.
/// The input of vector paths to perform the boolean operation on. Nested groups are automatically flattened.
content: IList<Graphic<'static>>,
/// Which boolean operation to perform on the paths.
///

View File

@@ -11,7 +11,7 @@ use graphic_types::Vector;
use graphic_types::raster_types::{CPU, GPU, Raster};
use vector_types::GradientStops;
/// Applies the specified transform to each lane of the input wire, composing onto the lane's transform attribute.
/// Applies the specified transform to each lane of the input, composing onto the lane's transform attribute.
#[node_macro::node(category("Math: Transform"), extent(transform_extent))]
fn transform<T>(
ctx: impl Ctx + DeriveCtx + ModifyFootprint,
@@ -88,14 +88,14 @@ fn reset_transform<T>(_: impl Ctx, (element, transform): (T, Attr<TransformAttr>
(element, Attr(row_transform))
}
/// Overwrites the transform of each lane of the input wire with the specified transform.
/// Overwrites the transform of each lane of the input with the specified transform.
#[node_macro::node(category("Math: Transform"))]
fn replace_transform<T>(_: impl Ctx + InjectFootprint, (element, _content_transform): (T, Attr<TransformAttr>), transform: DAffine2) -> (T, Attr<TransformAttr>) {
(element, Attr(transform))
}
// TODO: Figure out how this node should behave once #2982 is implemented.
/// Obtains the transform of the first lane of the input wire, if present.
/// Obtains the transform of the first lane of the input, if present.
#[node_macro::node(category("Math: Transform"), path(core_types::vector))]
fn extract_transform<T: Clone + Send + Sync + CacheHash + 'static>(_: impl Ctx, #[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, GradientStops)] content: IList<T>) -> DAffine2 {
match content.len() {