Add a bit more docs to compile

This commit is contained in:
Laurenz 2023-08-29 17:59:56 +02:00
parent a71a2057f2
commit 0e5c48ad0d
11 changed files with 66 additions and 51 deletions

View File

@ -73,7 +73,7 @@ pub fn compile_once(
world.reset(); world.reset();
world.source(world.main()).map_err(|err| err.to_string())?; world.source(world.main()).map_err(|err| err.to_string())?;
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
let result = typst::compile(world, &mut tracer); let result = typst::compile(world, &mut tracer);
let warnings = tracer.warnings(); let warnings = tracer.warnings();
@ -218,7 +218,7 @@ pub fn print_diagnostics(
config.display_style = term::DisplayStyle::Short; config.display_style = term::DisplayStyle::Short;
} }
for diagnostic in warnings.iter().chain(errors.iter()) { for diagnostic in warnings.iter().chain(errors) {
let diag = match diagnostic.severity { let diag = match diagnostic.severity {
Severity::Error => Diagnostic::error(), Severity::Error => Diagnostic::error(),
Severity::Warning => Diagnostic::warning(), Severity::Warning => Diagnostic::warning(),

View File

@ -20,7 +20,7 @@ pub fn query(command: QueryCommand) -> StrResult<()> {
world.reset(); world.reset();
world.source(world.main()).map_err(|err| err.to_string())?; world.source(world.main()).map_err(|err| err.to_string())?;
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
let result = typst::compile(&world, &mut tracer); let result = typst::compile(&world, &mut tracer);
let warnings = tracer.warnings(); let warnings = tracer.warnings();

View File

@ -429,8 +429,8 @@ fn code_block(resolver: &dyn Resolver, lang: &str, text: &str) -> Html {
let id = FileId::new(None, VirtualPath::new("main.typ")); let id = FileId::new(None, VirtualPath::new("main.typ"));
let source = Source::new(id, compile); let source = Source::new(id, compile);
let world = DocWorld(source); let world = DocWorld(source);
let mut tracer = Tracer::default();
let mut tracer = Tracer::new();
let mut frames = match typst::compile(&world, &mut tracer) { let mut frames = match typst::compile(&world, &mut tracer) {
Ok(doc) => doc.pages, Ok(doc) => doc.pages,
Err(err) => { Err(err) => {

View File

@ -90,7 +90,7 @@ const MAX_CALL_DEPTH: usize = 64;
/// Evaluate a source file and return the resulting module. /// Evaluate a source file and return the resulting module.
#[comemo::memoize] #[comemo::memoize]
#[tracing::instrument(skip(world, route, tracer, source))] #[tracing::instrument(skip_all)]
pub fn eval( pub fn eval(
world: Tracked<dyn World + '_>, world: Tracked<dyn World + '_>,
route: Tracked<Route>, route: Tracked<Route>,
@ -108,9 +108,9 @@ pub fn eval(
set_lang_items(library.items.clone()); set_lang_items(library.items.clone());
// Prepare VT. // Prepare VT.
let mut locator = Locator::default(); let mut locator = Locator::new();
let introspector = Introspector::default(); let introspector = Introspector::default();
let mut delayed = DelayedErrors::default(); let mut delayed = DelayedErrors::new();
let vt = Vt { let vt = Vt {
world, world,
introspector: introspector.track(), introspector: introspector.track(),
@ -126,7 +126,7 @@ pub fn eval(
let root = source.root(); let root = source.root();
let errors = root.errors(); let errors = root.errors();
if !errors.is_empty() && vm.traced.is_none() { if !errors.is_empty() && vm.inspected.is_none() {
return Err(Box::new(errors.into_iter().map(Into::into).collect())); return Err(Box::new(errors.into_iter().map(Into::into).collect()));
} }
@ -175,9 +175,9 @@ pub fn eval_string(
} }
// Prepare VT. // Prepare VT.
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
let mut locator = Locator::default(); let mut locator = Locator::new();
let mut delayed = DelayedErrors::default(); let mut delayed = DelayedErrors::new();
let introspector = Introspector::default(); let introspector = Introspector::default();
let vt = Vt { let vt = Vt {
world, world,
@ -242,8 +242,8 @@ pub struct Vm<'a> {
scopes: Scopes<'a>, scopes: Scopes<'a>,
/// The current call depth. /// The current call depth.
depth: usize, depth: usize,
/// A span that is currently traced. /// A span that is currently under inspection.
traced: Option<Span>, inspected: Option<Span>,
} }
impl<'a> Vm<'a> { impl<'a> Vm<'a> {
@ -254,7 +254,7 @@ impl<'a> Vm<'a> {
file: Option<FileId>, file: Option<FileId>,
scopes: Scopes<'a>, scopes: Scopes<'a>,
) -> Self { ) -> Self {
let traced = file.and_then(|id| vt.tracer.span(id)); let inspected = file.and_then(|id| vt.tracer.inspected(id));
let items = vt.world.library().items.clone(); let items = vt.world.library().items.clone();
Self { Self {
vt, vt,
@ -264,7 +264,7 @@ impl<'a> Vm<'a> {
flow: None, flow: None,
scopes, scopes,
depth: 0, depth: 0,
traced, inspected,
} }
} }
@ -294,8 +294,8 @@ impl<'a> Vm<'a> {
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub fn define(&mut self, var: ast::Ident, value: impl IntoValue) { pub fn define(&mut self, var: ast::Ident, value: impl IntoValue) {
let value = value.into_value(); let value = value.into_value();
if self.traced == Some(var.span()) { if self.inspected == Some(var.span()) {
self.vt.tracer.trace(value.clone()); self.vt.tracer.value(value.clone());
} }
self.scopes.top.define(var.get().clone(), value); self.scopes.top.define(var.get().clone(), value);
} }
@ -512,8 +512,8 @@ impl Eval for ast::Expr<'_> {
}? }?
.spanned(span); .spanned(span);
if vm.traced == Some(span) { if vm.inspected == Some(span) {
vm.vt.tracer.trace(v.clone()); vm.vt.tracer.value(v.clone());
} }
Ok(v) Ok(v)
@ -1954,8 +1954,8 @@ impl Access for ast::Ident<'_> {
fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> { fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value> {
let span = self.span(); let span = self.span();
let value = vm.scopes.get_mut(&self).at(span)?; let value = vm.scopes.get_mut(&self).at(span)?;
if vm.traced == Some(span) { if vm.inspected == Some(span) {
vm.vt.tracer.trace(value.clone()); vm.vt.tracer.value(value.clone());
} }
Ok(value) Ok(value)
} }

View File

@ -1,6 +1,6 @@
use std::collections::HashSet; use std::collections::HashSet;
use ecow::{eco_vec, EcoVec}; use ecow::EcoVec;
use super::Value; use super::Value;
use crate::diag::SourceDiagnostic; use crate::diag::SourceDiagnostic;
@ -10,27 +10,28 @@ use crate::util::hash128;
/// Traces warnings and which values existed for an expression at a span. /// Traces warnings and which values existed for an expression at a span.
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct Tracer { pub struct Tracer {
span: Option<Span>, inspected: Option<Span>,
values: EcoVec<Value>, values: EcoVec<Value>,
warnings: EcoVec<SourceDiagnostic>, warnings: EcoVec<SourceDiagnostic>,
warnings_set: HashSet<u128>, warnings_set: HashSet<u128>,
} }
impl Tracer { impl Tracer {
/// The maximum number of traced items. /// The maximum number of inspeted values.
pub const MAX: usize = 10; pub const MAX_VALUES: usize = 10;
/// Create a new tracer, possibly with a span under inspection. /// Create a new tracer.
pub fn new(span: Option<Span>) -> Self { pub fn new() -> Self {
Self { Self::default()
span,
values: eco_vec![],
warnings: eco_vec![],
warnings_set: HashSet::new(),
}
} }
/// Get the traced values. /// Mark a span as inspected. All values observed for this span can be
/// retrieved via `values` later.
pub fn inspect(&mut self, span: Span) {
self.inspected = Some(span);
}
/// Get the values for the inspeted span.
pub fn values(self) -> EcoVec<Value> { pub fn values(self) -> EcoVec<Value> {
self.values self.values
} }
@ -43,18 +44,18 @@ impl Tracer {
#[comemo::track] #[comemo::track]
impl Tracer { impl Tracer {
/// The traced span if it is part of the given source file. /// The inspeted span if it is part of the given source file.
pub fn span(&self, id: FileId) -> Option<Span> { pub fn inspected(&self, id: FileId) -> Option<Span> {
if self.span.and_then(Span::id) == Some(id) { if self.inspected.and_then(Span::id) == Some(id) {
self.span self.inspected
} else { } else {
None None
} }
} }
/// Trace a value for the span. /// Trace a value for the span.
pub fn trace(&mut self, v: Value) { pub fn value(&mut self, v: Value) {
if self.values.len() < Self::MAX { if self.values.len() < Self::MAX_VALUES {
self.values.push(v); self.values.push(v);
} }
} }

View File

@ -33,7 +33,8 @@ pub fn analyze_expr(world: &dyn World, node: &LinkedNode) -> EcoVec<Value> {
} }
} }
let mut tracer = Tracer::new(Some(node.span())); let mut tracer = Tracer::new();
tracer.inspect(node.span());
crate::compile(world, &mut tracer).ok(); crate::compile(world, &mut tracer).ok();
tracer.values() tracer.values()
} }
@ -45,7 +46,7 @@ pub fn analyze_expr(world: &dyn World, node: &LinkedNode) -> EcoVec<Value> {
/// Try to load a module from the current source file. /// Try to load a module from the current source file.
pub fn analyze_import(world: &dyn World, source: &Source, path: &str) -> Option<Module> { pub fn analyze_import(world: &dyn World, source: &Source, path: &str) -> Option<Module> {
let route = Route::default(); let route = Route::default();
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
let id = source.id().join(path); let id = source.id().join(path);
let source = world.source(id).ok()?; let source = world.source(id).ok()?;
eval(world.track(), route.track(), tracer.track_mut(), &source).ok() eval(world.track(), route.track(), tracer.track_mut(), &source).ok()

View File

@ -73,7 +73,7 @@ fn expr_tooltip(world: &(dyn World + 'static), leaf: &LinkedNode) -> Option<Tool
let mut last = None; let mut last = None;
let mut pieces: Vec<EcoString> = vec![]; let mut pieces: Vec<EcoString> = vec![];
let mut iter = values.iter(); let mut iter = values.iter();
for value in (&mut iter).take(Tracer::MAX - 1) { for value in (&mut iter).take(Tracer::MAX_VALUES - 1) {
if let Some((prev, count)) = &mut last { if let Some((prev, count)) = &mut last {
if *prev == value { if *prev == value {
*count += 1; *count += 1;

View File

@ -65,6 +65,13 @@ use crate::font::{Font, FontBook};
use crate::syntax::{FileId, PackageSpec, Source, Span}; use crate::syntax::{FileId, PackageSpec, Source, Span};
/// Compile a source file into a fully layouted document. /// Compile a source file into a fully layouted document.
///
/// - Returns `Ok(document)` if there were no fatal errors.
/// - Returns `Err(errors)` if there were fatal errors.
///
/// Requires a mutable reference to a tracer. Such a tracer can be created with
/// `Tracer::new()`. Independently of whether compilation succeeded, calling
/// `tracer.warnings()` after compilation will return all compiler warnings.
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub fn compile(world: &dyn World, tracer: &mut Tracer) -> SourceResult<Document> { pub fn compile(world: &dyn World, tracer: &mut Tracer) -> SourceResult<Document> {
let route = Route::default(); let route = Route::default();

View File

@ -60,7 +60,7 @@ pub fn typeset(
loop { loop {
tracing::info!("Layout iteration {iter}"); tracing::info!("Layout iteration {iter}");
delayed = DelayedErrors::default(); delayed = DelayedErrors::new();
let constraint = <Introspector as Validate>::Constraint::new(); let constraint = <Introspector as Validate>::Constraint::new();
let mut locator = Locator::new(); let mut locator = Locator::new();
@ -148,6 +148,13 @@ impl Vt<'_> {
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct DelayedErrors(Vec<SourceDiagnostic>); pub struct DelayedErrors(Vec<SourceDiagnostic>);
impl DelayedErrors {
/// Create an empty list of delayed errors.
pub fn new() -> Self {
Self::default()
}
}
#[comemo::track] #[comemo::track]
impl DelayedErrors { impl DelayedErrors {
/// Push a delayed error. /// Push a delayed error.

View File

@ -58,7 +58,7 @@ fn bench_edit(iai: &mut Iai) {
fn bench_eval(iai: &mut Iai) { fn bench_eval(iai: &mut Iai) {
let world = BenchWorld::new(); let world = BenchWorld::new();
let route = typst::eval::Route::default(); let route = typst::eval::Route::default();
let mut tracer = typst::eval::Tracer::default(); let mut tracer = typst::eval::Tracer::new();
iai.run(|| { iai.run(|| {
typst::eval::eval(world.track(), route.track(), tracer.track_mut(), &world.source) typst::eval::eval(world.track(), route.track(), tracer.track_mut(), &world.source)
.unwrap() .unwrap()
@ -68,7 +68,7 @@ fn bench_eval(iai: &mut Iai) {
fn bench_typeset(iai: &mut Iai) { fn bench_typeset(iai: &mut Iai) {
let world = BenchWorld::new(); let world = BenchWorld::new();
let route = typst::eval::Route::default(); let route = typst::eval::Route::default();
let mut tracer = typst::eval::Tracer::default(); let mut tracer = typst::eval::Tracer::new();
let module = typst::eval::eval( let module = typst::eval::eval(
world.track(), world.track(),
route.track(), route.track(),
@ -82,13 +82,13 @@ fn bench_typeset(iai: &mut Iai) {
fn bench_compile(iai: &mut Iai) { fn bench_compile(iai: &mut Iai) {
let world = BenchWorld::new(); let world = BenchWorld::new();
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
iai.run(|| typst::compile(&world, &mut tracer)); iai.run(|| typst::compile(&world, &mut tracer));
} }
fn bench_render(iai: &mut Iai) { fn bench_render(iai: &mut Iai) {
let world = BenchWorld::new(); let world = BenchWorld::new();
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
let document = typst::compile(&world, &mut tracer).unwrap(); let document = typst::compile(&world, &mut tracer).unwrap();
iai.run(|| typst::export::render(&document.pages[0], 1.0, Color::WHITE)) iai.run(|| typst::export::render(&document.pages[0], 1.0, Color::WHITE))
} }

View File

@ -526,15 +526,14 @@ fn test_part(
if world.print.model { if world.print.model {
let world = (world as &dyn World).track(); let world = (world as &dyn World).track();
let route = typst::eval::Route::default(); let route = typst::eval::Route::default();
let mut tracer = typst::eval::Tracer::default(); let mut tracer = typst::eval::Tracer::new();
let module = let module =
typst::eval::eval(world, route.track(), tracer.track_mut(), &source).unwrap(); typst::eval::eval(world, route.track(), tracer.track_mut(), &source).unwrap();
writeln!(output, "Model:\n{:#?}\n", module.content()).unwrap(); writeln!(output, "Model:\n{:#?}\n", module.content()).unwrap();
} }
let mut tracer = Tracer::default(); let mut tracer = Tracer::new();
let (mut frames, diagnostics) = match typst::compile(world, &mut tracer) { let (mut frames, diagnostics) = match typst::compile(world, &mut tracer) {
Ok(document) => (document.pages, tracer.warnings()), Ok(document) => (document.pages, tracer.warnings()),
Err(errors) => { Err(errors) => {