sdml_core/model/mod.rs
1/*!
2Provide the Rust types that implement an in-memory representation of the SDML Grammar.
3*/
4
5use crate::model::identifiers::{Identifier, IdentifierReference};
6use std::{
7 collections::HashSet,
8 fmt::{Debug, Display},
9 hash::Hash,
10 ops::Range,
11};
12
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16/// ------------------------------------------------------------------------------------------------
17/// Load the macros
18/// ------------------------------------------------------------------------------------------------
19#[macro_use]
20mod macros;
21
22// ------------------------------------------------------------------------------------------------
23// Public Types ❱ Traits
24// ------------------------------------------------------------------------------------------------
25
26///
27/// This trait is implemented by types that have a distinct *body* type.
28///
29pub trait HasBody {
30 ///
31 /// This type is the particular body for the enclosing type.
32 ///
33 type Body;
34
35 ///
36 /// Get the body of the enclosing type.
37 ///
38 fn body(&self) -> &Self::Body;
39
40 ///
41 /// Get a mutable reference to the body of the enclosing type.
42 ///
43 fn body_mut(&mut self) -> &mut Self::Body;
44
45 ///
46 /// Set the body of the enclosing type.
47 ///
48 fn set_body(&mut self, body: Self::Body);
49}
50
51///
52/// This trait is implemented by types that have a unique name.
53///
54pub trait HasName {
55 ///
56 /// Get the name of the enclosing type.
57 ///
58 fn name(&self) -> &Identifier;
59
60 ///
61 /// Set the name of the enclosing type.
62 ///
63 fn set_name(&mut self, name: Identifier);
64}
65
66///
67/// This trait is implemented by types whose name is derived from a reference.
68///
69pub trait HasNameReference {
70 ///
71 /// Get the name reference for the enclosing type.
72 ///
73 fn name_reference(&self) -> &IdentifierReference;
74
75 ///
76 /// Set the name reference for the enclosing type.
77 ///
78 fn set_name_reference(&mut self, name: IdentifierReference);
79}
80
81///
82/// This trait is implemented by types that have uniquely named members such as modules and
83/// structures.
84///
85pub trait Namespace {
86 type Member: HasName;
87
88 ///
89 /// Returns `true` of the namespace contains any members, else `false`.
90 ///
91 fn has_members(&self) -> bool;
92
93 ///
94 /// Returns the number of members in the namespace.
95 ///
96 fn member_count(&self) -> usize;
97
98 ///
99 /// Returns `true` if the namespace contains a member named `name`, else `false`.
100 ///
101 fn contains_member(&self, name: &Identifier) -> bool;
102
103 ///
104 /// Return the member with the name `name`, if present.
105 ///
106 fn member(&self, name: &Identifier) -> Option<&Self::Member>;
107
108 ///
109 /// Returns an iterator over all members in the namespace.
110 ///
111 fn members(&self) -> impl Iterator<Item = &Self::Member>;
112
113 ///
114 /// Returns an iterator over mutable members in the namespace.
115 ///
116 fn members_mut(&mut self) -> impl Iterator<Item = &mut Self::Member>;
117
118 ///
119 /// Returns an iterator over the names of namespace members.
120 ///
121 fn member_names(&self) -> impl Iterator<Item = &Identifier>;
122
123 ///
124 /// Add a member to the namespace. If a member already existed with the same name it
125 /// will be returned.
126 ///
127 fn add_to_members(&mut self, value: Self::Member) -> Option<Self::Member>;
128
129 ///
130 /// Add the members of the extension to the namespace. Any existing members with
131 /// the same names will be replaced.
132 ///
133 fn extend_members<I>(&mut self, extension: I)
134 where
135 I: IntoIterator<Item = Self::Member>;
136}
137
138///
139/// This trait is implemented by types that have a distinct, but optional, *body* type.
140///
141pub trait HasOptionalBody {
142 ///
143 /// This type is the particular body for the enclosing type.
144 ///
145 type Body;
146
147 fn has_body(&self) -> bool {
148 self.body().is_some()
149 }
150 fn body(&self) -> Option<&Self::Body>;
151 fn body_mut(&mut self) -> Option<&mut Self::Body>;
152 fn set_body(&mut self, body: Self::Body);
153 fn unset_body(&mut self);
154}
155
156///
157/// This trait is implemented by types that include a source location from which they were parsed.
158///
159pub trait HasSourceSpan {
160 fn with_source_span(self, ts_span: Span) -> Self;
161 fn has_source_span(&self) -> bool {
162 self.source_span().is_some()
163 }
164 fn source_span(&self) -> Option<&Span>;
165 fn set_source_span(&mut self, span: Span);
166 fn unset_source_span(&mut self);
167}
168
169///
170/// This trait is implemented by types to allow for query of references.
171///
172pub trait References {
173 #[allow(unused_variables)]
174 fn referenced_types<'a>(&'a self, names: &mut HashSet<&'a IdentifierReference>) {}
175
176 #[allow(unused_variables)]
177 fn referenced_annotations<'a>(&'a self, names: &mut HashSet<&'a IdentifierReference>) {}
178}
179
180// ------------------------------------------------------------------------------------------------
181// Public Types ❱ Structures
182// ------------------------------------------------------------------------------------------------
183
184///
185/// The source location information from the tree-sitter `Node` type. The location is stored as
186/// a start and end position, where the positions are byte indices.
187///
188#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
189#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
190pub struct Span {
191 start: SpanPosition,
192 end: SpanPosition,
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
196#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
197pub struct SpanPosition {
198 byte: usize,
199 line: usize,
200 column: usize,
201}
202
203// ------------------------------------------------------------------------------------------------
204// Implementations
205// ------------------------------------------------------------------------------------------------
206
207#[cfg(feature = "tree-sitter")]
208impl From<&tree_sitter::Node<'_>> for Span {
209 fn from(node: &tree_sitter::Node<'_>) -> Self {
210 Self {
211 start: SpanPosition::from(node.start_position(), node.start_byte()),
212 end: SpanPosition::from(node.end_position(), node.end_byte()),
213 }
214 }
215}
216
217#[cfg(feature = "tree-sitter")]
218impl From<tree_sitter::Node<'_>> for Span {
219 fn from(node: tree_sitter::Node<'_>) -> Self {
220 Self::from(&node)
221 }
222}
223
224impl From<&Span> for sdml_errors::Span {
225 fn from(value: &Span) -> Self {
226 value.byte_range()
227 }
228}
229
230impl From<Span> for sdml_errors::Span {
231 fn from(value: Span) -> Self {
232 value.byte_range()
233 }
234}
235
236impl Display for Span {
237 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 write!(f, "{}..{}", self.start.byte, self.end.byte)
239 }
240}
241
242impl Span {
243 // --------------------------------------------------------------------------------------------
244 // Constructors
245 // --------------------------------------------------------------------------------------------
246
247 /// Create a new span from the `start` byte and `end` byte indices.
248 #[inline(always)]
249 pub fn new(start: SpanPosition, end: SpanPosition) -> Self {
250 assert!(start.byte <= end.byte);
251 assert!(start.line <= end.line);
252 assert!(start.column <= end.column || end.line > start.line);
253
254 Self { start, end }
255 }
256
257 // --------------------------------------------------------------------------------------------
258 // Fields
259 // --------------------------------------------------------------------------------------------
260
261 /// Return the starting byte index of this span.
262 #[inline(always)]
263 pub fn start(&self) -> SpanPosition {
264 self.start
265 }
266
267 /// Return the ending byte index of this span.
268 #[inline(always)]
269 pub fn end(&self) -> SpanPosition {
270 self.end
271 }
272
273 /// Return this span as a `start..end` range.
274 #[inline(always)]
275 pub fn byte_range(&self) -> Range<usize> {
276 self.start.byte..self.end.byte
277 }
278}
279
280impl SpanPosition {
281 // --------------------------------------------------------------------------------------------
282 // Constructors
283 // --------------------------------------------------------------------------------------------
284
285 /// Create a new span position from the `byte`, `line`, and `column` indices.
286 #[inline(always)]
287 pub fn new(byte: usize, line: usize, column: usize) -> Self {
288 Self { byte, line, column }
289 }
290
291 /// Create a new span position from the `byte` and tree-sitter point.
292 #[cfg(feature = "tree-sitter")]
293 pub fn from(node_point: tree_sitter::Point, byte: usize) -> Self {
294 Self::new(byte, node_point.row + 1, node_point.column + 1)
295 }
296
297 pub const fn byte(&self) -> usize {
298 self.byte
299 }
300
301 pub const fn line(&self) -> usize {
302 self.line
303 }
304
305 pub const fn column(&self) -> usize {
306 self.column
307 }
308}
309
310// ------------------------------------------------------------------------------------------------
311// Modules
312// ------------------------------------------------------------------------------------------------
313
314pub mod annotations;
315
316pub mod check;
317
318pub mod constraints;
319
320pub mod definitions;
321
322pub mod identifiers;
323
324pub mod members;
325
326pub mod modules;
327
328pub mod values;
329
330pub mod walk;