sdml_core/model/constraints/
mod.rs

1/*!
2Provide the Rust types that implement *constraint*-related components of the SDML Grammar.
3 */
4
5use crate::{
6    load::ModuleLoader,
7    model::{
8        check::Validate, modules::Module, HasBody, HasName, HasSourceSpan, Identifier,
9        IdentifierReference, References, Span,
10    },
11    store::ModuleStore,
12};
13use std::collections::BTreeSet;
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18// ------------------------------------------------------------------------------------------------
19// Public Types ❱ Constraints
20// ------------------------------------------------------------------------------------------------
21
22/// Corresponds to the grammar rule `constraint`.
23#[derive(Clone, Debug)]
24#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
25pub struct Constraint {
26    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
27    span: Option<Span>,
28    name: Identifier,
29    body: ConstraintBody,
30}
31
32///
33/// Corresponds to the field `body` in the grammar rule `constraint`.
34///
35/// # Semantics
36///
37/// The domain of discourse, $\mathbb{D}$, is the set of all definitions present in the current
38/// module and the set of modules transitively imported by it.
39///
40#[derive(Clone, Debug)]
41#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
42pub enum ConstraintBody {
43    /// Corresponds to the grammar rule `informal_constraint`.
44    Informal(ControlledLanguageString),
45    /// Corresponds to the grammar rule `formal_constraint`.
46    Formal(FormalConstraint),
47}
48
49// ------------------------------------------------------------------------------------------------
50// Implementations ❱ Constraints ❱ Constraint
51// ------------------------------------------------------------------------------------------------
52
53impl HasName for Constraint {
54    fn name(&self) -> &Identifier {
55        &self.name
56    }
57
58    fn set_name(&mut self, name: Identifier) {
59        self.name = name;
60    }
61}
62
63impl HasBody for Constraint {
64    type Body = ConstraintBody;
65
66    fn body(&self) -> &Self::Body {
67        &self.body
68    }
69
70    fn body_mut(&mut self) -> &mut Self::Body {
71        &mut self.body
72    }
73
74    fn set_body(&mut self, body: Self::Body) {
75        self.body = body;
76    }
77}
78
79impl HasSourceSpan for Constraint {
80    fn with_source_span(self, span: Span) -> Self {
81        let mut self_mut = self;
82        self_mut.span = Some(span);
83        self_mut
84    }
85
86    fn source_span(&self) -> Option<&Span> {
87        self.span.as_ref()
88    }
89
90    fn set_source_span(&mut self, span: Span) {
91        self.span = Some(span);
92    }
93
94    fn unset_source_span(&mut self) {
95        self.span = None;
96    }
97}
98
99impl References for Constraint {
100    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
101        self.body.referenced_annotations(names);
102    }
103
104    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
105        self.body.referenced_types(names);
106    }
107}
108
109impl Validate for Constraint {
110    fn validate(
111        &self,
112        top: &Module,
113        cache: &impl ModuleStore,
114        loader: &impl ModuleLoader,
115        check_constraints: bool,
116    ) {
117        self.body.validate(top, cache, loader, check_constraints)
118    }
119}
120
121impl Constraint {
122    // --------------------------------------------------------------------------------------------
123    // Constructors
124    // --------------------------------------------------------------------------------------------
125
126    pub fn new<B>(name: Identifier, body: B) -> Self
127    where
128        B: Into<ConstraintBody>,
129    {
130        Self {
131            span: None,
132            name,
133            body: body.into(),
134        }
135    }
136}
137
138// ------------------------------------------------------------------------------------------------
139// Implementations ❱ Constraints ❱ ConstraintBody
140// ------------------------------------------------------------------------------------------------
141
142impl From<&ControlledLanguageString> for ConstraintBody {
143    fn from(v: &ControlledLanguageString) -> Self {
144        Self::Informal(v.clone())
145    }
146}
147
148impl From<ControlledLanguageString> for ConstraintBody {
149    fn from(v: ControlledLanguageString) -> Self {
150        Self::Informal(v)
151    }
152}
153
154impl From<&FormalConstraint> for ConstraintBody {
155    fn from(v: &FormalConstraint) -> Self {
156        Self::Formal(v.clone())
157    }
158}
159
160impl From<FormalConstraint> for ConstraintBody {
161    fn from(v: FormalConstraint) -> Self {
162        Self::Formal(v)
163    }
164}
165
166impl References for ConstraintBody {
167    fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
168        match self {
169            Self::Informal(v) => v.referenced_annotations(names),
170            Self::Formal(v) => v.referenced_annotations(names),
171        }
172    }
173
174    fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
175        match self {
176            Self::Informal(v) => v.referenced_types(names),
177            Self::Formal(v) => v.referenced_types(names),
178        }
179    }
180}
181
182impl Validate for ConstraintBody {
183    fn validate(
184        &self,
185        top: &Module,
186        cache: &impl ModuleStore,
187        loader: &impl ModuleLoader,
188        check_constraints: bool,
189    ) {
190        match self {
191            Self::Informal(v) => v.validate(top, cache, loader, check_constraints),
192            Self::Formal(v) => v.validate(top, cache, loader, check_constraints),
193        }
194    }
195}
196
197impl ConstraintBody {
198    // --------------------------------------------------------------------------------------------
199    // Variants
200    // --------------------------------------------------------------------------------------------
201
202    pub const fn is_informal(&self) -> bool {
203        matches!(self, Self::Informal(_))
204    }
205
206    pub const fn as_informal(&self) -> Option<&ControlledLanguageString> {
207        match self {
208            Self::Informal(v) => Some(v),
209            _ => None,
210        }
211    }
212
213    pub const fn is_formal(&self) -> bool {
214        matches!(self, Self::Formal(_))
215    }
216
217    pub const fn as_formal(&self) -> Option<&FormalConstraint> {
218        match self {
219            Self::Formal(v) => Some(v),
220            _ => None,
221        }
222    }
223}
224
225// ------------------------------------------------------------------------------------------------
226// Modules
227// ------------------------------------------------------------------------------------------------
228
229mod formal;
230pub use formal::{
231    AtomicSentence, BinaryBooleanSentence, BooleanSentence, ConnectiveOperator, ConstraintSentence,
232    Equation, FormalConstraint, FunctionBody, FunctionCardinality, FunctionComposition,
233    FunctionDef, FunctionParameter, FunctionSignature, FunctionType, FunctionTypeReference,
234    FunctionalTerm, InequalityRelation, Inequation, PredicateSequenceMember, PredicateValue,
235    QuantifiedSentence, QuantifiedVariable, QuantifiedVariableBinding, Quantifier, SequenceBuilder,
236    SequenceOfPredicateValues, SimpleSentence, Subject, Term, UnaryBooleanSentence, Variable,
237};
238
239mod informal;
240pub use informal::{ControlledLanguageString, ControlledLanguageTag};