diff options
| author | Laurenz <laurmaedje@gmail.com> | 2023-06-12 15:40:43 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2023-06-12 15:42:01 +0200 |
| commit | 378ebe5f5601f11c3f428c17bed492012feb251e (patch) | |
| tree | 4530bf009844faca40ca4fd6d0b9251fd51ef587 /src/model/mod.rs | |
| parent | 19bf1f58944a42f17903869c162a33aba22b80b0 (diff) | |
Delayed errors
Fixes #785. Thanks to @Dherse for the idea!
Diffstat (limited to 'src/model/mod.rs')
| -rw-r--r-- | src/model/mod.rs | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/src/model/mod.rs b/src/model/mod.rs index 632b691f..ee940236 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -28,7 +28,7 @@ use std::mem::ManuallyDrop; use comemo::{Track, Tracked, TrackedMut, Validate}; -use crate::diag::SourceResult; +use crate::diag::{SourceError, SourceResult}; use crate::doc::Document; use crate::eval::Tracer; use crate::World; @@ -46,8 +46,9 @@ pub fn typeset( let library = world.library(); let styles = StyleChain::new(&library.styles); - let mut document; let mut iter = 0; + let mut document; + let mut delayed; // We need `ManuallyDrop` until this lands in stable: // https://github.com/rust-lang/rust/issues/70919 @@ -58,6 +59,8 @@ pub fn typeset( loop { tracing::info!("Layout iteration {iter}"); + delayed = DelayedErrors::default(); + let constraint = <Introspector as Validate>::Constraint::new(); let mut locator = Locator::new(); let mut vt = Vt { @@ -65,6 +68,7 @@ pub fn typeset( tracer: TrackedMut::reborrow_mut(&mut tracer), locator: &mut locator, introspector: introspector.track_with(&constraint), + delayed: delayed.track_mut(), }; // Layout! @@ -86,6 +90,11 @@ pub fn typeset( // Drop the introspector. ManuallyDrop::into_inner(introspector); + // Promote delayed errors. + if !delayed.0.is_empty() { + return Err(Box::new(delayed.0)); + } + Ok(document) } @@ -95,10 +104,45 @@ pub fn typeset( pub struct Vt<'a> { /// The compilation environment. pub world: Tracked<'a, dyn World + 'a>, - /// The tracer for inspection of the values an expression produces. - pub tracer: TrackedMut<'a, Tracer>, - /// Provides stable identities to elements. - pub locator: &'a mut Locator<'a>, /// Provides access to information about the document. pub introspector: Tracked<'a, Introspector>, + /// Provides stable identities to elements. + pub locator: &'a mut Locator<'a>, + /// Delayed errors that do not immediately terminate execution. + pub delayed: TrackedMut<'a, DelayedErrors>, + /// The tracer for inspection of the values an expression produces. + pub tracer: TrackedMut<'a, Tracer>, +} + +impl Vt<'_> { + /// Perform a fallible operation that does not immediately terminate further + /// execution. Instead it produces a delayed error that is only promoted to + /// a fatal one if it remains at the end of the introspection loop. + pub fn delayed<F, T>(&mut self, f: F) -> T + where + F: FnOnce(&mut Self) -> SourceResult<T>, + T: Default, + { + match f(self) { + Ok(value) => value, + Err(errors) => { + for error in *errors { + self.delayed.push(error); + } + T::default() + } + } + } +} + +/// Holds delayed errors. +#[derive(Default, Clone)] +pub struct DelayedErrors(Vec<SourceError>); + +#[comemo::track] +impl DelayedErrors { + /// Push a delayed error. + fn push(&mut self, error: SourceError) { + self.0.push(error); + } } |
