sdml_core/model/definitions/
structures.rs

1use crate::{
2    load::ModuleLoader,
3    model::{
4        annotations::{Annotation, AnnotationBuilder, AnnotationProperty, HasAnnotations},
5        check::{MaybeIncomplete, Validate},
6        identifiers::{Identifier, IdentifierReference},
7        members::Member,
8        modules::Module,
9        values::Value,
10        HasName, HasOptionalBody, HasSourceSpan, References, Span,
11    },
12    store::ModuleStore,
13};
14use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
15use std::{
16    collections::{BTreeMap, BTreeSet},
17    fmt::Debug,
18};
19
20#[cfg(feature = "serde")]
21use serde::{Deserialize, Serialize};
22
23// ------------------------------------------------------------------------------------------------
24// Public Types ❱ Definitions ❱ Structures
25// ------------------------------------------------------------------------------------------------
26
27/// Corresponds to the grammar rule `structure_def`.
28#[derive(Clone, Debug)]
29#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
30pub struct StructureDef {
31    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
32    span: Option<Span>,
33    name: Identifier,
34    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
35    body: Option<StructureBody>,
36}
37
38/// Corresponds to the grammar rule `structure_body`.
39#[derive(Clone, Debug, Default)]
40#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
41pub struct StructureBody {
42    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
43    span: Option<Span>,
44    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
45    annotations: Vec<Annotation>,
46    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
47    members: BTreeMap<Identifier, Member>,
48}
49
50// ------------------------------------------------------------------------------------------------
51// Implementations ❱ Definitions ❱ StructureDef
52// ------------------------------------------------------------------------------------------------
53
54impl HasName for StructureDef {
55    fn name(&self) -> &Identifier {
56        &self.name
57    }
58
59    fn set_name(&mut self, name: Identifier) {
60        self.name = name;
61    }
62}
63
64impl HasOptionalBody for StructureDef {
65    type Body = StructureBody;
66
67    fn body(&self) -> Option<&Self::Body> {
68        self.body.as_ref()
69    }
70
71    fn body_mut(&mut self) -> Option<&mut Self::Body> {
72        self.body.as_mut()
73    }
74
75    fn set_body(&mut self, body: Self::Body) {
76        self.body = Some(body);
77    }
78
79    fn unset_body(&mut self) {
80        self.body = None;
81    }
82}
83
84impl HasSourceSpan for StructureDef {
85    fn with_source_span(self, span: Span) -> Self {
86        let mut self_mut = self;
87        self_mut.span = Some(span);
88        self_mut
89    }
90
91    fn source_span(&self) -> Option<&Span> {
92        self.span.as_ref()
93    }
94
95    fn set_source_span(&mut self, span: Span) {
96        self.span = Some(span);
97    }
98
99    fn unset_source_span(&mut self) {
100        self.span = None;
101    }
102}
103
104impl AnnotationBuilder for StructureDef {
105    fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
106    where
107        Self: Sized,
108        I: Into<IdentifierReference>,
109        V: Into<Value>,
110    {
111        let mut self_mut = self;
112        if let Some(ref mut inner) = self_mut.body {
113            inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
114        }
115        self_mut
116    }
117}
118
119impl References for StructureDef {
120    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
121        if let Some(inner) = &self.body {
122            inner.referenced_annotations(names);
123        }
124    }
125
126    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
127        if let Some(inner) = &self.body {
128            inner.referenced_types(names);
129        }
130    }
131}
132
133impl MaybeIncomplete for StructureDef {
134    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
135        if let Some(body) = &self.body {
136            body.is_incomplete(top, cache)
137        } else {
138            true
139        }
140    }
141}
142
143impl Validate for StructureDef {
144    fn validate(
145        &self,
146        top: &Module,
147        cache: &impl ModuleStore,
148        loader: &impl ModuleLoader,
149        check_constraints: bool,
150    ) {
151        self.name
152            .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
153        if let Some(body) = &self.body {
154            body.validate(top, cache, loader, check_constraints);
155        }
156    }
157}
158
159impl StructureDef {
160    // --------------------------------------------------------------------------------------------
161    // Constructors
162    // --------------------------------------------------------------------------------------------
163
164    pub fn new(name: Identifier) -> Self {
165        Self {
166            span: None,
167            name,
168            body: None,
169        }
170    }
171    pub fn with_body(self, body: StructureBody) -> Self {
172        let mut self_mut = self;
173        self_mut.body = Some(body);
174        self_mut
175    }
176}
177
178// ------------------------------------------------------------------------------------------------
179// Implementations ❱ Definitions ❱ StructureBody
180// ------------------------------------------------------------------------------------------------
181
182impl HasAnnotations for StructureBody {
183    fn has_annotations(&self) -> bool {
184        !self.annotations.is_empty()
185    }
186
187    fn annotation_count(&self) -> usize {
188        self.annotations.len()
189    }
190
191    fn annotations(&self) -> impl Iterator<Item = &Annotation> {
192        self.annotations.iter()
193    }
194
195    fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
196        self.annotations.iter_mut()
197    }
198
199    fn add_to_annotations<I>(&mut self, value: I)
200    where
201        I: Into<Annotation>,
202    {
203        self.annotations.push(value.into())
204    }
205
206    fn extend_annotations<I>(&mut self, extension: I)
207    where
208        I: IntoIterator<Item = Annotation>,
209    {
210        self.annotations.extend(extension)
211    }
212}
213
214impl HasSourceSpan for StructureBody {
215    fn with_source_span(self, span: Span) -> Self {
216        let mut self_mut = self;
217        self_mut.span = Some(span);
218        self_mut
219    }
220
221    fn source_span(&self) -> Option<&Span> {
222        self.span.as_ref()
223    }
224
225    fn set_source_span(&mut self, span: Span) {
226        self.span = Some(span);
227    }
228
229    fn unset_source_span(&mut self) {
230        self.span = None;
231    }
232}
233
234impl MaybeIncomplete for StructureBody {
235    fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
236        self.members().any(|elem| elem.is_incomplete(top, cache))
237    }
238}
239
240impl Validate for StructureBody {
241    fn validate(
242        &self,
243        top: &Module,
244        cache: &impl ModuleStore,
245        loader: &impl ModuleLoader,
246        check_constraints: bool,
247    ) {
248        self.annotations()
249            .for_each(|a| a.validate(top, cache, loader, check_constraints));
250        self.members()
251            .for_each(|m| m.validate(top, cache, loader, check_constraints));
252    }
253}
254
255impl References for StructureBody {
256    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
257        self.members().for_each(|m| m.referenced_types(names));
258    }
259
260    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
261        self.members().for_each(|m| m.referenced_annotations(names));
262    }
263}
264
265impl StructureBody {
266    // --------------------------------------------------------------------------------------------
267    // Constructors
268    // --------------------------------------------------------------------------------------------
269
270    pub fn with_members<I>(self, members: I) -> Self
271    where
272        I: IntoIterator<Item = Member>,
273    {
274        let mut self_mut = self;
275        self_mut.extend_members(members);
276        self_mut
277    }
278
279    // --------------------------------------------------------------------------------------------
280    // Members
281    // --------------------------------------------------------------------------------------------
282
283    pub fn has_members(&self) -> bool {
284        !self.members.is_empty()
285    }
286
287    pub fn member_count(&self) -> usize {
288        self.members.len()
289    }
290
291    pub fn contains_member(&self, name: &Identifier) -> bool {
292        self.members.contains_key(name)
293    }
294
295    pub fn member(&self, name: &Identifier) -> Option<&Member> {
296        self.members.get(name)
297    }
298
299    pub fn member_mut(&mut self, name: &Identifier) -> Option<&mut Member> {
300        self.members.get_mut(name)
301    }
302
303    pub fn members(&self) -> impl Iterator<Item = &Member> {
304        self.members.values()
305    }
306
307    pub fn members_mut(&mut self) -> impl Iterator<Item = &mut Member> {
308        self.members.values_mut()
309    }
310
311    pub fn member_names(&self) -> impl Iterator<Item = &Identifier> {
312        self.members.keys()
313    }
314
315    pub fn add_to_members(&mut self, value: Member) -> Option<Member> {
316        self.members.insert(value.name().clone(), value)
317    }
318
319    pub fn extend_members<I>(&mut self, extension: I)
320    where
321        I: IntoIterator<Item = Member>,
322    {
323        self.members.extend(
324            extension
325                .into_iter()
326                .map(|elem| (elem.name().clone(), elem)),
327        )
328    }
329}