summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-11-25 16:10:28 +0100
committerLaurenz <laurmaedje@gmail.com>2023-11-26 19:03:21 +0100
commit85b1d1d4dd4628d1fb8901c3280cde84da450bbe (patch)
treeb69a629be9295268e071667b1587a5701f2bc7ef /crates
parent2f795b5c07171affa0709195a9dae3ed5c0afbeb (diff)
Rework `Vt` into `Engine`
- Moves as much data out of the `Vm` - Removes duplication with call_vm and call_vt flavours - Uses tracked chain instead of fixed int for determining max nesting depth - This means that nesting checks now generalizes to layout and realization, to detect crashing show rules and overly nested layouts
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-ide/src/analyze.rs12
-rw-r--r--crates/typst-macros/src/elem.rs4
-rw-r--r--crates/typst-macros/src/func.rs13
-rw-r--r--crates/typst-syntax/src/span.rs10
-rw-r--r--crates/typst/src/engine.rs159
-rw-r--r--crates/typst/src/eval/access.rs2
-rw-r--r--crates/typst/src/eval/call.rs32
-rw-r--r--crates/typst/src/eval/code.rs4
-rw-r--r--crates/typst/src/eval/import.rs28
-rw-r--r--crates/typst/src/eval/markup.rs12
-rw-r--r--crates/typst/src/eval/mod.rs22
-rw-r--r--crates/typst/src/eval/rules.rs2
-rw-r--r--crates/typst/src/eval/vm.rs103
-rw-r--r--crates/typst/src/foundations/args.rs23
-rw-r--r--crates/typst/src/foundations/array.rs76
-rw-r--r--crates/typst/src/foundations/cast.rs1
-rw-r--r--crates/typst/src/foundations/content.rs11
-rw-r--r--crates/typst/src/foundations/datetime.rs9
-rw-r--r--crates/typst/src/foundations/element.rs28
-rw-r--r--crates/typst/src/foundations/func.rs75
-rw-r--r--crates/typst/src/foundations/mod.rs10
-rw-r--r--crates/typst/src/foundations/plugin.rs25
-rw-r--r--crates/typst/src/foundations/str.rs14
-rw-r--r--crates/typst/src/foundations/styles.rs46
-rw-r--r--crates/typst/src/foundations/ty.rs1
-rw-r--r--crates/typst/src/introspection/counter.rs93
-rw-r--r--crates/typst/src/introspection/locate.rs10
-rw-r--r--crates/typst/src/introspection/location.rs16
-rw-r--r--crates/typst/src/introspection/metadata.rs4
-rw-r--r--crates/typst/src/introspection/query.rs8
-rw-r--r--crates/typst/src/introspection/state.rs50
-rw-r--r--crates/typst/src/layout/align.rs5
-rw-r--r--crates/typst/src/layout/columns.rs9
-rw-r--r--crates/typst/src/layout/container.rs15
-rw-r--r--crates/typst/src/layout/flow.rs124
-rw-r--r--crates/typst/src/layout/grid.rs63
-rw-r--r--crates/typst/src/layout/hide.rs4
-rw-r--r--crates/typst/src/layout/inline/mod.rs98
-rw-r--r--crates/typst/src/layout/inline/shaping.rs27
-rw-r--r--crates/typst/src/layout/layout.rs9
-rw-r--r--crates/typst/src/layout/measure.rs8
-rw-r--r--crates/typst/src/layout/mod.rs90
-rw-r--r--crates/typst/src/layout/pad.rs9
-rw-r--r--crates/typst/src/layout/page.rs19
-rw-r--r--crates/typst/src/layout/place.rs9
-rw-r--r--crates/typst/src/layout/repeat.rs7
-rw-r--r--crates/typst/src/layout/stack.rs11
-rw-r--r--crates/typst/src/layout/transform.rs15
-rw-r--r--crates/typst/src/layout/vt.rs39
-rw-r--r--crates/typst/src/lib.rs12
-rw-r--r--crates/typst/src/loading/cbor.rs10
-rw-r--r--crates/typst/src/loading/csv.rs10
-rw-r--r--crates/typst/src/loading/json.rs10
-rw-r--r--crates/typst/src/loading/read.rs10
-rw-r--r--crates/typst/src/loading/toml.rs10
-rw-r--r--crates/typst/src/loading/xml.rs10
-rw-r--r--crates/typst/src/loading/yaml.rs10
-rw-r--r--crates/typst/src/math/cancel.rs2
-rw-r--r--crates/typst/src/math/ctx.rs17
-rw-r--r--crates/typst/src/math/equation.rs29
-rw-r--r--crates/typst/src/model/bibliography.rs42
-rw-r--r--crates/typst/src/model/cite.rs14
-rw-r--r--crates/typst/src/model/document.rs15
-rw-r--r--crates/typst/src/model/emph.rs4
-rw-r--r--crates/typst/src/model/enum.rs11
-rw-r--r--crates/typst/src/model/figure.rs23
-rw-r--r--crates/typst/src/model/footnote.rs24
-rw-r--r--crates/typst/src/model/heading.rs21
-rw-r--r--crates/typst/src/model/link.rs13
-rw-r--r--crates/typst/src/model/list.rs13
-rw-r--r--crates/typst/src/model/numbering.rs27
-rw-r--r--crates/typst/src/model/outline.rs33
-rw-r--r--crates/typst/src/model/par.rs12
-rw-r--r--crates/typst/src/model/quote.rs7
-rw-r--r--crates/typst/src/model/reference.rs42
-rw-r--r--crates/typst/src/model/strong.rs4
-rw-r--r--crates/typst/src/model/table.rs15
-rw-r--r--crates/typst/src/model/terms.rs7
-rw-r--r--crates/typst/src/realize/mod.rs149
-rw-r--r--crates/typst/src/text/deco.rs11
-rw-r--r--crates/typst/src/text/mod.rs6
-rw-r--r--crates/typst/src/text/raw.rs26
-rw-r--r--crates/typst/src/text/shift.rs15
-rw-r--r--crates/typst/src/visualize/image/mod.rs11
-rw-r--r--crates/typst/src/visualize/line.rs5
-rw-r--r--crates/typst/src/visualize/path.rs5
-rw-r--r--crates/typst/src/visualize/pattern.rs8
-rw-r--r--crates/typst/src/visualize/polygon.rs5
-rw-r--r--crates/typst/src/visualize/shape.rs25
89 files changed, 1204 insertions, 983 deletions
diff --git a/crates/typst-ide/src/analyze.rs b/crates/typst-ide/src/analyze.rs
index f3e417d5..8c5117f7 100644
--- a/crates/typst-ide/src/analyze.rs
+++ b/crates/typst-ide/src/analyze.rs
@@ -1,9 +1,10 @@
use comemo::Track;
use ecow::{eco_vec, EcoString, EcoVec};
-use typst::eval::{Route, Tracer, Vm};
+use typst::engine::{Engine, Route};
+use typst::eval::{Tracer, Vm};
use typst::foundations::{Label, Scopes, Value};
use typst::introspection::{Introspector, Locator};
-use typst::layout::{Frame, Vt};
+use typst::layout::Frame;
use typst::model::BibliographyElem;
use typst::syntax::{ast, LinkedNode, Span, SyntaxKind};
use typst::World;
@@ -46,7 +47,6 @@ pub fn analyze_expr(world: &dyn World, node: &LinkedNode) -> EcoVec<Value> {
/// Try to load a module from the current source file.
pub fn analyze_import(world: &dyn World, source: &LinkedNode) -> Option<Value> {
- let id = source.span().id()?;
let source = analyze_expr(world, source).into_iter().next()?;
if source.scope().is_some() {
return Some(source);
@@ -55,15 +55,15 @@ pub fn analyze_import(world: &dyn World, source: &LinkedNode) -> Option<Value> {
let mut locator = Locator::default();
let introspector = Introspector::default();
let mut tracer = Tracer::new();
- let vt = Vt {
+ let engine = Engine {
world: world.track(),
+ route: Route::default(),
introspector: introspector.track(),
locator: &mut locator,
tracer: tracer.track_mut(),
};
- let route = Route::default();
- let mut vm = Vm::new(vt, route.track(), Some(id), Scopes::new(Some(world.library())));
+ let mut vm = Vm::new(engine, 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-macros/src/elem.rs b/crates/typst-macros/src/elem.rs
index 9791427b..ce80cc66 100644
--- a/crates/typst-macros/src/elem.rs
+++ b/crates/typst-macros/src/elem.rs
@@ -1083,7 +1083,7 @@ fn create_construct_impl(element: &Elem) -> TokenStream {
quote! {
impl #foundations::Construct for #ident {
fn construct(
- vm: &mut ::typst::eval::Vm,
+ engine: &mut ::typst::engine::Engine,
args: &mut #foundations::Args,
) -> ::typst::diag::SourceResult<#foundations::Content> {
#(#pre)*
@@ -1115,7 +1115,7 @@ fn create_set_impl(element: &Elem) -> TokenStream {
quote! {
impl #foundations::Set for #ident {
fn set(
- vm: &mut ::typst::eval::Vm,
+ engine: &mut ::typst::engine::Engine,
args: &mut #foundations::Args,
) -> ::typst::diag::SourceResult<#foundations::Styles> {
let mut styles = #foundations::Styles::new();
diff --git a/crates/typst-macros/src/func.rs b/crates/typst-macros/src/func.rs
index 8537ac4f..953df428 100644
--- a/crates/typst-macros/src/func.rs
+++ b/crates/typst-macros/src/func.rs
@@ -36,8 +36,7 @@ struct Func {
#[derive(Default)]
struct SpecialParams {
self_: Option<Param>,
- vm: bool,
- vt: bool,
+ engine: bool,
args: bool,
span: bool,
}
@@ -171,8 +170,7 @@ fn parse_param(
};
match ident.to_string().as_str() {
- "vm" => special.vm = true,
- "vt" => special.vt = true,
+ "engine" => special.engine = true,
"args" => special.args = true,
"span" => special.span = true,
_ => {
@@ -322,13 +320,12 @@ fn create_wrapper_closure(func: &Func) -> TokenStream {
.as_ref()
.map(bind)
.map(|tokens| quote! { #tokens, });
- let vm_ = func.special.vm.then(|| quote! { vm, });
- let vt_ = func.special.vt.then(|| quote! { &mut vm.vt, });
+ let vt_ = func.special.engine.then(|| quote! { engine, });
let args_ = func.special.args.then(|| quote! { args, });
let span_ = func.special.span.then(|| quote! { args.span, });
let forwarded = func.params.iter().filter(|param| !param.external).map(bind);
quote! {
- __typst_func(#self_ #vm_ #vt_ #args_ #span_ #(#forwarded,)*)
+ __typst_func(#self_ #vt_ #args_ #span_ #(#forwarded,)*)
}
};
@@ -336,7 +333,7 @@ fn create_wrapper_closure(func: &Func) -> TokenStream {
let ident = &func.ident;
let parent = func.parent.as_ref().map(|ty| quote! { #ty:: });
quote! {
- |vm, args| {
+ |engine, args| {
let __typst_func = #parent #ident;
#handlers
#finish
diff --git a/crates/typst-syntax/src/span.rs b/crates/typst-syntax/src/span.rs
index 14e5e216..8138a316 100644
--- a/crates/typst-syntax/src/span.rs
+++ b/crates/typst-syntax/src/span.rs
@@ -2,6 +2,8 @@ use std::fmt::{self, Debug, Formatter};
use std::num::NonZeroU64;
use std::ops::Range;
+use ecow::EcoString;
+
use crate::FileId;
/// A unique identifier for a syntax node.
@@ -80,6 +82,14 @@ impl Span {
pub const fn number(self) -> u64 {
self.0.get() & ((1 << Self::BITS) - 1)
}
+
+ /// Resolve a file location relative to this span's source.
+ pub fn resolve_path(self, path: &str) -> Result<FileId, EcoString> {
+ let Some(file) = self.id() else {
+ return Err("cannot access file system from here".into());
+ };
+ Ok(file.join(path))
+ }
}
/// A value with a span locating it in the source code.
diff --git a/crates/typst/src/engine.rs b/crates/typst/src/engine.rs
new file mode 100644
index 00000000..189034cf
--- /dev/null
+++ b/crates/typst/src/engine.rs
@@ -0,0 +1,159 @@
+use std::cell::Cell;
+
+use comemo::{Track, Tracked, TrackedMut, Validate};
+
+use crate::diag::SourceResult;
+use crate::eval::Tracer;
+use crate::introspection::{Introspector, Locator};
+use crate::syntax::FileId;
+use crate::World;
+
+/// The maxmium stack nesting depth.
+const MAX_DEPTH: usize = 64;
+
+/// Holds all data needed during compilation.
+pub struct Engine<'a> {
+ /// The compilation environment.
+ pub world: Tracked<'a, dyn World + 'a>,
+ /// Provides access to information about the document.
+ pub introspector: Tracked<'a, Introspector>,
+ /// The route the engine took during compilation. This is used to detect
+ /// cyclic imports and too much nesting.
+ pub route: Route<'a>,
+ /// Provides stable identities to elements.
+ pub locator: &'a mut Locator<'a>,
+ /// The tracer for inspection of the values an expression produces.
+ pub tracer: TrackedMut<'a, Tracer>,
+}
+
+impl Engine<'_> {
+ /// 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) => {
+ self.tracer.delay(errors);
+ T::default()
+ }
+ }
+ }
+}
+
+/// The route the engine took during compilation. This is used to detect
+/// cyclic imports and too much nesting.
+#[derive(Clone)]
+pub struct Route<'a> {
+ // We need to override the constraint's lifetime here so that `Tracked` is
+ // covariant over the constraint. If it becomes invariant, we're in for a
+ // world of lifetime pain.
+ outer: Option<Tracked<'a, Self, <Route<'static> as Validate>::Constraint>>,
+ /// This is set if this route segment was inserted through the start of a
+ /// module evaluation.
+ id: Option<FileId>,
+ /// This is set whenever we enter a function, nested layout, or are applying
+ /// a show rule. The length of this segment plus the lengths of all `outer`
+ /// route segments make up the length of the route. If the length of the
+ /// route exceeds `MAX_DEPTH`, then we throw a "maximum ... depth exceeded"
+ /// error.
+ len: usize,
+ /// The upper bound we've established for the parent chain length. We don't
+ /// know the exact length (that would defeat the whole purpose because it
+ /// would prevent cache reuse of some computation at different,
+ /// non-exceeding depths).
+ upper: Cell<usize>,
+}
+
+impl<'a> Route<'a> {
+ /// Create a new, empty route.
+ pub fn root() -> Self {
+ Self { id: None, outer: None, len: 0, upper: Cell::new(0) }
+ }
+
+ /// Insert a new id into the route.
+ ///
+ /// You must guarantee that `outer` lives longer than the resulting
+ /// route is ever used.
+ pub fn insert(outer: Tracked<'a, Self>, id: FileId) -> Self {
+ Route {
+ outer: Some(outer),
+ id: Some(id),
+ len: 0,
+ upper: Cell::new(usize::MAX),
+ }
+ }
+
+ /// Extend the route without another id.
+ pub fn extend(outer: Tracked<'a, Self>) -> Self {
+ Route {
+ outer: Some(outer),
+ id: None,
+ len: 1,
+ upper: Cell::new(usize::MAX),
+ }
+ }
+
+ /// Start tracking this route.
+ ///
+ /// In comparison to [`Track::track`], this method skips this chain link
+ /// if it does not contribute anything.
+ pub fn track(&self) -> Tracked<'_, Self> {
+ match self.outer {
+ Some(outer) if self.id.is_none() && self.len == 0 => outer,
+ _ => Track::track(self),
+ }
+ }
+
+ /// Increase the nesting depth for this route segment.
+ pub fn increase(&mut self) {
+ self.len += 1;
+ }
+
+ /// Decrease the nesting depth for this route segment.
+ pub fn decrease(&mut self) {
+ self.len -= 1;
+ }
+
+ /// Check whether the nesting depth exceeds the limit.
+ pub fn exceeding(&self) -> bool {
+ !self.within(MAX_DEPTH)
+ }
+}
+
+#[comemo::track]
+impl<'a> Route<'a> {
+ /// Whether the given id is part of the route.
+ pub fn contains(&self, id: FileId) -> bool {
+ self.id == Some(id) || self.outer.map_or(false, |outer| outer.contains(id))
+ }
+
+ /// Whether the route's depth is less than or equal to the given depth.
+ pub fn within(&self, depth: usize) -> bool {
+ if self.upper.get().saturating_add(self.len) <= depth {
+ return true;
+ }
+
+ match self.outer {
+ Some(_) if depth < self.len => false,
+ Some(outer) => {
+ let within = outer.within(depth - self.len);
+ if within && depth < self.upper.get() {
+ self.upper.set(depth);
+ }
+ within
+ }
+ None => true,
+ }
+ }
+}
+
+impl Default for Route<'_> {
+ fn default() -> Self {
+ Self::root()
+ }
+}
diff --git a/crates/typst/src/eval/access.rs b/crates/typst/src/eval/access.rs
index ff0b7512..99b2f72e 100644
--- a/crates/typst/src/eval/access.rs
+++ b/crates/typst/src/eval/access.rs
@@ -31,7 +31,7 @@ impl Access for ast::Ident<'_> {
let span = self.span();
let value = vm.scopes.get_mut(&self).at(span)?;
if vm.inspected == Some(span) {
- vm.vt.tracer.value(value.clone());
+ vm.engine.tracer.value(value.clone());
}
Ok(value)
}
diff --git a/crates/typst/src/eval/call.rs b/crates/typst/src/eval/call.rs
index 7ccebe85..a57cb112 100644
--- a/crates/typst/src/eval/call.rs
+++ b/crates/typst/src/eval/call.rs
@@ -2,13 +2,13 @@ use comemo::{Prehashed, Tracked, TrackedMut};
use ecow::EcoVec;
use crate::diag::{bail, error, At, HintedStrResult, SourceResult, Trace, Tracepoint};
+use crate::engine::Engine;
use crate::eval::{Access, Eval, FlowEvent, Route, Tracer, Vm};
use crate::foundations::{
call_method_mut, is_mutating_method, Arg, Args, Bytes, Closure, Content, Func,
IntoValue, NativeElement, Scope, Scopes, Value,
};
use crate::introspection::{Introspector, Locator};
-use crate::layout::Vt;
use crate::math::{Accent, AccentElem, LrElem};
use crate::symbols::Symbol;
use crate::syntax::ast::{self, AstNode};
@@ -16,23 +16,19 @@ use crate::syntax::{Spanned, SyntaxNode};
use crate::text::TextElem;
use crate::World;
-/// The maxmium function call depth.
-const MAX_CALL_DEPTH: usize = 64;
-
impl Eval for ast::FuncCall<'_> {
type Output = Value;
#[tracing::instrument(name = "FuncCall::eval", skip_all)]
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let span = self.span();
- if vm.depth >= MAX_CALL_DEPTH {
- bail!(span, "maximum function call depth exceeded");
- }
-
let callee = self.callee();
let in_math = in_math(callee);
let callee_span = callee.span();
let args = self.args();
+ if vm.engine.route.exceeding() {
+ bail!(span, "maximum function call depth exceeded");
+ }
// Try to evaluate as a call to an associated function or field.
let (callee, mut args) = if let ast::Expr::FieldAccess(access) = callee {
@@ -146,7 +142,7 @@ impl Eval for ast::FuncCall<'_> {
let callee = callee.cast::<Func>().at(callee_span)?;
let point = || Tracepoint::Call(callee.name().map(Into::into));
- let f = || callee.call_vm(vm, args).trace(vm.world(), point, span);
+ let f = || callee.call(&mut vm.engine, args).trace(vm.world(), point, span);
// Stacker is broken on WASM.
#[cfg(target_arch = "wasm32")]
@@ -229,7 +225,6 @@ impl Eval for ast::Closure<'_> {
// Define the closure.
let closure = Closure {
node: self.to_untyped().clone(),
- file: vm.file,
defaults,
captured,
};
@@ -246,11 +241,10 @@ pub(crate) fn call_closure(
func: &Func,
closure: &Prehashed<Closure>,
world: Tracked<dyn World + '_>,
- route: Tracked<Route>,
introspector: Tracked<Introspector>,
+ route: Tracked<Route>,
locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>,
- depth: usize,
mut args: Args,
) -> SourceResult<Value> {
let node = closure.node.cast::<ast::Closure>().unwrap();
@@ -260,13 +254,18 @@ pub(crate) fn call_closure(
let mut scopes = Scopes::new(None);
scopes.top = closure.captured.clone();
- // Prepare VT.
+ // Prepare the engine.
let mut locator = Locator::chained(locator);
- let vt = Vt { world, introspector, locator: &mut locator, tracer };
+ let engine = Engine {
+ world,
+ introspector,
+ route: Route::extend(route),
+ locator: &mut locator,
+ tracer,
+ };
// Prepare VM.
- let mut vm = Vm::new(vt, route, closure.file, scopes);
- vm.depth = depth;
+ let mut vm = Vm::new(engine, scopes, node.span());
// Provide the closure itself for recursive calls.
if let Some(name) = node.name() {
@@ -279,6 +278,7 @@ pub(crate) fn call_closure(
.children()
.filter(|p| matches!(p, ast::Param::Pos(_)))
.count();
+
let num_pos_args = args.to_pos().len();
let sink_size = num_pos_args.checked_sub(num_pos_params);
diff --git a/crates/typst/src/eval/code.rs b/crates/typst/src/eval/code.rs
index 1df5876c..06b2f226 100644
--- a/crates/typst/src/eval/code.rs
+++ b/crates/typst/src/eval/code.rs
@@ -40,7 +40,7 @@ fn eval_code<'a>(
}
let tail = eval_code(vm, exprs)?.display();
- Value::Content(tail.styled_with_recipe(vm, recipe)?)
+ Value::Content(tail.styled_with_recipe(&mut vm.engine, recipe)?)
}
_ => expr.eval(vm)?,
};
@@ -130,7 +130,7 @@ impl Eval for ast::Expr<'_> {
.spanned(span);
if vm.inspected == Some(span) {
- vm.vt.tracer.value(v.clone());
+ vm.engine.tracer.value(v.clone());
}
Ok(v)
diff --git a/crates/typst/src/eval/import.rs b/crates/typst/src/eval/import.rs
index 79daf999..aa3388a1 100644
--- a/crates/typst/src/eval/import.rs
+++ b/crates/typst/src/eval/import.rs
@@ -38,7 +38,7 @@ impl Eval for ast::ModuleImport<'_> {
if let ast::Expr::Ident(ident) = self.source() {
if ident.as_str() == new_name.as_str() {
// Warn on `import x as x`
- vm.vt.tracer.warn(warning!(
+ vm.engine.tracer.warn(warning!(
new_name.span(),
"unnecessary import rename to same name",
));
@@ -73,7 +73,7 @@ impl Eval for ast::ModuleImport<'_> {
if renamed_item.original_name().as_str()
== renamed_item.new_name().as_str()
{
- vm.vt.tracer.warn(warning!(
+ vm.engine.tracer.warn(warning!(
renamed_item.new_name().span(),
"unnecessary import rename to same name",
));
@@ -145,27 +145,37 @@ fn import_package(vm: &mut Vm, spec: PackageSpec, span: Span) -> SourceResult<Mo
let entrypoint_id = manifest_id.join(&manifest.package.entrypoint);
let source = vm.world().source(entrypoint_id).at(span)?;
let point = || Tracepoint::Import;
- Ok(eval(vm.world(), vm.route, TrackedMut::reborrow_mut(&mut vm.vt.tracer), &source)
- .trace(vm.world(), point, span)?
- .with_name(manifest.package.name))
+ Ok(eval(
+ vm.world(),
+ vm.engine.route.track(),
+ TrackedMut::reborrow_mut(&mut vm.engine.tracer),
+ &source,
+ )
+ .trace(vm.world(), point, span)?
+ .with_name(manifest.package.name))
}
/// Import a file from a path.
fn import_file(vm: &mut Vm, path: &str, span: Span) -> SourceResult<Module> {
// Load the source file.
let world = vm.world();
- let id = vm.resolve_path(path).at(span)?;
+ let id = span.resolve_path(path).at(span)?;
let source = world.source(id).at(span)?;
// Prevent cyclic importing.
- if vm.route.contains(source.id()) {
+ if vm.engine.route.contains(source.id()) {
bail!(span, "cyclic import");
}
// Evaluate the file.
let point = || Tracepoint::Import;
- eval(world, vm.route, TrackedMut::reborrow_mut(&mut vm.vt.tracer), &source)
- .trace(world, point, span)
+ eval(
+ world,
+ vm.engine.route.track(),
+ TrackedMut::reborrow_mut(&mut vm.engine.tracer),
+ &source,
+ )
+ .trace(world, point, span)
}
/// A parsed package manifest.
diff --git a/crates/typst/src/eval/markup.rs b/crates/typst/src/eval/markup.rs
index 16ea9eef..a40b978e 100644
--- a/crates/typst/src/eval/markup.rs
+++ b/crates/typst/src/eval/markup.rs
@@ -43,7 +43,7 @@ fn eval_markup<'a>(
}
let tail = eval_markup(vm, exprs)?;
- seq.push(tail.styled_with_recipe(vm, recipe)?)
+ seq.push(tail.styled_with_recipe(&mut vm.engine, recipe)?)
}
expr => match expr.eval(vm)? {
Value::Label(label) => {
@@ -139,11 +139,11 @@ impl Eval for ast::Strong<'_> {
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let body = self.body();
if body.exprs().next().is_none() {
- vm.vt
- .tracer
- .warn(warning!(self.span(), "no text within stars").with_hint(
+ vm.engine.tracer.warn(
+ warning!(self.span(), "no text within stars").with_hint(
"using multiple consecutive stars (e.g. **) has no additional effect",
- ));
+ ),
+ );
}
Ok(StrongElem::new(body.eval(vm)?).pack())
@@ -157,7 +157,7 @@ impl Eval for ast::Emph<'_> {
fn eval(self, vm: &mut Vm) -> SourceResult<Self::Output> {
let body = self.body();
if body.exprs().next().is_none() {
- vm.vt
+ vm.engine
.tracer
.warn(warning!(self.span(), "no text within underscores").with_hint(
"using multiple consecutive underscores (e.g. __) has no additional effect"
diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs
index eaba69e0..9de4f1b7 100644
--- a/crates/typst/src/eval/mod.rs
+++ b/crates/typst/src/eval/mod.rs
@@ -26,9 +26,9 @@ pub(crate) use self::flow::*;
use comemo::{Track, Tracked, TrackedMut};
use crate::diag::{bail, SourceResult};
+use crate::engine::{Engine, Route};
use crate::foundations::{Cast, Module, NativeElement, Scope, Scopes, Value};
use crate::introspection::{Introspector, Locator};
-use crate::layout::Vt;
use crate::math::EquationElem;
use crate::syntax::{ast, parse, parse_code, parse_math, Source, Span};
use crate::World;
@@ -48,22 +48,23 @@ pub fn eval(
panic!("Tried to cyclicly evaluate {:?}", id.vpath());
}
- // Prepare VT.
+ // Prepare the engine.
let mut locator = Locator::new();
let introspector = Introspector::default();
- let vt = Vt {
+ let engine = Engine {
world,
+ route: Route::insert(route, id),
introspector: introspector.track(),
locator: &mut locator,
tracer,
};
// Prepare VM.
- let route = Route::insert(route, id);
+ let root = source.root();
let scopes = Scopes::new(Some(world.library()));
- let mut vm = Vm::new(vt, route.track(), Some(id), scopes);
+ let mut vm = Vm::new(engine, scopes, root.span());
- let root = source.root();
+ // Check for well-formedness unless we are in trace mode.
let errors = root.errors();
if !errors.is_empty() && vm.inspected.is_none() {
return Err(errors.into_iter().map(Into::into).collect());
@@ -108,26 +109,27 @@ pub fn eval_string(
root.synthesize(span);
+ // Check for well-formedness.
let errors = root.errors();
if !errors.is_empty() {
return Err(errors.into_iter().map(Into::into).collect());
}
- // Prepare VT.
+ // Prepare the engine.
let mut tracer = Tracer::new();
let mut locator = Locator::new();
let introspector = Introspector::default();
- let vt = Vt {
+ let engine = Engine {
world,
introspector: introspector.track(),
+ route: Route::default(),
locator: &mut locator,
tracer: tracer.track_mut(),
};
// Prepare VM.
- let route = Route::default();
let scopes = Scopes::new(Some(world.library()));
- let mut vm = Vm::new(vt, route.track(), None, scopes);
+ let mut vm = Vm::new(engine, scopes, root.span());
vm.scopes.scopes.push(scope);
// Evaluate the code.
diff --git a/crates/typst/src/eval/rules.rs b/crates/typst/src/eval/rules.rs
index c85b747b..e34fe5cd 100644
--- a/crates/typst/src/eval/rules.rs
+++ b/crates/typst/src/eval/rules.rs
@@ -24,7 +24,7 @@ impl Eval for ast::SetRule<'_> {
})
.at(target.span())?;
let args = self.args().eval(vm)?;
- Ok(target.set(vm, args)?.spanned(self.span()))
+ Ok(target.set(&mut vm.engine, args)?.spanned(self.span()))
}
}
diff --git a/crates/typst/src/eval/vm.rs b/crates/typst/src/eval/vm.rs
index c34c1070..8cedb906 100644
--- a/crates/typst/src/eval/vm.rs
+++ b/crates/typst/src/eval/vm.rs
@@ -1,74 +1,37 @@
-use comemo::{Track, Tracked, Validate};
+use comemo::Tracked;
-use crate::diag::{bail, StrResult};
+use crate::engine::Engine;
use crate::eval::FlowEvent;
use crate::foundations::{IntoValue, Scopes};
-use crate::layout::Vt;
use crate::syntax::ast::{self, AstNode};
-use crate::syntax::{FileId, Span};
+use crate::syntax::Span;
use crate::World;
/// A virtual machine.
///
-/// Holds the state needed to [evaluate](crate::eval::eval()) Typst sources. A new
-/// virtual machine is created for each module evaluation and function call.
+/// Holds the state needed to [evaluate](crate::eval::eval()) Typst sources. A
+/// new virtual machine is created for each module evaluation and function call.
pub struct Vm<'a> {
/// The underlying virtual typesetter.
- pub(crate) vt: Vt<'a>,
- /// The route of source ids the VM took to reach its current location.
- pub(crate) route: Tracked<'a, Route<'a>>,
- /// The id of the currently evaluated file.
- pub(crate) file: Option<FileId>,
+ pub(crate) engine: Engine<'a>,
/// A control flow event that is currently happening.
pub(crate) flow: Option<FlowEvent>,
/// The stack of scopes.
pub(crate) scopes: Scopes<'a>,
- /// The current call depth.
- pub(crate) depth: usize,
/// A span that is currently under inspection.
pub(crate) inspected: Option<Span>,
}
impl<'a> Vm<'a> {
/// Create a new virtual machine.
- pub fn new(
- vt: Vt<'a>,
- route: Tracked<'a, Route>,
- file: Option<FileId>,
- scopes: Scopes<'a>,
- ) -> Self {
- let inspected = file.and_then(|id| vt.tracer.inspected(id));
- Self {
- vt,
- route,
- file,
- flow: None,
- scopes,
- depth: 0,
- inspected,
- }
+ pub fn new(engine: Engine<'a>, scopes: Scopes<'a>, target: Span) -> Self {
+ let inspected = target.id().and_then(|id| engine.tracer.inspected(id));
+ Self { engine, flow: None, scopes, inspected }
}
/// Access the underlying world.
pub fn world(&self) -> Tracked<'a, dyn World + 'a> {
- self.vt.world
- }
-
- /// The id of the currently evaluated file.
- ///
- /// Returns `None` if the VM is in a detached context, e.g. when evaluating
- /// a user-provided string.
- pub fn file(&self) -> Option<FileId> {
- self.file
- }
-
- /// Resolve a path relative to the currently evaluated file.
- pub fn resolve_path(&self, path: &str) -> StrResult<FileId> {
- let Some(file) = self.file else {
- bail!("cannot access file system from here");
- };
-
- Ok(file.join(path))
+ self.engine.world
}
/// Define a variable in the current scope.
@@ -76,52 +39,8 @@ impl<'a> Vm<'a> {
pub fn define(&mut self, var: ast::Ident, value: impl IntoValue) {
let value = value.into_value();
if self.inspected == Some(var.span()) {
- self.vt.tracer.value(value.clone());
+ self.engine.tracer.value(value.clone());
}
self.scopes.top.define(var.get().clone(), value);
}
}
-
-/// A route of source ids.
-#[derive(Default)]
-pub struct Route<'a> {
- // We need to override the constraint's lifetime here so that `Tracked` is
- // covariant over the constraint. If it becomes invariant, we're in for a
- // world of lifetime pain.
- outer: Option<Tracked<'a, Self, <Route<'static> as Validate>::Constraint>>,
- id: Option<FileId>,
-}
-
-impl<'a> Route<'a> {
- /// Create a new route with just one entry.
- pub fn new(id: Option<FileId>) -> Self {
- Self { id, outer: None }
- }
-
- /// Insert a new id into the route.
- ///
- /// You must guarantee that `outer` lives longer than the resulting
- /// route is ever used.
- pub fn insert(outer: Tracked<'a, Self>, id: FileId) -> Self {
- Route { outer: Some(outer), id: Some(id) }
- }
-
- /// Start tracking this locator.
- ///
- /// In comparison to [`Track::track`], this method skips this chain link
- /// if it does not contribute anything.
- pub fn track(&self) -> Tracked<'_, Self> {
- match self.outer {
- Some(outer) if self.id.is_none() => outer,
- _ => Track::track(self),
- }
- }
-}
-
-#[comemo::track]
-impl<'a> Route<'a> {
- /// Whether the given id is part of the route.
- pub fn contains(&self, id: FileId) -> bool {
- self.id == Some(id) || self.outer.map_or(false, |outer| outer.contains(id))
- }
-}
diff --git a/crates/typst/src/foundations/args.rs b/crates/typst/src/foundations/args.rs
index af5d07b1..e11fe2bb 100644
--- a/crates/typst/src/foundations/args.rs
+++ b/crates/typst/src/foundations/args.rs
@@ -320,3 +320,26 @@ impl PartialEq for Arg {
self.name == other.name && self.value.v == other.value.v
}
}
+
+/// Things that can be used as arguments.
+pub trait IntoArgs {
+ /// Convert into arguments, attaching the `fallback` span in case `Self`
+ /// doesn't have a span.
+ fn into_args(self, fallback: Span) -> Args;
+}
+
+impl IntoArgs for Args {
+ fn into_args(self, _: Span) -> Args {
+ self
+ }
+}
+
+impl<I, T> IntoArgs for I
+where
+ I: IntoIterator<Item = T>,
+ T: IntoValue,
+{
+ fn into_args(self, fallback: Span) -> Args {
+ Args::new(fallback, self)
+ }
+}
diff --git a/crates/typst/src/foundations/array.rs b/crates/typst/src/foundations/array.rs
index 47afa9e2..8f2e9149 100644
--- a/crates/typst/src/foundations/array.rs
+++ b/crates/typst/src/foundations/array.rs
@@ -8,7 +8,8 @@ use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use crate::diag::{At, SourceResult, StrResult};
-use crate::eval::{ops, Vm};
+use crate::engine::Engine;
+use crate::eval::ops;
use crate::foundations::{
cast, func, repr, scope, ty, Args, Bytes, CastInfo, FromValue, Func, IntoValue,
Reflect, Repr, Value, Version,
@@ -297,14 +298,17 @@ impl Array {
#[func]
pub fn find(
&self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The function to apply to each item. Must return a boolean.
searcher: Func,
) -> SourceResult<Option<Value>> {
for item in self.iter() {
- let args = Args::new(searcher.span(), [item.clone()]);
- if searcher.call_vm(vm, args)?.cast::<bool>().at(searcher.span())? {
+ if searcher
+ .call(engine, [item.clone()])?
+ .cast::<bool>()
+ .at(searcher.span())?
+ {
return Ok(Some(item.clone()));
}
}
@@ -316,14 +320,17 @@ impl Array {
#[func]
pub fn position(
&self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The function to apply to each item. Must return a boolean.
searcher: Func,
) -> SourceResult<Option<i64>> {
for (i, item) in self.iter().enumerate() {
- let args = Args::new(searcher.span(), [item.clone()]);
- if searcher.call_vm(vm, args)?.cast::<bool>().at(searcher.span())? {
+ if searcher
+ .call(engine, [item.clone()])?
+ .cast::<bool>()
+ .at(searcher.span())?
+ {
return Ok(Some(i as i64));
}
}
@@ -388,15 +395,14 @@ impl Array {
#[func]
pub fn filter(
&self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The function to apply to each item. Must return a boolean.
test: Func,
) -> SourceResult<Array> {
let mut kept = EcoVec::new();
for item in self.iter() {
- let args = Args::new(test.span(), [item.clone()]);
- if test.call_vm(vm, args)?.cast::<bool>().at(test.span())? {
+ if test.call(engine, [item.clone()])?.cast::<bool>().at(test.span())? {
kept.push(item.clone())
}
}
@@ -408,17 +414,12 @@ impl Array {
#[func]
pub fn map(
self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The function to apply to each item.
mapper: Func,
) -> SourceResult<Array> {
- self.into_iter()
- .map(|item| {
- let args = Args::new(mapper.span(), [item]);
- mapper.call_vm(vm, args)
- })
- .collect()
+ self.into_iter().map(|item| mapper.call(engine, [item])).collect()
}
/// Returns a new array with the values alongside their indices.
@@ -518,8 +519,8 @@ impl Array {
#[func]
pub fn fold(
self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The initial value to start with.
init: Value,
/// The folding function. Must have two parameters: One for the
@@ -528,8 +529,7 @@ impl Array {
) -> SourceResult<Value> {
let mut acc = init;
for item in self {
- let args = Args::new(folder.span(), [acc, item]);
- acc = folder.call_vm(vm, args)?;
+ acc = folder.call(engine, [acc, item])?;
}
Ok(acc)
}
@@ -579,14 +579,13 @@ impl Array {
#[func]
pub fn any(
self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The function to apply to each item. Must return a boolean.
test: Func,
) -> SourceResult<bool> {
for item in self {
- let args = Args::new(test.span(), [item]);
- if test.call_vm(vm, args)?.cast::<bool>().at(test.span())? {
+ if test.call(engine, [item])?.cast::<bool>().at(test.span())? {
return Ok(true);
}
}
@@ -598,14 +597,13 @@ impl Array {
#[func]
pub fn all(
self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The function to apply to each item. Must return a boolean.
test: Func,
) -> SourceResult<bool> {
for item in self {
- let args = Args::new(test.span(), [item]);
- if !test.call_vm(vm, args)?.cast::<bool>().at(test.span())? {
+ if !test.call(engine, [item])?.cast::<bool>().at(test.span())? {
return Ok(false);
}
}
@@ -714,8 +712,8 @@ impl Array {
#[func]
pub fn sorted(
self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The callsite span.
span: Span,
/// If given, applies this function to the elements in the array to
@@ -728,7 +726,7 @@ impl Array {
let mut key_of = |x: Value| match &key {
// NOTE: We are relying on `comemo`'s memoization of function
// evaluation to not excessively reevaluate the `key`.
- Some(f) => f.call_vm(vm, Args::new(f.span(), [x])),
+ Some(f) => f.call(engine, [x]),
None => Ok(x),
};
vec.make_mut().sort_by(|a, b| {
@@ -762,8 +760,8 @@ impl Array {
#[func(title = "Deduplicate")]
pub fn dedup(
self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// If given, applies this function to the elements in the array to
/// determine the keys to deduplicate by.
#[named]
@@ -773,7 +771,7 @@ impl Array {
let mut key_of = |x: Value| match &key {
// NOTE: We are relying on `comemo`'s memoization of function
// evaluation to not excessively reevaluate the `key`.
- Some(f) => f.call_vm(vm, Args::new(f.span(), [x])),
+ Some(f) => f.call(engine, [x]),
None => Ok(x),
};
diff --git a/crates/typst/src/foundations/cast.rs b/crates/typst/src/foundations/cast.rs
index fbd5ab14..e3b7dd01 100644
--- a/crates/typst/src/foundations/cast.rs
+++ b/crates/typst/src/foundations/cast.rs
@@ -12,6 +12,7 @@ use crate::diag::{At, SourceResult, StrResult};
use crate::foundations::{repr, Repr, Type, Value};
use crate::syntax::{Span, Spanned};
+#[rustfmt::skip]
#[doc(inline)]
pub use typst_macros::{cast, Cast};
diff --git a/crates/typst/src/foundations/content.rs b/crates/typst/src/foundations/content.rs
index 7a402629..111b33ea 100644
--- a/crates/typst/src/foundations/content.rs
+++ b/crates/typst/src/foundations/content.rs
@@ -10,7 +10,7 @@ use serde::{Serialize, Serializer};
use smallvec::smallvec;
use crate::diag::{SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
elem, func, scope, ty, Dict, Element, FromValue, Guard, IntoValue, Label,
NativeElement, Recipe, Repr, Selector, Str, Style, Styles, Value,
@@ -299,16 +299,19 @@ impl Content {
/// Access the child and styles.
pub fn to_styled(&self) -> Option<(&Content, &Styles)> {
let styled = self.to::<StyledElem>()?;
-
let child = styled.child();
let styles = styled.styles();
Some((child, styles))
}
/// Style this content with a recipe, eagerly applying it if possible.
- pub fn styled_with_recipe(self, vm: &mut Vm, recipe: Recipe) -> SourceResult<Self> {
+ pub fn styled_with_recipe(
+ self,
+ engine: &mut Engine,
+ recipe: Recipe,
+ ) -> SourceResult<Self> {
if recipe.selector.is_none() {
- recipe.apply_vm(vm, self)
+ recipe.apply(engine, self)
} else {
Ok(self.styled(recipe))
}
diff --git a/crates/typst/src/foundations/datetime.rs b/crates/typst/src/foundations/datetime.rs
index f50daf72..78290c99 100644
--- a/crates/typst/src/foundations/datetime.rs
+++ b/crates/typst/src/foundations/datetime.rs
@@ -8,7 +8,7 @@ use time::macros::format_description;
use time::{format_description, Month, PrimitiveDateTime};
use crate::diag::{bail, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
cast, func, repr, scope, ty, Dict, Duration, Repr, Smart, Str, Value,
};
@@ -296,16 +296,15 @@ impl Datetime {
/// ```
#[func]
pub fn today(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// An offset to apply to the current UTC date. If set to `{auto}`, the
/// offset will be the local offset.
#[named]
#[default]
offset: Smart<i64>,
) -> StrResult<Datetime> {
- Ok(vm
- .vt
+ Ok(engine
.world
.today(offset.as_custom())
.ok_or("unable to get the current date")?)
diff --git a/crates/typst/src/foundations/element.rs b/crates/typst/src/foundations/element.rs
index 64b47b78..8e4d159a 100644
--- a/crates/typst/src/foundations/element.rs
+++ b/crates/typst/src/foundations/element.rs
@@ -10,13 +10,12 @@ use once_cell::sync::Lazy;
use smallvec::SmallVec;
use crate::diag::{SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
cast, Args, Content, Dict, Func, Label, ParamInfo, Repr, Scope, Selector, StyleChain,
Styles, Value,
};
use crate::introspection::Location;
-use crate::layout::Vt;
use crate::syntax::Span;
use crate::text::{Lang, Region};
use crate::util::Static;
@@ -66,13 +65,17 @@ impl Element {
}
/// Construct an instance of this element.
- pub fn construct(self, vm: &mut Vm, args: &mut Args) -> SourceResult<Content> {
- (self.0.construct)(vm, args)
+ pub fn construct(
+ self,
+ engine: &mut Engine,
+ args: &mut Args,
+ ) -> SourceResult<Content> {
+ (self.0.construct)(engine, args)
}
/// Execute the set rule for the element and return the resulting style map.
- pub fn set(self, vm: &mut Vm, mut args: Args) -> SourceResult<Styles> {
- let styles = (self.0.set)(vm, &mut args)?;
+ pub fn set(self, engine: &mut Engine, mut args: Args) -> SourceResult<Styles> {
+ let styles = (self.0.set)(engine, &mut args)?;
args.finish()?;
Ok(styles)
}
@@ -275,7 +278,7 @@ pub trait Construct {
///
/// This is passed only the arguments that remain after execution of the
/// element's set rule.
- fn construct(vm: &mut Vm, args: &mut Args) -> SourceResult<Content>
+ fn construct(engine: &mut Engine, args: &mut Args) -> SourceResult<Content>
where
Self: Sized;
}
@@ -283,7 +286,7 @@ pub trait Construct {
/// An element's set rule.
pub trait Set {
/// Parse relevant arguments into style properties for this element.
- fn set(vm: &mut Vm, args: &mut Args) -> SourceResult<Styles>
+ fn set(engine: &mut Engine, args: &mut Args) -> SourceResult<Styles>
where
Self: Sized;
}
@@ -295,8 +298,8 @@ pub struct NativeElementData {
pub title: &'static str,
pub docs: &'static str,
pub keywords: &'static [&'static str],
- pub construct: fn(&mut Vm, &mut Args) -> SourceResult<Content>,
- pub set: fn(&mut Vm, &mut Args) -> SourceResult<Styles>,
+ pub construct: fn(&mut Engine, &mut Args) -> SourceResult<Content>,
+ pub set: fn(&mut Engine, &mut Args) -> SourceResult<Styles>,
pub vtable: fn(of: TypeId) -> Option<*const ()>,
pub field_id: fn(name: &str) -> Option<u8>,
pub field_name: fn(u8) -> Option<&'static str>,
@@ -320,13 +323,14 @@ cast! {
/// rule.
pub trait Synthesize {
/// Prepare the element for show rule application.
- fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()>;
+ fn synthesize(&mut self, engine: &mut Engine, styles: StyleChain)
+ -> SourceResult<()>;
}
/// The base recipe for an element.
pub trait Show {
/// Execute the base recipe for this element.
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content>;
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content>;
}
/// Post-process an element after it was realized.
diff --git a/crates/typst/src/foundations/func.rs b/crates/typst/src/foundations/func.rs
index f1da6e37..6729b39d 100644
--- a/crates/typst/src/foundations/func.rs
+++ b/crates/typst/src/foundations/func.rs
@@ -6,14 +6,12 @@ use ecow::{eco_format, EcoString};
use once_cell::sync::Lazy;
use crate::diag::{bail, SourceResult, StrResult};
-use crate::eval::{Route, Vm};
+use crate::engine::Engine;
use crate::foundations::{
- cast, repr, scope, ty, Args, CastInfo, Content, Element, IntoValue, Scope, Scopes,
- Selector, Type, Value,
+ cast, repr, scope, ty, Args, CastInfo, Content, Element, IntoArgs, Scope, Selector,
+ Type, Value,
};
-use crate::introspection::Locator;
-use crate::layout::Vt;
-use crate::syntax::{ast, FileId, Span, SyntaxNode};
+use crate::syntax::{ast, Span, SyntaxNode};
use crate::util::Static;
#[doc(inline)]
@@ -252,7 +250,13 @@ impl Func {
}
/// Call the function with the given arguments.
- pub fn call_vm(&self, vm: &mut Vm, mut args: Args) -> SourceResult<Value> {
+ #[tracing::instrument(skip_all)]
+ pub fn call(&self, engine: &mut Engine, args: impl IntoArgs) -> SourceResult<Value> {
+ self.call_impl(engine, args.into_args(self.span))
+ }
+
+ /// Non-generic implementation of `call`.
+ fn call_impl(&self, engine: &mut Engine, mut args: Args) -> SourceResult<Value> {
let _span = tracing::info_span!(
"call",
name = self.name().unwrap_or("<anon>"),
@@ -261,59 +265,32 @@ impl Func {
match &self.repr {
Repr::Native(native) => {
- let value = (native.function)(vm, &mut args)?;
+ let value = (native.function)(engine, &mut args)?;
args.finish()?;
Ok(value)
}
Repr::Element(func) => {
- let value = func.construct(vm, &mut args)?;
+ let value = func.construct(engine, &mut args)?;
args.finish()?;
Ok(Value::Content(value))
}
- Repr::Closure(closure) => {
- // Determine the route inside the closure.
- let fresh = Route::new(closure.file);
- let route = if vm.file.is_none() { fresh.track() } else { vm.route };
- crate::eval::call_closure(
- self,
- closure,
- vm.world(),
- route,
- vm.vt.introspector,
- vm.vt.locator.track(),
- TrackedMut::reborrow_mut(&mut vm.vt.tracer),
- vm.depth + 1,
- args,
- )
- }
+ Repr::Closure(closure) => crate::eval::call_closure(
+ self,
+ closure,
+ engine.world,
+ engine.introspector,
+ engine.route.track(),
+ engine.locator.track(),
+ TrackedMut::reborrow_mut(&mut engine.tracer),
+ args,
+ ),
Repr::With(with) => {
args.items = with.1.items.iter().cloned().chain(args.items).collect();
- with.0.call_vm(vm, args)
+ with.0.call(engine, args)
}
}
}
- /// Call the function with a Vt.
- #[tracing::instrument(skip_all)]
- pub fn call_vt<T: IntoValue>(
- &self,
- vt: &mut Vt,
- args: impl IntoIterator<Item = T>,
- ) -> SourceResult<Value> {
- let route = Route::default();
- let scopes = Scopes::new(None);
- let mut locator = Locator::chained(vt.locator.track());
- let vt = Vt {
- world: vt.world,
- introspector: vt.introspector,
- locator: &mut locator,
- tracer: TrackedMut::reborrow_mut(&mut vt.tracer),
- };
- let mut vm = Vm::new(vt, route.track(), None, scopes);
- let args = Args::new(self.span(), args);
- self.call_vm(&mut vm, args)
- }
-
/// The function's span.
pub fn span(&self) -> Span {
self.span
@@ -443,7 +420,7 @@ pub trait NativeFunc {
/// Defines a native function.
#[derive(Debug)]
pub struct NativeFuncData {
- pub function: fn(&mut Vm, &mut Args) -> SourceResult<Value>,
+ pub function: fn(&mut Engine, &mut Args) -> SourceResult<Value>,
pub name: &'static str,
pub title: &'static str,
pub docs: &'static str,
@@ -495,8 +472,6 @@ pub struct ParamInfo {
pub struct Closure {
/// The closure's syntax node. Must be castable to `ast::Closure`.
pub node: SyntaxNode,
- /// The source file where the closure was defined.
- pub file: Option<FileId>,
/// Default values of named parameters.
pub defaults: Vec<Value>,
/// Captured values from outer scopes.
diff --git a/crates/typst/src/foundations/mod.rs b/crates/typst/src/foundations/mod.rs
index b2c35194..4ddc2162 100644
--- a/crates/typst/src/foundations/mod.rs
+++ b/crates/typst/src/foundations/mod.rs
@@ -60,6 +60,7 @@ pub use self::ty::*;
pub use self::value::*;
pub use self::version::*;
+#[rustfmt::skip]
#[doc(hidden)]
pub use {
ecow::{eco_format, eco_vec},
@@ -70,7 +71,8 @@ pub use {
use ecow::EcoString;
use crate::diag::{bail, SourceResult, StrResult};
-use crate::eval::{EvalMode, Vm};
+use crate::engine::Engine;
+use crate::eval::EvalMode;
use crate::syntax::Spanned;
/// Foundational types and functions.
@@ -251,8 +253,8 @@ impl assert {
/// ```
#[func(title = "Evaluate")]
pub fn eval(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// A string of Typst code to evaluate.
///
/// The code in the string cannot interact with the file system.
@@ -289,5 +291,5 @@ pub fn eval(
for (key, value) in dict {
scope.define(key, value);
}
- crate::eval::eval_string(vm.world(), &text, span, mode, scope)
+ crate::eval::eval_string(engine.world, &text, span, mode, scope)
}
diff --git a/crates/typst/src/foundations/plugin.rs b/crates/typst/src/foundations/plugin.rs
index 6071b3bd..89237f94 100644
--- a/crates/typst/src/foundations/plugin.rs
+++ b/crates/typst/src/foundations/plugin.rs
@@ -3,10 +3,10 @@ use std::hash::{Hash, Hasher};
use std::sync::{Arc, Mutex};
use ecow::{eco_format, EcoString};
-use wasmi::{AsContext, AsContextMut, Caller, Engine, Linker, Module};
+use wasmi::{AsContext, AsContextMut};
use crate::diag::{bail, At, SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, repr, scope, ty, Bytes};
use crate::syntax::Spanned;
use crate::World;
@@ -152,14 +152,14 @@ impl Plugin {
/// Creates a new plugin from a WebAssembly file.
#[func(constructor)]
pub fn construct(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a WebAssembly file.
path: Spanned<EcoString>,
) -> SourceResult<Plugin> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
Plugin::new(data).at(span)
}
}
@@ -168,11 +168,11 @@ impl Plugin {
/// Create a new plugin from raw WebAssembly bytes.
#[comemo::memoize]
pub fn new(bytes: Bytes) -> StrResult<Self> {
- let engine = Engine::default();
- let module = Module::new(&engine, bytes.as_slice())
+ let engine = wasmi::Engine::default();
+ let module = wasmi::Module::new(&engine, bytes.as_slice())
.map_err(|err| format!("failed to load WebAssembly module ({err})"))?;
- let mut linker = Linker::new(&engine);
+ let mut linker = wasmi::Linker::new(&engine);
linker
.func_wrap(
"typst_env",
@@ -323,7 +323,10 @@ impl Hash for Plugin {
}
/// Write the arguments to the plugin function into the plugin's memory.
-fn wasm_minimal_protocol_write_args_to_buffer(mut caller: Caller<StoreData>, ptr: u32) {
+fn wasm_minimal_protocol_write_args_to_buffer(
+ mut caller: wasmi::Caller<StoreData>,
+ ptr: u32,
+) {
let memory = caller.get_export("memory").unwrap().into_memory().unwrap();
let arguments = std::mem::take(&mut caller.data_mut().args);
let mut offset = ptr as usize;
@@ -342,7 +345,7 @@ fn wasm_minimal_protocol_write_args_to_buffer(mut caller: Caller<StoreData>, ptr
/// Extracts the output of the plugin function from the plugin's memory.
fn wasm_minimal_protocol_send_result_to_host(
- mut caller: Caller<StoreData>,
+ mut caller: wasmi::Caller<StoreData>,
ptr: u32,
len: u32,
) {
diff --git a/crates/typst/src/foundations/str.rs b/crates/typst/src/foundations/str.rs
index 4b56971a..83bde675 100644
--- a/crates/typst/src/foundations/str.rs
+++ b/crates/typst/src/foundations/str.rs
@@ -8,10 +8,10 @@ use serde::{Deserialize, Serialize};
use unicode_segmentation::UnicodeSegmentation;
use crate::diag::{bail, At, SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
- cast, dict, func, repr, scope, ty, Args, Array, Bytes, Dict, Func, IntoValue, Label,
- Repr, Type, Value, Version,
+ cast, dict, func, repr, scope, ty, Array, Bytes, Dict, Func, IntoValue, Label, Repr,
+ Type, Value, Version,
};
use crate::layout::Align;
use crate::syntax::{Span, Spanned};
@@ -422,8 +422,8 @@ impl Str {
#[func]
pub fn replace(
&self,
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The pattern to search for.
pattern: StrPattern,
/// The string to replace the matches with or a function that gets a
@@ -449,8 +449,8 @@ impl Str {
match &replacement {
Replacement::Str(s) => output.push_str(s),
Replacement::Func(func) => {
- let args = Args::new(func.span(), [dict.into_value()]);
- let piece = func.call_vm(vm, args)?.cast::<Str>().at(func.span())?;
+ let piece =
+ func.call(engine, [dict])?.cast::<Str>().at(func.span())?;
output.push_str(&piece);
}
}
diff --git a/crates/typst/src/foundations/styles.rs b/crates/typst/src/foundations/styles.rs
index 78bd24d6..ca6a9e78 100644
--- a/crates/typst/src/foundations/styles.rs
+++ b/crates/typst/src/foundations/styles.rs
@@ -10,12 +10,10 @@ use once_cell::sync::Lazy;
use smallvec::SmallVec;
use crate::diag::{SourceResult, Trace, Tracepoint};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
- cast, elem, func, ty, Args, Content, Element, Func, NativeElement, Repr, Selector,
- Show, Value,
+ cast, elem, func, ty, Content, Element, Func, NativeElement, Repr, Selector, Show,
};
-use crate::layout::Vt;
use crate::syntax::Span;
use crate::text::{FontFamily, FontList, TextElem};
@@ -58,8 +56,8 @@ struct StyleElem {
impl Show for StyleElem {
#[tracing::instrument(name = "StyleElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(self.func().call_vt(vt, [styles.to_map()])?.display())
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
+ Ok(self.func().call(engine, [styles.to_map()])?.display())
}
}
@@ -356,37 +354,23 @@ impl Recipe {
}
/// Apply the recipe to the given content.
- pub fn apply_vm(&self, vm: &mut Vm, content: Content) -> SourceResult<Content> {
- match &self.transform {
- Transformation::Content(content) => Ok(content.clone()),
+ pub fn apply(&self, engine: &mut Engine, content: Content) -> SourceResult<Content> {
+ let mut content = match &self.transform {
+ Transformation::Content(content) => content.clone(),
Transformation::Func(func) => {
- let args = Args::new(self.span, [Value::Content(content.clone())]);
- let mut result = func.call_vm(vm, args);
- // For selector-less show rules, a tracepoint makes no sense.
+ let mut result = func.call(engine, [content.clone()]);
if self.selector.is_some() {
let point = || Tracepoint::Show(content.func().name().into());
- result = result.trace(vm.world(), point, content.span());
+ result = result.trace(engine.world, point, content.span());
}
- Ok(result?.display())
+ result?.display()
}
- Transformation::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 {
- Transformation::Content(content) => Ok(content.clone()),
- Transformation::Func(func) => {
- let mut result = func.call_vt(vt, [Value::Content(content.clone())]);
- if self.selector.is_some() {
- let point = || Tracepoint::Show(content.func().name().into());
- result = result.trace(vt.world, point, content.span());
- }
- Ok(result?.display())
- }
- Transformation::Style(styles) => Ok(content.styled_with_map(styles.clone())),
+ Transformation::Style(styles) => content.styled_with_map(styles.clone()),
+ };
+ if content.span().is_detached() {
+ content = content.spanned(self.span);
}
+ Ok(content)
}
}
diff --git a/crates/typst/src/foundations/ty.rs b/crates/typst/src/foundations/ty.rs
index 47add6ec..4c2098f3 100644
--- a/crates/typst/src/foundations/ty.rs
+++ b/crates/typst/src/foundations/ty.rs
@@ -8,6 +8,7 @@ use crate::diag::StrResult;
use crate::foundations::{cast, func, Func, NativeFuncData, Repr, Scope, Value};
use crate::util::Static;
+#[rustfmt::skip]
#[doc(inline)]
pub use typst_macros::{scope, ty};
diff --git a/crates/typst/src/introspection/counter.rs b/crates/typst/src/introspection/counter.rs
index 7b073681..ce485997 100644
--- a/crates/typst/src/introspection/counter.rs
+++ b/crates/typst/src/introspection/counter.rs
@@ -6,6 +6,7 @@ use ecow::{eco_format, eco_vec, EcoString, EcoVec};
use smallvec::{smallvec, SmallVec};
use crate::diag::{At, SourceResult, StrResult};
+use crate::engine::{Engine, Route};
use crate::eval::Tracer;
use crate::foundations::{
cast, elem, func, scope, select_where, ty, Array, Content, Element, Func, IntoValue,
@@ -13,7 +14,7 @@ use crate::foundations::{
Value,
};
use crate::introspection::{Introspector, Locatable, Location, Locator, Meta};
-use crate::layout::{Frame, FrameItem, PageElem, Vt};
+use crate::layout::{Frame, FrameItem, PageElem};
use crate::math::EquationElem;
use crate::model::{FigureElem, HeadingElem, Numbering, NumberingPattern};
use crate::util::NonZeroExt;
@@ -222,9 +223,13 @@ impl Counter {
}
/// Gets the current and final value of the state combined in one state.
- pub fn both(&self, vt: &mut Vt, location: Location) -> SourceResult<CounterState> {
- let sequence = self.sequence(vt)?;
- let offset = vt
+ pub fn both(
+ &self,
+ engine: &mut Engine,
+ location: Location,
+ ) -> SourceResult<CounterState> {
+ let sequence = self.sequence(engine)?;
+ let offset = engine
.introspector
.query(&self.selector().before(location.into(), true))
.len();
@@ -232,10 +237,10 @@ impl Counter {
let (mut final_state, final_page) = sequence.last().unwrap().clone();
if self.is_page() {
let at_delta =
- vt.introspector.page(location).get().saturating_sub(at_page.get());
+ engine.introspector.page(location).get().saturating_sub(at_page.get());
at_state.step(NonZeroUsize::ONE, at_delta);
let final_delta =
- vt.introspector.pages().get().saturating_sub(final_page.get());
+ engine.introspector.pages().get().saturating_sub(final_page.get());
final_state.step(NonZeroUsize::ONE, final_delta);
}
Ok(CounterState(smallvec![at_state.first(), final_state.first()]))
@@ -247,13 +252,14 @@ impl Counter {
/// of counter updates from quadratic to linear.
fn sequence(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
) -> SourceResult<EcoVec<(CounterState, NonZeroUsize)>> {
self.sequence_impl(
- vt.world,
- vt.introspector,
- vt.locator.track(),
- TrackedMut::reborrow_mut(&mut vt.tracer),
+ engine.world,
+ engine.introspector,
+ engine.route.track(),
+ engine.locator.track(),
+ TrackedMut::reborrow_mut(&mut engine.tracer),
)
}
@@ -263,11 +269,18 @@ impl Counter {
&self,
world: Tracked<dyn World + '_>,
introspector: Tracked<Introspector>,
+ route: Tracked<Route>,
locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>,
) -> SourceResult<EcoVec<(CounterState, NonZeroUsize)>> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, introspector, locator: &mut locator, tracer };
+ let mut engine = Engine {
+ world,
+ introspector,
+ route: Route::extend(route),
+ locator: &mut locator,
+ tracer,
+ };
let mut state = CounterState::init(&self.0);
let mut page = NonZeroUsize::ONE;
@@ -288,7 +301,7 @@ impl Counter {
Some(countable) => countable.update(),
None => Some(CounterUpdate::Step(NonZeroUsize::ONE)),
} {
- state.update(&mut vt, update)?;
+ state.update(&mut engine, update)?;
}
stops.push((state.clone(), page));
@@ -399,21 +412,22 @@ impl Counter {
#[func]
pub fn at(
&self,
- /// The virtual typesetter.
- vt: &mut Vt,
+ /// The engine.
+ engine: &mut Engine,
/// The location at which the counter value should be retrieved. A
/// suitable location can be retrieved from [`locate`]($locate) or
/// [`query`]($query).
location: Location,
) -> SourceResult<CounterState> {
- let sequence = self.sequence(vt)?;
- let offset = vt
+ let sequence = self.sequence(engine)?;
+ let offset = engine
.introspector
.query(&self.selector().before(location.into(), true))
.len();
let (mut state, page) = sequence[offset].clone();
if self.is_page() {
- let delta = vt.introspector.page(location).get().saturating_sub(page.get());
+ let delta =
+ engine.introspector.page(location).get().saturating_sub(page.get());
state.step(NonZeroUsize::ONE, delta);
}
@@ -425,8 +439,8 @@ impl Counter {
#[func]
pub fn final_(
&self,
- /// The virtual typesetter.
- vt: &mut Vt,
+ /// The engine.
+ engine: &mut Engine,
/// Can be an arbitrary location, as its value is irrelevant for the
/// method's return value. Why is it required then? Typst has to
/// evaluate parts of your code multiple times to determine all counter
@@ -438,10 +452,10 @@ impl Counter {
location: Location,
) -> SourceResult<CounterState> {
let _ = location;
- let sequence = self.sequence(vt)?;
+ let sequence = self.sequence(engine)?;
let (mut state, page) = sequence.last().unwrap().clone();
if self.is_page() {
- let delta = vt.introspector.pages().get().saturating_sub(page.get());
+ let delta = engine.introspector.pages().get().saturating_sub(page.get());
state.step(NonZeroUsize::ONE, delta);
}
Ok(state)
@@ -544,12 +558,17 @@ impl CounterState {
}
/// Advance the counter and return the numbers for the given heading.
- pub fn update(&mut self, vt: &mut Vt, update: CounterUpdate) -> SourceResult<()> {
+ pub fn update(
+ &mut self,
+ engine: &mut Engine,
+ update: CounterUpdate,
+ ) -> SourceResult<()> {
match update {
CounterUpdate::Set(state) => *self = state,
CounterUpdate::Step(level) => self.step(level, 1),
CounterUpdate::Func(func) => {
- *self = func.call_vt(vt, self.0.iter().copied())?.cast().at(func.span())?
+ *self =
+ func.call(engine, self.0.iter().copied())?.cast().at(func.span())?
}
}
Ok(())
@@ -575,8 +594,12 @@ impl CounterState {
}
/// Display the counter state with a numbering.
- pub fn display(&self, vt: &mut Vt, numbering: &Numbering) -> SourceResult<Content> {
- Ok(numbering.apply_vt(vt, &self.0)?.display())
+ pub fn display(
+ &self,
+ engine: &mut Engine,
+ numbering: &Numbering,
+ ) -> SourceResult<Content> {
+ Ok(numbering.apply(engine, &self.0)?.display())
}
}
@@ -608,8 +631,8 @@ struct DisplayElem {
impl Show for DisplayElem {
#[tracing::instrument(name = "DisplayElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(vt.delayed(|vt| {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
+ Ok(engine.delayed(|engine| {
let location = self.location().unwrap();
let counter = self.counter();
let numbering = self
@@ -633,12 +656,12 @@ impl Show for DisplayElem {
.unwrap_or_else(|| NumberingPattern::from_str("1.1").unwrap().into());
let state = if *self.both() {
- counter.both(vt, location)?
+ counter.both(engine, location)?
} else {
- counter.at(vt, location)?
+ counter.at(engine, location)?
};
- state.display(vt, &numbering)
+ state.display(engine, &numbering)
}))
}
}
@@ -657,7 +680,7 @@ struct UpdateElem {
impl Show for UpdateElem {
#[tracing::instrument(name = "UpdateElem::show", skip(self))]
- fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
Ok(Content::empty())
}
}
@@ -693,15 +716,15 @@ impl ManualPageCounter {
}
/// Advance past a page.
- pub fn visit(&mut self, vt: &mut Vt, page: &Frame) -> SourceResult<()> {
+ pub fn visit(&mut self, engine: &mut Engine, page: &Frame) -> SourceResult<()> {
for (_, item) in page.items() {
match item {
- FrameItem::Group(group) => self.visit(vt, &group.frame)?,
+ FrameItem::Group(group) => self.visit(engine, &group.frame)?,
FrameItem::Meta(Meta::Elem(elem), _) => {
let Some(elem) = elem.to::<UpdateElem>() else { continue };
if *elem.key() == CounterKey::Page {
let mut state = CounterState(smallvec![self.logical]);
- state.update(vt, elem.update().clone())?;
+ state.update(engine, elem.update().clone())?;
self.logical = state.first();
}
}
diff --git a/crates/typst/src/introspection/locate.rs b/crates/typst/src/introspection/locate.rs
index 1c4f0e5a..69dcadd8 100644
--- a/crates/typst/src/introspection/locate.rs
+++ b/crates/typst/src/introspection/locate.rs
@@ -1,7 +1,7 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, func, Content, Func, NativeElement, Show, StyleChain};
use crate::introspection::Locatable;
-use crate::layout::Vt;
/// Provides access to the location of content.
///
@@ -37,11 +37,11 @@ struct LocateElem {
}
impl Show for LocateElem {
- #[tracing::instrument(name = "LocateElem::show", skip(self, vt))]
- fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- Ok(vt.delayed(|vt| {
+ #[tracing::instrument(name = "LocateElem::show", skip(self, engine))]
+ fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
+ Ok(engine.delayed(|engine| {
let location = self.location().unwrap();
- Ok(self.func().call_vt(vt, [location])?.display())
+ Ok(self.func().call(engine, [location])?.display())
}))
}
}
diff --git a/crates/typst/src/introspection/location.rs b/crates/typst/src/introspection/location.rs
index b70dc4ad..0ceaac8b 100644
--- a/crates/typst/src/introspection/location.rs
+++ b/crates/typst/src/introspection/location.rs
@@ -2,7 +2,7 @@ use std::num::NonZeroUsize;
use ecow::EcoString;
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{cast, func, scope, ty, Dict, Repr};
use crate::model::Numbering;
@@ -45,8 +45,8 @@ impl Location {
/// If you want to know the value of the page counter, use
/// `{counter(page).at(loc)}` instead.
#[func]
- pub fn page(self, vm: &mut Vm) -> NonZeroUsize {
- vm.vt.introspector.page(self)
+ pub fn page(self, engine: &mut Engine) -> NonZeroUsize {
+ engine.introspector.page(self)
}
/// Return a dictionary with the page number and the x, y position for this
@@ -56,8 +56,8 @@ impl Location {
/// If you only need the page number, use `page()` instead as it allows
/// Typst to skip unnecessary work.
#[func]
- pub fn position(self, vm: &mut Vm) -> Dict {
- vm.vt.introspector.position(self).into()
+ pub fn position(self, engine: &mut Engine) -> Dict {
+ engine.introspector.position(self).into()
}
/// Returns the page numbering pattern of the page at this location. This
@@ -68,8 +68,8 @@ impl Location {
/// If the page numbering is set to `none` at that location, this function
/// returns `none`.
#[func]
- pub fn page_numbering(self, vm: &mut Vm) -> Option<Numbering> {
- vm.vt.introspector.page_numbering(self).cloned()
+ pub fn page_numbering(self, engine: &mut Engine) -> Option<Numbering> {
+ engine.introspector.page_numbering(self).cloned()
}
}
@@ -83,5 +83,5 @@ cast! {
type Location,
}
-/// Makes this element locatable through `vt.locate`.
+/// Makes this element locatable through `engine.locate`.
pub trait Locatable {}
diff --git a/crates/typst/src/introspection/metadata.rs b/crates/typst/src/introspection/metadata.rs
index 4042bc04..15d144eb 100644
--- a/crates/typst/src/introspection/metadata.rs
+++ b/crates/typst/src/introspection/metadata.rs
@@ -1,7 +1,7 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Behave, Behaviour, Content, Show, StyleChain, Value};
use crate::introspection::Locatable;
-use crate::layout::Vt;
/// Exposes a value to the query system without producing visible content.
///
@@ -31,7 +31,7 @@ pub struct MetadataElem {
}
impl Show for MetadataElem {
- fn show(&self, _vt: &mut Vt, _styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _styles: StyleChain) -> SourceResult<Content> {
Ok(Content::empty())
}
}
diff --git a/crates/typst/src/introspection/query.rs b/crates/typst/src/introspection/query.rs
index 1024238e..5b70ba51 100644
--- a/crates/typst/src/introspection/query.rs
+++ b/crates/typst/src/introspection/query.rs
@@ -1,4 +1,4 @@
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, Array, LocatableSelector, Value};
use crate::introspection::Location;
@@ -129,8 +129,8 @@ use crate::introspection::Location;
/// ```
#[func]
pub fn query(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Can be an element function like a `heading` or `figure`, a `{<label>}`
/// or a more complex selector like `{heading.where(level: 1)}`.
///
@@ -152,7 +152,7 @@ pub fn query(
location: Location,
) -> Array {
let _ = location;
- let vec = vm.vt.introspector.query(&target.0);
+ let vec = engine.introspector.query(&target.0);
vec.into_iter()
.map(|elem| Value::Content(elem.into_inner()))
.collect()
diff --git a/crates/typst/src/introspection/state.rs b/crates/typst/src/introspection/state.rs
index af6d7933..8479bace 100644
--- a/crates/typst/src/introspection/state.rs
+++ b/crates/typst/src/introspection/state.rs
@@ -2,13 +2,13 @@ use comemo::{Tracked, TrackedMut};
use ecow::{eco_format, eco_vec, EcoString, EcoVec};
use crate::diag::SourceResult;
+use crate::engine::{Engine, Route};
use crate::eval::Tracer;
use crate::foundations::{
cast, elem, func, scope, select_where, ty, Content, Func, NativeElement, Repr,
Selector, Show, Str, StyleChain, Value,
};
use crate::introspection::{Introspector, Locatable, Location, Locator};
-use crate::layout::Vt;
use crate::World;
/// Manages stateful parts of your document.
@@ -204,12 +204,13 @@ impl State {
///
/// This has to happen just once for all states, cutting down the number
/// of state updates from quadratic to linear.
- fn sequence(&self, vt: &mut Vt) -> SourceResult<EcoVec<Value>> {
+ fn sequence(&self, engine: &mut Engine) -> SourceResult<EcoVec<Value>> {
self.sequence_impl(
- vt.world,
- vt.introspector,
- vt.locator.track(),
- TrackedMut::reborrow_mut(&mut vt.tracer),
+ engine.world,
+ engine.introspector,
+ engine.route.track(),
+ engine.locator.track(),
+ TrackedMut::reborrow_mut(&mut engine.tracer),
)
}
@@ -219,11 +220,18 @@ impl State {
&self,
world: Tracked<dyn World + '_>,
introspector: Tracked<Introspector>,
+ route: Tracked<Route>,
locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>,
) -> SourceResult<EcoVec<Value>> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, introspector, locator: &mut locator, tracer };
+ let mut engine = Engine {
+ world,
+ introspector,
+ route: Route::extend(route),
+ locator: &mut locator,
+ tracer,
+ };
let mut state = self.init.clone();
let mut stops = eco_vec![state.clone()];
@@ -231,7 +239,7 @@ impl State {
let elem = elem.to::<UpdateElem>().unwrap();
match elem.update() {
StateUpdate::Set(value) => state = value.clone(),
- StateUpdate::Func(func) => state = func.call_vt(&mut vt, [state])?,
+ StateUpdate::Func(func) => state = func.call(&mut engine, [state])?,
}
stops.push(state.clone());
}
@@ -295,15 +303,15 @@ impl State {
#[func]
pub fn at(
&self,
- /// The virtual typesetter.
- vt: &mut Vt,
+ /// The engine.
+ engine: &mut Engine,
/// The location at which the state's value should be retrieved. A
/// suitable location can be retrieved from [`locate`]($locate) or
/// [`query`]($query).
location: Location,
) -> SourceResult<Value> {
- let sequence = self.sequence(vt)?;
- let offset = vt
+ let sequence = self.sequence(engine)?;
+ let offset = engine
.introspector
.query(&self.selector().before(location.into(), true))
.len();
@@ -314,8 +322,8 @@ impl State {
#[func]
pub fn final_(
&self,
- /// The virtual typesetter.
- vt: &mut Vt,
+ /// The engine.
+ engine: &mut Engine,
/// Can be an arbitrary location, as its value is irrelevant for the
/// method's return value. Why is it required then? As noted before,
/// Typst has to evaluate parts of your code multiple times to determine
@@ -327,7 +335,7 @@ impl State {
location: Location,
) -> SourceResult<Value> {
let _ = location;
- let sequence = self.sequence(vt)?;
+ let sequence = self.sequence(engine)?;
Ok(sequence.last().unwrap().clone())
}
}
@@ -377,13 +385,13 @@ struct DisplayElem {
}
impl Show for DisplayElem {
- #[tracing::instrument(name = "DisplayElem::show", skip(self, vt))]
- fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- Ok(vt.delayed(|vt| {
+ #[tracing::instrument(name = "DisplayElem::show", skip(self, engine))]
+ fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
+ Ok(engine.delayed(|engine| {
let location = self.location().unwrap();
- let value = self.state().at(vt, location)?;
+ let value = self.state().at(engine, location)?;
Ok(match self.func() {
- Some(func) => func.call_vt(vt, [value])?.display(),
+ Some(func) => func.call(engine, [value])?.display(),
None => value.display(),
})
}))
@@ -404,7 +412,7 @@ struct UpdateElem {
impl Show for UpdateElem {
#[tracing::instrument(name = "UpdateElem::show")]
- fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
Ok(Content::empty())
}
}
diff --git a/crates/typst/src/layout/align.rs b/crates/typst/src/layout/align.rs
index 74db4373..3d4017f3 100644
--- a/crates/typst/src/layout/align.rs
+++ b/crates/typst/src/layout/align.rs
@@ -3,10 +3,11 @@ use std::ops::Add;
use ecow::{eco_format, EcoString};
use crate::diag::{bail, SourceResult, StrResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, func, scope, ty, Content, Fold, Repr, Resolve, Show, StyleChain,
};
-use crate::layout::{Abs, Axes, Axis, Dir, Side, Vt};
+use crate::layout::{Abs, Axes, Axis, Dir, Side};
use crate::text::TextElem;
/// Aligns content horizontally and vertically.
@@ -46,7 +47,7 @@ pub struct AlignElem {
impl Show for AlignElem {
#[tracing::instrument(name = "AlignElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
Ok(self
.body()
.clone()
diff --git a/crates/typst/src/layout/columns.rs b/crates/typst/src/layout/columns.rs
index 852ef8f8..275dbbeb 100644
--- a/crates/typst/src/layout/columns.rs
+++ b/crates/typst/src/layout/columns.rs
@@ -1,9 +1,10 @@
use std::num::NonZeroUsize;
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Behave, Behaviour, Content, StyleChain};
use crate::layout::{
- Abs, Axes, Dir, Fragment, Frame, Layout, Length, Point, Ratio, Regions, Rel, Size, Vt,
+ Abs, Axes, Dir, Fragment, Frame, Layout, Length, Point, Ratio, Regions, Rel, Size,
};
use crate::text::TextElem;
use crate::util::Numeric;
@@ -60,7 +61,7 @@ impl Layout for ColumnsElem {
#[tracing::instrument(name = "ColumnsElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -69,7 +70,7 @@ impl Layout for ColumnsElem {
// Separating the infinite space into infinite columns does not make
// much sense.
if !regions.size.x.is_finite() {
- return body.layout(vt, styles, regions);
+ return body.layout(engine, styles, regions);
}
// Determine the width of the gutter and each column.
@@ -94,7 +95,7 @@ impl Layout for ColumnsElem {
};
// Layout the children.
- let mut frames = body.layout(vt, styles, pod)?.into_iter();
+ let mut frames = body.layout(engine, styles, pod)?.into_iter();
let mut finished = vec![];
let dir = TextElem::dir_in(styles);
diff --git a/crates/typst/src/layout/container.rs b/crates/typst/src/layout/container.rs
index cb65d4d8..cdc5c489 100644
--- a/crates/typst/src/layout/container.rs
+++ b/crates/typst/src/layout/container.rs
@@ -1,10 +1,11 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, AutoValue, Content, NativeElement, Resolve, Smart, StyleChain, Value,
};
use crate::layout::{
Abs, Axes, Corners, Em, Fr, Fragment, FrameKind, Layout, Length, Ratio, Regions, Rel,
- Sides, Size, Spacing, VElem, Vt,
+ Sides, Size, Spacing, VElem,
};
use crate::util::Numeric;
use crate::visualize::{clip_rect, Paint, Stroke};
@@ -112,7 +113,7 @@ impl Layout for BoxElem {
#[tracing::instrument(name = "BoxElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -140,7 +141,7 @@ impl Layout for BoxElem {
// Select the appropriate base and expansion for the child depending
// on whether it is automatically or relatively sized.
let pod = Regions::one(size, expand);
- let mut frame = body.layout(vt, styles, pod)?.into_frame();
+ let mut frame = body.layout(engine, styles, pod)?.into_frame();
// Enforce correct size.
*frame.size_mut() = expand.select(size, frame.size());
@@ -344,7 +345,7 @@ impl Layout for BlockElem {
#[tracing::instrument(name = "BlockElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -368,7 +369,7 @@ impl Layout for BlockElem {
// Measure to ensure frames for all regions have the same width.
if sizing.x == Smart::Auto {
let pod = Regions::one(size, Axes::splat(false));
- let frame = body.measure(vt, styles, pod)?.into_frame();
+ let frame = body.measure(engine, styles, pod)?.into_frame();
size.x = frame.width();
expand.x = true;
}
@@ -403,7 +404,7 @@ impl Layout for BlockElem {
pod.last = None;
}
- let mut frames = body.layout(vt, styles, pod)?.into_frames();
+ let mut frames = body.layout(engine, styles, pod)?.into_frames();
for (frame, &height) in frames.iter_mut().zip(&heights) {
*frame.size_mut() =
expand.select(Size::new(size.x, height), frame.size());
@@ -411,7 +412,7 @@ impl Layout for BlockElem {
frames
} else {
let pod = Regions::one(size, expand);
- let mut frames = body.layout(vt, styles, pod)?.into_frames();
+ let mut frames = body.layout(engine, styles, pod)?.into_frames();
*frames[0].size_mut() = expand.select(size, frames[0].size());
frames
};
diff --git a/crates/typst/src/layout/flow.rs b/crates/typst/src/layout/flow.rs
index 1c97c110..b4e7afd1 100644
--- a/crates/typst/src/layout/flow.rs
+++ b/crates/typst/src/layout/flow.rs
@@ -1,12 +1,13 @@
use comemo::Prehashed;
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{elem, Content, NativeElement, Resolve, Smart, StyleChain};
use crate::introspection::{Meta, MetaElem};
use crate::layout::{
Abs, AlignElem, Axes, BlockElem, ColbreakElem, ColumnsElem, FixedAlign, Fr, Fragment,
Frame, FrameItem, Layout, PlaceElem, Point, Regions, Rel, Size, Spacing, VAlign,
- VElem, Vt,
+ VElem,
};
use crate::model::{FootnoteElem, FootnoteEntry, ParElem};
use crate::util::Numeric;
@@ -30,7 +31,7 @@ impl Layout for FlowElem {
#[tracing::instrument(name = "FlowElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -51,9 +52,9 @@ impl Layout for FlowElem {
}
if let Some(elem) = child.to::<VElem>() {
- layouter.layout_spacing(vt, elem, styles)?;
+ layouter.layout_spacing(engine, elem, styles)?;
} else if let Some(elem) = child.to::<ParElem>() {
- layouter.layout_par(vt, elem, styles)?;
+ layouter.layout_par(engine, elem, styles)?;
} else if child.is::<LineElem>()
|| child.is::<RectElem>()
|| child.is::<SquareElem>()
@@ -64,7 +65,7 @@ impl Layout for FlowElem {
|| child.is::<PathElem>()
{
let layoutable = child.with::<dyn Layout>().unwrap();
- layouter.layout_single(vt, layoutable, styles)?;
+ layouter.layout_single(engine, layoutable, styles)?;
} else if child.is::<MetaElem>() {
let mut frame = Frame::soft(Size::zero());
frame.meta(styles, true);
@@ -75,20 +76,20 @@ impl Layout for FlowElem {
movable: false,
});
} else if let Some(placed) = child.to::<PlaceElem>() {
- layouter.layout_placed(vt, placed, styles)?;
+ layouter.layout_placed(engine, placed, styles)?;
} else if child.can::<dyn Layout>() {
- layouter.layout_multiple(vt, child, styles)?;
+ layouter.layout_multiple(engine, child, styles)?;
} else if child.is::<ColbreakElem>() {
if !layouter.regions.backlog.is_empty() || layouter.regions.last.is_some()
{
- layouter.finish_region(vt)?;
+ layouter.finish_region(engine)?;
}
} else {
bail!(child.span(), "unexpected flow child");
}
}
- layouter.finish(vt)
+ layouter.finish(engine)
}
}
@@ -193,12 +194,12 @@ impl<'a> FlowLayouter<'a> {
#[tracing::instrument(name = "FlowLayouter::layout_spacing", skip_all)]
fn layout_spacing(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
v: &VElem,
styles: StyleChain,
) -> SourceResult<()> {
self.layout_item(
- vt,
+ engine,
match v.amount() {
Spacing::Rel(rel) => FlowItem::Absolute(
rel.resolve(styles).relative_to(self.initial.y),
@@ -213,7 +214,7 @@ impl<'a> FlowLayouter<'a> {
#[tracing::instrument(name = "FlowLayouter::layout_par", skip_all)]
fn layout_par(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
par: &ParElem,
styles: StyleChain,
) -> SourceResult<()> {
@@ -221,7 +222,13 @@ impl<'a> FlowLayouter<'a> {
let leading = ParElem::leading_in(styles);
let consecutive = self.last_was_par;
let lines = par
- .layout(vt, styles, consecutive, self.regions.base(), self.regions.expand.x)?
+ .layout(
+ engine,
+ styles,
+ consecutive,
+ self.regions.base(),
+ self.regions.expand.x,
+ )?
.into_frames();
let mut sticky = self.items.len();
@@ -236,20 +243,20 @@ impl<'a> FlowLayouter<'a> {
if let Some(first) = lines.first() {
if !self.regions.size.y.fits(first.height()) && !self.regions.in_last() {
let carry: Vec<_> = self.items.drain(sticky..).collect();
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
for item in carry {
- self.layout_item(vt, item)?;
+ self.layout_item(engine, item)?;
}
}
}
for (i, frame) in lines.into_iter().enumerate() {
if i > 0 {
- self.layout_item(vt, FlowItem::Absolute(leading, true))?;
+ self.layout_item(engine, FlowItem::Absolute(leading, true))?;
}
self.layout_item(
- vt,
+ engine,
FlowItem::Frame { frame, align, sticky: false, movable: true },
)?;
}
@@ -262,15 +269,18 @@ impl<'a> FlowLayouter<'a> {
#[tracing::instrument(name = "FlowLayouter::layout_single", skip_all)]
fn layout_single(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
content: &dyn Layout,
styles: StyleChain,
) -> SourceResult<()> {
let align = AlignElem::alignment_in(styles).resolve(styles);
let sticky = BlockElem::sticky_in(styles);
let pod = Regions::one(self.regions.base(), Axes::splat(false));
- let frame = content.layout(vt, styles, pod)?.into_frame();
- self.layout_item(vt, FlowItem::Frame { frame, align, sticky, movable: true })?;
+ let frame = content.layout(engine, styles, pod)?.into_frame();
+ self.layout_item(
+ engine,
+ FlowItem::Frame { frame, align, sticky, movable: true },
+ )?;
self.last_was_par = false;
Ok(())
}
@@ -278,7 +288,7 @@ impl<'a> FlowLayouter<'a> {
/// Layout a placed element.
fn layout_placed(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
placed: &PlaceElem,
styles: StyleChain,
) -> SourceResult<()> {
@@ -290,15 +300,15 @@ impl<'a> FlowLayouter<'a> {
align.x().unwrap_or_default().resolve(styles)
});
let y_align = alignment.map(|align| align.y().map(VAlign::fix));
- let frame = placed.layout(vt, styles, self.regions)?.into_frame();
+ let frame = placed.layout(engine, styles, self.regions)?.into_frame();
let item = FlowItem::Placed { frame, x_align, y_align, delta, float, clearance };
- self.layout_item(vt, item)
+ self.layout_item(engine, item)
}
/// Layout into multiple regions.
fn layout_multiple(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
block: &Content,
styles: StyleChain,
) -> SourceResult<()> {
@@ -313,7 +323,7 @@ impl<'a> FlowLayouter<'a> {
if self.regions.is_full() {
// Skip directly if region is already full.
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
// How to align the block.
@@ -328,7 +338,7 @@ impl<'a> FlowLayouter<'a> {
// Layout the block itself.
let sticky = BlockElem::sticky_in(styles);
- let fragment = block.layout(vt, styles, self.regions)?;
+ let fragment = block.layout(engine, styles, self.regions)?;
for (i, frame) in fragment.into_iter().enumerate() {
// Find footnotes in the frame.
@@ -337,14 +347,14 @@ impl<'a> FlowLayouter<'a> {
}
if i > 0 {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
let item = FlowItem::Frame { frame, align, sticky, movable: false };
- self.layout_item(vt, item)?;
+ self.layout_item(engine, item)?;
}
- self.try_handle_footnotes(vt, notes)?;
+ self.try_handle_footnotes(engine, notes)?;
self.root = is_root;
self.regions.root = false;
@@ -355,7 +365,11 @@ impl<'a> FlowLayouter<'a> {
/// Layout a finished frame.
#[tracing::instrument(name = "FlowLayouter::layout_item", skip_all)]
- fn layout_item(&mut self, vt: &mut Vt, mut item: FlowItem) -> SourceResult<()> {
+ fn layout_item(
+ &mut self,
+ engine: &mut Engine,
+ mut item: FlowItem,
+ ) -> SourceResult<()> {
match item {
FlowItem::Absolute(v, weak) => {
if weak
@@ -372,7 +386,7 @@ impl<'a> FlowLayouter<'a> {
FlowItem::Frame { ref frame, movable, .. } => {
let height = frame.height();
if !self.regions.size.y.fits(height) && !self.regions.in_last() {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
self.regions.size.y -= height;
@@ -380,12 +394,12 @@ impl<'a> FlowLayouter<'a> {
let mut notes = Vec::new();
find_footnotes(&mut notes, frame);
self.items.push(item);
- if !self.handle_footnotes(vt, &mut notes, true, false)? {
+ if !self.handle_footnotes(engine, &mut notes, true, false)? {
let item = self.items.pop();
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
self.items.extend(item);
self.regions.size.y -= height;
- self.handle_footnotes(vt, &mut notes, true, true)?;
+ self.handle_footnotes(engine, &mut notes, true, true)?;
}
return Ok(());
}
@@ -429,7 +443,7 @@ impl<'a> FlowLayouter<'a> {
if self.root {
let mut notes = vec![];
find_footnotes(&mut notes, frame);
- self.try_handle_footnotes(vt, notes)?;
+ self.try_handle_footnotes(engine, notes)?;
}
}
FlowItem::Footnote(_) => {}
@@ -440,7 +454,7 @@ impl<'a> FlowLayouter<'a> {
}
/// Finish the frame for one region.
- fn finish_region(&mut self, vt: &mut Vt) -> SourceResult<()> {
+ fn finish_region(&mut self, engine: &mut Engine) -> SourceResult<()> {
// Trim weak spacing.
while self
.items
@@ -567,23 +581,23 @@ impl<'a> FlowLayouter<'a> {
// Try to place floats.
for item in std::mem::take(&mut self.pending_floats) {
- self.layout_item(vt, item)?;
+ self.layout_item(engine, item)?;
}
Ok(())
}
/// Finish layouting and return the resulting fragment.
- fn finish(mut self, vt: &mut Vt) -> SourceResult<Fragment> {
+ fn finish(mut self, engine: &mut Engine) -> SourceResult<Fragment> {
if self.expand.y {
while !self.regions.backlog.is_empty() {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
}
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
while !self.items.is_empty() {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
Ok(Fragment::frames(self.finished))
@@ -593,12 +607,12 @@ impl<'a> FlowLayouter<'a> {
impl FlowLayouter<'_> {
fn try_handle_footnotes(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
mut notes: Vec<FootnoteElem>,
) -> SourceResult<()> {
- if self.root && !self.handle_footnotes(vt, &mut notes, false, false)? {
- self.finish_region(vt)?;
- self.handle_footnotes(vt, &mut notes, false, true)?;
+ if self.root && !self.handle_footnotes(engine, &mut notes, false, false)? {
+ self.finish_region(engine)?;
+ self.handle_footnotes(engine, &mut notes, false, true)?;
}
Ok(())
}
@@ -607,7 +621,7 @@ impl FlowLayouter<'_> {
#[tracing::instrument(skip_all)]
fn handle_footnotes(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
notes: &mut Vec<FootnoteElem>,
movable: bool,
force: bool,
@@ -624,14 +638,14 @@ impl FlowLayouter<'_> {
}
if !self.has_footnotes {
- self.layout_footnote_separator(vt)?;
+ self.layout_footnote_separator(engine)?;
}
self.regions.size.y -= self.footnote_config.gap;
- let checkpoint = vt.locator.clone();
+ let checkpoint = engine.locator.clone();
let frames = FootnoteEntry::new(notes[k].clone())
.pack()
- .layout(vt, self.styles, self.regions.with_root(false))?
+ .layout(engine, self.styles, self.regions.with_root(false))?
.into_frames();
// If the entries didn't fit, abort (to keep footnote and entry
@@ -649,8 +663,8 @@ impl FlowLayouter<'_> {
self.regions.size.y -= item.height();
}
- // Undo Vt modifications.
- *vt.locator = checkpoint;
+ // Undo locator modifications.
+ *engine.locator = checkpoint;
return Ok(false);
}
@@ -659,8 +673,8 @@ impl FlowLayouter<'_> {
for (i, frame) in frames.into_iter().enumerate() {
find_footnotes(notes, &frame);
if i > 0 {
- self.finish_region(vt)?;
- self.layout_footnote_separator(vt)?;
+ self.finish_region(engine)?;
+ self.layout_footnote_separator(engine)?;
self.regions.size.y -= self.footnote_config.gap;
}
self.regions.size.y -= frame.height();
@@ -682,12 +696,12 @@ impl FlowLayouter<'_> {
/// Layout and save the footnote separator, typically a line.
#[tracing::instrument(skip_all)]
- fn layout_footnote_separator(&mut self, vt: &mut Vt) -> SourceResult<()> {
+ fn layout_footnote_separator(&mut self, engine: &mut Engine) -> SourceResult<()> {
let expand = Axes::new(self.regions.expand.x, false);
let pod = Regions::one(self.regions.base(), expand);
let separator = &self.footnote_config.separator;
- let mut frame = separator.layout(vt, self.styles, pod)?.into_frame();
+ let mut frame = separator.layout(engine, self.styles, pod)?.into_frame();
frame.size_mut().y += self.footnote_config.clearance;
frame.translate(Point::with_y(self.footnote_config.clearance));
diff --git a/crates/typst/src/layout/grid.rs b/crates/typst/src/layout/grid.rs
index cc7d1d25..606aa4a7 100644
--- a/crates/typst/src/layout/grid.rs
+++ b/crates/typst/src/layout/grid.rs
@@ -3,12 +3,13 @@ use std::num::NonZeroUsize;
use smallvec::{smallvec, SmallVec};
use crate::diag::{bail, SourceResult, StrResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Array, Content, NativeElement, Resolve, StyleChain, Value,
};
use crate::layout::{
Abs, Axes, Dir, Fr, Fragment, Frame, Layout, Length, Point, Regions, Rel, Size,
- Sizing, Vt,
+ Sizing,
};
use crate::syntax::Span;
use crate::text::TextElem;
@@ -128,7 +129,7 @@ impl Layout for GridElem {
#[tracing::instrument(name = "GridElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -148,7 +149,7 @@ impl Layout for GridElem {
);
// Measure the columns and layout the grid row-by-row.
- Ok(layouter.layout(vt)?.fragment)
+ Ok(layouter.layout(engine)?.fragment)
}
}
@@ -311,24 +312,24 @@ impl<'a> GridLayouter<'a> {
}
/// Determines the columns sizes and then layouts the grid row-by-row.
- pub fn layout(mut self, vt: &mut Vt) -> SourceResult<GridLayout> {
- self.measure_columns(vt)?;
+ pub fn layout(mut self, engine: &mut Engine) -> SourceResult<GridLayout> {
+ self.measure_columns(engine)?;
for y in 0..self.rows.len() {
// Skip to next region if current one is full, but only for content
// rows, not for gutter rows.
if self.regions.is_full() && (!self.has_gutter || y % 2 == 0) {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
match self.rows[y] {
- Sizing::Auto => self.layout_auto_row(vt, y)?,
- Sizing::Rel(v) => self.layout_relative_row(vt, v, y)?,
+ Sizing::Auto => self.layout_auto_row(engine, y)?,
+ Sizing::Rel(v) => self.layout_relative_row(engine, v, y)?,
Sizing::Fr(v) => self.lrows.push(Row::Fr(v, y)),
}
}
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
Ok(GridLayout {
fragment: Fragment::frames(self.finished),
@@ -339,7 +340,7 @@ impl<'a> GridLayouter<'a> {
/// Determine all column sizes.
#[tracing::instrument(name = "GridLayouter::measure_columns", skip_all)]
- fn measure_columns(&mut self, vt: &mut Vt) -> SourceResult<()> {
+ fn measure_columns(&mut self, engine: &mut Engine) -> SourceResult<()> {
// Sum of sizes of resolved relative tracks.
let mut rel = Abs::zero();
@@ -365,7 +366,7 @@ impl<'a> GridLayouter<'a> {
let available = self.regions.size.x - rel;
if available >= Abs::zero() {
// Determine size of auto columns.
- let (auto, count) = self.measure_auto_columns(vt, available)?;
+ let (auto, count) = self.measure_auto_columns(engine, available)?;
// If there is remaining space, distribute it to fractional columns,
// otherwise shrink auto columns.
@@ -386,7 +387,7 @@ impl<'a> GridLayouter<'a> {
/// Measure the size that is available to auto columns.
fn measure_auto_columns(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
available: Abs,
) -> SourceResult<(Abs, usize)> {
let mut auto = Abs::zero();
@@ -413,7 +414,7 @@ impl<'a> GridLayouter<'a> {
let size = Size::new(available, height);
let pod = Regions::one(size, Axes::splat(false));
- let frame = cell.measure(vt, self.styles, pod)?.into_frame();
+ let frame = cell.measure(engine, self.styles, pod)?.into_frame();
resolved.set_max(frame.width());
}
}
@@ -474,14 +475,14 @@ impl<'a> GridLayouter<'a> {
/// Layout a row with automatic height. Such a row may break across multiple
/// regions.
- fn layout_auto_row(&mut self, vt: &mut Vt, y: usize) -> SourceResult<()> {
+ fn layout_auto_row(&mut self, engine: &mut Engine, y: usize) -> SourceResult<()> {
// Determine the size for each region of the row. If the first region
// ends up empty for some column, skip the region and remeasure.
- let mut resolved = match self.measure_auto_row(vt, y, true)? {
+ let mut resolved = match self.measure_auto_row(engine, y, true)? {
Some(resolved) => resolved,
None => {
- self.finish_region(vt)?;
- self.measure_auto_row(vt, y, false)?.unwrap()
+ self.finish_region(engine)?;
+ self.measure_auto_row(engine, y, false)?.unwrap()
}
};
@@ -492,7 +493,7 @@ impl<'a> GridLayouter<'a> {
// Layout into a single region.
if let &[first] = resolved.as_slice() {
- let frame = self.layout_single_row(vt, first, y)?;
+ let frame = self.layout_single_row(engine, first, y)?;
self.push_row(frame, y);
return Ok(());
}
@@ -510,12 +511,12 @@ impl<'a> GridLayouter<'a> {
}
// Layout into multiple regions.
- let fragment = self.layout_multi_row(vt, &resolved, y)?;
+ let fragment = self.layout_multi_row(engine, &resolved, y)?;
let len = fragment.len();
for (i, frame) in fragment.into_iter().enumerate() {
self.push_row(frame, y);
if i + 1 < len {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
}
}
@@ -526,7 +527,7 @@ impl<'a> GridLayouter<'a> {
/// if `can_skip` is false.
fn measure_auto_row(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
y: usize,
can_skip: bool,
) -> SourceResult<Option<Vec<Abs>>> {
@@ -537,7 +538,7 @@ impl<'a> GridLayouter<'a> {
let mut pod = self.regions;
pod.size.x = rcol;
- let frames = cell.measure(vt, self.styles, pod)?.into_frames();
+ let frames = cell.measure(engine, self.styles, pod)?.into_frames();
// Skip the first region if one cell in it is empty. Then,
// remeasure.
@@ -568,17 +569,17 @@ impl<'a> GridLayouter<'a> {
/// multiple regions, but it may force a region break.
fn layout_relative_row(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
v: Rel<Length>,
y: usize,
) -> SourceResult<()> {
let resolved = v.resolve(self.styles).relative_to(self.regions.base().y);
- let frame = self.layout_single_row(vt, resolved, y)?;
+ let frame = self.layout_single_row(engine, resolved, y)?;
// Skip to fitting region.
let height = frame.height();
while !self.regions.size.y.fits(height) && !self.regions.in_last() {
- self.finish_region(vt)?;
+ self.finish_region(engine)?;
// Don't skip multiple regions for gutter and don't push a row.
if self.has_gutter && y % 2 == 1 {
@@ -594,7 +595,7 @@ impl<'a> GridLayouter<'a> {
/// Layout a row with fixed height and return its frame.
fn layout_single_row(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
height: Abs,
y: usize,
) -> SourceResult<Frame> {
@@ -612,7 +613,7 @@ impl<'a> GridLayouter<'a> {
if self.rows[y] == Sizing::Auto {
pod.full = self.regions.full;
}
- let frame = cell.layout(vt, self.styles, pod)?.into_frame();
+ let frame = cell.layout(engine, self.styles, pod)?.into_frame();
output.push_frame(pos, frame);
}
@@ -625,7 +626,7 @@ impl<'a> GridLayouter<'a> {
/// Layout a row spanning multiple regions.
fn layout_multi_row(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
heights: &[Abs],
y: usize,
) -> SourceResult<Fragment> {
@@ -648,7 +649,7 @@ impl<'a> GridLayouter<'a> {
pod.size.x = rcol;
// Push the layouted frames into the individual output frames.
- let fragment = cell.layout(vt, self.styles, pod)?;
+ let fragment = cell.layout(engine, self.styles, pod)?;
for (output, frame) in outputs.iter_mut().zip(fragment) {
output.push_frame(pos, frame);
}
@@ -667,7 +668,7 @@ impl<'a> GridLayouter<'a> {
}
/// Finish rows for one region.
- fn finish_region(&mut self, vt: &mut Vt) -> SourceResult<()> {
+ fn finish_region(&mut self, engine: &mut Engine) -> SourceResult<()> {
// Determine the height of existing rows in the region.
let mut used = Abs::zero();
let mut fr = Fr::zero();
@@ -697,7 +698,7 @@ impl<'a> GridLayouter<'a> {
Row::Fr(v, y) => {
let remaining = self.regions.full - used;
let height = v.share(fr, remaining);
- (self.layout_single_row(vt, height, y)?, y)
+ (self.layout_single_row(engine, height, y)?, y)
}
};
diff --git a/crates/typst/src/layout/hide.rs b/crates/typst/src/layout/hide.rs
index b72f2ad2..50ce8467 100644
--- a/crates/typst/src/layout/hide.rs
+++ b/crates/typst/src/layout/hide.rs
@@ -1,9 +1,9 @@
use smallvec::smallvec;
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, Show, StyleChain};
use crate::introspection::{Meta, MetaElem};
-use crate::layout::Vt;
/// Hides content without affecting layout.
///
@@ -26,7 +26,7 @@ pub struct HideElem {
impl Show for HideElem {
#[tracing::instrument(name = "HideElem::show", skip(self))]
- fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone().styled(MetaElem::set_data(smallvec![Meta::Hide])))
}
}
diff --git a/crates/typst/src/layout/inline/mod.rs b/crates/typst/src/layout/inline/mod.rs
index 44b2e113..ba88f74e 100644
--- a/crates/typst/src/layout/inline/mod.rs
+++ b/crates/typst/src/layout/inline/mod.rs
@@ -11,12 +11,13 @@ use self::shaping::{
END_PUNCT_PAT,
};
use crate::diag::{bail, SourceResult};
+use crate::engine::{Engine, Route};
use crate::eval::Tracer;
use crate::foundations::{Content, Resolve, Smart, StyleChain};
use crate::introspection::{Introspector, Locator, MetaElem};
use crate::layout::{
Abs, AlignElem, Axes, BoxElem, Dir, Em, FixedAlign, Fr, Fragment, Frame, HElem,
- Layout, Point, Regions, Size, Sizing, Spacing, Vt,
+ Layout, Point, Regions, Size, Sizing, Spacing,
};
use crate::math::EquationElem;
use crate::model::{Linebreaks, ParElem};
@@ -30,7 +31,7 @@ use crate::World;
/// Layout's content inline.
pub(crate) fn layout_inline(
children: &[Prehashed<Content>],
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
consecutive: bool,
region: Size,
@@ -42,6 +43,7 @@ pub(crate) fn layout_inline(
children: &[Prehashed<Content>],
world: Tracked<dyn World + '_>,
introspector: Tracked<Introspector>,
+ route: Tracked<Route>,
locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>,
styles: StyleChain,
@@ -50,7 +52,13 @@ pub(crate) fn layout_inline(
expand: bool,
) -> SourceResult<Fragment> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, introspector, locator: &mut locator, tracer };
+ let mut engine = Engine {
+ world,
+ introspector,
+ route: Route::extend(route),
+ locator: &mut locator,
+ tracer,
+ };
// Collect all text into one string for BiDi analysis.
let (text, segments, spans) = collect(children, &styles, consecutive)?;
@@ -58,28 +66,29 @@ pub(crate) fn layout_inline(
// Perform BiDi analysis and then prepare paragraph layout by building a
// representation on which we can do line breaking without layouting
// each and every line from scratch.
- let p = prepare(&mut vt, children, &text, segments, spans, styles, region)?;
+ let p = prepare(&mut engine, children, &text, segments, spans, styles, region)?;
// Break the paragraph into lines.
- let lines = linebreak(&vt, &p, region.x - p.hang);
+ let lines = linebreak(&engine, &p, region.x - p.hang);
// Stack the lines into one frame per region.
- finalize(&mut vt, &p, &lines, region, expand)
+ finalize(&mut engine, &p, &lines, region, expand)
}
let fragment = cached(
children,
- vt.world,
- vt.introspector,
- vt.locator.track(),
- TrackedMut::reborrow_mut(&mut vt.tracer),
+ engine.world,
+ engine.introspector,
+ engine.route.track(),
+ engine.locator.track(),
+ TrackedMut::reborrow_mut(&mut engine.tracer),
styles,
consecutive,
region,
expand,
)?;
- vt.locator.visit_frames(&fragment);
+ engine.locator.visit_frames(&fragment);
Ok(fragment)
}
@@ -520,7 +529,7 @@ fn collect<'a>(
/// Prepare paragraph layout by shaping the whole paragraph and layouting all
/// contained inline-level content.
fn prepare<'a>(
- vt: &mut Vt,
+ engine: &mut Engine,
children: &'a [Prehashed<Content>],
text: &'a str,
segments: Vec<(Segment<'a>, StyleChain<'a>)>,
@@ -546,7 +555,7 @@ fn prepare<'a>(
let end = cursor + segment.len();
match segment {
Segment::Text(_) => {
- shape_range(&mut items, vt, &bidi, cursor..end, &spans, styles);
+ shape_range(&mut items, engine, &bidi, cursor..end, &spans, styles);
}
Segment::Spacing(spacing) => match spacing {
Spacing::Rel(v) => {
@@ -559,7 +568,7 @@ fn prepare<'a>(
},
Segment::Equation(equation) => {
let pod = Regions::one(region, Axes::splat(false));
- let mut frame = equation.layout(vt, styles, pod)?.into_frame();
+ let mut frame = equation.layout(engine, styles, pod)?.into_frame();
frame.translate(Point::with_y(TextElem::baseline_in(styles)));
items.push(Item::Frame(frame));
}
@@ -568,7 +577,7 @@ fn prepare<'a>(
items.push(Item::Fractional(v, Some((elem, styles))));
} else {
let pod = Regions::one(region, Axes::splat(false));
- let mut frame = elem.layout(vt, styles, pod)?.into_frame();
+ let mut frame = elem.layout(engine, styles, pod)?.into_frame();
frame.translate(Point::with_y(TextElem::baseline_in(styles)));
items.push(Item::Frame(frame));
}
@@ -655,7 +664,7 @@ fn add_cjk_latin_spacing(items: &mut [Item]) {
/// items for them.
fn shape_range<'a>(
items: &mut Vec<Item<'a>>,
- vt: &Vt,
+ engine: &Engine,
bidi: &BidiInfo<'a>,
range: Range,
spans: &SpanMapper,
@@ -666,8 +675,16 @@ fn shape_range<'a>(
let region = TextElem::region_in(styles);
let mut process = |range: Range, level: BidiLevel| {
let dir = if level.is_ltr() { Dir::LTR } else { Dir::RTL };
- let shaped =
- shape(vt, range.start, &bidi.text[range], spans, styles, dir, lang, region);
+ let shaped = shape(
+ engine,
+ range.start,
+ &bidi.text[range],
+ spans,
+ styles,
+ dir,
+ lang,
+ region,
+ );
items.push(Item::Text(shaped));
};
@@ -732,7 +749,7 @@ fn shared_get<T: PartialEq>(
}
/// Find suitable linebreaks.
-fn linebreak<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
+fn linebreak<'a>(engine: &Engine, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
let linebreaks = p.linebreaks.unwrap_or_else(|| {
if p.justify {
Linebreaks::Optimized
@@ -742,22 +759,26 @@ fn linebreak<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
});
match linebreaks {
- Linebreaks::Simple => linebreak_simple(vt, p, width),
- Linebreaks::Optimized => linebreak_optimized(vt, p, width),
+ Linebreaks::Simple => linebreak_simple(engine, p, width),
+ Linebreaks::Optimized => linebreak_optimized(engine, p, width),
}
}
/// Perform line breaking in simple first-fit style. This means that we build
/// lines greedily, always taking the longest possible line. This may lead to
/// very unbalanced line, but is fast and simple.
-fn linebreak_simple<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
+fn linebreak_simple<'a>(
+ engine: &Engine,
+ p: &'a Preparation<'a>,
+ width: Abs,
+) -> Vec<Line<'a>> {
let mut lines = Vec::with_capacity(16);
let mut start = 0;
let mut last = None;
breakpoints(p, |end, breakpoint| {
// Compute the line and its size.
- let mut attempt = line(vt, p, start..end, breakpoint);
+ let mut attempt = line(engine, p, start..end, breakpoint);
// If the line doesn't fit anymore, we push the last fitting attempt
// into the stack and rebuild the line from the attempt's end. The
@@ -766,7 +787,7 @@ fn linebreak_simple<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line
if let Some((last_attempt, last_end)) = last.take() {
lines.push(last_attempt);
start = last_end;
- attempt = line(vt, p, start..end, breakpoint);
+ attempt = line(engine, p, start..end, breakpoint);
}
}
@@ -806,7 +827,11 @@ fn linebreak_simple<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line
/// computed and stored in dynamic programming table) is minimal. The final
/// result is simply the layout determined for the last breakpoint at the end of
/// text.
-fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<Line<'a>> {
+fn linebreak_optimized<'a>(
+ engine: &Engine,
+ p: &'a Preparation<'a>,
+ width: Abs,
+) -> Vec<Line<'a>> {
/// The cost of a line or paragraph layout.
type Cost = f64;
@@ -829,7 +854,7 @@ fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<L
let mut table = vec![Entry {
pred: 0,
total: 0.0,
- line: line(vt, p, 0..0, Breakpoint::Mandatory),
+ line: line(engine, p, 0..0, Breakpoint::Mandatory),
}];
let em = p.size;
@@ -844,7 +869,7 @@ fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<L
// Layout the line.
let start = pred.line.end;
- let attempt = line(vt, p, start..end, breakpoint);
+ let attempt = line(engine, p, start..end, breakpoint);
// Determine how much the line's spaces would need to be stretched
// to make it the desired width.
@@ -953,7 +978,7 @@ fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<L
/// Create a line which spans the given range.
fn line<'a>(
- vt: &Vt,
+ engine: &Engine,
p: &'a Preparation,
mut range: Range,
breakpoint: Breakpoint,
@@ -1016,9 +1041,9 @@ fn line<'a>(
// are no other items in the line.
if hyphen || start + shaped.text.len() > range.end || maybe_adjust_last_glyph {
if hyphen || start < range.end || before.is_empty() {
- let mut reshaped = shaped.reshape(vt, &p.spans, start..range.end);
+ let mut reshaped = shaped.reshape(engine, &p.spans, start..range.end);
if hyphen || shy {
- reshaped.push_hyphen(vt, p.fallback);
+ reshaped.push_hyphen(engine, p.fallback);
}
if let Some(last_glyph) = reshaped.glyphs.last() {
@@ -1069,7 +1094,7 @@ fn line<'a>(
if range.start + shaped.text.len() > end || maybe_adjust_first_glyph {
// If the range is empty, we don't want to push an empty text item.
if range.start < end {
- let reshaped = shaped.reshape(vt, &p.spans, range.start..end);
+ let reshaped = shaped.reshape(engine, &p.spans, range.start..end);
width += reshaped.width;
first = Some(Item::Text(reshaped));
}
@@ -1129,7 +1154,7 @@ fn line<'a>(
/// Combine layouted lines into one frame per region.
fn finalize(
- vt: &mut Vt,
+ engine: &mut Engine,
p: &Preparation,
lines: &[Line],
region: Size,
@@ -1150,7 +1175,7 @@ fn finalize(
// Stack the lines into one frame per region.
let mut frames: Vec<Frame> = lines
.iter()
- .map(|line| commit(vt, p, line, width, region.y))
+ .map(|line| commit(engine, p, line, width, region.y))
.collect::<SourceResult<_>>()?;
// Prevent orphans.
@@ -1181,7 +1206,7 @@ fn merge(first: &mut Frame, second: Frame, leading: Abs) {
/// Commit to a line and build its frame.
fn commit(
- vt: &mut Vt,
+ engine: &mut Engine,
p: &Preparation,
line: &Line,
width: Abs,
@@ -1276,7 +1301,7 @@ fn commit(
if let Some((elem, styles)) = elem {
let region = Size::new(amount, full);
let pod = Regions::one(region, Axes::new(true, false));
- let mut frame = elem.layout(vt, *styles, pod)?.into_frame();
+ let mut frame = elem.layout(engine, *styles, pod)?.into_frame();
frame.translate(Point::with_y(TextElem::baseline_in(*styles)));
push(&mut offset, frame);
} else {
@@ -1284,7 +1309,8 @@ fn commit(
}
}
Item::Text(shaped) => {
- let frame = shaped.build(vt, justification_ratio, extra_justification);
+ let frame =
+ shaped.build(engine, justification_ratio, extra_justification);
push(&mut offset, frame);
}
Item::Frame(frame) | Item::Meta(frame) => {
diff --git a/crates/typst/src/layout/inline/shaping.rs b/crates/typst/src/layout/inline/shaping.rs
index 69e70967..08a617dc 100644
--- a/crates/typst/src/layout/inline/shaping.rs
+++ b/crates/typst/src/layout/inline/shaping.rs
@@ -9,8 +9,9 @@ use rustybuzz::{Tag, UnicodeBuffer};
use unicode_script::{Script, UnicodeScript};
use super::SpanMapper;
+use crate::engine::Engine;
use crate::foundations::StyleChain;
-use crate::layout::{Abs, Dir, Em, Frame, FrameItem, Point, Size, Vt};
+use crate::layout::{Abs, Dir, Em, Frame, FrameItem, Point, Size};
use crate::syntax::Span;
use crate::text::{
decorate, families, features, variant, Font, FontVariant, Glyph, Lang, Region,
@@ -213,11 +214,11 @@ impl<'a> ShapedText<'a> {
/// [justifiable glyph](ShapedGlyph::is_justifiable) will get.
pub fn build(
&self,
- vt: &Vt,
+ engine: &Engine,
justification_ratio: f64,
extra_justification: Abs,
) -> Frame {
- let (top, bottom) = self.measure(vt);
+ let (top, bottom) = self.measure(engine);
let size = Size::new(self.width, top + bottom);
let mut offset = Abs::zero();
@@ -307,7 +308,7 @@ impl<'a> ShapedText<'a> {
}
/// Measure the top and bottom extent of this text.
- fn measure(&self, vt: &Vt) -> (Abs, Abs) {
+ fn measure(&self, engine: &Engine) -> (Abs, Abs) {
let mut top = Abs::zero();
let mut bottom = Abs::zero();
@@ -323,7 +324,7 @@ impl<'a> ShapedText<'a> {
if self.glyphs.is_empty() {
// When there are no glyphs, we just use the vertical metrics of the
// first available font.
- let world = vt.world;
+ let world = engine.world;
for family in families(self.styles) {
if let Some(font) = world
.book()
@@ -387,7 +388,7 @@ impl<'a> ShapedText<'a> {
/// The text `range` is relative to the whole paragraph.
pub fn reshape(
&'a self,
- vt: &Vt,
+ engine: &Engine,
spans: &SpanMapper,
text_range: Range<usize>,
) -> ShapedText<'a> {
@@ -409,7 +410,7 @@ impl<'a> ShapedText<'a> {
}
} else {
shape(
- vt,
+ engine,
text_range.start,
text,
spans,
@@ -422,8 +423,8 @@ impl<'a> ShapedText<'a> {
}
/// Push a hyphen to end of the text.
- pub fn push_hyphen(&mut self, vt: &Vt, fallback: bool) {
- let world = vt.world;
+ pub fn push_hyphen(&mut self, engine: &Engine, fallback: bool) {
+ let world = engine.world;
let book = world.book();
let fallback_func = if fallback {
Some(|| book.select_fallback(None, self.variant, "-"))
@@ -553,7 +554,7 @@ impl Debug for ShapedText<'_> {
/// Holds shaping results and metadata common to all shaped segments.
struct ShapingContext<'a, 'v> {
- vt: &'a Vt<'v>,
+ engine: &'a Engine<'v>,
spans: &'a SpanMapper,
glyphs: Vec<ShapedGlyph>,
used: Vec<Font>,
@@ -568,7 +569,7 @@ struct ShapingContext<'a, 'v> {
/// Shape text into [`ShapedText`].
#[allow(clippy::too_many_arguments)]
pub(super) fn shape<'a>(
- vt: &Vt,
+ engine: &Engine,
base: usize,
text: &'a str,
spans: &SpanMapper,
@@ -579,7 +580,7 @@ pub(super) fn shape<'a>(
) -> ShapedText<'a> {
let size = TextElem::size_in(styles);
let mut ctx = ShapingContext {
- vt,
+ engine,
spans,
size,
glyphs: vec![],
@@ -630,7 +631,7 @@ fn shape_segment<'a>(
}
// Find the next available family.
- let world = ctx.vt.world;
+ let world = ctx.engine.world;
let book = world.book();
let mut selection = families.find_map(|family| {
book.select(family, ctx.variant)
diff --git a/crates/typst/src/layout/layout.rs b/crates/typst/src/layout/layout.rs
index e2c0fa2b..45b7c54a 100644
--- a/crates/typst/src/layout/layout.rs
+++ b/crates/typst/src/layout/layout.rs
@@ -1,6 +1,7 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{dict, elem, func, Content, Func, NativeElement, StyleChain};
-use crate::layout::{Fragment, Layout, Regions, Size, Vt};
+use crate::layout::{Fragment, Layout, Regions, Size};
/// Provides access to the current outer container's (or page's, if none) size
/// (width and height).
@@ -68,7 +69,7 @@ impl Layout for LayoutElem {
#[tracing::instrument(name = "LayoutElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -77,8 +78,8 @@ impl Layout for LayoutElem {
let Size { x, y } = regions.base();
let result = self
.func()
- .call_vt(vt, [dict! { "width" => x, "height" => y }])?
+ .call(engine, [dict! { "width" => x, "height" => y }])?
.display();
- result.layout(vt, styles, regions)
+ result.layout(engine, styles, regions)
}
}
diff --git a/crates/typst/src/layout/measure.rs b/crates/typst/src/layout/measure.rs
index 2b82c58b..1aff7ad4 100644
--- a/crates/typst/src/layout/measure.rs
+++ b/crates/typst/src/layout/measure.rs
@@ -1,5 +1,5 @@
use crate::diag::SourceResult;
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{dict, func, Content, Dict, StyleChain, Styles};
use crate::layout::{Abs, Axes, Layout, Regions, Size};
@@ -41,8 +41,8 @@ use crate::layout::{Abs, Axes, Layout, Regions, Size};
/// `height`, both of type [`length`]($length).
#[func]
pub fn measure(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// The content whose size to measure.
content: Content,
/// The styles with which to layout the content.
@@ -50,7 +50,7 @@ pub fn measure(
) -> SourceResult<Dict> {
let pod = Regions::one(Axes::splat(Abs::inf()), Axes::splat(false));
let styles = StyleChain::new(&styles);
- let frame = content.measure(&mut vm.vt, styles, pod)?.into_frame();
+ let frame = content.measure(engine, styles, pod)?.into_frame();
let Size { x, y } = frame.size();
Ok(dict! { "width" => x, "height" => y })
}
diff --git a/crates/typst/src/layout/mod.rs b/crates/typst/src/layout/mod.rs
index f291cfe9..1e1bcf9b 100644
--- a/crates/typst/src/layout/mod.rs
+++ b/crates/typst/src/layout/mod.rs
@@ -34,7 +34,6 @@ mod size;
mod spacing;
mod stack;
mod transform;
-mod vt;
pub use self::abs::*;
pub use self::align::*;
@@ -67,13 +66,13 @@ pub use self::size::*;
pub use self::spacing::*;
pub use self::stack::*;
pub use self::transform::*;
-pub use self::vt::*;
pub(crate) use self::inline::*;
use comemo::{Tracked, TrackedMut};
-use crate::diag::SourceResult;
+use crate::diag::{bail, error, SourceResult};
+use crate::engine::{Engine, Route};
use crate::eval::Tracer;
use crate::foundations::{category, Category, Content, Scope, StyleChain};
use crate::introspection::{Introspector, Locator};
@@ -122,7 +121,11 @@ pub fn define(global: &mut Scope) {
/// Root-level layout.
pub trait LayoutRoot {
/// Layout into one frame per page.
- fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document>;
+ fn layout_root(
+ &self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<Document>;
}
/// Layout into regions.
@@ -130,7 +133,7 @@ pub trait Layout {
/// Layout into one frame per region.
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment>;
@@ -142,50 +145,64 @@ pub trait Layout {
#[tracing::instrument(name = "Layout::measure", skip_all)]
fn measure(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
- let mut locator = Locator::chained(vt.locator.track());
- let mut vt = Vt {
- world: vt.world,
- introspector: vt.introspector,
+ let mut locator = Locator::chained(engine.locator.track());
+ let mut engine = Engine {
+ world: engine.world,
+ route: engine.route.clone(),
+ introspector: engine.introspector,
locator: &mut locator,
- tracer: TrackedMut::reborrow_mut(&mut vt.tracer),
+ tracer: TrackedMut::reborrow_mut(&mut engine.tracer),
};
- self.layout(&mut vt, styles, regions)
+ self.layout(&mut engine, styles, regions)
}
}
impl LayoutRoot for Content {
#[tracing::instrument(name = "Content::layout_root", skip_all)]
- fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document> {
+ fn layout_root(
+ &self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<Document> {
#[comemo::memoize]
fn cached(
content: &Content,
world: Tracked<dyn World + '_>,
introspector: Tracked<Introspector>,
+ route: Tracked<Route>,
locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>,
styles: StyleChain,
) -> SourceResult<Document> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, introspector, locator: &mut locator, tracer };
+ let mut engine = Engine {
+ world,
+ introspector,
+ route: Route::extend(route),
+ locator: &mut locator,
+ tracer,
+ };
let scratch = Scratch::default();
- let (realized, styles) = realize_root(&mut vt, &scratch, content, styles)?;
+ let (realized, styles) =
+ realize_root(&mut engine, &scratch, content, styles)?;
realized
.with::<dyn LayoutRoot>()
.unwrap()
- .layout_root(&mut vt, styles)
+ .layout_root(&mut engine, styles)
}
tracing::info!("Starting layout");
cached(
self,
- vt.world,
- vt.introspector,
- vt.locator.track(),
- TrackedMut::reborrow_mut(&mut vt.tracer),
+ engine.world,
+ engine.introspector,
+ engine.route.track(),
+ engine.locator.track(),
+ TrackedMut::reborrow_mut(&mut engine.tracer),
styles,
)
}
@@ -195,7 +212,7 @@ impl Layout for Content {
#[tracing::instrument(name = "Content::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -205,34 +222,49 @@ impl Layout for Content {
content: &Content,
world: Tracked<dyn World + '_>,
introspector: Tracked<Introspector>,
+ route: Tracked<Route>,
locator: Tracked<Locator>,
tracer: TrackedMut<Tracer>,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let mut locator = Locator::chained(locator);
- let mut vt = Vt { world, introspector, locator: &mut locator, tracer };
+ let mut engine = Engine {
+ world,
+ introspector,
+ route: Route::extend(route),
+ locator: &mut locator,
+ tracer,
+ };
+
+ if engine.route.exceeding() {
+ bail!(error!(content.span(), "maximum layout depth exceeded")
+ .with_hint("try to reduce the amount of nesting in your layout"));
+ }
+
let scratch = Scratch::default();
- let (realized, styles) = realize_block(&mut vt, &scratch, content, styles)?;
+ let (realized, styles) =
+ realize_block(&mut engine, &scratch, content, styles)?;
realized
.with::<dyn Layout>()
.unwrap()
- .layout(&mut vt, styles, regions)
+ .layout(&mut engine, styles, regions)
}
tracing::info!("Layouting `Content`");
let fragment = cached(
self,
- vt.world,
- vt.introspector,
- vt.locator.track(),
- TrackedMut::reborrow_mut(&mut vt.tracer),
+ engine.world,
+ engine.introspector,
+ engine.route.track(),
+ engine.locator.track(),
+ TrackedMut::reborrow_mut(&mut engine.tracer),
styles,
regions,
)?;
- vt.locator.visit_frames(&fragment);
+ engine.locator.visit_frames(&fragment);
Ok(fragment)
}
}
diff --git a/crates/typst/src/layout/pad.rs b/crates/typst/src/layout/pad.rs
index f5762409..35dfd0b4 100644
--- a/crates/typst/src/layout/pad.rs
+++ b/crates/typst/src/layout/pad.rs
@@ -1,8 +1,7 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, Resolve, StyleChain};
-use crate::layout::{
- Abs, Fragment, Layout, Length, Point, Regions, Rel, Sides, Size, Vt,
-};
+use crate::layout::{Abs, Fragment, Layout, Length, Point, Regions, Rel, Sides, Size};
/// Adds spacing around content.
///
@@ -63,7 +62,7 @@ impl Layout for PadElem {
#[tracing::instrument(name = "PadElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -78,7 +77,7 @@ impl Layout for PadElem {
let mut backlog = vec![];
let padding = sides.resolve(styles);
let pod = regions.map(&mut backlog, |size| shrink(size, padding));
- let mut fragment = self.body().layout(vt, styles, pod)?;
+ let mut fragment = self.body().layout(engine, styles, pod)?;
for frame in &mut fragment {
// Apply the padding inversely such that the grown size padded
diff --git a/crates/typst/src/layout/page.rs b/crates/typst/src/layout/page.rs
index 411f9769..96e6d96a 100644
--- a/crates/typst/src/layout/page.rs
+++ b/crates/typst/src/layout/page.rs
@@ -4,6 +4,7 @@ use std::ptr;
use std::str::FromStr;
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, AutoValue, Cast, Content, Dict, Fold, Func, NativeElement, Resolve,
Smart, StyleChain, Value,
@@ -11,7 +12,7 @@ use crate::foundations::{
use crate::introspection::{Counter, CounterKey, ManualPageCounter, Meta};
use crate::layout::{
Abs, Align, AlignElem, Axes, ColumnsElem, Dir, Fragment, Frame, HAlign, Layout,
- Length, Point, Ratio, Regions, Rel, Sides, Size, VAlign, Vt,
+ Length, Point, Ratio, Regions, Rel, Sides, Size, VAlign,
};
use crate::model::Numbering;
@@ -342,7 +343,7 @@ impl PageElem {
#[tracing::instrument(skip_all)]
pub fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
page_counter: &mut ManualPageCounter,
extend_to: Option<Parity>,
@@ -393,7 +394,7 @@ impl PageElem {
regions.root = true;
// Layout the child.
- let mut frames = child.layout(vt, styles, regions)?.into_frames();
+ let mut frames = child.layout(engine, styles, regions)?.into_frames();
// Align the child to the pagebreak's parity.
// Check for page count after adding the pending frames
@@ -496,7 +497,7 @@ impl PageElem {
let sub = content
.clone()
.styled(AlignElem::set_alignment(align))
- .layout(vt, styles, pod)?
+ .layout(engine, styles, pod)?
.into_frame();
if ptr::eq(marginal, &header) || ptr::eq(marginal, &background) {
@@ -510,7 +511,7 @@ impl PageElem {
frame.fill(fill.clone());
}
- page_counter.visit(vt, frame)?;
+ page_counter.visit(engine, frame)?;
// Add a PDF page label if there is a numbering.
if let Some(num) = numbering {
@@ -675,10 +676,14 @@ pub enum Marginal {
impl Marginal {
/// Resolve the marginal based on the page number.
- pub fn resolve(&self, vt: &mut Vt, page: usize) -> SourceResult<Cow<'_, Content>> {
+ pub fn resolve(
+ &self,
+ engine: &mut Engine,
+ page: usize,
+ ) -> SourceResult<Cow<'_, Content>> {
Ok(match self {
Self::Content(content) => Cow::Borrowed(content),
- Self::Func(func) => Cow::Owned(func.call_vt(vt, [page])?.display()),
+ Self::Func(func) => Cow::Owned(func.call(engine, [page])?.display()),
})
}
}
diff --git a/crates/typst/src/layout/place.rs b/crates/typst/src/layout/place.rs
index 537b47ed..3c0012aa 100644
--- a/crates/typst/src/layout/place.rs
+++ b/crates/typst/src/layout/place.rs
@@ -1,10 +1,9 @@
use crate::diag::{bail, At, Hint, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
elem, Behave, Behaviour, Content, NativeElement, Smart, StyleChain,
};
-use crate::layout::{
- Align, Axes, Em, Fragment, Layout, Length, Regions, Rel, VAlign, Vt,
-};
+use crate::layout::{Align, Axes, Em, Fragment, Layout, Length, Regions, Rel, VAlign};
/// Places content at an absolute position.
///
@@ -91,7 +90,7 @@ impl Layout for PlaceElem {
#[tracing::instrument(name = "PlaceElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -118,7 +117,7 @@ impl Layout for PlaceElem {
.aligned(alignment.unwrap_or_else(|| Align::CENTER));
let pod = Regions::one(base, Axes::splat(false));
- let frame = child.layout(vt, styles, pod)?.into_frame();
+ let frame = child.layout(engine, styles, pod)?.into_frame();
Ok(Fragment::frame(frame))
}
}
diff --git a/crates/typst/src/layout/repeat.rs b/crates/typst/src/layout/repeat.rs
index 29e34e18..c733ea7d 100644
--- a/crates/typst/src/layout/repeat.rs
+++ b/crates/typst/src/layout/repeat.rs
@@ -1,7 +1,8 @@
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{elem, Content, NativeElement, Resolve, StyleChain};
use crate::layout::{
- Abs, AlignElem, Axes, Fragment, Frame, Layout, Point, Regions, Size, Vt,
+ Abs, AlignElem, Axes, Fragment, Frame, Layout, Point, Regions, Size,
};
use crate::util::Numeric;
@@ -37,12 +38,12 @@ impl Layout for RepeatElem {
#[tracing::instrument(name = "RepeatElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let pod = Regions::one(regions.size, Axes::new(false, false));
- let piece = self.body().layout(vt, styles, pod)?.into_frame();
+ let piece = self.body().layout(engine, styles, pod)?.into_frame();
let align = AlignElem::alignment_in(styles).resolve(styles);
let fill = regions.size.x;
diff --git a/crates/typst/src/layout/stack.rs b/crates/typst/src/layout/stack.rs
index e4dd029a..fe36cc63 100644
--- a/crates/typst/src/layout/stack.rs
+++ b/crates/typst/src/layout/stack.rs
@@ -1,10 +1,11 @@
use std::fmt::{self, Debug, Formatter};
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{cast, elem, Content, Resolve, StyleChain};
use crate::layout::{
Abs, AlignElem, Axes, Axis, Dir, FixedAlign, Fr, Fragment, Frame, Layout, Point,
- Regions, Size, Spacing, Vt,
+ Regions, Size, Spacing,
};
use crate::util::{Get, Numeric};
@@ -54,7 +55,7 @@ impl Layout for StackElem {
#[tracing::instrument(name = "StackElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -75,7 +76,7 @@ impl Layout for StackElem {
layouter.layout_spacing(kind);
}
- layouter.layout_block(vt, block, styles)?;
+ layouter.layout_block(engine, block, styles)?;
deferred = spacing;
}
}
@@ -199,7 +200,7 @@ impl<'a> StackLayouter<'a> {
#[tracing::instrument(name = "StackLayouter::layout_block", skip_all)]
fn layout_block(
&mut self,
- vt: &mut Vt,
+ engine: &mut Engine,
block: &Content,
styles: StyleChain,
) -> SourceResult<()> {
@@ -217,7 +218,7 @@ impl<'a> StackLayouter<'a> {
}
.resolve(styles);
- let fragment = block.layout(vt, styles, self.regions)?;
+ let fragment = block.layout(engine, styles, self.regions)?;
let len = fragment.len();
for (i, frame) in fragment.into_iter().enumerate() {
// Grow our size, shrink the region and save the frame for later.
diff --git a/crates/typst/src/layout/transform.rs b/crates/typst/src/layout/transform.rs
index 51cc5d54..bfc35825 100644
--- a/crates/typst/src/layout/transform.rs
+++ b/crates/typst/src/layout/transform.rs
@@ -1,8 +1,9 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, Resolve, StyleChain};
use crate::layout::{
Abs, Align, Angle, Axes, FixedAlign, Fragment, HAlign, Layout, Length, Ratio,
- Regions, Rel, VAlign, Vt,
+ Regions, Rel, VAlign,
};
/// Moves content without affecting layout.
@@ -40,12 +41,12 @@ impl Layout for MoveElem {
#[tracing::instrument(name = "MoveElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let pod = Regions::one(regions.base(), Axes::splat(false));
- let mut frame = self.body().layout(vt, styles, pod)?.into_frame();
+ let mut frame = self.body().layout(engine, styles, pod)?.into_frame();
let delta = Axes::new(self.dx(styles), self.dy(styles)).resolve(styles);
let delta = delta.zip_map(regions.base(), Rel::relative_to);
frame.translate(delta.to_point());
@@ -106,12 +107,12 @@ impl Layout for RotateElem {
#[tracing::instrument(name = "RotateElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let pod = Regions::one(regions.base(), Axes::splat(false));
- let mut frame = self.body().layout(vt, styles, pod)?.into_frame();
+ let mut frame = self.body().layout(engine, styles, pod)?.into_frame();
let Axes { x, y } = self
.origin(styles)
.resolve(styles)
@@ -171,12 +172,12 @@ impl Layout for ScaleElem {
#[tracing::instrument(name = "ScaleElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
let pod = Regions::one(regions.base(), Axes::splat(false));
- let mut frame = self.body().layout(vt, styles, pod)?.into_frame();
+ let mut frame = self.body().layout(engine, styles, pod)?.into_frame();
let Axes { x, y } = self
.origin(styles)
.resolve(styles)
diff --git a/crates/typst/src/layout/vt.rs b/crates/typst/src/layout/vt.rs
deleted file mode 100644
index 78b8c511..00000000
--- a/crates/typst/src/layout/vt.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-use comemo::{Tracked, TrackedMut};
-
-use crate::diag::SourceResult;
-use crate::eval::Tracer;
-use crate::introspection::{Introspector, Locator};
-use crate::World;
-
-/// A virtual typesetter.
-///
-/// Holds the state needed during compilation.
-pub struct Vt<'a> {
- /// The compilation environment.
- pub world: Tracked<'a, dyn World + 'a>,
- /// Provides access to information about the document.
- pub introspector: Tracked<'a, Introspector>,
- /// Provides stable identities to elements.
- pub locator: &'a mut Locator<'a>,
- /// 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) => {
- self.tracer.delay(errors);
- T::default()
- }
- }
- }
-}
diff --git a/crates/typst/src/lib.rs b/crates/typst/src/lib.rs
index 8d0001c8..52634d45 100644
--- a/crates/typst/src/lib.rs
+++ b/crates/typst/src/lib.rs
@@ -40,6 +40,7 @@ extern crate self as typst;
#[macro_use]
pub mod util;
pub mod diag;
+pub mod engine;
pub mod eval;
pub mod foundations;
pub mod introspection;
@@ -62,12 +63,13 @@ use comemo::{Prehashed, Track, Tracked, Validate};
use ecow::{EcoString, EcoVec};
use crate::diag::{warning, FileResult, SourceDiagnostic, SourceResult};
-use crate::eval::{Route, Tracer};
+use crate::engine::{Engine, Route};
+use crate::eval::Tracer;
use crate::foundations::{
Array, Bytes, Content, Datetime, Module, Scope, StyleChain, Styles,
};
use crate::introspection::{Introspector, Locator};
-use crate::layout::{Align, Dir, LayoutRoot, Vt};
+use crate::layout::{Align, Dir, LayoutRoot};
use crate::model::Document;
use crate::syntax::{FileId, PackageSpec, Source, Span};
use crate::text::{Font, FontBook};
@@ -122,15 +124,17 @@ fn typeset(
let constraint = <Introspector as Validate>::Constraint::new();
let mut locator = Locator::new();
- let mut vt = Vt {
+ let mut engine = Engine {
world,
+ route: Route::default(),
tracer: tracer.track_mut(),
locator: &mut locator,
introspector: introspector.track_with(&constraint),
};
// Layout!
- document = content.layout_root(&mut vt, styles)?;
+ document = content.layout_root(&mut engine, styles)?;
+
introspector = Introspector::new(&document.pages);
iter += 1;
diff --git a/crates/typst/src/loading/cbor.rs b/crates/typst/src/loading/cbor.rs
index a1189dbe..ddf559f3 100644
--- a/crates/typst/src/loading/cbor.rs
+++ b/crates/typst/src/loading/cbor.rs
@@ -1,7 +1,7 @@
use ecow::{eco_format, EcoString};
use crate::diag::{At, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, scope, Bytes, Value};
use crate::syntax::Spanned;
use crate::World;
@@ -16,14 +16,14 @@ use crate::World;
/// whether they are whole numbers.
#[func(scope, title = "CBOR")]
pub fn cbor(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a CBOR file.
path: Spanned<EcoString>,
) -> SourceResult<Value> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
cbor::decode(Spanned::new(data, span))
}
diff --git a/crates/typst/src/loading/csv.rs b/crates/typst/src/loading/csv.rs
index e195f190..0d009560 100644
--- a/crates/typst/src/loading/csv.rs
+++ b/crates/typst/src/loading/csv.rs
@@ -1,7 +1,7 @@
use ecow::{eco_format, EcoString};
use crate::diag::{bail, At, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{cast, func, scope, Array, IntoValue, Value};
use crate::loading::Readable;
use crate::syntax::Spanned;
@@ -26,8 +26,8 @@ use crate::World;
/// ```
#[func(scope, title = "CSV")]
pub fn csv(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a CSV file.
path: Spanned<EcoString>,
/// The delimiter that separates columns in the CSV file.
@@ -37,8 +37,8 @@ pub fn csv(
delimiter: Delimiter,
) -> SourceResult<Array> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
self::csv::decode(Spanned::new(Readable::Bytes(data), span), delimiter)
}
diff --git a/crates/typst/src/loading/json.rs b/crates/typst/src/loading/json.rs
index cf209971..aae1f4ad 100644
--- a/crates/typst/src/loading/json.rs
+++ b/crates/typst/src/loading/json.rs
@@ -1,7 +1,7 @@
use ecow::{eco_format, EcoString};
use crate::diag::{At, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, scope, Str, Value};
use crate::loading::Readable;
use crate::syntax::Spanned;
@@ -46,14 +46,14 @@ use crate::World;
/// ```
#[func(scope, title = "JSON")]
pub fn json(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a JSON file.
path: Spanned<EcoString>,
) -> SourceResult<Value> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
json::decode(Spanned::new(Readable::Bytes(data), span))
}
diff --git a/crates/typst/src/loading/read.rs b/crates/typst/src/loading/read.rs
index 49a86699..50772bee 100644
--- a/crates/typst/src/loading/read.rs
+++ b/crates/typst/src/loading/read.rs
@@ -1,7 +1,7 @@
use ecow::EcoString;
use crate::diag::{At, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, Cast};
use crate::loading::Readable;
use crate::syntax::Spanned;
@@ -24,8 +24,8 @@ use crate::World;
/// ```
#[func]
pub fn read(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a file.
path: Spanned<EcoString>,
/// The encoding to read the file with.
@@ -36,8 +36,8 @@ pub fn read(
encoding: Option<Encoding>,
) -> SourceResult<Readable> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
Ok(match encoding {
None => Readable::Bytes(data),
Some(Encoding::Utf8) => Readable::Str(
diff --git a/crates/typst/src/loading/toml.rs b/crates/typst/src/loading/toml.rs
index a4388f74..6884e6fe 100644
--- a/crates/typst/src/loading/toml.rs
+++ b/crates/typst/src/loading/toml.rs
@@ -1,7 +1,7 @@
use ecow::{eco_format, EcoString};
use crate::diag::{At, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, scope, Str, Value};
use crate::loading::Readable;
use crate::syntax::{is_newline, Spanned};
@@ -29,14 +29,14 @@ use crate::World;
/// ```
#[func(scope, title = "TOML")]
pub fn toml(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a TOML file.
path: Spanned<EcoString>,
) -> SourceResult<Value> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
toml::decode(Spanned::new(Readable::Bytes(data), span))
}
diff --git a/crates/typst/src/loading/xml.rs b/crates/typst/src/loading/xml.rs
index 73aeb32a..338b2f30 100644
--- a/crates/typst/src/loading/xml.rs
+++ b/crates/typst/src/loading/xml.rs
@@ -1,7 +1,7 @@
use ecow::EcoString;
use crate::diag::{format_xml_like_error, At, FileError, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{dict, func, scope, Array, Dict, IntoValue, Str, Value};
use crate::loading::Readable;
use crate::syntax::Spanned;
@@ -57,14 +57,14 @@ use crate::World;
/// ```
#[func(scope, title = "XML")]
pub fn xml(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to an XML file.
path: Spanned<EcoString>,
) -> SourceResult<Value> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
xml::decode(Spanned::new(Readable::Bytes(data), span))
}
diff --git a/crates/typst/src/loading/yaml.rs b/crates/typst/src/loading/yaml.rs
index 03dd2a2c..501e3066 100644
--- a/crates/typst/src/loading/yaml.rs
+++ b/crates/typst/src/loading/yaml.rs
@@ -1,7 +1,7 @@
use ecow::{eco_format, EcoString};
use crate::diag::{At, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, scope, Str, Value};
use crate::loading::Readable;
use crate::syntax::Spanned;
@@ -38,14 +38,14 @@ use crate::World;
/// ```
#[func(scope, title = "YAML")]
pub fn yaml(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Path to a YAML file.
path: Spanned<EcoString>,
) -> SourceResult<Value> {
let Spanned { v: path, span } = path;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
yaml::decode(Spanned::new(Readable::Bytes(data), span))
}
diff --git a/crates/typst/src/math/cancel.rs b/crates/typst/src/math/cancel.rs
index 7a72f44a..6d3026b8 100644
--- a/crates/typst/src/math/cancel.rs
+++ b/crates/typst/src/math/cancel.rs
@@ -191,7 +191,7 @@ fn draw_cancel_line(
CancelAngle::Angle(v) => *v,
// This specifies a function that takes the default angle as input.
CancelAngle::Func(func) => {
- func.call_vt(ctx.vt, [default])?.cast().at(span)?
+ func.call(ctx.engine, [default])?.cast().at(span)?
}
},
};
diff --git a/crates/typst/src/math/ctx.rs b/crates/typst/src/math/ctx.rs
index 0f7ad933..9352f08b 100644
--- a/crates/typst/src/math/ctx.rs
+++ b/crates/typst/src/math/ctx.rs
@@ -9,8 +9,9 @@ use unicode_math_class::MathClass;
use unicode_segmentation::UnicodeSegmentation;
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{Content, NativeElement, Smart, StyleChain, Styles};
-use crate::layout::{Abs, Axes, BoxElem, Em, Frame, Layout, Regions, Size, Vt};
+use crate::layout::{Abs, Axes, BoxElem, Em, Frame, Layout, Regions, Size};
use crate::math::{
FrameFragment, GlyphFragment, LayoutMath, MathFragment, MathRow, MathSize, MathStyle,
MathVariant, THICK,
@@ -43,7 +44,7 @@ macro_rules! percent {
/// The context for math layout.
pub struct MathContext<'a, 'b, 'v> {
- pub vt: &'v mut Vt<'b>,
+ pub engine: &'v mut Engine<'b>,
pub regions: Regions<'static>,
pub font: &'a Font,
pub ttf: &'a ttf_parser::Face<'a>,
@@ -62,7 +63,7 @@ pub struct MathContext<'a, 'b, 'v> {
impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
pub fn new(
- vt: &'v mut Vt<'b>,
+ engine: &'v mut Engine<'b>,
styles: StyleChain<'a>,
regions: Regions,
font: &'a Font,
@@ -103,7 +104,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
let variant = variant(styles);
Self {
- vt,
+ engine,
regions: Regions::one(regions.base(), Axes::splat(false)),
font,
ttf: font.ttf(),
@@ -167,13 +168,13 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
pub fn layout_box(&mut self, boxed: &BoxElem) -> SourceResult<Frame> {
Ok(boxed
- .layout(self.vt, self.outer.chain(&self.local), self.regions)?
+ .layout(self.engine, self.outer.chain(&self.local), self.regions)?
.into_frame())
}
pub fn layout_content(&mut self, content: &Content) -> SourceResult<Frame> {
Ok(content
- .layout(self.vt, self.outer.chain(&self.local), self.regions)?
+ .layout(self.engine, self.outer.chain(&self.local), self.regions)?
.into_frame())
}
@@ -270,7 +271,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
let frame = ParElem::new(vec![Prehashed::new(elem)])
.spanned(span)
.layout(
- self.vt,
+ self.engine,
self.outer.chain(&self.local),
false,
Size::splat(Abs::inf()),
@@ -288,7 +289,7 @@ impl<'a, 'b, 'v> MathContext<'a, 'b, 'v> {
}
pub fn realize(&mut self, content: &Content) -> SourceResult<Option<Content>> {
- realize(self.vt, content, self.outer.chain(&self.local))
+ realize(self.engine, content, self.outer.chain(&self.local))
}
pub fn style(&mut self, style: MathStyle) {
diff --git a/crates/typst/src/math/equation.rs b/crates/typst/src/math/equation.rs
index fb58a5b7..f5fa6061 100644
--- a/crates/typst/src/math/equation.rs
+++ b/crates/typst/src/math/equation.rs
@@ -1,6 +1,7 @@
use std::num::NonZeroUsize;
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
elem, Content, Finalize, Guard, NativeElement, Resolve, Show, Smart, StyleChain,
Synthesize,
@@ -8,7 +9,7 @@ use crate::foundations::{
use crate::introspection::{Count, Counter, CounterUpdate, Locatable};
use crate::layout::{
Abs, Align, AlignElem, Axes, Dir, Em, FixedAlign, Fragment, Layout, Point, Regions,
- Size, Vt,
+ Size,
};
use crate::math::{LayoutMath, MathContext};
use crate::model::{Numbering, Outlinable, ParElem, Refable, Supplement};
@@ -88,12 +89,18 @@ pub struct EquationElem {
}
impl Synthesize for EquationElem {
- fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(
+ &mut self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<()> {
// Resolve the supplement.
let supplement = match self.supplement(styles) {
Smart::Auto => TextElem::packed(Self::local_name_in(styles)),
Smart::Custom(None) => Content::empty(),
- Smart::Custom(Some(supplement)) => supplement.resolve(vt, [self.clone()])?,
+ Smart::Custom(Some(supplement)) => {
+ supplement.resolve(engine, [self.clone()])?
+ }
};
self.push_block(self.block(styles));
@@ -106,7 +113,7 @@ impl Synthesize for EquationElem {
impl Show for EquationElem {
#[tracing::instrument(name = "EquationElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.clone().pack().guarded(Guard::Base(Self::elem()));
if self.block(styles) {
realized = AlignElem::new(realized).pack();
@@ -133,7 +140,7 @@ impl Layout for EquationElem {
#[tracing::instrument(name = "EquationElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -143,7 +150,7 @@ impl Layout for EquationElem {
// Find a math font.
let variant = variant(styles);
- let world = vt.world;
+ let world = engine.world;
let Some(font) = families(styles).find_map(|family| {
let id = world.book().select(family, variant)?;
let font = world.font(id)?;
@@ -153,7 +160,7 @@ impl Layout for EquationElem {
bail!(self.span(), "current font does not support math");
};
- let mut ctx = MathContext::new(vt, styles, regions, &font, block);
+ let mut ctx = MathContext::new(engine, styles, regions, &font, block);
let mut frame = ctx.layout_frame(self)?;
if block {
@@ -161,7 +168,7 @@ impl Layout for EquationElem {
let pod = Regions::one(regions.base(), Axes::splat(false));
let counter = Counter::of(Self::elem())
.display(Some(numbering), false)
- .layout(vt, styles, pod)?
+ .layout(engine, styles, pod)?
.into_frame();
let full_counter_width = counter.width() + NUMBER_GUTTER.resolve(styles);
@@ -274,7 +281,7 @@ impl Refable for EquationElem {
}
impl Outlinable for EquationElem {
- fn outline(&self, vt: &mut Vt) -> SourceResult<Option<Content>> {
+ fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>> {
if !self.block(StyleChain::default()) {
return Ok(None);
}
@@ -294,8 +301,8 @@ impl Outlinable for EquationElem {
let numbers = self
.counter()
- .at(vt, self.location().unwrap())?
- .display(vt, &numbering)?;
+ .at(engine, self.location().unwrap())?
+ .display(engine, &numbering)?;
Ok(Some(supplement + numbers))
}
diff --git a/crates/typst/src/model/bibliography.rs b/crates/typst/src/model/bibliography.rs
index f6e189e1..626468dc 100644
--- a/crates/typst/src/model/bibliography.rs
+++ b/crates/typst/src/model/bibliography.rs
@@ -20,7 +20,8 @@ use smallvec::{smallvec, SmallVec};
use typed_arena::Arena;
use crate::diag::{bail, error, At, FileError, SourceResult, StrResult};
-use crate::eval::{eval_string, EvalMode, Vm};
+use crate::engine::Engine;
+use crate::eval::{eval_string, EvalMode};
use crate::foundations::{
cast, elem, ty, Args, Array, Bytes, CastInfo, Content, Finalize, FromValue,
IntoValue, Label, NativeElement, Reflect, Repr, Scope, Show, Smart, Str, StyleChain,
@@ -28,7 +29,7 @@ use crate::foundations::{
};
use crate::introspection::{Introspector, Locatable, Location};
use crate::layout::{
- BlockElem, Em, GridElem, HElem, PadElem, Sizing, TrackSizings, VElem, Vt,
+ BlockElem, Em, GridElem, HElem, PadElem, Sizing, TrackSizings, VElem,
};
use crate::model::{
CitationForm, CiteGroup, Destination, FootnoteElem, HeadingElem, LinkElem, ParElem,
@@ -88,7 +89,7 @@ pub struct BibliographyElem {
/// Path(s) to Hayagriva `.yml` and/or BibLaTeX `.bib` files.
#[required]
#[parse(
- let (paths, bibliography) = Bibliography::parse(vm, args)?;
+ let (paths, bibliography) = Bibliography::parse(engine, args)?;
paths
)]
pub path: BibliographyPaths,
@@ -120,7 +121,7 @@ pub struct BibliographyElem {
/// a [CSL file](https://citationstyles.org/). Some of the styles listed
/// below appear twice, once with their full name and once with a short
/// alias.
- #[parse(CslStyle::parse(vm, args)?)]
+ #[parse(CslStyle::parse(engine, args)?)]
#[default(CslStyle::from_name("ieee").unwrap())]
pub style: CslStyle,
@@ -169,9 +170,10 @@ impl BibliographyElem {
}
/// Whether the bibliography contains the given key.
- pub fn has(vt: &Vt, key: impl Into<PicoStr>) -> bool {
+ pub fn has(engine: &Engine, key: impl Into<PicoStr>) -> bool {
let key = key.into();
- vt.introspector
+ engine
+ .introspector
.query(&Self::elem().select())
.iter()
.any(|elem| elem.to::<Self>().unwrap().bibliography().has(key))
@@ -195,7 +197,7 @@ impl BibliographyElem {
}
impl Synthesize for BibliographyElem {
- fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
self.push_full(self.full(styles));
self.push_style(self.style(styles));
self.push_lang(TextElem::lang_in(styles));
@@ -206,7 +208,7 @@ impl Synthesize for BibliographyElem {
impl Show for BibliographyElem {
#[tracing::instrument(name = "BibliographyElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
const COLUMN_GUTTER: Em = Em::new(0.65);
const INDENT: Em = Em::new(1.5);
@@ -219,9 +221,9 @@ impl Show for BibliographyElem {
seq.push(HeadingElem::new(title).with_level(NonZeroUsize::ONE).pack());
}
- Ok(vt.delayed(|vt| {
+ Ok(engine.delayed(|engine| {
let span = self.span();
- let works = Works::generate(vt.world, vt.introspector).at(span)?;
+ let works = Works::generate(engine.world, engine.introspector).at(span)?;
let references = works
.references
.as_ref()
@@ -316,7 +318,7 @@ pub struct Bibliography {
impl Bibliography {
/// Parse the bibliography argument.
fn parse(
- vm: &mut Vm,
+ engine: &mut Engine,
args: &mut Args,
) -> SourceResult<(BibliographyPaths, Bibliography)> {
let Spanned { v: paths, span } =
@@ -327,8 +329,8 @@ impl Bibliography {
.0
.iter()
.map(|path| {
- let id = vm.resolve_path(path).at(span)?;
- vm.world().file(id).at(span)
+ let id = span.resolve_path(path).at(span)?;
+ engine.world.file(id).at(span)
})
.collect::<SourceResult<Vec<Bytes>>>()?;
@@ -438,19 +440,19 @@ pub struct CslStyle {
impl CslStyle {
/// Parse the style argument.
- pub fn parse(vm: &mut Vm, args: &mut Args) -> SourceResult<Option<CslStyle>> {
+ pub fn parse(engine: &mut Engine, args: &mut Args) -> SourceResult<Option<CslStyle>> {
let Some(Spanned { v: string, span }) =
args.named::<Spanned<EcoString>>("style")?
else {
return Ok(None);
};
- Ok(Some(Self::parse_impl(vm, &string).at(span)?))
+ Ok(Some(Self::parse_impl(engine, &string, span).at(span)?))
}
/// Parse the style argument with `Smart`.
pub fn parse_smart(
- vm: &mut Vm,
+ engine: &mut Engine,
args: &mut Args,
) -> SourceResult<Option<Smart<CslStyle>>> {
let Some(Spanned { v: smart, span }) =
@@ -462,13 +464,13 @@ impl CslStyle {
Ok(Some(match smart {
Smart::Auto => Smart::Auto,
Smart::Custom(string) => {
- Smart::Custom(Self::parse_impl(vm, &string).at(span)?)
+ Smart::Custom(Self::parse_impl(engine, &string, span).at(span)?)
}
}))
}
/// Parse internally.
- fn parse_impl(vm: &mut Vm, string: &str) -> StrResult<CslStyle> {
+ fn parse_impl(engine: &mut Engine, string: &str, span: Span) -> StrResult<CslStyle> {
let ext = Path::new(string)
.extension()
.and_then(OsStr::to_str)
@@ -476,8 +478,8 @@ impl CslStyle {
.to_lowercase();
if ext == "csl" {
- let id = vm.resolve_path(string)?;
- let data = vm.world().file(id)?;
+ let id = span.resolve_path(string)?;
+ let data = engine.world.file(id)?;
CslStyle::from_data(&data)
} else {
CslStyle::from_name(string)
diff --git a/crates/typst/src/model/cite.rs b/crates/typst/src/model/cite.rs
index 7ead5907..3657e83d 100644
--- a/crates/typst/src/model/cite.rs
+++ b/crates/typst/src/model/cite.rs
@@ -1,9 +1,9 @@
use crate::diag::{bail, At, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Cast, Content, Label, NativeElement, Show, Smart, StyleChain, Synthesize,
};
use crate::introspection::Locatable;
-use crate::layout::Vt;
use crate::model::bibliography::Works;
use crate::model::CslStyle;
use crate::text::{Lang, Region, TextElem};
@@ -85,7 +85,7 @@ pub struct CiteElem {
///
/// When set to `{auto}`, automatically use the
/// [bibliography's style]($bibliography.style) for the citations.
- #[parse(CslStyle::parse_smart(vm, args)?)]
+ #[parse(CslStyle::parse_smart(engine, args)?)]
pub style: Smart<CslStyle>,
/// The text language setting where the citation is.
@@ -100,7 +100,7 @@ pub struct CiteElem {
}
impl Synthesize for CiteElem {
- fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
self.push_supplement(self.supplement(styles));
self.push_form(self.form(styles));
self.push_style(self.style(styles));
@@ -143,12 +143,12 @@ pub struct CiteGroup {
}
impl Show for CiteGroup {
- #[tracing::instrument(name = "CiteGroup::show", skip(self, vt))]
- fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
- Ok(vt.delayed(|vt| {
+ #[tracing::instrument(name = "CiteGroup::show", skip(self, engine))]
+ fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
+ Ok(engine.delayed(|engine| {
let location = self.location().unwrap();
let span = self.span();
- Works::generate(vt.world, vt.introspector)
+ Works::generate(engine.world, engine.introspector)
.at(span)?
.citations
.get(&location)
diff --git a/crates/typst/src/model/document.rs b/crates/typst/src/model/document.rs
index f6ea7d24..373a1545 100644
--- a/crates/typst/src/model/document.rs
+++ b/crates/typst/src/model/document.rs
@@ -2,12 +2,12 @@ use comemo::Prehashed;
use ecow::EcoString;
use crate::diag::{bail, SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Args, Array, Construct, Content, Datetime, Smart, StyleChain, Value,
};
use crate::introspection::ManualPageCounter;
-use crate::layout::{Frame, LayoutRoot, PageElem, Vt};
+use crate::layout::{Frame, LayoutRoot, PageElem};
/// The root element of a document and its metadata.
///
@@ -56,7 +56,7 @@ pub struct DocumentElem {
}
impl Construct for DocumentElem {
- fn construct(_: &mut Vm, args: &mut Args) -> SourceResult<Content> {
+ fn construct(_: &mut Engine, args: &mut Args) -> SourceResult<Content> {
bail!(args.span, "can only be used in set rules")
}
}
@@ -64,7 +64,11 @@ impl Construct for DocumentElem {
impl LayoutRoot for DocumentElem {
/// Layout the document into a sequence of frames, one per page.
#[tracing::instrument(name = "DocumentElem::layout_root", skip_all)]
- fn layout_root(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Document> {
+ fn layout_root(
+ &self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<Document> {
tracing::info!("Document layout");
let mut pages = vec![];
@@ -88,7 +92,8 @@ impl LayoutRoot for DocumentElem {
.to::<PageElem>()?
.clear_to(styles)
});
- let fragment = page.layout(vt, styles, &mut page_counter, extend_to)?;
+ let fragment =
+ page.layout(engine, styles, &mut page_counter, extend_to)?;
pages.extend(fragment);
} else {
bail!(child.span(), "unexpected document child");
diff --git a/crates/typst/src/model/emph.rs b/crates/typst/src/model/emph.rs
index 1b7f654c..de7b8bef 100644
--- a/crates/typst/src/model/emph.rs
+++ b/crates/typst/src/model/emph.rs
@@ -1,6 +1,6 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, Show, StyleChain};
-use crate::layout::Vt;
use crate::text::{ItalicToggle, TextElem};
/// Emphasizes content by setting it in italics.
@@ -35,7 +35,7 @@ pub struct EmphElem {
impl Show for EmphElem {
#[tracing::instrument(name = "EmphElem::show", skip(self))]
- fn show(&self, _: &mut Vt, _: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone().styled(TextElem::set_emph(ItalicToggle)))
}
}
diff --git a/crates/typst/src/model/enum.rs b/crates/typst/src/model/enum.rs
index f440bc39..f4583f8d 100644
--- a/crates/typst/src/model/enum.rs
+++ b/crates/typst/src/model/enum.rs
@@ -1,12 +1,13 @@
use std::str::FromStr;
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, Array, Content, Fold, NativeElement, Smart, StyleChain,
};
use crate::layout::{
Axes, BlockElem, Em, Fragment, GridLayouter, HAlign, Layout, Length, Regions, Sizing,
- Spacing, VAlign, Vt,
+ Spacing, VAlign,
};
use crate::model::{Numbering, NumberingPattern, ParElem};
use crate::text::TextElem;
@@ -209,7 +210,7 @@ impl Layout for EnumElem {
#[tracing::instrument(name = "EnumElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -239,7 +240,7 @@ impl Layout for EnumElem {
let resolved = if full {
parents.push(number);
- let content = numbering.apply_vt(vt, &parents)?.display();
+ let content = numbering.apply(engine, &parents)?.display();
parents.pop();
content
} else {
@@ -247,7 +248,7 @@ impl Layout for EnumElem {
Numbering::Pattern(pattern) => {
TextElem::packed(pattern.apply_kth(parents.len(), number))
}
- other => other.apply_vt(vt, &[number])?.display(),
+ other => other.apply(engine, &[number])?.display(),
}
};
@@ -277,7 +278,7 @@ impl Layout for EnumElem {
self.span(),
);
- Ok(layouter.layout(vt)?.fragment)
+ Ok(layouter.layout(engine)?.fragment)
}
}
diff --git a/crates/typst/src/model/figure.rs b/crates/typst/src/model/figure.rs
index 26a96db1..e6ab7a2a 100644
--- a/crates/typst/src/model/figure.rs
+++ b/crates/typst/src/model/figure.rs
@@ -5,6 +5,7 @@ use std::str::FromStr;
use ecow::EcoString;
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, select_where, Content, Element, Finalize, NativeElement, Selector,
Show, Smart, StyleChain, Synthesize,
@@ -12,7 +13,7 @@ use crate::foundations::{
use crate::introspection::{
Count, Counter, CounterKey, CounterUpdate, Locatable, Location,
};
-use crate::layout::{Align, BlockElem, Em, HAlign, Length, PlaceElem, VAlign, VElem, Vt};
+use crate::layout::{Align, BlockElem, Em, HAlign, Length, PlaceElem, VAlign, VElem};
use crate::model::{Numbering, NumberingPattern, Outlinable, Refable, Supplement};
use crate::syntax::Spanned;
use crate::text::{Lang, Region, TextElem};
@@ -220,7 +221,11 @@ impl FigureElem {
}
impl Synthesize for FigureElem {
- fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(
+ &mut self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<()> {
let numbering = self.numbering(styles);
// Determine the figure's kind.
@@ -264,7 +269,7 @@ impl Synthesize for FigureElem {
};
let target = descendant.unwrap_or_else(|| Cow::Borrowed(self.body()));
- Some(supplement.resolve(vt, [target])?)
+ Some(supplement.resolve(engine, [target])?)
}
};
@@ -296,7 +301,7 @@ impl Synthesize for FigureElem {
impl Show for FigureElem {
#[tracing::instrument(name = "FigureElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.body().clone();
// Build the caption, if any.
@@ -364,7 +369,7 @@ impl Refable for FigureElem {
}
impl Outlinable for FigureElem {
- fn outline(&self, vt: &mut Vt) -> SourceResult<Option<Content>> {
+ fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>> {
if !self.outlined(StyleChain::default()) {
return Ok(None);
}
@@ -384,7 +389,7 @@ impl Outlinable for FigureElem {
self.numbering(StyleChain::default()),
) {
let location = self.location().unwrap();
- let numbers = counter.at(vt, location)?.display(vt, &numbering)?;
+ let numbers = counter.at(engine, location)?.display(engine, &numbering)?;
if !supplement.is_empty() {
supplement += TextElem::packed('\u{a0}');
@@ -538,7 +543,7 @@ impl FigureCaption {
}
impl Synthesize for FigureCaption {
- fn synthesize(&mut self, _: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
self.push_position(self.position(styles));
self.push_separator(Smart::Custom(self.get_separator(styles)));
Ok(())
@@ -547,7 +552,7 @@ impl Synthesize for FigureCaption {
impl Show for FigureCaption {
#[tracing::instrument(name = "FigureCaption::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.body().clone();
if let (Some(mut supplement), Some(numbering), Some(counter), Some(location)) = (
@@ -556,7 +561,7 @@ impl Show for FigureCaption {
self.counter(),
self.figure_location(),
) {
- let numbers = counter.at(vt, *location)?.display(vt, numbering)?;
+ let numbers = counter.at(engine, *location)?.display(engine, numbering)?;
if !supplement.is_empty() {
supplement += TextElem::packed('\u{a0}');
}
diff --git a/crates/typst/src/model/footnote.rs b/crates/typst/src/model/footnote.rs
index d51ee226..df88b58c 100644
--- a/crates/typst/src/model/footnote.rs
+++ b/crates/typst/src/model/footnote.rs
@@ -4,12 +4,13 @@ use std::str::FromStr;
use comemo::Prehashed;
use crate::diag::{bail, error, At, SourceResult, StrResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, Content, Finalize, Label, NativeElement, Show, Smart, StyleChain,
Synthesize,
};
use crate::introspection::{Count, Counter, CounterUpdate, Locatable, Location};
-use crate::layout::{Abs, Em, HElem, Length, Ratio, Vt};
+use crate::layout::{Abs, Em, HElem, Length, Ratio};
use crate::model::{Destination, Numbering, NumberingPattern, ParElem};
use crate::text::{SuperElem, TextElem, TextSize};
use crate::util::NonZeroExt;
@@ -107,14 +108,15 @@ impl FootnoteElem {
}
/// Returns the location of the definition of this footnote.
- pub fn declaration_location(&self, vt: &Vt) -> StrResult<Location> {
+ pub fn declaration_location(&self, engine: &Engine) -> StrResult<Location> {
match self.body() {
FootnoteBody::Reference(label) => {
- let element: Prehashed<Content> = vt.introspector.query_label(*label)?;
+ let element: Prehashed<Content> =
+ engine.introspector.query_label(*label)?;
let footnote = element
.to::<FootnoteElem>()
.ok_or("referenced element should be a footnote")?;
- footnote.declaration_location(vt)
+ footnote.declaration_location(engine)
}
_ => Ok(self.location().unwrap()),
}
@@ -122,7 +124,7 @@ impl FootnoteElem {
}
impl Synthesize for FootnoteElem {
- fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
self.push_numbering(self.numbering(styles).clone());
Ok(())
}
@@ -130,12 +132,12 @@ impl Synthesize for FootnoteElem {
impl Show for FootnoteElem {
#[tracing::instrument(name = "FootnoteElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(vt.delayed(|vt| {
- let loc = self.declaration_location(vt).at(self.span())?;
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
+ Ok(engine.delayed(|engine| {
+ let loc = self.declaration_location(engine).at(self.span())?;
let numbering = self.numbering(styles);
let counter = Counter::of(Self::elem());
- let num = counter.at(vt, loc)?.display(vt, numbering)?;
+ let num = counter.at(engine, loc)?.display(engine, numbering)?;
let sup = SuperElem::new(num).pack();
let loc = loc.variant(1);
// Add zero-width weak spacing to make the footnote "sticky".
@@ -271,7 +273,7 @@ pub struct FootnoteEntry {
}
impl Show for FootnoteEntry {
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let note = self.note();
let number_gap = Em::new(0.05);
let default = StyleChain::default();
@@ -283,7 +285,7 @@ impl Show for FootnoteEntry {
))
};
- let num = counter.at(vt, loc)?.display(vt, numbering)?;
+ let num = counter.at(engine, loc)?.display(engine, numbering)?;
let sup = SuperElem::new(num)
.pack()
.linked(Destination::Location(loc))
diff --git a/crates/typst/src/model/heading.rs b/crates/typst/src/model/heading.rs
index 3365f00c..6f8932d4 100644
--- a/crates/typst/src/model/heading.rs
+++ b/crates/typst/src/model/heading.rs
@@ -1,12 +1,13 @@
use std::num::NonZeroUsize;
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Content, Finalize, NativeElement, Show, Smart, StyleChain, Styles,
Synthesize,
};
use crate::introspection::{Count, Counter, CounterUpdate, Locatable};
-use crate::layout::{BlockElem, Em, HElem, VElem, Vt};
+use crate::layout::{BlockElem, Em, HElem, VElem};
use crate::model::{Numbering, Outlinable, Refable, Supplement};
use crate::text::{FontWeight, Lang, LocalName, Region, SpaceElem, TextElem, TextSize};
use crate::util::{option_eq, NonZeroExt};
@@ -126,12 +127,18 @@ pub struct HeadingElem {
}
impl Synthesize for HeadingElem {
- fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(
+ &mut self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<()> {
// Resolve the supplement.
let supplement = match self.supplement(styles) {
Smart::Auto => TextElem::packed(Self::local_name_in(styles)),
Smart::Custom(None) => Content::empty(),
- Smart::Custom(Some(supplement)) => supplement.resolve(vt, [self.clone()])?,
+ Smart::Custom(Some(supplement)) => {
+ supplement.resolve(engine, [self.clone()])?
+ }
};
self.push_level(self.level(styles));
@@ -146,7 +153,7 @@ impl Synthesize for HeadingElem {
impl Show for HeadingElem {
#[tracing::instrument(name = "HeadingElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.body().clone();
if let Some(numbering) = self.numbering(styles).as_ref() {
realized = Counter::of(Self::elem())
@@ -214,7 +221,7 @@ impl Refable for HeadingElem {
}
impl Outlinable for HeadingElem {
- fn outline(&self, vt: &mut Vt) -> SourceResult<Option<Content>> {
+ fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>> {
if !self.outlined(StyleChain::default()) {
return Ok(None);
}
@@ -223,8 +230,8 @@ impl Outlinable for HeadingElem {
let default = StyleChain::default();
if let Some(numbering) = self.numbering(default).as_ref() {
let numbers = Counter::of(Self::elem())
- .at(vt, self.location().unwrap())?
- .display(vt, numbering)?;
+ .at(engine, self.location().unwrap())?
+ .display(engine, numbering)?;
content = numbers + SpaceElem::new().pack() + content;
};
diff --git a/crates/typst/src/model/link.rs b/crates/typst/src/model/link.rs
index 27a05737..5d1b4f19 100644
--- a/crates/typst/src/model/link.rs
+++ b/crates/typst/src/model/link.rs
@@ -1,11 +1,12 @@
use ecow::{eco_format, EcoString};
use crate::diag::{At, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Content, Label, NativeElement, Repr, Show, Smart, StyleChain,
};
use crate::introspection::Location;
-use crate::layout::{Position, Vt};
+use crate::layout::Position;
use crate::text::{Hyphenate, TextElem};
/// Links to a URL or a location in the document.
@@ -89,14 +90,14 @@ impl LinkElem {
}
impl Show for LinkElem {
- #[tracing::instrument(name = "LinkElem::show", skip(self, vt))]
- fn show(&self, vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
+ #[tracing::instrument(name = "LinkElem::show", skip(self, engine))]
+ fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult<Content> {
let body = self.body().clone();
let linked = match self.dest() {
LinkTarget::Dest(dest) => body.linked(dest.clone()),
- LinkTarget::Label(label) => vt
- .delayed(|vt| {
- let elem = vt.introspector.query_label(*label).at(self.span())?;
+ LinkTarget::Label(label) => engine
+ .delayed(|engine| {
+ let elem = engine.introspector.query_label(*label).at(self.span())?;
let dest = Destination::Location(elem.location().unwrap());
Ok(Some(body.clone().linked(dest)))
})
diff --git a/crates/typst/src/model/list.rs b/crates/typst/src/model/list.rs
index e9275f03..623cafa2 100644
--- a/crates/typst/src/model/list.rs
+++ b/crates/typst/src/model/list.rs
@@ -1,11 +1,12 @@
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, Array, Content, Fold, Func, NativeElement, Smart, StyleChain,
Value,
};
use crate::layout::{
Axes, BlockElem, Em, Fragment, GridLayouter, HAlign, Layout, Length, Regions, Sizing,
- Spacing, VAlign, Vt,
+ Spacing, VAlign,
};
use crate::model::ParElem;
use crate::text::TextElem;
@@ -130,7 +131,7 @@ impl Layout for ListElem {
#[tracing::instrument(name = "ListElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -146,7 +147,7 @@ impl Layout for ListElem {
let depth = self.depth(styles);
let marker = self
.marker(styles)
- .resolve(vt, depth)?
+ .resolve(engine, depth)?
// avoid '#set align' interference with the list
.aligned(HAlign::Start + VAlign::Top);
@@ -172,7 +173,7 @@ impl Layout for ListElem {
self.span(),
);
- Ok(layouter.layout(vt)?.fragment)
+ Ok(layouter.layout(engine)?.fragment)
}
}
@@ -198,12 +199,12 @@ pub enum ListMarker {
impl ListMarker {
/// Resolve the marker for the given depth.
- fn resolve(&self, vt: &mut Vt, depth: usize) -> SourceResult<Content> {
+ fn resolve(&self, engine: &mut Engine, depth: usize) -> SourceResult<Content> {
Ok(match self {
Self::Content(list) => {
list.get(depth).or(list.last()).cloned().unwrap_or_default()
}
- Self::Func(func) => func.call_vt(vt, [depth])?.display(),
+ Self::Func(func) => func.call(engine, [depth])?.display(),
})
}
}
diff --git a/crates/typst/src/model/numbering.rs b/crates/typst/src/model/numbering.rs
index fa7a88c4..d91a5c52 100644
--- a/crates/typst/src/model/numbering.rs
+++ b/crates/typst/src/model/numbering.rs
@@ -5,9 +5,9 @@ use chinese_number::{ChineseCase, ChineseCountMethod, ChineseVariant, NumberToCh
use ecow::{eco_format, EcoString, EcoVec};
use crate::diag::SourceResult;
-use crate::eval::Vm;
-use crate::foundations::{cast, func, Args, Func, Str, Value};
-use crate::layout::{PdfPageLabel, PdfPageLabelStyle, Vt};
+use crate::engine::Engine;
+use crate::foundations::{cast, func, Func, Str, Value};
+use crate::layout::{PdfPageLabel, PdfPageLabelStyle};
use crate::text::Case;
/// Applies a numbering to a sequence of numbers.
@@ -35,8 +35,8 @@ use crate::text::Case;
/// ```
#[func]
pub fn numbering(
- /// The virtual machine.
- vm: &mut Vm,
+ /// The engine.
+ engine: &mut Engine,
/// Defines how the numbering works.
///
/// **Counting symbols** are `1`, `a`, `A`, `i`, `I`, `い`, `イ`, `א`, `가`,
@@ -68,7 +68,7 @@ pub fn numbering(
#[variadic]
numbers: Vec<usize>,
) -> SourceResult<Value> {
- numbering.apply_vm(vm, &numbers)
+ numbering.apply(engine, &numbers)
}
/// How to number a sequence of things.
@@ -82,21 +82,10 @@ pub enum Numbering {
impl Numbering {
/// Apply the pattern to the given numbers.
- pub fn apply_vm(&self, vm: &mut Vm, numbers: &[usize]) -> SourceResult<Value> {
+ pub fn apply(&self, engine: &mut Engine, numbers: &[usize]) -> SourceResult<Value> {
Ok(match self {
Self::Pattern(pattern) => Value::Str(pattern.apply(numbers).into()),
- Self::Func(func) => {
- let args = Args::new(func.span(), numbers.iter().copied());
- func.call_vm(vm, args)?
- }
- })
- }
-
- /// Apply the pattern to the given numbers.
- pub fn apply_vt(&self, vt: &mut Vt, numbers: &[usize]) -> SourceResult<Value> {
- Ok(match self {
- Self::Pattern(pattern) => Value::Str(pattern.apply(numbers).into()),
- Self::Func(func) => func.call_vt(vt, numbers.iter().copied())?,
+ Self::Func(func) => func.call(engine, numbers.iter().copied())?,
})
}
diff --git a/crates/typst/src/model/outline.rs b/crates/typst/src/model/outline.rs
index 3b23098e..91526a9c 100644
--- a/crates/typst/src/model/outline.rs
+++ b/crates/typst/src/model/outline.rs
@@ -2,12 +2,13 @@ use std::num::NonZeroUsize;
use std::str::FromStr;
use crate::diag::{bail, error, At, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, select_where, Content, Finalize, Func, LocatableSelector,
NativeElement, Show, Smart, StyleChain,
};
use crate::introspection::{Counter, CounterKey, Locatable};
-use crate::layout::{BoxElem, Fr, HElem, HideElem, Length, Rel, RepeatElem, Spacing, Vt};
+use crate::layout::{BoxElem, Fr, HElem, HideElem, Length, Rel, RepeatElem, Spacing};
use crate::model::{Destination, HeadingElem, NumberingPattern, ParbreakElem, Refable};
use crate::syntax::Span;
use crate::text::{Lang, LinebreakElem, LocalName, Region, SpaceElem, TextElem};
@@ -186,7 +187,7 @@ impl OutlineElem {
impl Show for OutlineElem {
#[tracing::instrument(name = "OutlineElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut seq = vec![ParbreakElem::new().pack()];
// Build the outline title.
if let Some(title) = self.title(styles) {
@@ -201,11 +202,11 @@ impl Show for OutlineElem {
let depth = self.depth(styles).unwrap_or(NonZeroUsize::new(usize::MAX).unwrap());
let mut ancestors: Vec<&Content> = vec![];
- let elems = vt.introspector.query(&self.target(styles).0);
+ let elems = engine.introspector.query(&self.target(styles).0);
for elem in &elems {
let Some(entry) = OutlineEntry::from_outlinable(
- vt,
+ engine,
self.span(),
elem.clone().into_inner(),
self.fill(styles),
@@ -229,7 +230,7 @@ impl Show for OutlineElem {
ancestors.pop();
}
- OutlineIndent::apply(indent, vt, &ancestors, &mut seq, self.span())?;
+ OutlineIndent::apply(indent, engine, &ancestors, &mut seq, self.span())?;
// Add the overridable outline entry, followed by a line break.
seq.push(entry.pack());
@@ -292,7 +293,7 @@ impl LocalName for OutlineElem {
/// `#outline()` element.
pub trait Outlinable: Refable {
/// Produce an outline item for this element.
- fn outline(&self, vt: &mut Vt) -> SourceResult<Option<Content>>;
+ fn outline(&self, engine: &mut Engine) -> SourceResult<Option<Content>>;
/// Returns the nesting level of this element.
fn level(&self) -> NonZeroUsize {
@@ -311,7 +312,7 @@ pub enum OutlineIndent {
impl OutlineIndent {
fn apply(
indent: &Option<Smart<Self>>,
- vt: &mut Vt,
+ engine: &mut Engine,
ancestors: &Vec<&Content>,
seq: &mut Vec<Content>,
span: Span,
@@ -330,8 +331,8 @@ impl OutlineIndent {
if let Some(numbering) = ancestor_outlinable.numbering() {
let numbers = ancestor_outlinable
.counter()
- .at(vt, ancestor.location().unwrap())?
- .display(vt, &numbering)?;
+ .at(engine, ancestor.location().unwrap())?
+ .display(engine, &numbering)?;
hidden += numbers + SpaceElem::new().pack();
};
@@ -355,7 +356,7 @@ impl OutlineIndent {
Some(Smart::Custom(OutlineIndent::Func(func))) => {
let depth = ancestors.len();
let LengthOrContent(content) =
- func.call_vt(vt, [depth])?.cast().at(span)?;
+ func.call(engine, [depth])?.cast().at(span)?;
if !content.is_empty() {
seq.push(content);
}
@@ -455,7 +456,7 @@ impl OutlineEntry {
/// be outlined (e.g. heading with 'outlined: false'), does not generate an
/// entry instance (returns `Ok(None)`).
fn from_outlinable(
- vt: &mut Vt,
+ engine: &mut Engine,
span: Span,
elem: Content,
fill: Option<Content>,
@@ -464,27 +465,27 @@ impl OutlineEntry {
bail!(span, "cannot outline {}", elem.func().name());
};
- let Some(body) = outlinable.outline(vt)? else {
+ let Some(body) = outlinable.outline(engine)? else {
return Ok(None);
};
let location = elem.location().unwrap();
- let page_numbering = vt
+ let page_numbering = engine
.introspector
.page_numbering(location)
.cloned()
.unwrap_or_else(|| NumberingPattern::from_str("1").unwrap().into());
let page = Counter::new(CounterKey::Page)
- .at(vt, location)?
- .display(vt, &page_numbering)?;
+ .at(engine, location)?
+ .display(engine, &page_numbering)?;
Ok(Some(Self::new(outlinable.level(), elem, body, fill, page)))
}
}
impl Show for OutlineEntry {
- fn show(&self, _vt: &mut Vt, _: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
let mut seq = vec![];
let elem = self.element();
diff --git a/crates/typst/src/model/par.rs b/crates/typst/src/model/par.rs
index 84274661..c9f64efb 100644
--- a/crates/typst/src/model/par.rs
+++ b/crates/typst/src/model/par.rs
@@ -1,12 +1,12 @@
use comemo::Prehashed;
use crate::diag::SourceResult;
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
elem, Args, Cast, Construct, Content, NativeElement, Set, Smart, StyleChain,
Unlabellable,
};
-use crate::layout::{Em, Fragment, Length, Size, Vt};
+use crate::layout::{Em, Fragment, Length, Size};
/// Arranges text, spacing and inline-level elements into a paragraph.
///
@@ -108,11 +108,11 @@ pub struct ParElem {
}
impl Construct for ParElem {
- fn construct(vm: &mut Vm, args: &mut Args) -> SourceResult<Content> {
+ fn construct(engine: &mut Engine, args: &mut Args) -> SourceResult<Content> {
// The paragraph constructor is special: It doesn't create a paragraph
// element. Instead, it just ensures that the passed content lives in a
// separate paragraph and styles it.
- let styles = Self::set(vm, args)?;
+ let styles = Self::set(engine, args)?;
let body = args.expect::<Content>("body")?;
Ok(Content::sequence([
ParbreakElem::new().pack(),
@@ -127,7 +127,7 @@ impl ParElem {
#[tracing::instrument(name = "ParElement::layout", skip_all)]
pub fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
consecutive: bool,
region: Size,
@@ -135,7 +135,7 @@ impl ParElem {
) -> SourceResult<Fragment> {
crate::layout::layout_inline(
self.children(),
- vt,
+ engine,
styles,
consecutive,
region,
diff --git a/crates/typst/src/model/quote.rs b/crates/typst/src/model/quote.rs
index 489e2657..2a709071 100644
--- a/crates/typst/src/model/quote.rs
+++ b/crates/typst/src/model/quote.rs
@@ -1,9 +1,10 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Content, Finalize, Label, NativeElement, Show, Smart, StyleChain,
Synthesize,
};
-use crate::layout::{Align, BlockElem, Em, HElem, PadElem, Spacing, VElem, Vt};
+use crate::layout::{Align, BlockElem, Em, HElem, PadElem, Spacing, VElem};
use crate::model::{CitationForm, CiteElem};
use crate::text::{SmartQuoteElem, SpaceElem, TextElem};
@@ -145,7 +146,7 @@ cast! {
}
impl Synthesize for QuoteElem {
- fn synthesize(&mut self, _: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
self.push_block(self.block(styles));
self.push_quotes(self.quotes(styles));
Ok(())
@@ -153,7 +154,7 @@ impl Synthesize for QuoteElem {
}
impl Show for QuoteElem {
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut realized = self.body().clone();
let block = self.block(styles);
diff --git a/crates/typst/src/model/reference.rs b/crates/typst/src/model/reference.rs
index 7f328e28..d64de1ae 100644
--- a/crates/typst/src/model/reference.rs
+++ b/crates/typst/src/model/reference.rs
@@ -1,12 +1,12 @@
use ecow::eco_format;
use crate::diag::{bail, At, Hint, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, Content, Func, IntoValue, Label, NativeElement, Show, Smart, StyleChain,
Synthesize,
};
use crate::introspection::{Counter, Locatable};
-use crate::layout::Vt;
use crate::math::EquationElem;
use crate::model::{
BibliographyElem, CiteElem, Destination, Figurable, FootnoteElem, Numbering,
@@ -137,14 +137,18 @@ pub struct RefElem {
}
impl Synthesize for RefElem {
- fn synthesize(&mut self, vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
- let citation = self.to_citation(vt, styles)?;
+ fn synthesize(
+ &mut self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<()> {
+ let citation = self.to_citation(engine, styles)?;
self.push_citation(Some(citation));
self.push_element(None);
let target = *self.target();
- if !BibliographyElem::has(vt, target) {
- if let Ok(elem) = vt.introspector.query_label(target) {
+ if !BibliographyElem::has(engine, target) {
+ if let Ok(elem) = engine.introspector.query_label(target) {
self.push_element(Some(elem.into_inner()));
return Ok(());
}
@@ -156,18 +160,18 @@ impl Synthesize for RefElem {
impl Show for RefElem {
#[tracing::instrument(name = "RefElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
- Ok(vt.delayed(|vt| {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
+ Ok(engine.delayed(|engine| {
let target = *self.target();
- let elem = vt.introspector.query_label(target);
+ let elem = engine.introspector.query_label(target);
let span = self.span();
- if BibliographyElem::has(vt, target) {
+ if BibliographyElem::has(engine, target) {
if elem.is_ok() {
bail!(span, "label occurs in the document and its bibliography");
}
- return Ok(self.to_citation(vt, styles)?.spanned(span).pack());
+ return Ok(self.to_citation(engine, styles)?.spanned(span).pack());
}
let elem = elem.at(span)?;
@@ -211,14 +215,14 @@ impl Show for RefElem {
let numbers = refable
.counter()
- .at(vt, elem.location().unwrap())?
- .display(vt, &numbering.trimmed())?;
+ .at(engine, elem.location().unwrap())?
+ .display(engine, &numbering.trimmed())?;
let supplement = match self.supplement(styles).as_ref() {
Smart::Auto => refable.supplement(),
Smart::Custom(None) => Content::empty(),
Smart::Custom(Some(supplement)) => {
- supplement.resolve(vt, [(*elem).clone()])?
+ supplement.resolve(engine, [(*elem).clone()])?
}
};
@@ -234,10 +238,14 @@ impl Show for RefElem {
impl RefElem {
/// Turn the reference into a citation.
- pub fn to_citation(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<CiteElem> {
+ pub fn to_citation(
+ &self,
+ engine: &mut Engine,
+ styles: StyleChain,
+ ) -> SourceResult<CiteElem> {
let mut elem = CiteElem::new(*self.target());
elem.set_location(self.location().unwrap());
- elem.synthesize(vt, styles)?;
+ elem.synthesize(engine, styles)?;
elem.push_supplement(match self.supplement(styles).clone() {
Smart::Custom(Some(Supplement::Content(content))) => Some(content),
_ => None,
@@ -258,12 +266,12 @@ impl Supplement {
/// Tries to resolve the supplement into its content.
pub fn resolve<T: IntoValue>(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
args: impl IntoIterator<Item = T>,
) -> SourceResult<Content> {
Ok(match self {
Supplement::Content(content) => content.clone(),
- Supplement::Func(func) => func.call_vt(vt, args)?.display(),
+ Supplement::Func(func) => func.call(engine, args)?.display(),
})
}
}
diff --git a/crates/typst/src/model/strong.rs b/crates/typst/src/model/strong.rs
index 40b99b2f..666a4aa0 100644
--- a/crates/typst/src/model/strong.rs
+++ b/crates/typst/src/model/strong.rs
@@ -1,6 +1,6 @@
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, Show, StyleChain};
-use crate::layout::Vt;
use crate::text::{TextElem, WeightDelta};
/// Strongly emphasizes content by increasing the font weight.
@@ -39,7 +39,7 @@ pub struct StrongElem {
impl Show for StrongElem {
#[tracing::instrument(name = "StrongElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
Ok(self
.body()
.clone()
diff --git a/crates/typst/src/model/table.rs b/crates/typst/src/model/table.rs
index 278b898c..31c6636f 100644
--- a/crates/typst/src/model/table.rs
+++ b/crates/typst/src/model/table.rs
@@ -1,11 +1,12 @@
use crate::diag::{At, SourceResult, StrResult};
+use crate::engine::Engine;
use crate::foundations::{
elem, Array, CastInfo, Content, FromValue, Func, IntoValue, NativeElement, Reflect,
Smart, StyleChain, Value,
};
use crate::layout::{
Abs, Align, AlignElem, Axes, Fragment, FrameItem, GridLayouter, Layout, Length,
- Point, Regions, Rel, Sides, Size, TrackSizings, Vt,
+ Point, Regions, Rel, Sides, Size, TrackSizings,
};
use crate::model::Figurable;
use crate::text::{Lang, LocalName, Region};
@@ -158,7 +159,7 @@ impl Layout for TableElem {
#[tracing::instrument(name = "TableElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -181,7 +182,7 @@ impl Layout for TableElem {
let x = i % cols;
let y = i / cols;
- if let Smart::Custom(alignment) = align.resolve(vt, x, y)? {
+ if let Smart::Custom(alignment) = align.resolve(engine, x, y)? {
child = child.styled(AlignElem::set_alignment(alignment));
}
@@ -197,7 +198,7 @@ impl Layout for TableElem {
GridLayouter::new(tracks, gutter, &cells, regions, styles, self.span());
// Measure the columns and layout the grid row-by-row.
- let mut layout = layouter.layout(vt)?;
+ let mut layout = layouter.layout(engine)?;
// Add lines and backgrounds.
for (frame, rows) in layout.fragment.iter_mut().zip(&layout.rows) {
@@ -236,7 +237,7 @@ impl Layout for TableElem {
for (x, &col) in layout.cols.iter().enumerate() {
let mut dy = Abs::zero();
for row in rows {
- if let Some(fill) = fill.resolve(vt, x, row.y)? {
+ if let Some(fill) = fill.resolve(engine, x, row.y)? {
let pos = Point::new(dx, dy);
let size = Size::new(col, row.height);
let rect = Geometry::Rect(size).filled(fill);
@@ -275,10 +276,10 @@ pub enum Celled<T> {
impl<T: Default + Clone + FromValue> Celled<T> {
/// Resolve the value based on the cell position.
- pub fn resolve(&self, vt: &mut Vt, x: usize, y: usize) -> SourceResult<T> {
+ pub fn resolve(&self, engine: &mut Engine, x: usize, y: usize) -> SourceResult<T> {
Ok(match self {
Self::Value(value) => value.clone(),
- Self::Func(func) => func.call_vt(vt, [x, y])?.cast().at(func.span())?,
+ Self::Func(func) => func.call(engine, [x, y])?.cast().at(func.span())?,
Self::Array(array) => x
.checked_rem(array.len())
.and_then(|i| array.get(i))
diff --git a/crates/typst/src/model/terms.rs b/crates/typst/src/model/terms.rs
index 1d256626..bbb6129a 100644
--- a/crates/typst/src/model/terms.rs
+++ b/crates/typst/src/model/terms.rs
@@ -1,9 +1,10 @@
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, Array, Content, NativeElement, Smart, StyleChain,
};
use crate::layout::{
- BlockElem, Em, Fragment, HElem, Layout, Length, Regions, Spacing, VElem, Vt,
+ BlockElem, Em, Fragment, HElem, Layout, Length, Regions, Spacing, VElem,
};
use crate::model::ParElem;
use crate::util::Numeric;
@@ -110,7 +111,7 @@ impl Layout for TermsElem {
#[tracing::instrument(name = "TermsElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -139,7 +140,7 @@ impl Layout for TermsElem {
Content::sequence(seq)
.styled(ParElem::set_hanging_indent(hanging_indent + indent))
- .layout(vt, styles, regions)
+ .layout(engine, styles, regions)
}
}
diff --git a/crates/typst/src/realize/mod.rs b/crates/typst/src/realize/mod.rs
index 2b5ce22d..c2f19303 100644
--- a/crates/typst/src/realize/mod.rs
+++ b/crates/typst/src/realize/mod.rs
@@ -10,7 +10,8 @@ use std::mem;
use smallvec::smallvec;
use typed_arena::Arena;
-use crate::diag::{bail, SourceResult};
+use crate::diag::{bail, error, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
Content, Finalize, Guard, NativeElement, Recipe, Selector, Show, StyleChain,
StyleVecBuilder, Styles, Synthesize,
@@ -18,7 +19,7 @@ use crate::foundations::{
use crate::introspection::{Locatable, Meta, MetaElem};
use crate::layout::{
AlignElem, BlockElem, BoxElem, ColbreakElem, FlowElem, HElem, Layout, LayoutRoot,
- PageElem, PagebreakElem, Parity, PlaceElem, VElem, Vt,
+ PageElem, PagebreakElem, Parity, PlaceElem, VElem,
};
use crate::math::{EquationElem, LayoutMath};
use crate::model::{
@@ -33,6 +34,58 @@ use crate::visualize::{
SquareElem,
};
+/// Realize into an element that is capable of root-level layout.
+#[tracing::instrument(skip_all)]
+pub fn realize_root<'a>(
+ engine: &mut Engine,
+ scratch: &'a Scratch<'a>,
+ content: &'a Content,
+ styles: StyleChain<'a>,
+) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> {
+ if content.can::<dyn LayoutRoot>() && !applicable(content, styles) {
+ return Ok((Cow::Borrowed(content), styles));
+ }
+
+ let mut builder = Builder::new(engine, scratch, true);
+ builder.accept(content, styles)?;
+ builder.interrupt_page(Some(styles), true)?;
+ let (pages, shared) = builder.doc.unwrap().pages.finish();
+ Ok((Cow::Owned(DocumentElem::new(pages.to_vec()).pack()), shared))
+}
+
+/// Realize into an element that is capable of block-level layout.
+#[tracing::instrument(skip_all)]
+pub fn realize_block<'a>(
+ engine: &mut Engine,
+ scratch: &'a Scratch<'a>,
+ content: &'a Content,
+ styles: StyleChain<'a>,
+) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> {
+ // These elements implement `Layout` but still require a flow for
+ // proper layout.
+ if content.can::<dyn Layout>()
+ && !content.is::<BoxElem>()
+ && !content.is::<LineElem>()
+ && !content.is::<RectElem>()
+ && !content.is::<SquareElem>()
+ && !content.is::<EllipseElem>()
+ && !content.is::<CircleElem>()
+ && !content.is::<ImageElem>()
+ && !content.is::<PolygonElem>()
+ && !content.is::<PathElem>()
+ && !content.is::<PlaceElem>()
+ && !applicable(content, styles)
+ {
+ return Ok((Cow::Borrowed(content), styles));
+ }
+
+ let mut builder = Builder::new(engine, scratch, false);
+ builder.accept(content, styles)?;
+ builder.interrupt_par()?;
+ let (children, shared) = builder.flow.0.finish();
+ Ok((Cow::Owned(FlowElem::new(children.to_vec()).pack()), shared))
+}
+
/// Whether the target is affected by show rules in the given style chain.
pub fn applicable(target: &Content, styles: StyleChain) -> bool {
if target.needs_preparation() {
@@ -59,7 +112,7 @@ pub fn applicable(target: &Content, styles: StyleChain) -> bool {
/// Apply the show rules in the given style chain to a target.
pub fn realize(
- vt: &mut Vt,
+ engine: &mut Engine,
target: &Content,
styles: StyleChain,
) -> SourceResult<Option<Content>> {
@@ -67,12 +120,12 @@ pub fn realize(
if target.needs_preparation() {
let mut elem = target.clone();
if target.can::<dyn Locatable>() || target.label().is_some() {
- let location = vt.locator.locate(hash128(target));
+ let location = engine.locator.locate(hash128(target));
elem.set_location(location);
}
if let Some(elem) = elem.with_mut::<dyn Synthesize>() {
- elem.synthesize(vt, styles)?;
+ elem.synthesize(engine, styles)?;
}
elem.mark_prepared();
@@ -97,7 +150,7 @@ pub fn realize(
for recipe in styles.recipes() {
let guard = Guard::Nth(n);
if recipe.applicable(target) && !target.is_guarded(guard) {
- if let Some(content) = try_apply(vt, target, recipe, guard)? {
+ if let Some(content) = try_apply(engine, target, recipe, guard)? {
realized = Some(content);
break;
}
@@ -109,7 +162,7 @@ pub fn realize(
if let Some(showable) = target.with::<dyn Show>() {
let guard = Guard::Base(target.func());
if realized.is_none() && !target.is_guarded(guard) {
- realized = Some(showable.show(vt, styles)?);
+ realized = Some(showable.show(engine, styles)?);
}
}
@@ -127,7 +180,7 @@ pub fn realize(
/// Try to apply a recipe to the target.
fn try_apply(
- vt: &mut Vt,
+ engine: &mut Engine,
target: &Content,
recipe: &Recipe,
guard: Guard,
@@ -138,7 +191,7 @@ fn try_apply(
return Ok(None);
}
- recipe.apply_vt(vt, target.clone().guarded(guard)).map(Some)
+ recipe.apply(engine, target.clone().guarded(guard)).map(Some)
}
Some(Selector::Label(label)) => {
@@ -146,7 +199,7 @@ fn try_apply(
return Ok(None);
}
- recipe.apply_vt(vt, target.clone().guarded(guard)).map(Some)
+ recipe.apply(engine, target.clone().guarded(guard)).map(Some)
}
Some(Selector::Regex(regex)) => {
@@ -172,7 +225,7 @@ fn try_apply(
}
let piece = make(m.as_str()).guarded(guard);
- let transformed = recipe.apply_vt(vt, piece)?;
+ let transformed = recipe.apply(engine, piece)?;
result.push(transformed);
cursor = m.end();
}
@@ -202,62 +255,10 @@ fn try_apply(
}
}
-/// Realize into an element that is capable of root-level layout.
-#[tracing::instrument(skip_all)]
-pub fn realize_root<'a>(
- vt: &mut Vt,
- scratch: &'a Scratch<'a>,
- content: &'a Content,
- styles: StyleChain<'a>,
-) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> {
- if content.can::<dyn LayoutRoot>() && !applicable(content, styles) {
- return Ok((Cow::Borrowed(content), styles));
- }
-
- let mut builder = Builder::new(vt, scratch, true);
- builder.accept(content, styles)?;
- builder.interrupt_page(Some(styles), true)?;
- let (pages, shared) = builder.doc.unwrap().pages.finish();
- Ok((Cow::Owned(DocumentElem::new(pages.to_vec()).pack()), shared))
-}
-
-/// Realize into an element that is capable of block-level layout.
-#[tracing::instrument(skip_all)]
-pub fn realize_block<'a>(
- vt: &mut Vt,
- scratch: &'a Scratch<'a>,
- content: &'a Content,
- styles: StyleChain<'a>,
-) -> SourceResult<(Cow<'a, Content>, StyleChain<'a>)> {
- // These elements implement `Layout` but still require a flow for
- // proper layout.
- if content.can::<dyn Layout>()
- && !content.is::<BoxElem>()
- && !content.is::<LineElem>()
- && !content.is::<RectElem>()
- && !content.is::<SquareElem>()
- && !content.is::<EllipseElem>()
- && !content.is::<CircleElem>()
- && !content.is::<ImageElem>()
- && !content.is::<PolygonElem>()
- && !content.is::<PathElem>()
- && !content.is::<PlaceElem>()
- && !applicable(content, styles)
- {
- return Ok((Cow::Borrowed(content), styles));
- }
-
- let mut builder = Builder::new(vt, scratch, false);
- builder.accept(content, styles)?;
- builder.interrupt_par()?;
- let (children, shared) = builder.flow.0.finish();
- Ok((Cow::Owned(FlowElem::new(children.to_vec()).pack()), shared))
-}
-
/// Builds a document or a flow element from content.
struct Builder<'a, 'v, 't> {
- /// The virtual typesetter.
- vt: &'v mut Vt<'t>,
+ /// The engine.
+ engine: &'v mut Engine<'t>,
/// Scratch arenas for building.
scratch: &'a Scratch<'a>,
/// The current document building state.
@@ -282,9 +283,9 @@ pub struct Scratch<'a> {
}
impl<'a, 'v, 't> Builder<'a, 'v, 't> {
- fn new(vt: &'v mut Vt<'t>, scratch: &'a Scratch<'a>, top: bool) -> Self {
+ fn new(engine: &'v mut Engine<'t>, scratch: &'a Scratch<'a>, top: bool) -> Self {
Self {
- vt,
+ engine,
scratch,
doc: top.then(DocBuilder::default),
flow: FlowBuilder::default(),
@@ -304,9 +305,19 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> {
self.scratch.content.alloc(EquationElem::new(content.clone()).pack());
}
- if let Some(realized) = realize(self.vt, content, styles)? {
+ if let Some(realized) = realize(self.engine, content, styles)? {
+ self.engine.route.increase();
+ if self.engine.route.exceeding() {
+ bail!(error!(content.span(), "maximum show rule depth exceeded")
+ .with_hint("check whether the show rule matches its own output")
+ .with_hint(
+ "this is a current compiler limitation that will be resolved in the future"
+ ));
+ }
let stored = self.scratch.content.alloc(realized);
- return self.accept(stored, styles);
+ let v = self.accept(stored, styles);
+ self.engine.route.decrease();
+ return v;
}
if let Some((elem, local)) = content.to_styled() {
diff --git a/crates/typst/src/text/deco.rs b/crates/typst/src/text/deco.rs
index f7ee8cbc..348ddf34 100644
--- a/crates/typst/src/text/deco.rs
+++ b/crates/typst/src/text/deco.rs
@@ -4,8 +4,9 @@ use ttf_parser::{GlyphId, OutlineBuilder};
use ecow::{eco_format, EcoString};
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{cast, elem, ty, Content, Fold, Repr, Show, Smart, StyleChain};
-use crate::layout::{Abs, Em, Frame, FrameItem, Length, Point, Size, Vt};
+use crate::layout::{Abs, Em, Frame, FrameItem, Length, Point, Size};
use crate::syntax::Span;
use crate::text::{
BottomEdge, BottomEdgeMetric, TextElem, TextItem, TopEdge, TopEdgeMetric,
@@ -85,7 +86,7 @@ pub struct UnderlineElem {
impl Show for UnderlineElem {
#[tracing::instrument(name = "UnderlineElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
line: DecoLine::Underline {
stroke: self.stroke(styles).unwrap_or_default(),
@@ -177,7 +178,7 @@ pub struct OverlineElem {
impl Show for OverlineElem {
#[tracing::instrument(name = "OverlineElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
line: DecoLine::Overline {
stroke: self.stroke(styles).unwrap_or_default(),
@@ -254,7 +255,7 @@ pub struct StrikeElem {
impl Show for StrikeElem {
#[tracing::instrument(name = "StrikeElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
// Note that we do not support evade option for strikethrough.
line: DecoLine::Strikethrough {
@@ -324,7 +325,7 @@ pub struct HighlightElem {
impl Show for HighlightElem {
#[tracing::instrument(name = "HighlightElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone().styled(TextElem::set_deco(Decoration {
line: DecoLine::Highlight {
fill: self.fill(styles),
diff --git a/crates/typst/src/text/mod.rs b/crates/typst/src/text/mod.rs
index 45de35f9..da3580a5 100644
--- a/crates/typst/src/text/mod.rs
+++ b/crates/typst/src/text/mod.rs
@@ -35,7 +35,7 @@ use rustybuzz::{Feature, Tag};
use ttf_parser::Rect;
use crate::diag::{bail, error, SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
cast, category, elem, Args, Array, Cast, Category, Construct, Content, Dict, Fold,
NativeElement, Never, PlainText, Repr, Resolve, Scope, Set, Smart, StyleChain, Value,
@@ -656,11 +656,11 @@ impl Repr for TextElem {
}
impl Construct for TextElem {
- fn construct(vm: &mut Vm, args: &mut Args) -> SourceResult<Content> {
+ fn construct(engine: &mut Engine, args: &mut Args) -> SourceResult<Content> {
// The text constructor is special: It doesn't create a text element.
// Instead, it leaves the passed argument structurally unchanged, but
// styles all text in it.
- let styles = Self::set(vm, args)?;
+ let styles = Self::set(engine, args)?;
let body = args.expect::<Content>("body")?;
Ok(body.styled_with_map(styles))
}
diff --git a/crates/typst/src/text/raw.rs b/crates/typst/src/text/raw.rs
index 1142281c..6962dbce 100644
--- a/crates/typst/src/text/raw.rs
+++ b/crates/typst/src/text/raw.rs
@@ -10,12 +10,12 @@ use syntect::parsing::{SyntaxDefinition, SyntaxSet, SyntaxSetBuilder};
use unicode_segmentation::UnicodeSegmentation;
use crate::diag::{At, FileError, SourceResult, StrResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, scope, Args, Array, Bytes, Content, Finalize, Fold, NativeElement,
PlainText, Show, Smart, StyleChain, Styles, Synthesize, Value,
};
-use crate::layout::{BlockElem, Em, HAlign, Vt};
+use crate::layout::{BlockElem, Em, HAlign};
use crate::model::Figurable;
use crate::syntax::{split_newlines, LinkedNode, Spanned};
use crate::text::{
@@ -191,7 +191,7 @@ pub struct RawElem {
/// ```
/// ````
#[parse(
- let (syntaxes, syntaxes_data) = parse_syntaxes(vm, args)?;
+ let (syntaxes, syntaxes_data) = parse_syntaxes(engine, args)?;
syntaxes
)]
#[fold]
@@ -229,7 +229,7 @@ pub struct RawElem {
/// ```
/// ````
#[parse(
- let (theme_path, theme_data) = parse_theme(vm, args)?;
+ let (theme_path, theme_data) = parse_theme(engine, args)?;
theme_path.map(Some)
)]
#[borrowed]
@@ -288,7 +288,7 @@ impl RawElem {
}
impl Synthesize for RawElem {
- fn synthesize(&mut self, _vt: &mut Vt, styles: StyleChain) -> SourceResult<()> {
+ fn synthesize(&mut self, _: &mut Engine, styles: StyleChain) -> SourceResult<()> {
self.push_lang(self.lang(styles).clone());
let mut text = self.text().clone();
@@ -393,7 +393,7 @@ impl Synthesize for RawElem {
impl Show for RawElem {
#[tracing::instrument(name = "RawElem::show", skip_all)]
- fn show(&self, _: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let mut lines = EcoVec::with_capacity((2 * self.lines().len()).saturating_sub(1));
for (i, line) in self.lines().iter().enumerate() {
if i != 0 {
@@ -495,7 +495,7 @@ pub struct RawLine {
}
impl Show for RawLine {
- fn show(&self, _vt: &mut Vt, _styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, _: &mut Engine, _styles: StyleChain) -> SourceResult<Content> {
Ok(self.body().clone())
}
}
@@ -676,7 +676,7 @@ fn load_syntaxes(paths: &SyntaxPaths, bytes: &[Bytes]) -> StrResult<Arc<SyntaxSe
/// Function to parse the syntaxes argument.
/// Much nicer than having it be part of the `element` macro.
fn parse_syntaxes(
- vm: &mut Vm,
+ engine: &mut Engine,
args: &mut Args,
) -> SourceResult<(Option<SyntaxPaths>, Option<Vec<Bytes>>)> {
let Some(Spanned { v: paths, span }) =
@@ -690,8 +690,8 @@ fn parse_syntaxes(
.0
.iter()
.map(|path| {
- let id = vm.resolve_path(path).at(span)?;
- vm.world().file(id).at(span)
+ let id = span.resolve_path(path).at(span)?;
+ engine.world.file(id).at(span)
})
.collect::<SourceResult<Vec<Bytes>>>()?;
@@ -713,7 +713,7 @@ fn load_theme(path: &str, bytes: &Bytes) -> StrResult<Arc<synt::Theme>> {
/// Function to parse the theme argument.
/// Much nicer than having it be part of the `element` macro.
fn parse_theme(
- vm: &mut Vm,
+ engine: &mut Engine,
args: &mut Args,
) -> SourceResult<(Option<EcoString>, Option<Bytes>)> {
let Some(Spanned { v: path, span }) = args.named::<Spanned<EcoString>>("theme")?
@@ -722,8 +722,8 @@ fn parse_theme(
};
// Load theme file.
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
// Check that parsing works.
let _ = load_theme(&path, &data).at(span)?;
diff --git a/crates/typst/src/text/shift.rs b/crates/typst/src/text/shift.rs
index 73f28343..e467d6c0 100644
--- a/crates/typst/src/text/shift.rs
+++ b/crates/typst/src/text/shift.rs
@@ -1,8 +1,9 @@
use ecow::EcoString;
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, Show, StyleChain};
-use crate::layout::{Em, Length, Vt};
+use crate::layout::{Em, Length};
use crate::text::{variant, SpaceElem, TextElem, TextSize};
use crate::World;
@@ -48,12 +49,12 @@ pub struct SubElem {
impl Show for SubElem {
#[tracing::instrument(name = "SubElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let body = self.body().clone();
let mut transformed = None;
if self.typographic(styles) {
if let Some(text) = search_text(&body, true) {
- if is_shapable(vt, &text, styles) {
+ if is_shapable(engine, &text, styles) {
transformed = Some(TextElem::packed(text));
}
}
@@ -108,12 +109,12 @@ pub struct SuperElem {
impl Show for SuperElem {
#[tracing::instrument(name = "SuperElem::show", skip_all)]
- fn show(&self, vt: &mut Vt, styles: StyleChain) -> SourceResult<Content> {
+ fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult<Content> {
let body = self.body().clone();
let mut transformed = None;
if self.typographic(styles) {
if let Some(text) = search_text(&body, false) {
- if is_shapable(vt, &text, styles) {
+ if is_shapable(engine, &text, styles) {
transformed = Some(TextElem::packed(text));
}
}
@@ -149,8 +150,8 @@ fn search_text(content: &Content, sub: bool) -> Option<EcoString> {
/// Checks whether the first retrievable family contains all code points of the
/// given string.
-fn is_shapable(vt: &Vt, text: &str, styles: StyleChain) -> bool {
- let world = vt.world;
+fn is_shapable(engine: &Engine, text: &str, styles: StyleChain) -> bool {
+ let world = engine.world;
for family in TextElem::font_in(styles) {
if let Some(font) = world
.book()
diff --git a/crates/typst/src/visualize/image/mod.rs b/crates/typst/src/visualize/image/mod.rs
index 722e77a6..159dc14a 100644
--- a/crates/typst/src/visualize/image/mod.rs
+++ b/crates/typst/src/visualize/image/mod.rs
@@ -14,13 +14,14 @@ use comemo::{Prehashed, Tracked};
use ecow::EcoString;
use crate::diag::{bail, At, SourceResult, StrResult};
+use crate::engine::Engine;
use crate::foundations::{
cast, elem, func, scope, Bytes, Cast, Content, NativeElement, Resolve, Smart,
StyleChain,
};
use crate::layout::{
Abs, Axes, FixedAlign, Fragment, Frame, FrameItem, Layout, Length, Point, Regions,
- Rel, Size, Vt,
+ Rel, Size,
};
use crate::loading::Readable;
use crate::model::Figurable;
@@ -57,8 +58,8 @@ pub struct ImageElem {
#[parse(
let Spanned { v: path, span } =
args.expect::<Spanned<EcoString>>("path to image file")?;
- let id = vm.resolve_path(&path).at(span)?;
- let data = vm.world().file(id).at(span)?;
+ let id = span.resolve_path(&path).at(span)?;
+ let data = engine.world.file(id).at(span)?;
path
)]
#[borrowed]
@@ -145,7 +146,7 @@ impl Layout for ImageElem {
#[tracing::instrument(name = "ImageElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
@@ -181,7 +182,7 @@ impl Layout for ImageElem {
data.clone().into(),
format,
self.alt(styles),
- vt.world,
+ engine.world,
&families(styles).map(|s| s.into()).collect::<Vec<_>>(),
)
.at(self.span())?;
diff --git a/crates/typst/src/visualize/line.rs b/crates/typst/src/visualize/line.rs
index 118395ec..ece93727 100644
--- a/crates/typst/src/visualize/line.rs
+++ b/crates/typst/src/visualize/line.rs
@@ -1,7 +1,8 @@
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{elem, NativeElement, StyleChain};
use crate::layout::{
- Abs, Angle, Axes, Fragment, Frame, FrameItem, Layout, Length, Regions, Rel, Size, Vt,
+ Abs, Angle, Axes, Fragment, Frame, FrameItem, Layout, Length, Regions, Rel, Size,
};
use crate::util::Numeric;
use crate::visualize::{Geometry, Stroke};
@@ -61,7 +62,7 @@ impl Layout for LineElem {
#[tracing::instrument(name = "LineElem::layout", skip_all)]
fn layout(
&self,
- _: &mut Vt,
+ _: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
diff --git a/crates/typst/src/visualize/path.rs b/crates/typst/src/visualize/path.rs
index f2e1466f..6ed07cb2 100644
--- a/crates/typst/src/visualize/path.rs
+++ b/crates/typst/src/visualize/path.rs
@@ -1,11 +1,12 @@
use kurbo::{CubicBez, ParamCurveExtrema};
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
array, cast, elem, Array, NativeElement, Reflect, Resolve, Smart, StyleChain,
};
use crate::layout::{
- Abs, Axes, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel, Size, Vt,
+ Abs, Axes, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel, Size,
};
use crate::visualize::{FixedStroke, Geometry, Paint, Shape, Stroke};
@@ -73,7 +74,7 @@ impl Layout for PathElem {
#[tracing::instrument(name = "PathElem::layout", skip_all)]
fn layout(
&self,
- _: &mut Vt,
+ _: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
diff --git a/crates/typst/src/visualize/pattern.rs b/crates/typst/src/visualize/pattern.rs
index 55d68500..3014a8e0 100644
--- a/crates/typst/src/visualize/pattern.rs
+++ b/crates/typst/src/visualize/pattern.rs
@@ -5,7 +5,7 @@ use comemo::Prehashed;
use ecow::{eco_format, EcoString};
use crate::diag::{bail, error, SourceResult};
-use crate::eval::Vm;
+use crate::engine::Engine;
use crate::foundations::{func, scope, ty, Content, Repr, Smart, StyleChain};
use crate::layout::{Abs, Axes, Em, Frame, Layout, Length, Regions, Size};
use crate::syntax::{Span, Spanned};
@@ -120,7 +120,7 @@ impl Pattern {
/// ```
#[func(constructor)]
pub fn construct(
- vm: &mut Vm,
+ engine: &mut Engine,
/// The bounding box of each cell of the pattern.
#[named]
#[default(Spanned::new(Smart::Auto, Span::detached()))]
@@ -173,11 +173,11 @@ impl Pattern {
let region = size.unwrap_or_else(|| Axes::splat(Abs::inf()));
// Layout the pattern.
- let world = vm.vt.world;
+ let world = engine.world;
let library = world.library();
let styles = StyleChain::new(&library.styles);
let pod = Regions::one(region, Axes::splat(false));
- let mut frame = body.layout(&mut vm.vt, styles, pod)?.into_frame();
+ let mut frame = body.layout(engine, styles, pod)?.into_frame();
// Check that the frame is non-zero.
if size.is_auto() && frame.size().is_zero() {
diff --git a/crates/typst/src/visualize/polygon.rs b/crates/typst/src/visualize/polygon.rs
index 3b818fa4..7436f63e 100644
--- a/crates/typst/src/visualize/polygon.rs
+++ b/crates/typst/src/visualize/polygon.rs
@@ -1,11 +1,12 @@
use std::f64::consts::PI;
use crate::diag::{bail, SourceResult};
+use crate::engine::Engine;
use crate::foundations::{
elem, func, scope, Content, NativeElement, Resolve, Smart, StyleChain,
};
use crate::layout::{
- Axes, Em, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel, Vt,
+ Axes, Em, Fragment, Frame, FrameItem, Layout, Length, Point, Regions, Rel,
};
use crate::util::Numeric;
use crate::visualize::{FixedStroke, Geometry, Paint, Path, Shape, Stroke};
@@ -125,7 +126,7 @@ impl Layout for PolygonElem {
#[tracing::instrument(name = "PolygonElem::layout", skip_all)]
fn layout(
&self,
- _: &mut Vt,
+ _: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
diff --git a/crates/typst/src/visualize/shape.rs b/crates/typst/src/visualize/shape.rs
index d1a2a155..fcdcfc31 100644
--- a/crates/typst/src/visualize/shape.rs
+++ b/crates/typst/src/visualize/shape.rs
@@ -1,10 +1,11 @@
use std::f64::consts::SQRT_2;
use crate::diag::SourceResult;
+use crate::engine::Engine;
use crate::foundations::{elem, Content, NativeElement, Resolve, Smart, StyleChain};
use crate::layout::{
Abs, Axes, Corner, Corners, Fragment, Frame, FrameItem, Layout, Length, Point, Ratio,
- Regions, Rel, Sides, Size, Vt,
+ Regions, Rel, Sides, Size,
};
use crate::syntax::Span;
use crate::util::Get;
@@ -134,12 +135,12 @@ impl Layout for RectElem {
#[tracing::instrument(name = "RectElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
layout(
- vt,
+ engine,
styles,
regions,
ShapeKind::Rect,
@@ -240,12 +241,12 @@ impl Layout for SquareElem {
#[tracing::instrument(name = "SquareElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
layout(
- vt,
+ engine,
styles,
regions,
ShapeKind::Square,
@@ -318,12 +319,12 @@ impl Layout for EllipseElem {
#[tracing::instrument(name = "EllipseElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
layout(
- vt,
+ engine,
styles,
regions,
ShapeKind::Ellipse,
@@ -421,12 +422,12 @@ impl Layout for CircleElem {
#[tracing::instrument(name = "CircleElem::layout", skip_all)]
fn layout(
&self,
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
) -> SourceResult<Fragment> {
layout(
- vt,
+ engine,
styles,
regions,
ShapeKind::Circle,
@@ -446,7 +447,7 @@ impl Layout for CircleElem {
#[tracing::instrument(name = "shape::layout", skip_all)]
#[allow(clippy::too_many_arguments)]
fn layout(
- vt: &mut Vt,
+ engine: &mut Engine,
styles: StyleChain,
regions: Regions,
kind: ShapeKind,
@@ -473,7 +474,7 @@ fn layout(
let child = child.clone().padded(inset.map(|side| side.map(Length::from)));
let expand = sizing.as_ref().map(Smart::is_custom);
let pod = Regions::one(region, expand);
- frame = child.layout(vt, styles, pod)?.into_frame();
+ frame = child.layout(engine, styles, pod)?.into_frame();
// Enforce correct size.
*frame.size_mut() = expand.select(region, frame.size());
@@ -484,7 +485,7 @@ fn layout(
frame.set_size(Size::splat(frame.size().max_by_side()));
let length = frame.size().max_by_side().min(region.min_by_side());
let pod = Regions::one(Size::splat(length), Axes::splat(true));
- frame = child.layout(vt, styles, pod)?.into_frame();
+ frame = child.layout(engine, styles, pod)?.into_frame();
}
// Enforce correct size again.