sdml_core/model/definitions/
enums.rs

1use crate::{
2    load::ModuleLoader,
3    model::{
4        annotations::{
5            Annotation, AnnotationBuilder, AnnotationOnlyBody, AnnotationProperty, HasAnnotations,
6        },
7        check::{MaybeIncomplete, Validate},
8        identifiers::{Identifier, IdentifierReference},
9        modules::Module,
10        values::Value,
11        HasName, HasOptionalBody, HasSourceSpan, References, Span,
12    },
13    store::ModuleStore,
14};
15use sdml_errors::diagnostics::functions::IdentifierCaseConvention;
16use std::{
17    collections::{BTreeMap, BTreeSet},
18    fmt::Debug,
19};
20use tracing::warn;
21
22#[cfg(feature = "serde")]
23use serde::{Deserialize, Serialize};
24
25// ------------------------------------------------------------------------------------------------
26// Public Types ❱ Definitions ❱ Enumerations
27// ------------------------------------------------------------------------------------------------
28
29/// Corresponds to the grammar rule `enum_def`.
30#[derive(Clone, Debug)]
31#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
32pub struct EnumDef {
33    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
34    span: Option<Span>,
35    name: Identifier,
36    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
37    body: Option<EnumBody>,
38}
39
40/// Corresponds to the grammar rule `enum_body`.
41#[derive(Clone, Debug, Default)]
42#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
43pub struct EnumBody {
44    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
45    span: Option<Span>,
46    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
47    annotations: Vec<Annotation>,
48    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "BTreeMap::is_empty"))]
49    variants: BTreeMap<Identifier, ValueVariant>, // assert!(!variants.is_empty());
50}
51
52/// Corresponds to the grammar rule `enum_variant`.
53#[derive(Clone, Debug)]
54#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
55pub struct ValueVariant {
56    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
57    span: Option<Span>,
58    name: Identifier,
59    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
60    body: Option<AnnotationOnlyBody>,
61}
62
63// ------------------------------------------------------------------------------------------------
64// Implementations ❱ Definitions ❱ EnumDef
65// ------------------------------------------------------------------------------------------------
66
67impl HasName for EnumDef {
68    fn name(&self) -> &Identifier {
69        &self.name
70    }
71
72    fn set_name(&mut self, name: Identifier) {
73        self.name = name;
74    }
75}
76
77impl HasOptionalBody for EnumDef {
78    type Body = EnumBody;
79
80    fn body(&self) -> Option<&Self::Body> {
81        self.body.as_ref()
82    }
83
84    fn body_mut(&mut self) -> Option<&mut Self::Body> {
85        self.body.as_mut()
86    }
87
88    fn set_body(&mut self, body: Self::Body) {
89        self.body = Some(body);
90    }
91
92    fn unset_body(&mut self) {
93        self.body = None;
94    }
95}
96
97impl HasSourceSpan for EnumDef {
98    fn with_source_span(self, span: Span) -> Self {
99        let mut self_mut = self;
100        self_mut.span = Some(span);
101        self_mut
102    }
103
104    fn source_span(&self) -> Option<&Span> {
105        self.span.as_ref()
106    }
107
108    fn set_source_span(&mut self, span: Span) {
109        self.span = Some(span);
110    }
111
112    fn unset_source_span(&mut self) {
113        self.span = None;
114    }
115}
116
117impl MaybeIncomplete for EnumDef {
118    fn is_incomplete(&self, _: &Module, _: &impl ModuleStore) -> bool {
119        self.body.is_none()
120    }
121}
122
123impl AnnotationBuilder for EnumDef {
124    fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
125    where
126        Self: Sized,
127        I: Into<IdentifierReference>,
128        V: Into<Value>,
129    {
130        let mut self_mut = self;
131        if let Some(ref mut inner) = self_mut.body {
132            inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
133        }
134        self_mut
135    }
136}
137
138impl Validate for EnumDef {
139    fn validate(
140        &self,
141        top: &Module,
142        cache: &impl ModuleStore,
143        loader: &impl ModuleLoader,
144        check_constraints: bool,
145    ) {
146        // TODO check that any equivalent class is a datatype.
147        self.name()
148            .validate(top, loader, Some(IdentifierCaseConvention::TypeDefinition));
149        if let Some(body) = &self.body {
150            body.validate(top, cache, loader, check_constraints);
151        }
152    }
153}
154
155impl References for EnumDef {
156    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
157        self.body
158            .as_ref()
159            .map(|b| b.referenced_annotations(names))
160            .unwrap_or_default()
161    }
162}
163
164impl EnumDef {
165    // --------------------------------------------------------------------------------------------
166    // Constructors
167    // --------------------------------------------------------------------------------------------
168
169    pub fn new(name: Identifier) -> Self {
170        Self {
171            span: None,
172            name,
173            body: None,
174        }
175    }
176
177    pub fn with_body(self, body: EnumBody) -> Self {
178        let mut self_mut = self;
179        self_mut.body = Some(body);
180        self_mut
181    }
182}
183
184// ------------------------------------------------------------------------------------------------
185// Implementations ❱ Definitions ❱ EnumBody
186// ------------------------------------------------------------------------------------------------
187
188impl HasAnnotations for EnumBody {
189    fn has_annotations(&self) -> bool {
190        !self.annotations.is_empty()
191    }
192
193    fn annotation_count(&self) -> usize {
194        self.annotations.len()
195    }
196
197    fn annotations(&self) -> impl Iterator<Item = &Annotation> {
198        self.annotations.iter()
199    }
200
201    fn annotations_mut(&mut self) -> impl Iterator<Item = &mut Annotation> {
202        self.annotations.iter_mut()
203    }
204
205    fn add_to_annotations<I>(&mut self, value: I)
206    where
207        I: Into<Annotation>,
208    {
209        self.annotations.push(value.into())
210    }
211
212    fn extend_annotations<I>(&mut self, extension: I)
213    where
214        I: IntoIterator<Item = Annotation>,
215    {
216        self.annotations.extend(extension.into_iter())
217    }
218}
219
220impl HasSourceSpan for EnumBody {
221    fn with_source_span(self, span: Span) -> Self {
222        let mut self_mut = self;
223        self_mut.span = Some(span);
224        self_mut
225    }
226
227    fn source_span(&self) -> Option<&Span> {
228        self.span.as_ref()
229    }
230
231    fn set_source_span(&mut self, span: Span) {
232        self.span = Some(span);
233    }
234
235    fn unset_source_span(&mut self) {
236        self.span = None;
237    }
238}
239
240impl References for EnumBody {
241    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
242        self.variants()
243            .for_each(|v| v.referenced_annotations(names));
244    }
245}
246
247impl Validate for EnumBody {
248    fn validate(
249        &self,
250        top: &Module,
251        cache: &impl ModuleStore,
252        loader: &impl ModuleLoader,
253        check_constraints: bool,
254    ) {
255        self.annotations()
256            .for_each(|a| a.validate(top, cache, loader, check_constraints));
257        self.variants()
258            .for_each(|v| v.validate(top, cache, loader, check_constraints));
259    }
260}
261
262impl EnumBody {
263    // --------------------------------------------------------------------------------------------
264    // Constructors
265    // --------------------------------------------------------------------------------------------
266
267    pub fn with_variants<I>(self, variants: I) -> Self
268    where
269        I: IntoIterator<Item = ValueVariant>,
270    {
271        let mut self_mut = self;
272        self_mut.variants = variants
273            .into_iter()
274            .map(|elem| (elem.name().clone(), elem))
275            .collect();
276        self_mut
277    }
278
279    // --------------------------------------------------------------------------------------------
280    // Variants
281    // --------------------------------------------------------------------------------------------
282
283    pub fn has_variants(&self) -> bool {
284        !self.variants.is_empty()
285    }
286
287    pub fn variant_count(&self) -> usize {
288        self.variants.len()
289    }
290
291    pub fn contains_variant(&self, name: &Identifier) -> bool {
292        self.variants.contains_key(name)
293    }
294
295    pub fn variant(&self, name: &Identifier) -> Option<&ValueVariant> {
296        self.variants.get(name)
297    }
298
299    pub fn variant_mut(&mut self, name: &Identifier) -> Option<&mut ValueVariant> {
300        self.variants.get_mut(name)
301    }
302
303    pub fn variants(&self) -> impl Iterator<Item = &ValueVariant> {
304        self.variants.values()
305    }
306
307    pub fn variants_mut(&mut self) -> impl Iterator<Item = &mut ValueVariant> {
308        self.variants.values_mut()
309    }
310
311    pub fn variant_names(&self) -> impl Iterator<Item = &Identifier> {
312        self.variants.keys()
313    }
314
315    pub fn add_to_variants(&mut self, value: ValueVariant) -> Option<ValueVariant> {
316        self.variants.insert(value.name().clone(), value)
317    }
318
319    pub fn extend_variants<I>(&mut self, extension: I)
320    where
321        I: IntoIterator<Item = ValueVariant>,
322    {
323        self.variants.extend(
324            extension
325                .into_iter()
326                .map(|elem| (elem.name().clone(), elem)),
327        )
328    }
329}
330
331// ------------------------------------------------------------------------------------------------
332// Implementations ❱ Definitions ❱ ValueVariant
333// ------------------------------------------------------------------------------------------------
334
335impl HasName for ValueVariant {
336    fn name(&self) -> &Identifier {
337        &self.name
338    }
339
340    fn set_name(&mut self, name: Identifier) {
341        self.name = name;
342    }
343}
344
345impl HasOptionalBody for ValueVariant {
346    type Body = AnnotationOnlyBody;
347
348    fn body(&self) -> Option<&Self::Body> {
349        self.body.as_ref()
350    }
351
352    fn body_mut(&mut self) -> Option<&mut Self::Body> {
353        self.body.as_mut()
354    }
355
356    fn set_body(&mut self, body: Self::Body) {
357        self.body = Some(body);
358    }
359
360    fn unset_body(&mut self) {
361        self.body = None;
362    }
363}
364
365impl HasSourceSpan for ValueVariant {
366    fn with_source_span(self, span: Span) -> Self {
367        let mut self_mut = self;
368        self_mut.span = Some(span);
369        self_mut
370    }
371
372    fn source_span(&self) -> Option<&Span> {
373        self.span.as_ref()
374    }
375
376    fn set_source_span(&mut self, span: Span) {
377        self.span = Some(span);
378    }
379
380    fn unset_source_span(&mut self) {
381        self.span = None;
382    }
383}
384
385impl AnnotationBuilder for ValueVariant {
386    fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
387    where
388        Self: Sized,
389        I: Into<IdentifierReference>,
390        V: Into<Value>,
391    {
392        let mut self_mut = self;
393        if let Some(ref mut inner) = self_mut.body {
394            inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
395        }
396        self_mut
397    }
398}
399
400impl Validate for ValueVariant {
401    fn validate(
402        &self,
403        top: &Module,
404        _cache: &impl ModuleStore,
405        loader: &impl ModuleLoader,
406        _check_constraints: bool,
407    ) {
408        warn!("Missing validation for ValueVariant values.");
409        self.name()
410            .validate(top, loader, Some(IdentifierCaseConvention::ValueVariant));
411    }
412}
413
414impl References for ValueVariant {
415    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
416        self.body
417            .as_ref()
418            .map(|b| b.referenced_annotations(names))
419            .unwrap_or_default()
420    }
421}
422
423impl ValueVariant {
424    // --------------------------------------------------------------------------------------------
425    // Constructors
426    // --------------------------------------------------------------------------------------------
427
428    pub fn new(name: Identifier) -> Self {
429        Self {
430            span: None,
431            name,
432            body: None,
433        }
434    }
435
436    pub fn with_body(self, body: AnnotationOnlyBody) -> Self {
437        let mut self_mut = self;
438        self_mut.body = Some(body);
439        self_mut
440    }
441}