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