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