diff --git a/benches/oneshot.rs b/benches/oneshot.rs index fef0e6e13..7a5a3dba7 100644 --- a/benches/oneshot.rs +++ b/benches/oneshot.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use iai::{black_box, main, Iai}; use unscanny::Scanner; -use typst::eval::evaluate; use typst::loading::MemLoader; use typst::parse::{TokenMode, Tokens}; use typst::source::SourceId; @@ -88,7 +87,7 @@ fn bench_eval(iai: &mut Iai) { fn bench_layout(iai: &mut Iai) { let (mut ctx, id) = context(); - let module = evaluate(&mut ctx, id, vec![]).unwrap(); + let module = typst::eval::evaluate(&mut ctx, id, vec![]).unwrap(); iai.run(|| typst::model::layout(&mut ctx, &module.content)); } diff --git a/src/eval/func.rs b/src/eval/func.rs index 16575c80a..f15549dce 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -230,6 +230,7 @@ impl Closure { // Evaluate the body. let mut sub = Machine::new(vm.ctx, route, scopes); let result = self.body.eval(&mut sub); + vm.deps.extend(sub.deps); // Handle control flow. match sub.flow { diff --git a/src/eval/machine.rs b/src/eval/machine.rs index 146339788..904a64c8f 100644 --- a/src/eval/machine.rs +++ b/src/eval/machine.rs @@ -13,6 +13,8 @@ pub struct Machine<'a> { pub ctx: &'a mut Context, /// The route of source ids at which the machine is located. pub route: Vec, + /// The dependencies of the current evaluation process. + pub deps: Vec<(SourceId, usize)>, /// The stack of scopes. pub scopes: Scopes<'a>, /// A control flow event that is currently happening. @@ -22,7 +24,13 @@ pub struct Machine<'a> { impl<'a> Machine<'a> { /// Create a new virtual machine. pub fn new(ctx: &'a mut Context, route: Vec, scopes: Scopes<'a>) -> Self { - Self { ctx, route, scopes, flow: None } + Self { + ctx, + route, + deps: vec![], + scopes, + flow: None, + } } /// Resolve a user-entered path to be relative to the compilation diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 702a76b2f..e403c3cba 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -73,28 +73,26 @@ pub fn evaluate( // Parse the file. let source = ctx.sources.get(id); let ast = source.ast()?; - - // Save the old dependencies. - let prev_deps = std::mem::replace(&mut ctx.deps, vec![(id, source.rev())]); + let rev = source.rev(); // Evaluate the module. let std = ctx.config.std.clone(); let scopes = Scopes::new(Some(&std)); let mut vm = Machine::new(ctx, route, scopes); let result = ast.eval(&mut vm); - let scope = vm.scopes.top; - let flow = vm.flow; - - // Restore the and dependencies. - let deps = std::mem::replace(&mut ctx.deps, prev_deps); + vm.deps.push((id, rev)); // Handle control flow. - if let Some(flow) = flow { + if let Some(flow) = vm.flow { return Err(flow.forbidden()); } // Assemble the module. - let module = Module { scope, content: result?, deps }; + let module = Module { + scope: vm.scopes.top, + content: result?, + deps: vm.deps, + }; // Save the evaluated module. ctx.modules.insert(id, module.clone()); @@ -987,7 +985,8 @@ fn import(vm: &mut Machine, path: &str, span: Span) -> TypResult { // Evaluate the file. let route = vm.route.clone(); let module = evaluate(vm.ctx, id, route).trace(|| Tracepoint::Import, span)?; - vm.ctx.deps.extend(module.deps.iter().cloned()); + vm.deps.extend(module.deps.iter().cloned()); + Ok(module) } diff --git a/src/lib.rs b/src/lib.rs index 81c4afe69..7d848c53c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,30 +76,27 @@ pub fn typeset(ctx: &mut Context, id: SourceId) -> TypResult>> { /// The core context which holds the configuration and stores. pub struct Context { + /// The context's configuration. + pub config: Config, /// Stores loaded source files. pub sources: SourceStore, /// Stores parsed font faces. pub fonts: FontStore, /// Stores decoded images. pub images: ImageStore, - /// The context's configuration. - pub config: Config, - /// Cached modules. - modules: HashMap, - /// The dependencies of the current evaluation process. - deps: Vec<(SourceId, usize)>, + /// Stores evaluated modules. + pub modules: HashMap, } impl Context { /// Create a new context. pub fn new(loader: Arc, config: Config) -> Self { Self { + config, sources: SourceStore::new(Arc::clone(&loader)), fonts: FontStore::new(Arc::clone(&loader)), images: ImageStore::new(loader), - config, modules: HashMap::new(), - deps: vec![], } } } diff --git a/src/library/utility/mod.rs b/src/library/utility/mod.rs index 051f81958..10aa7c7a1 100644 --- a/src/library/utility/mod.rs +++ b/src/library/utility/mod.rs @@ -39,6 +39,7 @@ pub fn eval(vm: &mut Machine, args: &mut Args) -> TypResult { let scopes = Scopes::new(Some(&std)); let mut sub = Machine::new(vm.ctx, vec![], scopes); let result = ast.eval(&mut sub); + assert!(vm.deps.is_empty()); // Handle control flow. if let Some(flow) = sub.flow { diff --git a/src/main.rs b/src/main.rs index 821f10083..33302eee4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,13 +11,11 @@ use same_file::is_same_file; use termcolor::{ColorChoice, StandardStream, WriteColor}; use typst::diag::{Error, StrResult}; -use typst::export; use typst::font::{FaceInfo, FontStore}; use typst::library::text::THEME; use typst::loading::FsLoader; use typst::parse::TokenMode; use typst::source::SourceStore; -use typst::syntax; use typst::{Config, Context}; /// What to do. @@ -217,7 +215,7 @@ fn typeset(command: TypesetCommand) -> StrResult<()> { match typst::typeset(&mut ctx, id) { // Export the PDF. Ok(frames) => { - let buffer = export::pdf(&ctx, &frames); + let buffer = typst::export::pdf(&ctx, &frames); fs::write(&command.output, buffer).map_err(|_| "failed to write PDF file")?; } @@ -266,7 +264,7 @@ fn highlight(command: HighlightCommand) -> StrResult<()> { let input = std::fs::read_to_string(&command.input) .map_err(|_| "failed to load source file")?; - let html = syntax::highlight_html(&input, TokenMode::Markup, &THEME); + let html = typst::syntax::highlight_html(&input, TokenMode::Markup, &THEME); fs::write(&command.output, html).map_err(|_| "failed to write HTML file")?; Ok(())