mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Probe lower-bound inner levels to their exact span
This commit is contained in:
@@ -821,7 +821,7 @@ impl<'a, 'e, N> RecordLazyInput<'a, 'e, N> {
|
||||
B: crate::context::DeriveCtx,
|
||||
N: for<'d> DerivedRecordEdge<'d, crate::context::Derived<'d, B>>,
|
||||
{
|
||||
inner_extent_of(self.node, ctx, 0, self.inner_levels)
|
||||
inner_extent_of(self.node, ctx, 0, self.inner_levels, self.input_index)
|
||||
}
|
||||
|
||||
/// The flat lane count of the copy at `copy`, for edges whose inner
|
||||
@@ -831,12 +831,12 @@ impl<'a, 'e, N> RecordLazyInput<'a, 'e, N> {
|
||||
B: crate::context::DeriveCtx,
|
||||
N: for<'d> DerivedRecordEdge<'d, crate::context::Derived<'d, B>>,
|
||||
{
|
||||
inner_extent_of(self.node, ctx, copy, self.inner_levels)
|
||||
inner_extent_of(self.node, ctx, copy, self.inner_levels, self.input_index)
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`RecordLazyInput::inner_extent`].
|
||||
fn inner_extent_of<B, N>(node: &N, ctx: &B, copy: u64, levels: u8) -> Result<u64, crate::gpoll::Interrupt>
|
||||
fn inner_extent_of<B, N>(node: &N, ctx: &B, copy: u64, levels: u8, input_index: usize) -> Result<u64, crate::gpoll::Interrupt>
|
||||
where
|
||||
B: crate::context::DeriveCtx,
|
||||
N: for<'d> DerivedRecordEdge<'d, crate::context::Derived<'d, B>>,
|
||||
@@ -847,6 +847,7 @@ where
|
||||
for level in 0..levels {
|
||||
match node.extent_at_derived(&derived, level) {
|
||||
GPoll::Final(crate::gpoll::Extent::Exactly(count)) => inner *= count as u64,
|
||||
GPoll::Final(crate::gpoll::Extent::AtLeast(_)) => return probed_inner(node, ctx, copy, input_index),
|
||||
GPoll::Pending => return Err(crate::gpoll::Interrupt::Pending),
|
||||
_ => return Err(crate::gpoll::GraphError::new("structure decomposition over a non-exact extent").into()),
|
||||
}
|
||||
@@ -854,6 +855,32 @@ where
|
||||
Ok(inner)
|
||||
}
|
||||
|
||||
/// The flat lane count of one copy of a lower-bound edge, 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) -> Result<u64, crate::gpoll::Interrupt>
|
||||
where
|
||||
B: crate::context::DeriveCtx,
|
||||
N: for<'d> DerivedRecordEdge<'d, crate::context::Derived<'d, B>>,
|
||||
{
|
||||
let cell = crate::node::StatusCell::new();
|
||||
let mut count: u64 = 0;
|
||||
loop {
|
||||
let mark = stack::sp();
|
||||
let mut frame = crate::context::IndexLink { index: 0, outer: None };
|
||||
let probe = ctx.push_level(&mut frame, copy, count);
|
||||
let result = node.eval_derived(&cell, input_index, &probe);
|
||||
// SAFETY: the probed record is discarded, so nothing above the mark
|
||||
// is live.
|
||||
unsafe { stack::rewind(mark) };
|
||||
match result {
|
||||
Ok(_) => count += 1,
|
||||
Err(crate::gpoll::Interrupt::Error(error)) if error.kind == crate::gpoll::ErrorKind::PastEnd => return Ok(count),
|
||||
Err(interrupt) => return Err(interrupt),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The derive-routing carrier beside its declared attribute reads: evaluating
|
||||
/// at a derived context yields the opaque row token and the read values in one
|
||||
/// step, so the kernel drives the per-copy eval while reads stay resolved
|
||||
@@ -890,7 +917,7 @@ impl<'a, 'e, Out, N> DerivedLazyInput<'a, 'e, Out, N> {
|
||||
B: crate::context::DeriveCtx,
|
||||
N: for<'d> DerivedRecordEdge<'d, crate::context::Derived<'d, B>>,
|
||||
{
|
||||
inner_extent_of(self.node, ctx, 0, self.inner_levels)
|
||||
inner_extent_of(self.node, ctx, 0, self.inner_levels, self.input_index)
|
||||
}
|
||||
|
||||
pub fn eval<'d, C>(&self, ctx: &C) -> Result<Out, crate::gpoll::Interrupt>
|
||||
|
||||
Reference in New Issue
Block a user