No more collisions between syntax::Tree and layout::Tree

This commit is contained in:
Laurenz 2021-06-30 11:40:27 +02:00
parent 45812b7001
commit 470f8001a1
13 changed files with 69 additions and 66 deletions

View File

@ -8,10 +8,10 @@ use typst::cache::Cache;
use typst::eval::{eval, Module, Scope};
use typst::exec::{exec, State};
use typst::export::pdf;
use typst::layout::{self, layout, Frame};
use typst::layout::{layout, Frame, LayoutTree};
use typst::loading::FsLoader;
use typst::parse::parse;
use typst::syntax;
use typst::syntax::SyntaxTree;
use typst::typeset;
const FONT_DIR: &str = "../fonts";
@ -26,7 +26,6 @@ fn benchmarks(c: &mut Criterion) {
let src = std::fs::read_to_string(&path).unwrap();
let case = Case::new(src, ctx.clone());
/// Bench with all caches.
macro_rules! bench {
($step:literal, setup = |$cache:ident| $setup:expr, code = $code:expr $(,)?) => {
c.bench_function(&format!("{}-{}", $step, name), |b| {
@ -97,9 +96,9 @@ struct Case {
src: String,
scope: Scope,
state: State,
ast: Rc<syntax::Tree>,
ast: Rc<SyntaxTree>,
module: Module,
tree: layout::Tree,
tree: LayoutTree,
frames: Vec<Rc<Frame>>,
}
@ -111,7 +110,7 @@ impl Case {
let state = typst::exec::State::default();
let src = src.into();
let ast = Rc::new(parse(&src).output);
let module = eval(loader, cache, None, ast.clone(), &scope).output;
let module = eval(loader, cache, None, Rc::clone(&ast), &scope).output;
let tree = exec(&module.template, state.clone()).output;
let frames = layout(loader, cache, &tree);
drop(borrowed);
@ -127,17 +126,17 @@ impl Case {
}
}
fn parse(&self) -> syntax::Tree {
fn parse(&self) -> SyntaxTree {
parse(&self.src).output
}
fn eval(&self) -> Module {
let mut borrowed = self.ctx.borrow_mut();
let Context { loader, cache } = &mut *borrowed;
eval(loader, cache, None, self.ast.clone(), &self.scope).output
eval(loader, cache, None, Rc::clone(&self.ast), &self.scope).output
}
fn exec(&self) -> layout::Tree {
fn exec(&self) -> LayoutTree {
exec(&self.module.template, self.state.clone()).output
}

View File

@ -30,11 +30,11 @@ pub fn eval(
loader: &mut dyn Loader,
cache: &mut Cache,
path: Option<&Path>,
tree: Rc<Tree>,
ast: Rc<SyntaxTree>,
scope: &Scope,
) -> Pass<Module> {
let mut ctx = EvalContext::new(loader, cache, path, scope);
let template = tree.eval(&mut ctx);
let template = ast.eval(&mut ctx);
let module = Module { scope: ctx.scopes.top, template };
Pass::new(module, ctx.diags)
}
@ -148,8 +148,8 @@ impl<'a> EvalContext<'a> {
self.route.push(hash);
// Evaluate the module.
let tree = Rc::new(parsed.output);
let template = tree.eval(self);
let ast = Rc::new(parsed.output);
let template = ast.eval(self);
// Restore the old context.
let new_scopes = mem::replace(&mut self.scopes, old_scopes);
@ -212,7 +212,7 @@ pub trait Eval {
fn eval(&self, ctx: &mut EvalContext) -> Self::Output;
}
impl Eval for Rc<Tree> {
impl Eval for Rc<SyntaxTree> {
type Output = TemplateValue;
fn eval(&self, ctx: &mut EvalContext) -> Self::Output {

View File

@ -10,7 +10,7 @@ use super::EvalContext;
use crate::color::{Color, RgbaColor};
use crate::exec::ExecContext;
use crate::geom::{Angle, Fractional, Length, Linear, Relative};
use crate::syntax::{Expr, Span, Spanned, Tree};
use crate::syntax::{Expr, Span, Spanned, SyntaxTree};
/// A computational value.
#[derive(Debug, Clone, PartialEq)]
@ -165,8 +165,8 @@ pub enum TemplateNode {
/// expression.
Tree {
/// The syntax tree of the corresponding template expression.
tree: Rc<Tree>,
/// The evaluated expressions for the `tree`.
tree: Rc<SyntaxTree>,
/// The evaluated expressions in the syntax tree.
map: ExprMap,
},
/// A template that was converted from a string.
@ -184,10 +184,10 @@ impl PartialEq for TemplateNode {
/// A map from expressions to the values they evaluated to.
///
/// The raw pointers point into the expressions contained in some [`Tree`].
/// Since the lifetime is erased, the tree could go out of scope while the hash
/// map still lives. Although this could lead to lookup panics, it is not unsafe
/// since the pointers are never dereferenced.
/// The raw pointers point into the expressions contained in some
/// [`SyntaxTree`]. Since the lifetime is erased, the tree could go out of scope
/// while the hash map still lives. Although this could lead to lookup panics,
/// it is not unsafe since the pointers are never dereferenced.
pub type ExprMap = HashMap<*const Expr, Value>;
/// A reference-counted dynamic template node that can implement custom

View File

@ -6,9 +6,9 @@ use crate::diag::{Diag, DiagSet, Pass};
use crate::eval::{ExprMap, TemplateValue};
use crate::geom::{Align, Dir, Gen, GenAxis, Length, Linear, Sides, Size};
use crate::layout::{
AnyNode, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode, Tree,
AnyNode, LayoutTree, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode,
};
use crate::syntax::{self, Span};
use crate::syntax::{Span, SyntaxTree};
/// The context for execution.
pub struct ExecContext {
@ -17,7 +17,7 @@ pub struct ExecContext {
/// Execution diagnostics.
pub diags: DiagSet,
/// The tree of finished page runs.
tree: Tree,
tree: LayoutTree,
/// When we are building the top-level stack, this contains metrics of the
/// page. While building a group stack through `exec_group`, this is `None`.
page: Option<PageBuilder>,
@ -30,7 +30,7 @@ impl ExecContext {
pub fn new(state: State) -> Self {
Self {
diags: DiagSet::new(),
tree: Tree { runs: vec![] },
tree: LayoutTree { runs: vec![] },
page: Some(PageBuilder::new(&state, true)),
stack: StackBuilder::new(&state),
state,
@ -56,8 +56,8 @@ impl ExecContext {
self.exec_stack(|ctx| template.exec(ctx))
}
/// Execute a tree with a map and return the result as a stack node.
pub fn exec_tree_stack(&mut self, tree: &syntax::Tree, map: &ExprMap) -> StackNode {
/// Execute a syntax tree with a map and return the result as a stack node.
pub fn exec_tree_stack(&mut self, tree: &SyntaxTree, map: &ExprMap) -> StackNode {
self.exec_stack(|ctx| tree.exec_with_map(ctx, map))
}
@ -137,7 +137,7 @@ impl ExecContext {
}
/// Finish execution and return the created layout tree.
pub fn finish(mut self) -> Pass<Tree> {
pub fn finish(mut self) -> Pass<LayoutTree> {
assert!(self.page.is_some());
self.pagebreak(true, false, Span::default());
Pass::new(self.tree, self.diags)

View File

@ -11,12 +11,12 @@ use std::rc::Rc;
use crate::diag::Pass;
use crate::eval::{ExprMap, TemplateFunc, TemplateNode, TemplateValue, Value};
use crate::geom::{Dir, Gen};
use crate::layout::{self, StackChild, StackNode};
use crate::layout::{LayoutTree, StackChild, StackNode};
use crate::pretty::pretty;
use crate::syntax;
use crate::syntax::*;
/// Execute a template to produce a layout tree.
pub fn exec(template: &TemplateValue, state: State) -> Pass<layout::Tree> {
pub fn exec(template: &TemplateValue, state: State) -> Pass<LayoutTree> {
let mut ctx = ExecContext::new(state);
template.exec(&mut ctx);
ctx.finish()
@ -40,7 +40,7 @@ pub trait ExecWithMap {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap);
}
impl ExecWithMap for syntax::Tree {
impl ExecWithMap for SyntaxTree {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
for node in self {
node.exec_with_map(ctx, map);
@ -48,7 +48,7 @@ impl ExecWithMap for syntax::Tree {
}
}
impl ExecWithMap for syntax::Node {
impl ExecWithMap for Node {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
match self {
Self::Text(text) => ctx.push_text(text),
@ -66,7 +66,7 @@ impl ExecWithMap for syntax::Node {
}
}
impl Exec for syntax::RawNode {
impl Exec for RawNode {
fn exec(&self, ctx: &mut ExecContext) {
if self.block {
ctx.parbreak();
@ -83,7 +83,7 @@ impl Exec for syntax::RawNode {
}
}
impl ExecWithMap for syntax::HeadingNode {
impl ExecWithMap for HeadingNode {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
ctx.parbreak();
@ -100,20 +100,20 @@ impl ExecWithMap for syntax::HeadingNode {
}
}
impl ExecWithMap for syntax::ListItem {
impl ExecWithMap for ListItem {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
exec_item(ctx, "".to_string(), &self.body, map);
}
}
impl ExecWithMap for syntax::EnumItem {
impl ExecWithMap for EnumItem {
fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
let label = self.number.unwrap_or(1).to_string() + ".";
exec_item(ctx, label, &self.body, map);
}
}
fn exec_item(ctx: &mut ExecContext, label: String, body: &syntax::Tree, map: &ExprMap) {
fn exec_item(ctx: &mut ExecContext, label: String, body: &SyntaxTree, map: &ExprMap) {
let label = ctx.exec_stack(|ctx| ctx.push_text(label));
let body = ctx.exec_tree_stack(body, map);
let stack = StackNode {

View File

@ -37,7 +37,11 @@ use crate::geom::*;
use crate::loading::Loader;
/// Layout a tree into a collection of frames.
pub fn layout(loader: &mut dyn Loader, cache: &mut Cache, tree: &Tree) -> Vec<Rc<Frame>> {
pub fn layout(
loader: &mut dyn Loader,
cache: &mut Cache,
tree: &LayoutTree,
) -> Vec<Rc<Frame>> {
tree.layout(&mut LayoutContext {
loader,
cache,
@ -48,12 +52,12 @@ pub fn layout(loader: &mut dyn Loader, cache: &mut Cache, tree: &Tree) -> Vec<Rc
/// A tree of layout nodes.
#[derive(Debug, Clone, PartialEq)]
pub struct Tree {
pub struct LayoutTree {
/// Runs of pages with the same properties.
pub runs: Vec<PageRun>,
}
impl Tree {
impl LayoutTree {
/// Layout the tree into a collection of frames.
pub fn layout(&self, ctx: &mut LayoutContext) -> Vec<Rc<Frame>> {
self.runs.iter().flat_map(|run| run.layout(ctx)).collect()

View File

@ -20,11 +20,11 @@
//!
//! [tokens]: parse::Tokens
//! [parsed]: parse::parse
//! [syntax tree]: syntax::Tree
//! [syntax tree]: syntax::SyntaxTree
//! [evaluate]: eval::eval
//! [module]: eval::Module
//! [execute]: exec::exec
//! [layout tree]: layout::Tree
//! [layout tree]: layout::LayoutTree
//! [layouted]: layout::layout
//! [PDF]: export::pdf
@ -84,14 +84,14 @@ pub fn typeset(
scope: &Scope,
state: State,
) -> Pass<Vec<Rc<Frame>>> {
let parsed = parse::parse(src);
let evaluated = eval::eval(loader, cache, path, Rc::new(parsed.output), scope);
let executed = exec::exec(&evaluated.output.template, state);
let layouted = layout::layout(loader, cache, &executed.output);
let ast = parse::parse(src);
let module = eval::eval(loader, cache, path, Rc::new(ast.output), scope);
let tree = exec::exec(&module.output.template, state);
let frames = layout::layout(loader, cache, &tree.output);
let mut diags = parsed.diags;
diags.extend(evaluated.diags);
diags.extend(executed.diags);
let mut diags = ast.diags;
diags.extend(module.diags);
diags.extend(tree.diags);
Pass::new(layouted, diags)
Pass::new(frames, diags)
}

View File

@ -19,19 +19,19 @@ use crate::syntax::visit::{mutable::visit_expr, VisitMut};
use crate::syntax::*;
/// Parse a string of source code.
pub fn parse(src: &str) -> Pass<Tree> {
pub fn parse(src: &str) -> Pass<SyntaxTree> {
let mut p = Parser::new(src);
Pass::new(tree(&mut p), p.diags)
}
/// Parse a syntax tree.
fn tree(p: &mut Parser) -> Tree {
fn tree(p: &mut Parser) -> SyntaxTree {
tree_while(p, true, &mut |_| true)
}
/// Parse a syntax tree that stays right of the column at the start of the next
/// non-whitespace token.
fn tree_indented(p: &mut Parser) -> Tree {
fn tree_indented(p: &mut Parser) -> SyntaxTree {
p.eat_while(|t| match t {
Token::Space(n) => n == 0,
Token::LineComment(_) | Token::BlockComment(_) => true,
@ -46,7 +46,7 @@ fn tree_indented(p: &mut Parser) -> Tree {
}
/// Parse a syntax tree.
fn tree_while<F>(p: &mut Parser, mut at_start: bool, f: &mut F) -> Tree
fn tree_while<F>(p: &mut Parser, mut at_start: bool, f: &mut F) -> SyntaxTree
where
F: FnMut(&mut Parser) -> bool,
{
@ -72,7 +72,7 @@ where
tree_while(self.p, true, self.f)
} else {
self.p.diag(error!(call.callee.span(), "duplicate wide call"));
Tree::default()
SyntaxTree::default()
};
call.args.items.push(CallArg::Pos(Expr::Template(TemplateExpr {

View File

@ -78,7 +78,7 @@ impl Write for Printer {
}
}
impl Pretty for Tree {
impl Pretty for SyntaxTree {
fn pretty(&self, p: &mut Printer) {
for node in self {
node.pretty(p);
@ -630,10 +630,10 @@ mod tests {
#[track_caller]
fn test_parse(src: &str, exp: &str) {
let tree = parse(src).output;
let found = pretty(&tree);
let ast = parse(src).output;
let found = pretty(&ast);
if exp != found {
println!("tree: {:#?}", tree);
println!("tree: {:#?}", ast);
println!("expected: {}", exp);
println!("found: {}", found);
panic!("test failed");

View File

@ -158,7 +158,7 @@ pub struct TemplateExpr {
/// The source code location.
pub span: Span,
/// The contents of the template.
pub tree: Rc<Tree>,
pub tree: Rc<SyntaxTree>,
}
/// A grouped expression: `(1 + 2)`.

View File

@ -16,4 +16,4 @@ pub use token::*;
/// The abstract syntax tree.
///
/// This type can represent a full parsed document.
pub type Tree = Vec<Node>;
pub type SyntaxTree = Vec<Node>;

View File

@ -52,7 +52,7 @@ pub struct HeadingNode {
/// The section depth (numer of equals signs).
pub level: usize,
/// The contents of the heading.
pub body: Rc<Tree>,
pub body: Rc<SyntaxTree>,
}
/// An item in an unordered list: `- ...`.
@ -61,7 +61,7 @@ pub struct ListItem {
/// The source code location.
pub span: Span,
/// The contents of the list item.
pub body: Tree,
pub body: SyntaxTree,
}
/// An item in an enumeration (ordered list): `1. ...`.
@ -72,5 +72,5 @@ pub struct EnumItem {
/// The number, if any.
pub number: Option<usize>,
/// The contents of the list item.
pub body: Tree,
pub body: SyntaxTree,
}

View File

@ -79,7 +79,7 @@ macro_rules! impl_visitor {
}
impl_visitors! {
visit_tree(v, tree: Tree) {
visit_tree(v, tree: SyntaxTree) {
for node in tree {
v.visit_node(node);
}