1use std::num::NonZeroU16;
2use std::sync::Arc;
3
4use arborium_tree_sitter::Language;
5
6use plotnik_core::grammar::Grammar;
7use plotnik_core::{Cardinality, DynamicNodeTypes, NodeFieldId, NodeTypeId, NodeTypes, RawNode};
8
9pub mod builtin;
10pub mod dynamic;
11
12#[cfg(test)]
13mod lib_tests;
14
15pub use builtin::*;
16
17pub type Lang = Arc<dyn LangImpl>;
19
20pub trait LangImpl: Send + Sync {
23 fn name(&self) -> &str;
24
25 fn parse(&self, source: &str) -> arborium_tree_sitter::Tree;
27
28 fn resolve_named_node(&self, kind: &str) -> Option<NodeTypeId>;
29 fn resolve_anonymous_node(&self, kind: &str) -> Option<NodeTypeId>;
30 fn resolve_field(&self, name: &str) -> Option<NodeFieldId>;
31
32 fn all_named_node_kinds(&self) -> Vec<&'static str>;
34 fn all_field_names(&self) -> Vec<&'static str>;
35 fn node_type_name(&self, node_type_id: NodeTypeId) -> Option<&'static str>;
36 fn field_name(&self, field_id: NodeFieldId) -> Option<&'static str>;
37 fn fields_for_node_type(&self, node_type_id: NodeTypeId) -> Vec<&'static str>;
38
39 fn is_supertype(&self, node_type_id: NodeTypeId) -> bool;
40 fn subtypes(&self, supertype: NodeTypeId) -> &[u16];
41
42 fn root(&self) -> Option<NodeTypeId>;
43 fn is_extra(&self, node_type_id: NodeTypeId) -> bool;
44
45 fn has_field(&self, node_type_id: NodeTypeId, node_field_id: NodeFieldId) -> bool;
46 fn field_cardinality(
47 &self,
48 node_type_id: NodeTypeId,
49 node_field_id: NodeFieldId,
50 ) -> Option<Cardinality>;
51 fn valid_field_types(
52 &self,
53 node_type_id: NodeTypeId,
54 node_field_id: NodeFieldId,
55 ) -> &[NodeTypeId];
56 fn is_valid_field_type(
57 &self,
58 node_type_id: NodeTypeId,
59 node_field_id: NodeFieldId,
60 child: NodeTypeId,
61 ) -> bool;
62
63 fn children_cardinality(&self, node_type_id: NodeTypeId) -> Option<Cardinality>;
64 fn valid_child_types(&self, node_type_id: NodeTypeId) -> &[NodeTypeId];
65 fn is_valid_child_type(&self, node_type_id: NodeTypeId, child: NodeTypeId) -> bool;
66
67 fn grammar(&self) -> &Grammar;
69}
70
71#[derive(Debug)]
73pub struct LangInner {
74 name: String,
75 ts_lang: Language,
76 node_types: DynamicNodeTypes,
77 grammar: Grammar,
78}
79
80impl LangInner {
81 pub fn new(name: &str, ts_lang: Language, raw_nodes: Vec<RawNode>, grammar: Grammar) -> Self {
83 let node_types = DynamicNodeTypes::build(
84 &raw_nodes,
85 |kind, named| {
86 let id = ts_lang.id_for_node_kind(kind, named);
87 NonZeroU16::new(id)
88 },
89 |field_name| ts_lang.field_id_for_name(field_name),
90 );
91
92 Self {
93 name: name.to_owned(),
94 ts_lang,
95 node_types,
96 grammar,
97 }
98 }
99
100 pub fn node_types(&self) -> &DynamicNodeTypes {
101 &self.node_types
102 }
103}
104
105impl LangImpl for LangInner {
106 fn name(&self) -> &str {
107 &self.name
108 }
109
110 fn parse(&self, source: &str) -> arborium_tree_sitter::Tree {
111 let mut parser = arborium_tree_sitter::Parser::new();
112 parser
113 .set_language(&self.ts_lang)
114 .expect("failed to set language");
115 parser.parse(source, None).expect("failed to parse source")
116 }
117
118 fn resolve_named_node(&self, kind: &str) -> Option<NodeTypeId> {
119 let id = self.ts_lang.id_for_node_kind(kind, true);
120 NonZeroU16::new(id)
121 }
122
123 fn resolve_anonymous_node(&self, kind: &str) -> Option<NodeTypeId> {
124 let id = self.ts_lang.id_for_node_kind(kind, false);
125 NonZeroU16::new(id)
127 }
128
129 fn resolve_field(&self, name: &str) -> Option<NodeFieldId> {
130 self.ts_lang.field_id_for_name(name)
131 }
132
133 fn all_named_node_kinds(&self) -> Vec<&'static str> {
134 let count = self.ts_lang.node_kind_count();
135 (0..count as u16)
136 .filter(|&id| self.ts_lang.node_kind_is_named(id))
137 .filter_map(|id| self.ts_lang.node_kind_for_id(id))
138 .collect()
139 }
140
141 fn all_field_names(&self) -> Vec<&'static str> {
142 let count = self.ts_lang.field_count();
143 (1..=count as u16)
144 .filter_map(|id| self.ts_lang.field_name_for_id(id))
145 .collect()
146 }
147
148 fn node_type_name(&self, node_type_id: NodeTypeId) -> Option<&'static str> {
149 self.ts_lang.node_kind_for_id(node_type_id.get())
150 }
151
152 fn field_name(&self, field_id: NodeFieldId) -> Option<&'static str> {
153 self.ts_lang.field_name_for_id(field_id.get())
154 }
155
156 fn fields_for_node_type(&self, node_type_id: NodeTypeId) -> Vec<&'static str> {
157 let count = self.ts_lang.field_count();
158 (1..=count as u16)
159 .filter_map(|id| {
160 let field_id = std::num::NonZeroU16::new(id)?;
161 if self.node_types.has_field(node_type_id, field_id) {
162 self.ts_lang.field_name_for_id(id)
163 } else {
164 None
165 }
166 })
167 .collect()
168 }
169
170 fn is_supertype(&self, node_type_id: NodeTypeId) -> bool {
171 self.ts_lang.node_kind_is_supertype(node_type_id.get())
172 }
173
174 fn subtypes(&self, supertype: NodeTypeId) -> &[u16] {
175 self.ts_lang.subtypes_for_supertype(supertype.get())
176 }
177
178 fn root(&self) -> Option<NodeTypeId> {
179 self.node_types.root()
180 }
181
182 fn is_extra(&self, node_type_id: NodeTypeId) -> bool {
183 self.node_types.is_extra(node_type_id)
184 }
185
186 fn has_field(&self, node_type_id: NodeTypeId, node_field_id: NodeFieldId) -> bool {
187 self.node_types.has_field(node_type_id, node_field_id)
188 }
189
190 fn field_cardinality(
191 &self,
192 node_type_id: NodeTypeId,
193 node_field_id: NodeFieldId,
194 ) -> Option<Cardinality> {
195 self.node_types
196 .field_cardinality(node_type_id, node_field_id)
197 }
198
199 fn valid_field_types(
200 &self,
201 node_type_id: NodeTypeId,
202 node_field_id: NodeFieldId,
203 ) -> &[NodeTypeId] {
204 self.node_types
205 .valid_field_types(node_type_id, node_field_id)
206 }
207
208 fn is_valid_field_type(
209 &self,
210 node_type_id: NodeTypeId,
211 node_field_id: NodeFieldId,
212 child: NodeTypeId,
213 ) -> bool {
214 self.node_types
215 .is_valid_field_type(node_type_id, node_field_id, child)
216 }
217
218 fn children_cardinality(&self, node_type_id: NodeTypeId) -> Option<Cardinality> {
219 self.node_types.children_cardinality(node_type_id)
220 }
221
222 fn valid_child_types(&self, node_type_id: NodeTypeId) -> &[NodeTypeId] {
223 self.node_types.valid_child_types(node_type_id)
224 }
225
226 fn is_valid_child_type(&self, node_type_id: NodeTypeId, child: NodeTypeId) -> bool {
227 self.node_types.is_valid_child_type(node_type_id, child)
228 }
229
230 fn grammar(&self) -> &Grammar {
231 &self.grammar
232 }
233}