diff --git a/crates/typst-ide/src/analyze.rs b/crates/typst-ide/src/analyze.rs index 1fef1b49c..9d67b322d 100644 --- a/crates/typst-ide/src/analyze.rs +++ b/crates/typst-ide/src/analyze.rs @@ -67,8 +67,12 @@ pub fn analyze_import(world: &dyn World, source: &LinkedNode) -> Option { }; let context = Context::none(); - let mut vm = - Vm::new(engine, &context, Scopes::new(Some(world.library())), Span::detached()); + let mut vm = Vm::new( + engine, + context.track(), + Scopes::new(Some(world.library())), + Span::detached(), + ); typst::eval::import(&mut vm, source, Span::detached(), true) .ok() .map(Value::Module) diff --git a/crates/typst/src/eval/call.rs b/crates/typst/src/eval/call.rs index 97ca6c2ce..ddc054166 100644 --- a/crates/typst/src/eval/call.rs +++ b/crates/typst/src/eval/call.rs @@ -278,7 +278,7 @@ pub(crate) fn call_closure( route: Tracked, locator: Tracked, tracer: TrackedMut, - context: &Context, + context: Tracked, mut args: Args, ) -> SourceResult { let (name, params, body) = match closure.node.cast::() { diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs index 07d270216..3622c0127 100644 --- a/crates/typst/src/eval/mod.rs +++ b/crates/typst/src/eval/mod.rs @@ -63,7 +63,7 @@ pub fn eval( let context = Context::none(); let scopes = Scopes::new(Some(world.library())); 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. let errors = root.errors(); @@ -131,7 +131,7 @@ pub fn eval_string( // Prepare VM. let context = Context::none(); 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); // Evaluate the code. diff --git a/crates/typst/src/eval/vm.rs b/crates/typst/src/eval/vm.rs index 27d141cc8..be43b5bae 100644 --- a/crates/typst/src/eval/vm.rs +++ b/crates/typst/src/eval/vm.rs @@ -21,14 +21,14 @@ pub struct Vm<'a> { /// A span that is currently under inspection. pub(crate) inspected: Option, /// 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> { /// Create a new virtual machine. pub fn new( engine: Engine<'a>, - context: &'a Context<'a>, + context: Tracked<'a, Context<'a>>, scopes: Scopes<'a>, target: Span, ) -> Self { @@ -55,6 +55,6 @@ impl<'a> Vm<'a> { pub fn trace(&mut self, value: Value) { self.engine .tracer - .value(value.clone(), self.context.styles.map(|s| s.to_map())); + .value(value.clone(), self.context.styles().ok().map(|s| s.to_map())); } } diff --git a/crates/typst/src/foundations/array.rs b/crates/typst/src/foundations/array.rs index a1e93d7b2..8f5703bbb 100644 --- a/crates/typst/src/foundations/array.rs +++ b/crates/typst/src/foundations/array.rs @@ -3,6 +3,7 @@ use std::fmt::{Debug, Formatter}; use std::num::{NonZeroI64, NonZeroUsize}; use std::ops::{Add, AddAssign}; +use comemo::Tracked; use ecow::{eco_format, EcoString, EcoVec}; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; @@ -301,7 +302,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The function to apply to each item. Must return a boolean. searcher: Func, ) -> SourceResult> { @@ -325,7 +326,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The function to apply to each item. Must return a boolean. searcher: Func, ) -> SourceResult> { @@ -402,7 +403,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The function to apply to each item. Must return a boolean. test: Func, ) -> SourceResult { @@ -427,7 +428,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The function to apply to each item. mapper: Func, ) -> SourceResult { @@ -536,7 +537,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The initial value to start with. init: Value, /// The folding function. Must have two parameters: One for the @@ -598,7 +599,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The function to apply to each item. Must return a boolean. test: Func, ) -> SourceResult { @@ -618,7 +619,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The function to apply to each item. Must return a boolean. test: Func, ) -> SourceResult { @@ -765,7 +766,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The callsite span. span: Span, /// If given, applies this function to the elements in the array to @@ -815,7 +816,7 @@ impl Array { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// If given, applies this function to the elements in the array to /// determine the keys to deduplicate by. #[named] diff --git a/crates/typst/src/foundations/content.rs b/crates/typst/src/foundations/content.rs index 83e94d302..6184f4cf7 100644 --- a/crates/typst/src/foundations/content.rs +++ b/crates/typst/src/foundations/content.rs @@ -6,6 +6,7 @@ use std::marker::PhantomData; use std::ops::{Add, AddAssign, Deref, DerefMut}; use std::sync::Arc; +use comemo::Tracked; use ecow::{eco_format, EcoString}; use serde::{Serialize, Serializer}; use smallvec::smallvec; @@ -345,7 +346,7 @@ impl Content { pub fn styled_with_recipe( self, engine: &mut Engine, - context: &Context, + context: Tracked, recipe: Recipe, ) -> SourceResult { if recipe.selector.is_none() { diff --git a/crates/typst/src/foundations/context.rs b/crates/typst/src/foundations/context.rs index 41fdbfecb..bf4bdcd25 100644 --- a/crates/typst/src/foundations/context.rs +++ b/crates/typst/src/foundations/context.rs @@ -1,3 +1,5 @@ +use comemo::Track; + use crate::diag::{bail, Hint, HintedStrResult, SourceResult}; use crate::engine::Engine; use crate::foundations::{ @@ -28,7 +30,10 @@ impl<'a> Context<'a> { pub fn new(location: Option, styles: Option>) -> Self { Self { location, styles } } +} +#[comemo::track] +impl<'a> Context<'a> { /// Try to extract the location. pub fn location(&self) -> HintedStrResult { require(self.location) @@ -75,6 +80,6 @@ impl Show for Packed { fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult { let loc = self.location().unwrap(); 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()) } } diff --git a/crates/typst/src/foundations/func.rs b/crates/typst/src/foundations/func.rs index 7871e2971..70fbea77d 100644 --- a/crates/typst/src/foundations/func.rs +++ b/crates/typst/src/foundations/func.rs @@ -1,7 +1,7 @@ use std::fmt::{self, Debug, Formatter}; use std::sync::Arc; -use comemo::TrackedMut; +use comemo::{Tracked, TrackedMut}; use ecow::{eco_format, EcoString}; use once_cell::sync::Lazy; @@ -261,7 +261,7 @@ impl Func { pub fn call( &self, engine: &mut Engine, - context: &Context, + context: Tracked, args: A, ) -> SourceResult { self.call_impl(engine, context, args.into_args(self.span)) @@ -272,7 +272,7 @@ impl Func { fn call_impl( &self, engine: &mut Engine, - context: &Context, + context: Tracked, mut args: Args, ) -> SourceResult { match &self.repr { @@ -440,7 +440,7 @@ pub trait NativeFunc { /// Defines a native function. #[derive(Debug)] pub struct NativeFuncData { - pub function: fn(&mut Engine, &Context, &mut Args) -> SourceResult, + pub function: fn(&mut Engine, Tracked, &mut Args) -> SourceResult, pub name: &'static str, pub title: &'static str, pub docs: &'static str, diff --git a/crates/typst/src/foundations/selector.rs b/crates/typst/src/foundations/selector.rs index 92bfa8231..4dc8ab3b9 100644 --- a/crates/typst/src/foundations/selector.rs +++ b/crates/typst/src/foundations/selector.rs @@ -304,7 +304,7 @@ impl LocatableSelector { pub fn resolve_unique( &self, introspector: Tracked, - context: &Context, + context: Tracked, ) -> HintedStrResult { match &self.0 { Selector::Location(loc) => Ok(*loc), diff --git a/crates/typst/src/foundations/str.rs b/crates/typst/src/foundations/str.rs index e1c5d8b09..897ca45b3 100644 --- a/crates/typst/src/foundations/str.rs +++ b/crates/typst/src/foundations/str.rs @@ -3,6 +3,7 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::hash::{Hash, Hasher}; use std::ops::{Add, AddAssign, Deref, Range}; +use comemo::Tracked; use ecow::EcoString; use serde::{Deserialize, Serialize}; use unicode_segmentation::UnicodeSegmentation; @@ -425,7 +426,7 @@ impl Str { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The pattern to search for. pattern: StrPattern, /// The string to replace the matches with or a function that gets a diff --git a/crates/typst/src/foundations/styles.rs b/crates/typst/src/foundations/styles.rs index 469cad1af..dd09b6056 100644 --- a/crates/typst/src/foundations/styles.rs +++ b/crates/typst/src/foundations/styles.rs @@ -3,6 +3,7 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::{mem, ptr}; +use comemo::{Track, Tracked}; use ecow::{eco_vec, EcoString, EcoVec}; use smallvec::SmallVec; @@ -57,7 +58,10 @@ impl Show for Packed { #[typst_macros::time(name = "style", span = self.span())] fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult { 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( &self, engine: &mut Engine, - context: &Context, + context: Tracked, content: Content, ) -> SourceResult { let mut content = match &self.transform { diff --git a/crates/typst/src/introspection/counter.rs b/crates/typst/src/introspection/counter.rs index 4a9bae036..dd2fdcffa 100644 --- a/crates/typst/src/introspection/counter.rs +++ b/crates/typst/src/introspection/counter.rs @@ -1,7 +1,7 @@ use std::num::NonZeroUsize; use std::str::FromStr; -use comemo::{Tracked, TrackedMut}; +use comemo::{Track, Tracked, TrackedMut}; use ecow::{eco_format, eco_vec, EcoString, EcoVec}; use smallvec::{smallvec, SmallVec}; @@ -271,7 +271,7 @@ impl Counter { let context = Context::new(Some(loc), Some(styles)); Ok(self .at_loc(engine, loc)? - .display(engine, &context, numbering)? + .display(engine, context.track(), numbering)? .display()) } @@ -392,7 +392,7 @@ impl Counter { }; 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. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The callsite span. span: Span, ) -> SourceResult { @@ -446,7 +446,7 @@ impl Counter { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The call span of the display. span: Span, /// A [numbering pattern or a function]($numbering), which specifies how @@ -468,8 +468,8 @@ impl Counter { #[default(false)] both: bool, ) -> SourceResult { - if let Some(loc) = context.location { - self.display_impl(engine, loc, numbering, both, context.styles) + if let Ok(loc) = context.location() { + self.display_impl(engine, loc, numbering, both, context.styles().ok()) } else { Ok(CounterDisplayElem::new(self, numbering, both) .pack() @@ -494,7 +494,7 @@ impl Counter { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The callsite span. span: Span, /// The place at which the counter's value should be retrieved. @@ -512,7 +512,7 @@ impl Counter { /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The callsite span. span: Span, /// _Compatibility:_ This argument only exists for compatibility with @@ -669,7 +669,7 @@ impl CounterState { CounterUpdate::Step(level) => self.step(level, 1), CounterUpdate::Func(func) => { *self = func - .call(engine, &Context::none(), self.0.iter().copied())? + .call(engine, Context::none().track(), self.0.iter().copied())? .cast() .at(func.span())? } @@ -700,7 +700,7 @@ impl CounterState { pub fn display( &self, engine: &mut Engine, - context: &Context, + context: Tracked, numbering: &Numbering, ) -> SourceResult { numbering.apply(engine, context, &self.0) diff --git a/crates/typst/src/introspection/here.rs b/crates/typst/src/introspection/here.rs index ac6b53358..e921079b9 100644 --- a/crates/typst/src/introspection/here.rs +++ b/crates/typst/src/introspection/here.rs @@ -1,3 +1,5 @@ +use comemo::Tracked; + use crate::diag::HintedStrResult; use crate::foundations::{func, Context}; use crate::introspection::Location; @@ -44,7 +46,7 @@ use crate::introspection::Location; #[func(contextual)] pub fn here( /// The callsite context. - context: &Context, + context: Tracked, ) -> HintedStrResult { context.location() } diff --git a/crates/typst/src/introspection/locate.rs b/crates/typst/src/introspection/locate.rs index 1ce3ae383..373b1fe27 100644 --- a/crates/typst/src/introspection/locate.rs +++ b/crates/typst/src/introspection/locate.rs @@ -1,3 +1,5 @@ +use comemo::{Track, Tracked}; + use crate::diag::{HintedStrResult, SourceResult}; use crate::engine::Engine; use crate::foundations::{ @@ -37,7 +39,7 @@ pub fn locate( /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// The span of the `locate` call. span: Span, /// A selector that should match exactly one element. This element will be @@ -106,6 +108,6 @@ impl Show for Packed { fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult { let location = self.location().unwrap(); 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()) } } diff --git a/crates/typst/src/introspection/query.rs b/crates/typst/src/introspection/query.rs index a6ddb815c..eb2b9df44 100644 --- a/crates/typst/src/introspection/query.rs +++ b/crates/typst/src/introspection/query.rs @@ -1,3 +1,5 @@ +use comemo::Tracked; + use crate::diag::HintedStrResult; use crate::engine::Engine; use crate::foundations::{func, Array, Context, LocatableSelector, Value}; @@ -135,7 +137,7 @@ pub fn query( /// The engine. engine: &mut Engine, /// The callsite context. - context: &Context, + context: Tracked, /// Can be /// - an element function like a `heading` or `figure`, /// - a `{