diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 7c038c2a4..aa75f8b70 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -35,7 +35,6 @@ use once_cell::sync::Lazy; use syntect::easy::HighlightLines; use syntect::highlighting::{FontStyle, Highlighter, Style as SynStyle, Theme, ThemeSet}; use syntect::parsing::SyntaxSet; - use unicode_segmentation::UnicodeSegmentation; use crate::diag::{At, Error, StrResult, Trace, Tracepoint, TypResult}; @@ -255,11 +254,7 @@ impl Eval for RawNode { fn eval(&self, _: &mut EvalContext) -> TypResult { let code = self.highlighted(); - Ok(if self.block { - Template::Block(code.into_block()) - } else { - code - }) + Ok(if self.block { Template::Block(code.pack()) } else { code }) } } @@ -352,7 +347,7 @@ impl Eval for MathNode { fn eval(&self, _: &mut EvalContext) -> TypResult { let text = Template::Text(self.formula.trim().into()).monospaced(); Ok(if self.display { - Template::Block(text.into_block()) + Template::Block(text.pack()) } else { text }) @@ -364,7 +359,7 @@ impl Eval for HeadingNode { fn eval(&self, ctx: &mut EvalContext) -> TypResult { Ok(Template::block(library::HeadingNode { - child: self.body().eval(ctx)?.into_block(), + child: self.body().eval(ctx)?.pack(), level: self.level(), })) } @@ -375,7 +370,7 @@ impl Eval for ListNode { fn eval(&self, ctx: &mut EvalContext) -> TypResult { Ok(Template::block(library::ListNode { - child: self.body().eval(ctx)?.into_block(), + child: self.body().eval(ctx)?.pack(), kind: library::Unordered, })) } @@ -386,7 +381,7 @@ impl Eval for EnumNode { fn eval(&self, ctx: &mut EvalContext) -> TypResult { Ok(Template::block(library::ListNode { - child: self.body().eval(ctx)?.into_block(), + child: self.body().eval(ctx)?.pack(), kind: library::Ordered(self.number()), })) } diff --git a/src/eval/template.rs b/src/eval/template.rs index c1a2b44cd..6515c2713 100644 --- a/src/eval/template.rs +++ b/src/eval/template.rs @@ -27,18 +27,18 @@ use crate::util::EcoString; /// represented as a `Styled(Text("Hello"), [TextNode::STRONG: true])` /// template. /// -/// 2. A `Sequence` template simply combines multiple templates and will be -/// layouted as a [flow](FlowNode). So, when you write `[Hi] + [you]` in -/// Typst, this type's [`Add`] implementation is invoked and the two -/// templates are combined into a single [`Sequence`](Self::Sequence) -/// template. +/// 2. A `Sequence` template combines multiple arbitrary templates and is the +/// representation of a "flow" of content. So, when you write `[Hi] + [you]` +/// in Typst, this type's [`Add`] implementation is invoked and the two +/// [`Text`](Self::Text) templates are combined into a single +/// [`Sequence`](Self::Sequence) template. /// /// A sequence may contain nested sequences (meaning this variant effectively -/// allows nodes to form trees). All nested sequences can equivalently be +/// allows templates to form trees). All nested sequences can equivalently be /// represented as a single flat sequence, but allowing nesting doesn't hurt -/// since we can just recurse into the nested sequences during packing. Also, -/// in theory, this allows better complexity when adding (large) sequence -/// nodes (just like for a text rope). +/// since we can just recurse into the nested sequences. Also, in theory, +/// this allows better complexity when adding large sequence nodes just like +/// for something like a text rope. #[derive(Debug, PartialEq, Clone, Hash)] pub enum Template { /// A word space. @@ -116,8 +116,16 @@ impl Template { self.styled(TextNode::MONOSPACE, true) } - /// Lift to a type-erased block-level template. - pub fn into_block(self) -> PackedNode { + /// Repeat this template `n` times. + pub fn repeat(&self, n: i64) -> StrResult { + let count = usize::try_from(n) + .map_err(|_| format!("cannot repeat this template {} times", n))?; + + Ok(Self::Sequence(vec![self.clone(); count])) + } + + /// Convert to a type-erased block-level node. + pub fn pack(self) -> PackedNode { if let Template::Block(packed) = self { packed } else { @@ -133,14 +141,6 @@ impl Template { packer.walk(self, StyleMap::new()); packer.into_root() } - - /// Repeat this template `n` times. - pub fn repeat(&self, n: i64) -> StrResult { - let count = usize::try_from(n) - .map_err(|_| format!("cannot repeat this template {} times", n))?; - - Ok(Self::Sequence(vec![self.clone(); count])) - } } impl Default for Template { diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 6e1764733..538bcd739 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -267,6 +267,8 @@ impl Debug for PackedNode { impl PartialEq for PackedNode { fn eq(&self, other: &Self) -> bool { + // We cast to thin pointers for comparison because we don't want to + // compare vtables (which can be different across codegen units). std::ptr::eq( Arc::as_ptr(&self.node) as *const (), Arc::as_ptr(&other.node) as *const (), diff --git a/src/library/list.rs b/src/library/list.rs index 93b942b3a..639b57154 100644 --- a/src/library/list.rs +++ b/src/library/list.rs @@ -54,7 +54,7 @@ impl Layout for ListNode { gutter: Spec::default(), children: vec![ PackedNode::default(), - Template::Text(self.kind.label()).into_block(), + Template::Text(self.kind.label()).pack(), PackedNode::default(), self.child.clone(), ], diff --git a/src/library/mod.rs b/src/library/mod.rs index 9b7dc0ebf..a86d8bb34 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -228,5 +228,5 @@ castable! { castable! { PackedNode, Expected: "template", - Value::Template(template) => template.into_block(), + Value::Template(template) => template.pack(), } diff --git a/src/library/stack.rs b/src/library/stack.rs index 409e58679..394b0a38b 100644 --- a/src/library/stack.rs +++ b/src/library/stack.rs @@ -61,7 +61,7 @@ castable! { Value::Relative(v) => Self::Spacing(SpacingKind::Linear(v.into())), Value::Linear(v) => Self::Spacing(SpacingKind::Linear(v)), Value::Fractional(v) => Self::Spacing(SpacingKind::Fractional(v)), - Value::Template(v) => Self::Node(v.into_block()), + Value::Template(v) => Self::Node(v.pack()), } /// Performs stack layout.