summaryrefslogtreecommitdiff
path: root/src/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/model')
-rw-r--r--src/model/content.rs10
-rw-r--r--src/model/realize.rs8
-rw-r--r--src/model/styles.rs32
-rw-r--r--src/model/typeset.rs19
4 files changed, 41 insertions, 28 deletions
diff --git a/src/model/content.rs b/src/model/content.rs
index bd24829d..5317236e 100644
--- a/src/model/content.rs
+++ b/src/model/content.rs
@@ -4,7 +4,6 @@ use std::hash::{Hash, Hasher};
use std::iter::{self, Sum};
use std::ops::{Add, AddAssign, Deref};
-use comemo::Tracked;
use ecow::{eco_format, EcoString, EcoVec};
use once_cell::sync::Lazy;
@@ -19,7 +18,6 @@ use crate::eval::{
};
use crate::syntax::Span;
use crate::util::pretty_array_like;
-use crate::World;
/// Composable representation of styled content.
#[derive(Clone, Hash)]
@@ -219,13 +217,9 @@ impl Content {
}
/// Style this content with a recipe, eagerly applying it if possible.
- pub fn styled_with_recipe(
- self,
- world: Tracked<dyn World>,
- recipe: Recipe,
- ) -> SourceResult<Self> {
+ pub fn styled_with_recipe(self, vm: &mut Vm, recipe: Recipe) -> SourceResult<Self> {
if recipe.selector.is_none() {
- recipe.apply(world, self)
+ recipe.apply_vm(vm, self)
} else {
Ok(self.styled(Style::Recipe(recipe)))
}
diff --git a/src/model/realize.rs b/src/model/realize.rs
index 70c75644..634a31fd 100644
--- a/src/model/realize.rs
+++ b/src/model/realize.rs
@@ -97,7 +97,7 @@ pub fn realize(
/// Try to apply a recipe to the target.
fn try_apply(
- vt: &Vt,
+ vt: &mut Vt,
target: &Content,
recipe: &Recipe,
guard: Guard,
@@ -108,7 +108,7 @@ fn try_apply(
return Ok(None);
}
- recipe.apply(vt.world, target.clone().guarded(guard)).map(Some)
+ recipe.apply_vt(vt, target.clone().guarded(guard)).map(Some)
}
Some(Selector::Label(label)) => {
@@ -116,7 +116,7 @@ fn try_apply(
return Ok(None);
}
- recipe.apply(vt.world, target.clone().guarded(guard)).map(Some)
+ recipe.apply_vt(vt, target.clone().guarded(guard)).map(Some)
}
Some(Selector::Regex(regex)) => {
@@ -140,7 +140,7 @@ fn try_apply(
}
let piece = make(m.as_str().into()).guarded(guard);
- let transformed = recipe.apply(vt.world, piece)?;
+ let transformed = recipe.apply_vt(vt, piece)?;
result.push(transformed);
cursor = m.end();
}
diff --git a/src/model/styles.rs b/src/model/styles.rs
index 359f1461..8cccb5f6 100644
--- a/src/model/styles.rs
+++ b/src/model/styles.rs
@@ -1,15 +1,13 @@
use std::fmt::{self, Debug, Formatter, Write};
use std::iter;
-use comemo::Tracked;
use ecow::{eco_format, EcoString, EcoVec};
-use super::{Content, Label, Node, NodeId};
+use super::{Content, Label, Node, NodeId, Vt};
use crate::diag::{SourceResult, Trace, Tracepoint};
-use crate::eval::{cast_from_value, Args, Cast, Dict, Func, Regex, Value};
+use crate::eval::{cast_from_value, Args, Cast, Dict, Func, Regex, Value, Vm};
use crate::syntax::Span;
use crate::util::pretty_array_like;
-use crate::World;
/// A map of style properties.
#[derive(Default, Clone, Hash)]
@@ -197,20 +195,32 @@ impl Recipe {
}
/// Apply the recipe to the given content.
- pub fn apply(
- &self,
- world: Tracked<dyn World>,
- content: Content,
- ) -> SourceResult<Content> {
+ pub fn apply_vm(&self, vm: &mut Vm, content: Content) -> SourceResult<Content> {
match &self.transform {
Transform::Content(content) => Ok(content.clone()),
Transform::Func(func) => {
let args = Args::new(self.span, [Value::Content(content.clone())]);
- let mut result = func.call_detached(world, args);
+ let mut result = func.call_vm(vm, args);
// For selector-less show rules, a tracepoint makes no sense.
if self.selector.is_some() {
let point = || Tracepoint::Show(content.id().name.into());
- result = result.trace(world, point, content.span());
+ result = result.trace(vm.world(), point, content.span());
+ }
+ Ok(result?.display())
+ }
+ Transform::Style(styles) => Ok(content.styled_with_map(styles.clone())),
+ }
+ }
+
+ /// Apply the recipe to the given content.
+ pub fn apply_vt(&self, vt: &mut Vt, content: Content) -> SourceResult<Content> {
+ match &self.transform {
+ Transform::Content(content) => Ok(content.clone()),
+ Transform::Func(func) => {
+ let mut result = func.call_vt(vt, [Value::Content(content.clone())]);
+ if self.selector.is_some() {
+ let point = || Tracepoint::Show(content.id().name.into());
+ result = result.trace(vt.world, point, content.span());
}
Ok(result?.display())
}
diff --git a/src/model/typeset.rs b/src/model/typeset.rs
index e9cb3d2c..683f2846 100644
--- a/src/model/typeset.rs
+++ b/src/model/typeset.rs
@@ -6,13 +6,18 @@ use comemo::{Constraint, Track, Tracked, TrackedMut};
use super::{Content, Selector, StyleChain};
use crate::diag::SourceResult;
use crate::doc::{Document, Element, Frame, Location, Meta};
+use crate::eval::Tracer;
use crate::geom::{Point, Transform};
use crate::util::NonZeroExt;
use crate::World;
/// Typeset content into a fully layouted document.
#[comemo::memoize]
-pub fn typeset(world: Tracked<dyn World>, content: &Content) -> SourceResult<Document> {
+pub fn typeset(
+ world: Tracked<dyn World>,
+ mut tracer: TrackedMut<Tracer>,
+ content: &Content,
+) -> SourceResult<Document> {
let library = world.library();
let styles = StyleChain::new(&library.styles);
@@ -27,6 +32,7 @@ pub fn typeset(world: Tracked<dyn World>, content: &Content) -> SourceResult<Doc
let mut provider = StabilityProvider::new();
let mut vt = Vt {
world,
+ tracer: TrackedMut::reborrow_mut(&mut tracer),
provider: provider.track_mut(),
introspector: introspector.track_with(&constraint),
};
@@ -52,6 +58,8 @@ pub fn typeset(world: Tracked<dyn World>, content: &Content) -> SourceResult<Doc
pub struct Vt<'a> {
/// The compilation environment.
pub world: Tracked<'a, dyn World>,
+ /// The tracer for inspection of the values an expression produces.
+ pub tracer: TrackedMut<'a, Tracer>,
/// Provides stable identities to nodes.
pub provider: TrackedMut<'a, StabilityProvider>,
/// Provides access to information about the document.
@@ -162,8 +170,8 @@ impl Introspector {
}
/// Query for all metadata matches for the given selector.
- pub fn query(&self, selector: Selector) -> Vec<&Content> {
- self.all().filter(|node| selector.matches(node)).collect()
+ pub fn query(&self, selector: Selector) -> Vec<Content> {
+ self.all().filter(|node| selector.matches(node)).cloned().collect()
}
/// Query for all metadata matches before the given id.
@@ -171,14 +179,15 @@ impl Introspector {
&self,
selector: Selector,
id: StableId,
- ) -> (Vec<&Content>, Vec<&Content>) {
+ ) -> (Vec<Content>, Vec<Content>) {
let mut iter = self.all();
let before = iter
.by_ref()
.take_while(|node| node.stable_id() != Some(id))
.filter(|node| selector.matches(node))
+ .cloned()
.collect();
- let after = iter.filter(|node| selector.matches(node)).collect();
+ let after = iter.filter(|node| selector.matches(node)).cloned().collect();
(before, after)
}