oak_core/parser/
session.rs1use crate::{
2 Language,
3 lexer::{LexOutput, LexerCache, Token},
4 memory::arena::SyntaxArena,
5 tree::GreenNode,
6};
7use std::{
8 any::Any,
9 cell::Cell,
10 collections::HashMap,
11 ptr::NonNull,
12};
13
14pub trait ParseCache<L: Language>: LexerCache<L> {
16 fn arena(&self) -> &SyntaxArena;
18
19 fn old_tree(&self) -> Option<&GreenNode<'_, L>>;
21
22 fn lex_output(&self) -> Option<&LexOutput<L>>;
24
25 fn prepare_generation(&mut self);
27
28 fn commit_generation(&self, root: &GreenNode<L>);
30}
31
32pub struct ParseSession<L: Language + Send + Sync> {
37 arena_active: SyntaxArena,
39 arena_old: Option<SyntaxArena>,
41 last_root: Cell<Option<NonNull<()>>>,
43 last_lex: Option<LexOutput<L>>,
45 pub(crate) typed_nodes: HashMap<NonNull<()>, Box<dyn Any + Send + Sync>>,
47}
48
49unsafe impl<L: Language + Send + Sync> Send for ParseSession<L> {}
50unsafe impl<L: Language + Send + Sync> Sync for ParseSession<L> {}
51
52impl<L: Language + Send + Sync> Default for ParseSession<L> {
53 fn default() -> Self {
54 Self::new(16)
55 }
56}
57
58impl<L: Language + Send + Sync> ParseSession<L> {
59 pub fn new(capacity: usize) -> Self {
61 Self { arena_active: SyntaxArena::new(capacity), arena_old: None, last_root: Cell::new(None), last_lex: None, typed_nodes: HashMap::new() }
62 }
63
64 pub fn last_root(&self) -> Option<&GreenNode<'_, L>> {
66 let ptr = self.last_root.get()?;
67 unsafe { Some(&*(ptr.as_ptr() as *const GreenNode<'_, L>)) }
69 }
70
71 pub(crate) fn get_typed_node<T: Any + Clone>(&self, node: &GreenNode<L>) -> Option<T> {
72 let ptr = NonNull::from(node).cast::<()>();
73 self.typed_nodes.get(&ptr).and_then(|any| any.downcast_ref::<T>()).cloned()
74 }
75
76 pub(crate) fn set_typed_node<T: Any + Send + Sync>(&mut self, node: &GreenNode<L>, value: T) {
77 let ptr = NonNull::from(node).cast::<()>();
78 self.typed_nodes.insert(ptr, Box::new(value));
79 }
80}
81
82impl<L: Language + Send + Sync> ParseCache<L> for ParseSession<L> {
83 fn arena(&self) -> &SyntaxArena {
84 &self.arena_active
85 }
86
87 fn old_tree(&self) -> Option<&GreenNode<'_, L>> {
88 let ptr = self.last_root.get()?;
89 if self.arena_old.is_some() {
90 unsafe { Some(&*(ptr.as_ptr() as *const GreenNode<'_, L>)) }
92 }
93 else {
94 None
95 }
96 }
97
98 fn lex_output(&self) -> Option<&LexOutput<L>> {
99 self.last_lex.as_ref()
100 }
101
102 fn prepare_generation(&mut self) {
103 self.arena_old = Some(std::mem::replace(&mut self.arena_active, SyntaxArena::new(16)));
105 self.last_lex = None;
107 self.typed_nodes.clear();
108 }
109
110 fn commit_generation(&self, root: &GreenNode<L>) {
111 let ptr = NonNull::from(root).cast::<()>();
112 self.last_root.set(Some(ptr));
113 }
114}
115
116impl<L: Language + Send + Sync> LexerCache<L> for ParseSession<L> {
117 fn set_lex_output(&mut self, output: LexOutput<L>) {
118 self.last_lex = Some(output)
119 }
120
121 fn get_token(&self, index: usize) -> Option<Token<L::TokenType>> {
122 self.last_lex.as_ref()?.result.as_ref().ok()?.get(index).cloned()
123 }
124
125 fn count_tokens(&self) -> usize {
126 self.last_lex.as_ref().and_then(|out| out.result.as_ref().ok()).map(|tokens| tokens.len()).unwrap_or(0)
127 }
128
129 fn has_tokens(&self) -> bool {
130 self.last_lex.as_ref().and_then(|out| out.result.as_ref().ok()).map(|tokens| !tokens.is_empty()).unwrap_or(false)
131 }
132
133 fn get_tokens(&self) -> Option<&[Token<L::TokenType>]> {
134 self.last_lex.as_ref()?.result.as_ref().ok().map(|tokens| &**tokens)
135 }
136}
137
138impl<'a, L: Language, C: ParseCache<L> + ?Sized> ParseCache<L> for &'a mut C {
139 fn arena(&self) -> &SyntaxArena {
140 (**self).arena()
141 }
142
143 fn old_tree(&self) -> Option<&GreenNode<'_, L>> {
144 (**self).old_tree()
145 }
146
147 fn lex_output(&self) -> Option<&LexOutput<L>> {
148 (**self).lex_output()
149 }
150
151 fn prepare_generation(&mut self) {
152 (**self).prepare_generation()
153 }
154
155 fn commit_generation(&self, root: &GreenNode<L>) {
156 (**self).commit_generation(root)
157 }
158}