typst/src/lib.rs
Laurenz 1ee1d078e2 Fatal errors
- Makes errors fatal, so that a phase is only reached when all previous phases were error-free
- Parsing still recovers and can produce multiple errors
- Evaluation fails fast and can thus produce only a single error (except for parse errors due to an import)
- The single error that could occur during execution is removed for now
- Removes Value::Error variant
2021-07-30 18:49:19 +02:00

153 lines
4.8 KiB
Rust

//! The compiler for the _Typst_ typesetting language.
//!
//! # Steps
//! - **Parsing:** The parsing step first transforms a plain string into an
//! [iterator of tokens][tokens]. This token stream is [parsed] into a [syntax
//! tree]. The structures describing the tree can be found in the [syntax]
//! module.
//! - **Evaluation:** The next step is to [evaluate] the syntax tree. This
//! computes the value of each node in the document and produces a [module].
//! - **Execution:** Now, we can [execute] the parsed and evaluated module. This
//! results in a [layout tree], a high-level, fully styled representation of
//! the document. The nodes of this tree are self-contained and
//! order-independent and thus much better suited for layouting than the
//! syntax tree.
//! - **Layouting:** Next, the tree is [layouted] into a portable version of the
//! typeset document. The output of this is a collection of [`Frame`]s (one
//! per page), ready for exporting.
//! - **Exporting:** The finished layout can be exported into a supported
//! format. Currently, the only supported output format is [PDF].
//!
//! [tokens]: parse::Tokens
//! [parsed]: parse::parse
//! [syntax tree]: syntax::SyntaxTree
//! [evaluate]: eval::eval
//! [module]: eval::Module
//! [execute]: exec::exec
//! [layout tree]: layout::LayoutTree
//! [layouted]: layout::layout
//! [PDF]: export::pdf
#[macro_use]
pub mod diag;
#[macro_use]
pub mod eval;
pub mod color;
pub mod exec;
pub mod export;
pub mod font;
pub mod geom;
pub mod image;
pub mod layout;
pub mod library;
pub mod loading;
pub mod paper;
pub mod parse;
pub mod pretty;
pub mod syntax;
pub mod util;
use std::rc::Rc;
use crate::diag::TypResult;
use crate::eval::{ModuleCache, Scope};
use crate::exec::State;
use crate::font::FontCache;
use crate::image::ImageCache;
use crate::layout::Frame;
#[cfg(feature = "layout-cache")]
use crate::layout::LayoutCache;
use crate::loading::{FileId, Loader};
/// The core context which holds the loader, configuration and cached artifacts.
pub struct Context {
/// The loader the context was created with.
pub loader: Rc<dyn Loader>,
/// Caches parsed font faces.
pub fonts: FontCache,
/// Caches decoded images.
pub images: ImageCache,
/// Caches evaluated modules.
pub modules: ModuleCache,
/// Caches layouting artifacts.
#[cfg(feature = "layout-cache")]
pub layouts: LayoutCache,
/// The standard library scope.
std: Scope,
/// The default state.
state: State,
}
impl Context {
/// Create a new context with the default settings.
pub fn new(loader: Rc<dyn Loader>) -> Self {
Self::builder().build(loader)
}
/// Create a new context with advanced settings.
pub fn builder() -> ContextBuilder {
ContextBuilder::default()
}
/// Garbage-collect caches.
pub fn turnaround(&mut self) {
#[cfg(feature = "layout-cache")]
self.layouts.turnaround();
}
/// Typeset a source file into a collection of layouted frames.
///
/// The `file` identifies the source file and is used to resolve relative
/// paths (for importing and image loading).
///
/// Returns either a vector of frames representing individual pages or
/// diagnostics in the form of a vector of error message with file and span
/// information.
pub fn typeset(&mut self, file: FileId, src: &str) -> TypResult<Vec<Rc<Frame>>> {
let ast = parse::parse(file, src)?;
let module = eval::eval(self, file, Rc::new(ast))?;
let tree = exec::exec(self, &module.template);
let frames = layout::layout(self, &tree);
Ok(frames)
}
}
/// A builder for a [`Context`].
///
/// This struct is created by [`Context::builder`].
#[derive(Default)]
pub struct ContextBuilder {
std: Option<Scope>,
state: Option<State>,
}
impl ContextBuilder {
/// The scope containing definitions that are available everywhere
/// (the standard library).
pub fn std(mut self, std: Scope) -> Self {
self.std = Some(std);
self
}
/// The initial properties for page size, font selection and so on.
pub fn state(mut self, state: State) -> Self {
self.state = Some(state);
self
}
/// Finish building the context by providing the `loader` used to load
/// fonts, images, source files and other resources.
pub fn build(self, loader: Rc<dyn Loader>) -> Context {
Context {
loader: Rc::clone(&loader),
fonts: FontCache::new(Rc::clone(&loader)),
images: ImageCache::new(loader),
modules: ModuleCache::new(),
#[cfg(feature = "layout-cache")]
layouts: LayoutCache::new(),
std: self.std.unwrap_or(library::new()),
state: self.state.unwrap_or_default(),
}
}
}