oak_core/tree/
green_tree.rs

1//! Green tree implementation for immutable kind tree representation.
2//!
3//! This module provides the "green" side of the red-green tree architecture,
4//! where green nodes are immutable and don't contain position information,
5//! making them cacheable and shareable across different parse trees.
6
7use triomphe::Arc;
8
9/// A green tree element - either a node or a leaf kind.
10///
11/// Green trees represent the immutable structure of kind trees without
12/// position information. They are designed to be cacheable and shareable
13/// across different parse trees and incremental updates.
14#[derive(Debug, Clone)]
15pub enum GreenTree<K: Copy> {
16    /// A green node with child elements
17    Node(Arc<GreenNode<K>>),
18    /// A green leaf kind
19    Leaf(GreenLeaf<K>),
20}
21
22impl<K: Copy> GreenTree<K> {
23    /// Returns the total byte length of this green tree element.
24    ///
25    /// # Returns
26    ///
27    /// The byte length of the element, either from the node's total length
28    /// or the leaf's text length
29    #[inline]
30    pub fn len(&self) -> usize {
31        match self {
32            GreenTree::Node(n) => n.length,
33            GreenTree::Leaf(t) => t.length,
34        }
35    }
36}
37
38/// A green leaf kind that stores only kind and length.
39///
40/// Green leaves represent individual tokens (keywords, identifiers, literals, etc.)
41/// without storing the actual text content. They only store the kind kind and
42/// length, avoiding text duplication and enabling efficient sharing.
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct GreenLeaf<K: Copy> {
45    /// The kind kind/category (e.g., keyword, identifier, literal)
46    pub kind: K,
47    /// The byte length of the kind text
48    pub length: usize,
49}
50
51impl<K: Copy> GreenLeaf<K> {
52    /// Creates a new green leaf kind.
53    ///
54    /// # Arguments
55    ///
56    /// * `kind` - The kind kind/category
57    /// * `len` - The byte length of the kind text
58    ///
59    /// # Returns
60    ///
61    /// A new [`GreenLeaf`] with the given kind and length
62    #[inline]
63    pub fn new(kind: K, len: usize) -> Self {
64        Self { kind, length: len }
65    }
66}
67
68/// A green node that contains child elements without parent pointers.
69///
70/// Green nodes represent kind tree nodes with their structural information
71/// but without position data or parent references. This design makes them
72/// immutable and shareable across different parse trees.
73#[derive(Debug, Clone)]
74pub struct GreenNode<K: Copy> {
75    /// The node kind/category (e.g., expression, statement, declaration)
76    pub kind: K,
77    /// The child elements of this node
78    pub children: Vec<GreenTree<K>>,
79    /// The total byte length of this node and all its children
80    pub length: usize,
81}
82
83impl<K: Copy> GreenNode<K> {
84    /// Creates a new green node from kind and children.
85    ///
86    /// # Arguments
87    ///
88    /// * `kind` - The node kind/category
89    /// * `children` - The child elements of this node
90    ///
91    /// # Returns
92    ///
93    /// A reference-counted [`GreenNode`] with computed total length
94    pub fn new(kind: K, children: Vec<GreenTree<K>>) -> Arc<Self> {
95        let len = children.iter().map(|c| c.len()).sum();
96        Arc::new(Self { kind, children, length: len })
97    }
98}
99
100impl<K: Copy> GreenNode<K> {
101    /// Replaces a range of child elements with new children.
102    ///
103    /// This method is essential for incremental parsing, allowing efficient
104    /// updates to kind trees by replacing only the changed portions.
105    ///
106    /// # Arguments
107    ///
108    /// * `replace_start` - The starting index of the range to replace (inclusive)
109    /// * `replace_end` - The ending index of the range to replace (exclusive)
110    /// * `new_children` - The new child elements to insert
111    ///
112    /// # Returns
113    ///
114    /// A new [`Arc<GreenNode<K>>`] with the specified children replaced
115    ///
116    /// # Panics
117    ///
118    /// Panics if the indices are out of bounds or if `replace_start > replace_end`
119    pub fn replace_range(&self, replace_start: usize, replace_end: usize, new_children: Vec<GreenTree<K>>) -> Arc<Self> {
120        assert!(replace_start <= replace_end && replace_end <= self.children.len());
121        let mut children = Vec::with_capacity(self.children.len() - (replace_end - replace_start) + new_children.len());
122        children.extend_from_slice(&self.children[..replace_start]);
123        children.extend(new_children.into_iter());
124        children.extend_from_slice(&self.children[replace_end..]);
125        GreenNode::new(self.kind, children)
126    }
127}