mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Documentation
This commit is contained in:
parent
94b375ce55
commit
af10b08cc1
@ -141,7 +141,8 @@ impl SourceStore {
|
|||||||
self.sources[id.0 as usize].edit(replace, with)
|
self.sources[id.0 as usize].edit(replace, with)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map a span that points into this source store to a byte range.
|
/// Map a span that points into a [file](SourceFile::range) stored in this
|
||||||
|
/// source store to a byte range.
|
||||||
///
|
///
|
||||||
/// Panics if the span does not point into this source store.
|
/// Panics if the span does not point into this source store.
|
||||||
pub fn range(&self, span: Span) -> Range<usize> {
|
pub fn range(&self, span: Span) -> Range<usize> {
|
||||||
|
@ -122,7 +122,7 @@ impl SyntaxNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a synthetic node id for the node and all its descendants.
|
/// Set a synthetic span for the node and all its descendants.
|
||||||
pub fn synthesize(&mut self, span: Span) {
|
pub fn synthesize(&mut self, span: Span) {
|
||||||
match self {
|
match self {
|
||||||
Self::Inner(inner) => Arc::make_mut(inner).synthesize(span),
|
Self::Inner(inner) => Arc::make_mut(inner).synthesize(span),
|
||||||
@ -258,7 +258,7 @@ impl InnerNode {
|
|||||||
self.children.iter()
|
self.children.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a synthetic node id for the node and all its descendants.
|
/// Set a synthetic span for the node and all its descendants.
|
||||||
pub fn synthesize(&mut self, span: Span) {
|
pub fn synthesize(&mut self, span: Span) {
|
||||||
self.data.synthesize(span);
|
self.data.synthesize(span);
|
||||||
for child in &mut self.children {
|
for child in &mut self.children {
|
||||||
@ -266,13 +266,15 @@ impl InnerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign spans to this subtree or some a range of children.
|
/// Assign span numbers `within` an interval to this node's subtree or just
|
||||||
|
/// a `range` of its children.
|
||||||
pub fn numberize(
|
pub fn numberize(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: SourceId,
|
id: SourceId,
|
||||||
range: Option<Range<usize>>,
|
range: Option<Range<usize>>,
|
||||||
within: Range<u64>,
|
within: Range<u64>,
|
||||||
) -> NumberingResult {
|
) -> NumberingResult {
|
||||||
|
// Determine how many nodes we will number.
|
||||||
let descendants = match &range {
|
let descendants = match &range {
|
||||||
Some(range) if range.is_empty() => return Ok(()),
|
Some(range) if range.is_empty() => return Ok(()),
|
||||||
Some(range) => self.children[range.clone()]
|
Some(range) => self.children[range.clone()]
|
||||||
@ -282,6 +284,9 @@ impl InnerNode {
|
|||||||
None => self.descendants,
|
None => self.descendants,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Determine the distance between two neighbouring assigned numbers. If
|
||||||
|
// possible, we try to fit all numbers into the left half of `within`
|
||||||
|
// so that there is space for future insertions.
|
||||||
let space = within.end - within.start;
|
let space = within.end - within.start;
|
||||||
let mut stride = space / (2 * descendants as u64);
|
let mut stride = space / (2 * descendants as u64);
|
||||||
if stride == 0 {
|
if stride == 0 {
|
||||||
@ -291,6 +296,7 @@ impl InnerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Number this node itself.
|
||||||
let mut start = within.start;
|
let mut start = within.start;
|
||||||
if range.is_none() {
|
if range.is_none() {
|
||||||
let end = start + stride;
|
let end = start + stride;
|
||||||
@ -299,6 +305,7 @@ impl InnerNode {
|
|||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Number the children.
|
||||||
let len = self.children.len();
|
let len = self.children.len();
|
||||||
for child in &mut self.children[range.unwrap_or(0 .. len)] {
|
for child in &mut self.children[range.unwrap_or(0 .. len)] {
|
||||||
let end = start + child.descendants() as u64 * stride;
|
let end = start + child.descendants() as u64 * stride;
|
||||||
@ -309,7 +316,7 @@ impl InnerNode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The maximum assigned number in this subtree.
|
/// The upper bound of assigned numbers in this subtree.
|
||||||
pub fn upper(&self) -> u64 {
|
pub fn upper(&self) -> u64 {
|
||||||
self.upper
|
self.upper
|
||||||
}
|
}
|
||||||
@ -387,39 +394,44 @@ impl InnerNode {
|
|||||||
self.children.splice(range.clone(), replacement);
|
self.children.splice(range.clone(), replacement);
|
||||||
range.end = range.start + replacement_count;
|
range.end = range.start + replacement_count;
|
||||||
|
|
||||||
// Renumber the new children. Retries until it works taking
|
// Renumber the new children. Retries until it works, taking
|
||||||
// exponentially more children into account.
|
// exponentially more children into account.
|
||||||
let max_left = range.start;
|
|
||||||
let max_right = self.children.len() - range.end;
|
|
||||||
let mut left = 0;
|
let mut left = 0;
|
||||||
let mut right = 0;
|
let mut right = 0;
|
||||||
|
let max_left = range.start;
|
||||||
|
let max_right = self.children.len() - range.end;
|
||||||
loop {
|
loop {
|
||||||
let renumber = range.start - left .. range.end + right;
|
let renumber = range.start - left .. range.end + right;
|
||||||
|
|
||||||
// The minimum assignable number is the upper bound of the node
|
// The minimum assignable number is either
|
||||||
// right before the to-be-renumbered children (or the number after
|
// - the upper bound of the node right before the to-be-renumbered
|
||||||
// this inner node's span if renumbering starts at the first child).
|
// children,
|
||||||
|
// - or this inner node's span number plus one if renumbering starts
|
||||||
|
// at the first child.
|
||||||
let start_number = renumber
|
let start_number = renumber
|
||||||
.start
|
.start
|
||||||
.checked_sub(1)
|
.checked_sub(1)
|
||||||
.and_then(|i| self.children.get(i))
|
.and_then(|i| self.children.get(i))
|
||||||
.map_or(self.span().number() + 1, |child| child.upper());
|
.map_or(self.span().number() + 1, |child| child.upper());
|
||||||
|
|
||||||
// The upper bound of the is the span of the first child after the to-be-renumbered children
|
// The upper bound for renumbering is either
|
||||||
// or this node's upper bound.
|
// - the span number of the first child after the to-be-renumbered
|
||||||
|
// children,
|
||||||
|
// - or this node's upper bound if renumbering ends behind the last
|
||||||
|
// child.
|
||||||
let end_number = self
|
let end_number = self
|
||||||
.children
|
.children
|
||||||
.get(renumber.end)
|
.get(renumber.end)
|
||||||
.map_or(self.upper(), |next| next.span().number());
|
.map_or(self.upper(), |next| next.span().number());
|
||||||
|
|
||||||
// Try to renumber within the number range.
|
// Try to renumber.
|
||||||
let within = start_number .. end_number;
|
let within = start_number .. end_number;
|
||||||
let id = self.span().source();
|
let id = self.span().source();
|
||||||
if self.numberize(id, Some(renumber), within).is_ok() {
|
if self.numberize(id, Some(renumber), within).is_ok() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doesn't even work with all children, so we give up.
|
// If it didn't even work with all children, we give up.
|
||||||
if left == max_left && right == max_right {
|
if left == max_left && right == max_right {
|
||||||
return Err(Unnumberable);
|
return Err(Unnumberable);
|
||||||
}
|
}
|
||||||
@ -430,8 +442,8 @@ impl InnerNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the length of this node given the old and new length of
|
/// Update the this node given after changes were made to one of its
|
||||||
/// replaced children.
|
/// children.
|
||||||
pub(crate) fn update_parent(
|
pub(crate) fn update_parent(
|
||||||
&mut self,
|
&mut self,
|
||||||
prev_len: usize,
|
prev_len: usize,
|
||||||
|
@ -42,42 +42,47 @@ impl<T: Debug> Debug for Spanned<T> {
|
|||||||
/// A unique identifier for a syntax node.
|
/// A unique identifier for a syntax node.
|
||||||
///
|
///
|
||||||
/// This is used throughout the compiler to track which source section an error
|
/// This is used throughout the compiler to track which source section an error
|
||||||
/// or element stems from. Can be mapped back to a source id + byte range for
|
/// or element stems from. Can be [mapped back](crate::source::SourceStore::range)
|
||||||
/// user facing display.
|
/// to a source id + byte range for user facing display.
|
||||||
///
|
///
|
||||||
/// Node ids are ordered in the tree to enable quickly finding the node with
|
/// Span ids are ordered in the tree to enable quickly finding the node with
|
||||||
/// some id:
|
/// some id:
|
||||||
/// - The id of a parent is always smaller than the ids of any of its children.
|
/// - The id of a parent is always smaller than the ids of any of its children.
|
||||||
/// - The id of a node is always greater than any id in the subtrees of any left
|
/// - The id of a node is always greater than any id in the subtrees of any left
|
||||||
/// sibling and smaller than any id the subtrees of any right sibling.
|
/// sibling and smaller than any id in the subtrees of any right sibling.
|
||||||
///
|
///
|
||||||
/// Node ids stay mostly stable, even for nodes behind an insertion. This is not
|
/// The internal ids of spans stay mostly stable, even for nodes behind an
|
||||||
/// true for simple spans/ranges as they shift. Node ids can be used as inputs
|
/// insertion. This is not true for simple ranges as they shift. Spans can be
|
||||||
/// to memoized functions without hurting cache performance when text is
|
/// used as inputs to memoized functions without hurting cache performance when
|
||||||
/// inserted somewhere in the document other than the end.
|
/// text is inserted somewhere in the document other than the end.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
///
|
||||||
|
/// This type takes 8 bytes and is null-optimized (i.e. `Option<Span>` also
|
||||||
|
/// takes 8 bytes).
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Span(NonZeroU64);
|
pub struct Span(NonZeroU64);
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
// Number of bits for and minimum and maximum numbers assigned to nodes.
|
// Number of bits for and minimum and maximum numbers assignable to spans.
|
||||||
const BITS: usize = 48;
|
const BITS: usize = 48;
|
||||||
const DETACHED: u64 = 1;
|
const DETACHED: u64 = 1;
|
||||||
const MIN: u64 = 2;
|
const MIN: u64 = 2;
|
||||||
const MAX: u64 = (1 << Self::BITS) - 1;
|
const MAX: u64 = (1 << Self::BITS) - 1;
|
||||||
|
|
||||||
// The root numbering range.
|
/// The full range of numbers available to spans.
|
||||||
pub const FULL: Range<u64> = Self::MIN .. Self::MAX + 1;
|
pub const FULL: Range<u64> = Self::MIN .. Self::MAX + 1;
|
||||||
|
|
||||||
/// Create a new span from a source id and a unique number.
|
/// Create a new span from a source id and a unique number.
|
||||||
pub fn new(id: SourceId, number: u64) -> Self {
|
///
|
||||||
assert!(number >= Self::MIN && number <= Self::MAX, "{number}");
|
/// Panics if the `number` is not contained in `FULL`.
|
||||||
|
pub const fn new(id: SourceId, number: u64) -> Self {
|
||||||
|
assert!(number >= Self::MIN && number <= Self::MAX);
|
||||||
let bits = ((id.into_raw() as u64) << Self::BITS) | number;
|
let bits = ((id.into_raw() as u64) << Self::BITS) | number;
|
||||||
Self(convert(bits))
|
Self(to_non_zero(bits))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A node that does not belong to any source file.
|
/// A span that does not point into any source file.
|
||||||
pub const fn detached() -> Self {
|
pub const fn detached() -> Self {
|
||||||
Self(convert(Self::DETACHED))
|
Self(to_non_zero(Self::DETACHED))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The id of the source file the span points into.
|
/// The id of the source file the span points into.
|
||||||
@ -92,7 +97,7 @@ impl Span {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a non zero u64.
|
/// Convert to a non zero u64.
|
||||||
const fn convert(v: u64) -> NonZeroU64 {
|
const fn to_non_zero(v: u64) -> NonZeroU64 {
|
||||||
match NonZeroU64::new(v) {
|
match NonZeroU64::new(v) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => unreachable!(),
|
None => unreachable!(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user