summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/eval/func.rs25
-rw-r--r--src/eval/mod.rs19
-rw-r--r--src/model/introspect.rs5
-rw-r--r--src/model/mod.rs56
4 files changed, 79 insertions, 26 deletions
diff --git a/src/eval/func.rs b/src/eval/func.rs
index 1745dfb1..28d4a40d 100644
--- a/src/eval/func.rs
+++ b/src/eval/func.rs
@@ -11,7 +11,7 @@ use super::{
Value, Vm,
};
use crate::diag::{bail, SourceResult, StrResult};
-use crate::model::{ElemFunc, Introspector, Locator, Vt};
+use crate::model::{DelayedErrors, ElemFunc, Introspector, Locator, Vt};
use crate::syntax::ast::{self, AstNode, Expr, Ident};
use crate::syntax::{SourceId, Span, SyntaxNode};
use crate::World;
@@ -102,9 +102,10 @@ impl Func {
self,
vm.world(),
route,
- TrackedMut::reborrow_mut(&mut vm.vt.tracer),
- vm.vt.locator.track(),
vm.vt.introspector,
+ vm.vt.locator.track(),
+ TrackedMut::reborrow_mut(&mut vm.vt.delayed),
+ TrackedMut::reborrow_mut(&mut vm.vt.tracer),
vm.depth + 1,
args,
)
@@ -129,9 +130,10 @@ impl Func {
let mut locator = Locator::chained(vt.locator.track());
let vt = Vt {
world: vt.world,
- tracer: TrackedMut::reborrow_mut(&mut vt.tracer),
- locator: &mut locator,
introspector: vt.introspector,
+ locator: &mut locator,
+ delayed: TrackedMut::reborrow_mut(&mut vt.delayed),
+ tracer: TrackedMut::reborrow_mut(&mut vt.tracer),
};
let mut vm = Vm::new(vt, route.track(), id, scopes);
let args = Args::new(self.span(), args);
@@ -326,9 +328,10 @@ impl Closure {
this: &Func,
world: Tracked<dyn World + '_>,
route: Tracked<Route>,
- tracer: TrackedMut<Tracer>,
- locator: Tracked<Locator>,
introspector: Tracked<Introspector>,
+ locator: Tracked<Locator>,
+ delayed: TrackedMut<DelayedErrors>,
+ tracer: TrackedMut<Tracer>,
depth: usize,
mut args: Args,
) -> SourceResult<Value> {
@@ -344,7 +347,13 @@ impl Closure {
// Prepare VT.
let mut locator = Locator::chained(locator);
- let vt = Vt { world, tracer, locator: &mut locator, introspector };
+ let vt = Vt {
+ world,
+ introspector,
+ locator: &mut locator,
+ delayed,
+ tracer,
+ };
// Prepare VM.
let mut vm = Vm::new(vt, route, closure.location, scopes);
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index e6016218..fe11606a 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -62,9 +62,6 @@ use ecow::{EcoString, EcoVec};
use unicode_segmentation::UnicodeSegmentation;
use self::func::{CapturesVisitor, Closure};
-use crate::diag::{
- bail, error, At, SourceError, SourceResult, StrResult, Trace, Tracepoint,
-};
use crate::model::{
Content, Introspector, Label, Locator, Recipe, ShowableSelector, Styles, Transform,
Unlabellable, Vt,
@@ -75,6 +72,10 @@ use crate::syntax::{
};
use crate::util::PathExt;
use crate::World;
+use crate::{
+ diag::{bail, error, At, SourceError, SourceResult, StrResult, Trace, Tracepoint},
+ model::DelayedErrors,
+};
const MAX_ITERATIONS: usize = 10_000;
const MAX_CALL_DEPTH: usize = 64;
@@ -102,11 +103,13 @@ pub fn eval(
// Prepare VT.
let mut locator = Locator::default();
let introspector = Introspector::default();
+ let mut delayed = DelayedErrors::default();
let vt = Vt {
world,
- tracer,
- locator: &mut locator,
introspector: introspector.track(),
+ locator: &mut locator,
+ delayed: delayed.track_mut(),
+ tracer,
};
// Prepare VM.
@@ -151,12 +154,14 @@ pub fn eval_string(
// Prepare VT.
let mut tracer = Tracer::default();
let mut locator = Locator::default();
+ let mut delayed = DelayedErrors::default();
let introspector = Introspector::default();
let vt = Vt {
world,
- tracer: tracer.track_mut(),
- locator: &mut locator,
introspector: introspector.track(),
+ locator: &mut locator,
+ delayed: delayed.track_mut(),
+ tracer: tracer.track_mut(),
};
// Prepare VM.
diff --git a/src/model/introspect.rs b/src/model/introspect.rs
index f00f89f5..b150fabf 100644
--- a/src/model/introspect.rs
+++ b/src/model/introspect.rs
@@ -241,11 +241,6 @@ impl Introspector {
#[comemo::track]
impl Introspector {
- /// Whether this introspector is not yet initialized.
- pub fn init(&self) -> bool {
- self.pages > 0
- }
-
/// Query for all matching elements.
pub fn query(&self, selector: &Selector) -> EcoVec<Prehashed<Content>> {
let hash = crate::util::hash128(selector);
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);
+ }
}