miden_rowan/green/
builder.rs1use alloc::vec::Vec;
2use core::num::NonZeroUsize;
3
4use crate::{
5 NodeOrToken,
6 cow_mut::CowMut,
7 green::{GreenElement, GreenNode, SyntaxKind, node_cache::NodeCache},
8};
9
10#[derive(Clone, Copy, Debug)]
12pub struct Checkpoint(NonZeroUsize);
13
14impl Checkpoint {
15 fn new(inner: usize) -> Self {
16 Self(NonZeroUsize::new(inner + 1).unwrap())
17 }
18
19 fn into_inner(self) -> usize {
20 self.0.get() - 1
21 }
22}
23
24#[derive(Default, Debug)]
26pub struct GreenNodeBuilder<'cache> {
27 cache: CowMut<'cache, NodeCache>,
28 parents: Vec<(SyntaxKind, usize)>,
29 children: Vec<(u64, GreenElement)>,
30}
31
32impl GreenNodeBuilder<'_> {
33 pub fn new() -> GreenNodeBuilder<'static> {
35 GreenNodeBuilder::default()
36 }
37
38 pub fn with_cache(cache: &mut NodeCache) -> GreenNodeBuilder<'_> {
41 GreenNodeBuilder {
42 cache: CowMut::Borrowed(cache),
43 parents: Vec::new(),
44 children: Vec::new(),
45 }
46 }
47
48 #[inline]
50 pub fn token(&mut self, kind: SyntaxKind, text: &str) {
51 let (hash, token) = self.cache.token(kind, text);
52 self.children.push((hash, token.into()));
53 }
54
55 #[inline]
57 pub fn start_node(&mut self, kind: SyntaxKind) {
58 let len = self.children.len();
59 self.parents.push((kind, len));
60 }
61
62 #[inline]
65 pub fn finish_node(&mut self) {
66 let (kind, first_child) = self.parents.pop().unwrap();
67 let (hash, node) = self.cache.node(kind, &mut self.children, first_child);
68 self.children.push((hash, node.into()));
69 }
70
71 #[inline]
97 pub fn checkpoint(&self) -> Checkpoint {
98 Checkpoint::new(self.children.len())
99 }
100
101 #[inline]
104 pub fn start_node_at(&mut self, checkpoint: Checkpoint, kind: SyntaxKind) {
105 let checkpoint = checkpoint.into_inner();
106 assert!(
107 checkpoint <= self.children.len(),
108 "checkpoint no longer valid, was finish_node called early?"
109 );
110
111 if let Some(&(_, first_child)) = self.parents.last() {
112 assert!(
113 checkpoint >= first_child,
114 "checkpoint no longer valid, was an unmatched start_node_at called?"
115 );
116 }
117
118 self.parents.push((kind, checkpoint));
119 }
120
121 #[inline]
125 pub fn finish(mut self) -> GreenNode {
126 assert_eq!(self.children.len(), 1);
127 match self.children.pop().unwrap().1 {
128 NodeOrToken::Node(node) => node,
129 NodeOrToken::Token(_) => panic!(),
130 }
131 }
132}