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