sdml_core/model/definitions/
unions.rs1use 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#[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#[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>, }
50
51#[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
64impl 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 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
170impl 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 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 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
329impl 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 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 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 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}