Track context (#3623)

This commit is contained in:
Laurenz 2024-03-12 11:28:15 +01:00 committed by GitHub
parent d01ccffad6
commit 633c32a552
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 108 additions and 67 deletions

View File

@ -67,8 +67,12 @@ pub fn analyze_import(world: &dyn World, source: &LinkedNode) -> Option<Value> {
}; };
let context = Context::none(); let context = Context::none();
let mut vm = let mut vm = Vm::new(
Vm::new(engine, &context, Scopes::new(Some(world.library())), Span::detached()); engine,
context.track(),
Scopes::new(Some(world.library())),
Span::detached(),
);
typst::eval::import(&mut vm, source, Span::detached(), true) typst::eval::import(&mut vm, source, Span::detached(), true)
.ok() .ok()
.map(Value::Module) .map(Value::Module)

View File

@ -278,7 +278,7 @@ pub(crate) fn call_closure(
route: Tracked<Route>, route: Tracked<Route>,
locator: Tracked<Locator>, locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>, tracer: TrackedMut<Tracer>,
context: &Context, context: Tracked<Context>,
mut args: Args, mut args: Args,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
let (name, params, body) = match closure.node.cast::<ast::Closure>() { let (name, params, body) = match closure.node.cast::<ast::Closure>() {

View File

@ -63,7 +63,7 @@ pub fn eval(
let context = Context::none(); let context = Context::none();
let scopes = Scopes::new(Some(world.library())); let scopes = Scopes::new(Some(world.library()));
let root = source.root(); let root = source.root();
let mut vm = Vm::new(engine, &context, scopes, root.span()); let mut vm = Vm::new(engine, context.track(), scopes, root.span());
// Check for well-formedness unless we are in trace mode. // Check for well-formedness unless we are in trace mode.
let errors = root.errors(); let errors = root.errors();
@ -131,7 +131,7 @@ pub fn eval_string(
// Prepare VM. // Prepare VM.
let context = Context::none(); let context = Context::none();
let scopes = Scopes::new(Some(world.library())); let scopes = Scopes::new(Some(world.library()));
let mut vm = Vm::new(engine, &context, scopes, root.span()); let mut vm = Vm::new(engine, context.track(), scopes, root.span());
vm.scopes.scopes.push(scope); vm.scopes.scopes.push(scope);
// Evaluate the code. // Evaluate the code.

View File

@ -21,14 +21,14 @@ pub struct Vm<'a> {
/// A span that is currently under inspection. /// A span that is currently under inspection.
pub(crate) inspected: Option<Span>, pub(crate) inspected: Option<Span>,
/// Data that is contextually made accessible to code behind the scenes. /// Data that is contextually made accessible to code behind the scenes.
pub(crate) context: &'a Context<'a>, pub(crate) context: Tracked<'a, Context<'a>>,
} }
impl<'a> Vm<'a> { impl<'a> Vm<'a> {
/// Create a new virtual machine. /// Create a new virtual machine.
pub fn new( pub fn new(
engine: Engine<'a>, engine: Engine<'a>,
context: &'a Context<'a>, context: Tracked<'a, Context<'a>>,
scopes: Scopes<'a>, scopes: Scopes<'a>,
target: Span, target: Span,
) -> Self { ) -> Self {
@ -55,6 +55,6 @@ impl<'a> Vm<'a> {
pub fn trace(&mut self, value: Value) { pub fn trace(&mut self, value: Value) {
self.engine self.engine
.tracer .tracer
.value(value.clone(), self.context.styles.map(|s| s.to_map())); .value(value.clone(), self.context.styles().ok().map(|s| s.to_map()));
} }
} }

View File

@ -3,6 +3,7 @@ use std::fmt::{Debug, Formatter};
use std::num::{NonZeroI64, NonZeroUsize}; use std::num::{NonZeroI64, NonZeroUsize};
use std::ops::{Add, AddAssign}; use std::ops::{Add, AddAssign};
use comemo::Tracked;
use ecow::{eco_format, EcoString, EcoVec}; use ecow::{eco_format, EcoString, EcoVec};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -301,7 +302,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The function to apply to each item. Must return a boolean. /// The function to apply to each item. Must return a boolean.
searcher: Func, searcher: Func,
) -> SourceResult<Option<Value>> { ) -> SourceResult<Option<Value>> {
@ -325,7 +326,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The function to apply to each item. Must return a boolean. /// The function to apply to each item. Must return a boolean.
searcher: Func, searcher: Func,
) -> SourceResult<Option<i64>> { ) -> SourceResult<Option<i64>> {
@ -402,7 +403,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The function to apply to each item. Must return a boolean. /// The function to apply to each item. Must return a boolean.
test: Func, test: Func,
) -> SourceResult<Array> { ) -> SourceResult<Array> {
@ -427,7 +428,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The function to apply to each item. /// The function to apply to each item.
mapper: Func, mapper: Func,
) -> SourceResult<Array> { ) -> SourceResult<Array> {
@ -536,7 +537,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The initial value to start with. /// The initial value to start with.
init: Value, init: Value,
/// The folding function. Must have two parameters: One for the /// The folding function. Must have two parameters: One for the
@ -598,7 +599,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The function to apply to each item. Must return a boolean. /// The function to apply to each item. Must return a boolean.
test: Func, test: Func,
) -> SourceResult<bool> { ) -> SourceResult<bool> {
@ -618,7 +619,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The function to apply to each item. Must return a boolean. /// The function to apply to each item. Must return a boolean.
test: Func, test: Func,
) -> SourceResult<bool> { ) -> SourceResult<bool> {
@ -765,7 +766,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// If given, applies this function to the elements in the array to /// If given, applies this function to the elements in the array to
@ -815,7 +816,7 @@ impl Array {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// If given, applies this function to the elements in the array to /// If given, applies this function to the elements in the array to
/// determine the keys to deduplicate by. /// determine the keys to deduplicate by.
#[named] #[named]

View File

@ -6,6 +6,7 @@ use std::marker::PhantomData;
use std::ops::{Add, AddAssign, Deref, DerefMut}; use std::ops::{Add, AddAssign, Deref, DerefMut};
use std::sync::Arc; use std::sync::Arc;
use comemo::Tracked;
use ecow::{eco_format, EcoString}; use ecow::{eco_format, EcoString};
use serde::{Serialize, Serializer}; use serde::{Serialize, Serializer};
use smallvec::smallvec; use smallvec::smallvec;
@ -345,7 +346,7 @@ impl Content {
pub fn styled_with_recipe( pub fn styled_with_recipe(
self, self,
engine: &mut Engine, engine: &mut Engine,
context: &Context, context: Tracked<Context>,
recipe: Recipe, recipe: Recipe,
) -> SourceResult<Self> { ) -> SourceResult<Self> {
if recipe.selector.is_none() { if recipe.selector.is_none() {

View File

@ -1,3 +1,5 @@
use comemo::Track;
use crate::diag::{bail, Hint, HintedStrResult, SourceResult}; use crate::diag::{bail, Hint, HintedStrResult, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
@ -28,7 +30,10 @@ impl<'a> Context<'a> {
pub fn new(location: Option<Location>, styles: Option<StyleChain<'a>>) -> Self { pub fn new(location: Option<Location>, styles: Option<StyleChain<'a>>) -> Self {
Self { location, styles } Self { location, styles }
} }
}
#[comemo::track]
impl<'a> Context<'a> {
/// Try to extract the location. /// Try to extract the location.
pub fn location(&self) -> HintedStrResult<Location> { pub fn location(&self) -> HintedStrResult<Location> {
require(self.location) require(self.location)
@ -75,6 +80,6 @@ impl Show for Packed<ContextElem> {
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> { fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let loc = self.location().unwrap(); let loc = self.location().unwrap();
let context = Context::new(Some(loc), Some(styles)); let context = Context::new(Some(loc), Some(styles));
Ok(self.func.call::<[Value; 0]>(engine, &context, [])?.display()) Ok(self.func.call::<[Value; 0]>(engine, context.track(), [])?.display())
} }
} }

View File

@ -1,7 +1,7 @@
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use std::sync::Arc; use std::sync::Arc;
use comemo::TrackedMut; use comemo::{Tracked, TrackedMut};
use ecow::{eco_format, EcoString}; use ecow::{eco_format, EcoString};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -261,7 +261,7 @@ impl Func {
pub fn call<A: IntoArgs>( pub fn call<A: IntoArgs>(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
context: &Context, context: Tracked<Context>,
args: A, args: A,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
self.call_impl(engine, context, args.into_args(self.span)) self.call_impl(engine, context, args.into_args(self.span))
@ -272,7 +272,7 @@ impl Func {
fn call_impl( fn call_impl(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
context: &Context, context: Tracked<Context>,
mut args: Args, mut args: Args,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
match &self.repr { match &self.repr {
@ -440,7 +440,7 @@ pub trait NativeFunc {
/// Defines a native function. /// Defines a native function.
#[derive(Debug)] #[derive(Debug)]
pub struct NativeFuncData { pub struct NativeFuncData {
pub function: fn(&mut Engine, &Context, &mut Args) -> SourceResult<Value>, pub function: fn(&mut Engine, Tracked<Context>, &mut Args) -> SourceResult<Value>,
pub name: &'static str, pub name: &'static str,
pub title: &'static str, pub title: &'static str,
pub docs: &'static str, pub docs: &'static str,

View File

@ -304,7 +304,7 @@ impl LocatableSelector {
pub fn resolve_unique( pub fn resolve_unique(
&self, &self,
introspector: Tracked<Introspector>, introspector: Tracked<Introspector>,
context: &Context, context: Tracked<Context>,
) -> HintedStrResult<Location> { ) -> HintedStrResult<Location> {
match &self.0 { match &self.0 {
Selector::Location(loc) => Ok(*loc), Selector::Location(loc) => Ok(*loc),

View File

@ -3,6 +3,7 @@ use std::fmt::{self, Debug, Display, Formatter};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::{Add, AddAssign, Deref, Range}; use std::ops::{Add, AddAssign, Deref, Range};
use comemo::Tracked;
use ecow::EcoString; use ecow::EcoString;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
@ -425,7 +426,7 @@ impl Str {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The pattern to search for. /// The pattern to search for.
pattern: StrPattern, pattern: StrPattern,
/// The string to replace the matches with or a function that gets a /// The string to replace the matches with or a function that gets a

View File

@ -3,6 +3,7 @@ use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::{mem, ptr}; use std::{mem, ptr};
use comemo::{Track, Tracked};
use ecow::{eco_vec, EcoString, EcoVec}; use ecow::{eco_vec, EcoString, EcoVec};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -57,7 +58,10 @@ impl Show for Packed<StyleElem> {
#[typst_macros::time(name = "style", span = self.span())] #[typst_macros::time(name = "style", span = self.span())]
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> { fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let context = Context::new(self.location(), Some(styles)); let context = Context::new(self.location(), Some(styles));
Ok(self.func().call(engine, &context, [styles.to_map()])?.display()) Ok(self
.func()
.call(engine, context.track(), [styles.to_map()])?
.display())
} }
} }
@ -385,7 +389,7 @@ impl Recipe {
pub fn apply( pub fn apply(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
context: &Context, context: Tracked<Context>,
content: Content, content: Content,
) -> SourceResult<Content> { ) -> SourceResult<Content> {
let mut content = match &self.transform { let mut content = match &self.transform {

View File

@ -1,7 +1,7 @@
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::str::FromStr; use std::str::FromStr;
use comemo::{Tracked, TrackedMut}; use comemo::{Track, Tracked, TrackedMut};
use ecow::{eco_format, eco_vec, EcoString, EcoVec}; use ecow::{eco_format, eco_vec, EcoString, EcoVec};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -271,7 +271,7 @@ impl Counter {
let context = Context::new(Some(loc), Some(styles)); let context = Context::new(Some(loc), Some(styles));
Ok(self Ok(self
.at_loc(engine, loc)? .at_loc(engine, loc)?
.display(engine, &context, numbering)? .display(engine, context.track(), numbering)?
.display()) .display())
} }
@ -392,7 +392,7 @@ impl Counter {
}; };
let context = Context::new(Some(location), styles); let context = Context::new(Some(location), styles);
state.display(engine, &context, &numbering) state.display(engine, context.track(), &numbering)
} }
} }
@ -425,7 +425,7 @@ impl Counter {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
) -> SourceResult<CounterState> { ) -> SourceResult<CounterState> {
@ -446,7 +446,7 @@ impl Counter {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The call span of the display. /// The call span of the display.
span: Span, span: Span,
/// A [numbering pattern or a function]($numbering), which specifies how /// A [numbering pattern or a function]($numbering), which specifies how
@ -468,8 +468,8 @@ impl Counter {
#[default(false)] #[default(false)]
both: bool, both: bool,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
if let Some(loc) = context.location { if let Ok(loc) = context.location() {
self.display_impl(engine, loc, numbering, both, context.styles) self.display_impl(engine, loc, numbering, both, context.styles().ok())
} else { } else {
Ok(CounterDisplayElem::new(self, numbering, both) Ok(CounterDisplayElem::new(self, numbering, both)
.pack() .pack()
@ -494,7 +494,7 @@ impl Counter {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// The place at which the counter's value should be retrieved. /// The place at which the counter's value should be retrieved.
@ -512,7 +512,7 @@ impl Counter {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// _Compatibility:_ This argument only exists for compatibility with /// _Compatibility:_ This argument only exists for compatibility with
@ -669,7 +669,7 @@ impl CounterState {
CounterUpdate::Step(level) => self.step(level, 1), CounterUpdate::Step(level) => self.step(level, 1),
CounterUpdate::Func(func) => { CounterUpdate::Func(func) => {
*self = func *self = func
.call(engine, &Context::none(), self.0.iter().copied())? .call(engine, Context::none().track(), self.0.iter().copied())?
.cast() .cast()
.at(func.span())? .at(func.span())?
} }
@ -700,7 +700,7 @@ impl CounterState {
pub fn display( pub fn display(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
context: &Context, context: Tracked<Context>,
numbering: &Numbering, numbering: &Numbering,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
numbering.apply(engine, context, &self.0) numbering.apply(engine, context, &self.0)

View File

@ -1,3 +1,5 @@
use comemo::Tracked;
use crate::diag::HintedStrResult; use crate::diag::HintedStrResult;
use crate::foundations::{func, Context}; use crate::foundations::{func, Context};
use crate::introspection::Location; use crate::introspection::Location;
@ -44,7 +46,7 @@ use crate::introspection::Location;
#[func(contextual)] #[func(contextual)]
pub fn here( pub fn here(
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
) -> HintedStrResult<Location> { ) -> HintedStrResult<Location> {
context.location() context.location()
} }

View File

@ -1,3 +1,5 @@
use comemo::{Track, Tracked};
use crate::diag::{HintedStrResult, SourceResult}; use crate::diag::{HintedStrResult, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
@ -37,7 +39,7 @@ pub fn locate(
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The span of the `locate` call. /// The span of the `locate` call.
span: Span, span: Span,
/// A selector that should match exactly one element. This element will be /// A selector that should match exactly one element. This element will be
@ -106,6 +108,6 @@ impl Show for Packed<LocateElem> {
fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> { fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let location = self.location().unwrap(); let location = self.location().unwrap();
let context = Context::new(Some(location), Some(styles)); let context = Context::new(Some(location), Some(styles));
Ok(self.func().call(engine, &context, [location])?.display()) Ok(self.func().call(engine, context.track(), [location])?.display())
} }
} }

View File

@ -1,3 +1,5 @@
use comemo::Tracked;
use crate::diag::HintedStrResult; use crate::diag::HintedStrResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{func, Array, Context, LocatableSelector, Value}; use crate::foundations::{func, Array, Context, LocatableSelector, Value};
@ -135,7 +137,7 @@ pub fn query(
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// Can be /// Can be
/// - an element function like a `heading` or `figure`, /// - an element function like a `heading` or `figure`,
/// - a `{<label>}`, /// - a `{<label>}`,

View File

@ -1,4 +1,4 @@
use comemo::{Tracked, TrackedMut}; use comemo::{Track, Tracked, TrackedMut};
use ecow::{eco_format, eco_vec, EcoString, EcoVec}; use ecow::{eco_format, eco_vec, EcoString, EcoVec};
use crate::diag::{bail, At, SourceResult}; use crate::diag::{bail, At, SourceResult};
@ -249,7 +249,7 @@ impl State {
match elem.update() { match elem.update() {
StateUpdate::Set(value) => state = value.clone(), StateUpdate::Set(value) => state = value.clone(),
StateUpdate::Func(func) => { StateUpdate::Func(func) => {
state = func.call(&mut engine, &Context::none(), [state])? state = func.call(&mut engine, Context::none().track(), [state])?
} }
} }
stops.push(state.clone()); stops.push(state.clone());
@ -287,7 +287,7 @@ impl State {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
@ -310,7 +310,7 @@ impl State {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// The place at which the state's value should be retrieved. /// The place at which the state's value should be retrieved.
@ -327,7 +327,7 @@ impl State {
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// _Compatibility:_ This argument only exists for compatibility with /// _Compatibility:_ This argument only exists for compatibility with
@ -451,7 +451,7 @@ impl Show for Packed<StateDisplayElem> {
let context = Context::new(Some(location), Some(styles)); let context = Context::new(Some(location), Some(styles));
let value = self.state().at_loc(engine, location)?; let value = self.state().at_loc(engine, location)?;
Ok(match self.func() { Ok(match self.func() {
Some(func) => func.call(engine, &context, [value])?.display(), Some(func) => func.call(engine, context.track(), [value])?.display(),
None => value.display(), None => value.display(),
}) })
} }

View File

@ -3,6 +3,7 @@ use std::hash::Hash;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::sync::Arc; use std::sync::Arc;
use comemo::Track;
use ecow::eco_format; use ecow::eco_format;
use super::lines::{ use super::lines::{
@ -50,7 +51,7 @@ impl<T: Default + Clone + FromValue> Celled<T> {
Ok(match self { Ok(match self {
Self::Value(value) => value.clone(), Self::Value(value) => value.clone(),
Self::Func(func) => func Self::Func(func) => func
.call(engine, &Context::new(None, Some(styles)), [x, y])? .call(engine, Context::new(None, Some(styles)).track(), [x, y])?
.cast() .cast()
.at(func.span())?, .at(func.span())?,
Self::Array(array) => x Self::Array(array) => x
@ -151,7 +152,7 @@ where
Ok(match &self.0 { Ok(match &self.0 {
Celled::Value(value) => value.clone(), Celled::Value(value) => value.clone(),
Celled::Func(func) => func Celled::Func(func) => func
.call(engine, &Context::new(None, Some(styles)), [x, y])? .call(engine, Context::new(None, Some(styles)).track(), [x, y])?
.cast::<T>() .cast::<T>()
.at(func.span())? .at(func.span())?
.resolve(styles), .resolve(styles),

View File

@ -1,3 +1,5 @@
use comemo::Track;
use crate::diag::SourceResult; use crate::diag::SourceResult;
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
@ -84,7 +86,7 @@ impl LayoutMultiple for Packed<LayoutElem> {
let context = Context::new(Some(loc), Some(styles)); let context = Context::new(Some(loc), Some(styles));
let result = self let result = self
.func() .func()
.call(engine, &context, [dict! { "width" => x, "height" => y }])? .call(engine, context.track(), [dict! { "width" => x, "height" => y }])?
.display(); .display();
result.layout(engine, styles, regions) result.layout(engine, styles, regions)
} }

View File

@ -2,6 +2,7 @@ use std::cmp::Ordering;
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use std::ops::{Add, Div, Mul, Neg}; use std::ops::{Add, Div, Mul, Neg};
use comemo::Tracked;
use ecow::{eco_format, EcoString}; use ecow::{eco_format, EcoString};
use crate::diag::{At, Hint, HintedStrResult, SourceResult}; use crate::diag::{At, Hint, HintedStrResult, SourceResult};
@ -151,7 +152,7 @@ impl Length {
/// ] /// ]
/// ``` /// ```
#[func] #[func]
pub fn to_absolute(&self, context: &Context) -> HintedStrResult<Length> { pub fn to_absolute(&self, context: Tracked<Context>) -> HintedStrResult<Length> {
Ok(self.resolve(context.styles()?).into()) Ok(self.resolve(context.styles()?).into())
} }
} }

View File

@ -1,3 +1,5 @@
use comemo::Tracked;
use crate::diag::{At, SourceResult}; use crate::diag::{At, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{dict, func, Content, Context, Dict, StyleChain, Styles}; use crate::foundations::{dict, func, Content, Context, Dict, StyleChain, Styles};
@ -43,7 +45,7 @@ pub fn measure(
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// The callsite span. /// The callsite span.
span: Span, span: Span,
/// The content whose size to measure. /// The content whose size to measure.

View File

@ -3,6 +3,8 @@ use std::num::NonZeroUsize;
use std::ptr; use std::ptr;
use std::str::FromStr; use std::str::FromStr;
use comemo::Track;
use crate::diag::{bail, SourceResult}; use crate::diag::{bail, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
@ -691,7 +693,7 @@ impl Marginal {
Ok(match self { Ok(match self {
Self::Content(content) => Cow::Borrowed(content), Self::Content(content) => Cow::Borrowed(content),
Self::Func(func) => Cow::Owned( Self::Func(func) => Cow::Owned(
func.call(engine, &Context::new(None, Some(styles)), [page])? func.call(engine, Context::new(None, Some(styles)).track(), [page])?
.display(), .display(),
), ),
}) })

View File

@ -1,3 +1,5 @@
use comemo::Track;
use crate::diag::{At, SourceResult}; use crate::diag::{At, SourceResult};
use crate::foundations::{ use crate::foundations::{
cast, elem, Content, Context, Func, Packed, Resolve, Smart, StyleChain, cast, elem, Content, Context, Func, Packed, Resolve, Smart, StyleChain,
@ -204,7 +206,7 @@ fn draw_cancel_line(
CancelAngle::Angle(v) => *v, CancelAngle::Angle(v) => *v,
// This specifies a function that takes the default angle as input. // This specifies a function that takes the default angle as input.
CancelAngle::Func(func) => func CancelAngle::Func(func) => func
.call(ctx.engine, &Context::new(None, Some(styles)), [default])? .call(ctx.engine, Context::new(None, Some(styles)).track(), [default])?
.cast() .cast()
.at(span)?, .at(span)?,
}, },

View File

@ -1,5 +1,6 @@
use std::str::FromStr; use std::str::FromStr;
use comemo::Track;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use crate::diag::{bail, SourceResult}; use crate::diag::{bail, SourceResult};
@ -247,7 +248,8 @@ impl LayoutMultiple for Packed<EnumElem> {
let context = Context::new(None, Some(styles)); let context = Context::new(None, Some(styles));
let resolved = if full { let resolved = if full {
parents.push(number); parents.push(number);
let content = numbering.apply(engine, &context, &parents)?.display(); let content =
numbering.apply(engine, context.track(), &parents)?.display();
parents.pop(); parents.pop();
content content
} else { } else {
@ -255,7 +257,7 @@ impl LayoutMultiple for Packed<EnumElem> {
Numbering::Pattern(pattern) => { Numbering::Pattern(pattern) => {
TextElem::packed(pattern.apply_kth(parents.len(), number)) TextElem::packed(pattern.apply_kth(parents.len(), number))
} }
other => other.apply(engine, &context, &[number])?.display(), other => other.apply(engine, context.track(), &[number])?.display(),
} }
}; };

View File

@ -1,3 +1,5 @@
use comemo::Track;
use crate::diag::{bail, SourceResult}; use crate::diag::{bail, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
@ -218,7 +220,7 @@ impl ListMarker {
list.get(depth % list.len()).cloned().unwrap_or_default() list.get(depth % list.len()).cloned().unwrap_or_default()
} }
Self::Func(func) => func Self::Func(func) => func
.call(engine, &Context::new(None, Some(styles)), [depth])? .call(engine, Context::new(None, Some(styles)).track(), [depth])?
.display(), .display(),
}) })
} }

View File

@ -1,6 +1,7 @@
use std::str::FromStr; use std::str::FromStr;
use chinese_number::{ChineseCase, ChineseCountMethod, ChineseVariant, NumberToChinese}; use chinese_number::{ChineseCase, ChineseCountMethod, ChineseVariant, NumberToChinese};
use comemo::Tracked;
use ecow::{eco_format, EcoString, EcoVec}; use ecow::{eco_format, EcoString, EcoVec};
use crate::diag::SourceResult; use crate::diag::SourceResult;
@ -36,7 +37,7 @@ pub fn numbering(
/// The engine. /// The engine.
engine: &mut Engine, engine: &mut Engine,
/// The callsite context. /// The callsite context.
context: &Context, context: Tracked<Context>,
/// Defines how the numbering works. /// Defines how the numbering works.
/// ///
/// **Counting symbols** are `1`, `a`, `A`, `i`, `I`, `一`, `壹`, `あ`, `い`, `ア`, `イ`, `א`, `가`, /// **Counting symbols** are `1`, `a`, `A`, `i`, `I`, `一`, `壹`, `あ`, `い`, `ア`, `イ`, `א`, `가`,
@ -85,7 +86,7 @@ impl Numbering {
pub fn apply( pub fn apply(
&self, &self,
engine: &mut Engine, engine: &mut Engine,
context: &Context, context: Tracked<Context>,
numbers: &[usize], numbers: &[usize],
) -> SourceResult<Value> { ) -> SourceResult<Value> {
Ok(match self { Ok(match self {

View File

@ -1,6 +1,8 @@
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::str::FromStr; use std::str::FromStr;
use comemo::Track;
use crate::diag::{bail, At, SourceResult}; use crate::diag::{bail, At, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
@ -381,7 +383,7 @@ impl OutlineIndent {
Some(Smart::Custom(OutlineIndent::Func(func))) => { Some(Smart::Custom(OutlineIndent::Func(func))) => {
let depth = ancestors.len(); let depth = ancestors.len();
let LengthOrContent(content) = func let LengthOrContent(content) = func
.call(engine, &Context::new(None, Some(styles)), [depth])? .call(engine, Context::new(None, Some(styles)).track(), [depth])?
.cast() .cast()
.at(span)?; .at(span)?;
if !content.is_empty() { if !content.is_empty() {

View File

@ -1,3 +1,4 @@
use comemo::Track;
use ecow::eco_format; use ecow::eco_format;
use crate::diag::{bail, At, Hint, SourceResult}; use crate::diag::{bail, At, Hint, SourceResult};
@ -275,9 +276,9 @@ impl Supplement {
) -> SourceResult<Content> { ) -> SourceResult<Content> {
Ok(match self { Ok(match self {
Supplement::Content(content) => content.clone(), Supplement::Content(content) => content.clone(),
Supplement::Func(func) => { Supplement::Func(func) => func
func.call(engine, &Context::new(None, Some(styles)), args)?.display() .call(engine, Context::new(None, Some(styles)).track(), args)?
} .display(),
}) })
} }
} }

View File

@ -1,5 +1,6 @@
use std::cell::OnceCell; use std::cell::OnceCell;
use comemo::{Track, Tracked};
use smallvec::smallvec; use smallvec::smallvec;
use crate::diag::SourceResult; use crate::diag::SourceResult;
@ -255,11 +256,11 @@ fn show(
// text element. This invokes special regex handling. // text element. This invokes special regex handling.
Some(Selector::Regex(regex)) => { Some(Selector::Regex(regex)) => {
let text = target.into_packed::<TextElem>().unwrap(); let text = target.into_packed::<TextElem>().unwrap();
show_regex(engine, &text, regex, recipe, guard, &context) show_regex(engine, &text, regex, recipe, guard, context.track())
} }
// Just apply the recipe. // Just apply the recipe.
_ => recipe.apply(engine, &context, target.guarded(guard)), _ => recipe.apply(engine, context.track(), target.guarded(guard)),
} }
} }
@ -276,7 +277,7 @@ fn show_regex(
regex: &Regex, regex: &Regex,
recipe: &Recipe, recipe: &Recipe,
index: RecipeIndex, index: RecipeIndex,
context: &Context, context: Tracked<Context>,
) -> SourceResult<Content> { ) -> SourceResult<Content> {
let make = |s: &str| { let make = |s: &str| {
let mut fresh = target.clone(); let mut fresh = target.clone();