1use crate::ast::{Attribute, AttributeArg};
7use crate::semantic::{ActionInfo, EnumInfo, RelationInfo, StateInfo, StructInfo, Type};
8use crate::Span;
9use indexmap::IndexMap;
10use smol_str::SmolStr;
11use std::sync::Arc;
12
13#[derive(Debug, Clone)]
15pub struct CompiledAttribute {
16 pub name: SmolStr,
18 pub args: Vec<CompiledAttributeArg>,
20}
21
22#[derive(Debug, Clone)]
24pub enum CompiledAttributeArg {
25 String(SmolStr),
27 Ident(SmolStr),
29 Int(i64),
31}
32
33impl CompiledAttribute {
34 #[must_use]
36 pub fn from_ast(attr: &Attribute) -> Self {
37 Self {
38 name: attr.name.name.clone(),
39 args: attr.args.iter().map(CompiledAttributeArg::from_ast).collect(),
40 }
41 }
42
43 #[must_use]
45 pub fn first_arg_string(&self) -> Option<&str> {
46 self.args.first().and_then(|arg| match arg {
47 CompiledAttributeArg::String(s) | CompiledAttributeArg::Ident(s) => Some(s.as_str()),
48 CompiledAttributeArg::Int(_) => None,
49 })
50 }
51}
52
53impl CompiledAttributeArg {
54 #[must_use]
56 pub fn from_ast(arg: &AttributeArg) -> Self {
57 match arg {
58 AttributeArg::String(s, _) => CompiledAttributeArg::String(s.clone()),
59 AttributeArg::Ident(ident) => CompiledAttributeArg::Ident(ident.name.clone()),
60 AttributeArg::Int(n, _) => CompiledAttributeArg::Int(*n),
61 }
62 }
63}
64
65impl std::fmt::Display for CompiledAttributeArg {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 match self {
68 CompiledAttributeArg::String(s) => write!(f, "\"{s}\""),
69 CompiledAttributeArg::Ident(s) => write!(f, "{s}"),
70 CompiledAttributeArg::Int(n) => write!(f, "{n}"),
71 }
72 }
73}
74
75#[derive(Debug, Clone)]
77pub struct CompiledSpec {
78 pub module: Option<SmolStr>,
80 pub imports: Vec<Import>,
82 pub structs: IndexMap<SmolStr, CompiledStruct>,
84 pub type_aliases: IndexMap<SmolStr, CompiledTypeAlias>,
86 pub enums: IndexMap<SmolStr, CompiledEnum>,
88 pub states: IndexMap<SmolStr, CompiledState>,
90 pub actions: IndexMap<SmolStr, CompiledAction>,
92 pub relations: IndexMap<SmolStr, CompiledRelation>,
94 pub scenarios: Vec<CompiledScenario>,
96 pub properties: Vec<CompiledProperty>,
98 pub qualities: Vec<CompiledQuality>,
100}
101
102impl CompiledSpec {
103 #[must_use]
105 pub fn new() -> Self {
106 Self {
107 module: None,
108 imports: Vec::new(),
109 structs: IndexMap::new(),
110 type_aliases: IndexMap::new(),
111 enums: IndexMap::new(),
112 states: IndexMap::new(),
113 actions: IndexMap::new(),
114 relations: IndexMap::new(),
115 scenarios: Vec::new(),
116 properties: Vec::new(),
117 qualities: Vec::new(),
118 }
119 }
120
121 #[must_use]
123 pub fn is_empty(&self) -> bool {
124 self.structs.is_empty()
125 && self.type_aliases.is_empty()
126 && self.enums.is_empty()
127 && self.states.is_empty()
128 && self.actions.is_empty()
129 && self.relations.is_empty()
130 && self.scenarios.is_empty()
131 && self.properties.is_empty()
132 && self.qualities.is_empty()
133 }
134
135 #[must_use]
137 pub fn definition_count(&self) -> usize {
138 self.structs.len()
139 + self.type_aliases.len()
140 + self.enums.len()
141 + self.states.len()
142 + self.actions.len()
143 + self.relations.len()
144 }
145}
146
147impl Default for CompiledSpec {
148 fn default() -> Self {
149 Self::new()
150 }
151}
152
153#[derive(Debug, Clone)]
155pub struct Import {
156 pub path: Vec<SmolStr>,
158 pub items: Vec<SmolStr>,
160 pub span: Span,
162}
163
164#[derive(Debug, Clone)]
166pub struct CompiledStruct {
167 pub name: SmolStr,
169 pub type_params: Vec<SmolStr>,
171 pub fields: IndexMap<SmolStr, Type>,
173 pub refinement: Option<Arc<crate::ast::Expr>>,
175 pub attributes: Vec<CompiledAttribute>,
177 pub doc: Option<String>,
179 pub span: Span,
181}
182
183#[derive(Debug, Clone)]
185pub struct CompiledTypeAlias {
186 pub name: SmolStr,
188 pub type_params: Vec<SmolStr>,
190 pub base: Type,
192 pub refinement: Option<Arc<crate::ast::Expr>>,
194 pub attributes: Vec<CompiledAttribute>,
196 pub doc: Option<String>,
198 pub span: Span,
200}
201
202impl CompiledStruct {
203 #[must_use]
205 pub fn from_info(
206 info: &StructInfo,
207 refinement: Option<Arc<crate::ast::Expr>>,
208 attributes: Vec<CompiledAttribute>,
209 span: Span,
210 ) -> Self {
211 Self {
212 name: info.id.name.clone(),
213 type_params: info.type_params.clone(),
214 fields: info.fields.clone(),
215 refinement,
216 attributes,
217 doc: None,
218 span,
219 }
220 }
221}
222
223#[derive(Debug, Clone)]
225pub struct CompiledEnum {
226 pub name: SmolStr,
228 pub type_params: Vec<SmolStr>,
230 pub variants: IndexMap<SmolStr, CompiledVariant>,
232 pub attributes: Vec<CompiledAttribute>,
234 pub doc: Option<String>,
236 pub span: Span,
238}
239
240impl CompiledEnum {
241 #[must_use]
243 pub fn from_info(info: &EnumInfo, attributes: Vec<CompiledAttribute>, span: Span) -> Self {
244 let variants = info
245 .variants
246 .iter()
247 .map(|(name, v)| {
248 (
249 name.clone(),
250 CompiledVariant {
251 name: v.name.clone(),
252 fields: v.fields.clone(),
253 is_tuple: v.is_tuple,
254 },
255 )
256 })
257 .collect();
258
259 Self {
260 name: info.id.name.clone(),
261 type_params: info.type_params.clone(),
262 variants,
263 attributes,
264 doc: None,
265 span,
266 }
267 }
268}
269
270#[derive(Debug, Clone)]
272pub struct CompiledVariant {
273 pub name: SmolStr,
275 pub fields: IndexMap<SmolStr, Type>,
277 pub is_tuple: bool,
279}
280
281impl CompiledVariant {
282 #[must_use]
284 pub fn is_unit(&self) -> bool {
285 self.fields.is_empty()
286 }
287}
288
289#[derive(Debug, Clone)]
291pub struct CompiledState {
292 pub name: SmolStr,
294 pub fields: IndexMap<SmolStr, Type>,
296 pub invariants: Vec<CompiledInvariant>,
298 pub attributes: Vec<CompiledAttribute>,
300 pub doc: Option<String>,
302 pub span: Span,
304}
305
306impl CompiledState {
307 #[must_use]
309 pub fn from_info(info: &StateInfo, attributes: Vec<CompiledAttribute>, span: Span) -> Self {
310 Self {
311 name: info.name.clone(),
312 fields: info.fields.clone(),
313 invariants: Vec::new(),
314 attributes,
315 doc: None,
316 span,
317 }
318 }
319}
320
321#[derive(Debug, Clone)]
323pub struct CompiledInvariant {
324 pub name: Option<String>,
326 pub expr: Arc<crate::ast::Expr>,
328 pub span: Span,
330}
331
332#[derive(Debug, Clone)]
334pub struct CompiledAction {
335 pub name: SmolStr,
337 pub params: IndexMap<SmolStr, Type>,
339 pub return_type: Type,
341 pub requires: Vec<CompiledContract>,
343 pub ensures: Vec<CompiledContract>,
345 pub attributes: Vec<CompiledAttribute>,
347 pub doc: Option<String>,
349 pub span: Span,
351}
352
353impl CompiledAction {
354 #[must_use]
356 pub fn from_info(info: &ActionInfo, attributes: Vec<CompiledAttribute>, span: Span) -> Self {
357 Self {
358 name: info.name.clone(),
359 params: info.params.clone(),
360 return_type: info.return_type.clone(),
361 requires: Vec::new(),
362 ensures: Vec::new(),
363 attributes,
364 doc: None,
365 span,
366 }
367 }
368}
369
370#[derive(Debug, Clone)]
372pub struct CompiledContract {
373 pub expr: Arc<crate::ast::Expr>,
375 pub span: Span,
377}
378
379#[derive(Debug, Clone)]
381pub struct CompiledRelation {
382 pub name: SmolStr,
384 pub source: Type,
386 pub target: Type,
388 pub properties: Vec<RelationProperty>,
390 pub attributes: Vec<CompiledAttribute>,
392 pub doc: Option<String>,
394 pub span: Span,
396}
397
398impl CompiledRelation {
399 #[must_use]
401 pub fn from_info(info: &RelationInfo, attributes: Vec<CompiledAttribute>, span: Span) -> Self {
402 Self {
403 name: info.name.clone(),
404 source: info.source.clone(),
405 target: info.target.clone(),
406 properties: Vec::new(),
407 attributes,
408 doc: None,
409 span,
410 }
411 }
412}
413
414#[derive(Debug, Clone, Copy, PartialEq, Eq)]
416pub enum RelationProperty {
417 Symmetric,
419 Reflexive,
421 Irreflexive,
423 Transitive,
425 Antisymmetric,
427}
428
429#[derive(Debug, Clone)]
431pub struct CompiledScenario {
432 pub name: String,
434 pub given: Vec<CompiledGiven>,
436 pub when: Vec<CompiledWhen>,
438 pub then: Vec<CompiledThen>,
440 pub alternatives: Vec<CompiledAlternative>,
442 pub attributes: Vec<CompiledAttribute>,
444 pub doc: Option<String>,
446 pub span: Span,
448}
449
450#[derive(Debug, Clone)]
452pub struct CompiledAlternative {
453 pub name: String,
455 pub condition: Option<Arc<crate::ast::Expr>>,
457 pub given: Option<CompiledGiven>,
459 pub when: Option<CompiledWhen>,
461 pub then: CompiledThen,
463 pub attributes: Vec<CompiledAttribute>,
465 pub span: Span,
467}
468
469#[derive(Debug, Clone)]
471pub struct CompiledGiven {
472 pub assignments: Vec<CompiledAssignment>,
474 pub span: Span,
476}
477
478#[derive(Debug, Clone)]
480pub struct CompiledWhen {
481 pub actions: Vec<CompiledWhenAction>,
483 pub span: Span,
485}
486
487#[derive(Debug, Clone)]
489pub struct CompiledWhenAction {
490 pub binding: Option<SmolStr>,
492 pub expr: Arc<crate::ast::Expr>,
494 pub span: Span,
496}
497
498#[derive(Debug, Clone)]
500pub struct CompiledThen {
501 pub assertions: Vec<CompiledAssertion>,
503 pub span: Span,
505}
506
507#[derive(Debug, Clone)]
509pub struct CompiledAssignment {
510 pub name: SmolStr,
512 pub value: Arc<crate::ast::Expr>,
514 pub span: Span,
516}
517
518#[derive(Debug, Clone)]
520pub struct CompiledAssertion {
521 pub expr: Arc<crate::ast::Expr>,
523 pub span: Span,
525}
526
527#[derive(Debug, Clone)]
529pub struct CompiledProperty {
530 pub name: String,
532 pub expr: Arc<crate::ast::Expr>,
534 pub temporal: Option<TemporalOp>,
536 pub attributes: Vec<CompiledAttribute>,
538 pub doc: Option<String>,
540 pub span: Span,
542}
543
544#[derive(Debug, Clone, Copy, PartialEq, Eq)]
546pub enum TemporalOp {
547 Always,
549 Eventually,
551 Until,
553 Next,
555}
556
557#[derive(Debug, Clone)]
559pub struct CompiledQuality {
560 pub category: QualityCategory,
562 pub description: SmolStr,
564 pub metric: SmolStr,
566 pub target: String,
568 pub properties: Vec<CompiledQualityProperty>,
570 pub attributes: Vec<CompiledAttribute>,
572 pub span: Span,
574}
575
576#[derive(Debug, Clone, Copy, PartialEq, Eq)]
578pub enum QualityCategory {
579 Performance,
581 Reliability,
583 Security,
585 Usability,
587 Scalability,
589 Maintainability,
591}
592
593impl std::fmt::Display for QualityCategory {
594 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
595 match self {
596 QualityCategory::Performance => write!(f, "Performance"),
597 QualityCategory::Reliability => write!(f, "Reliability"),
598 QualityCategory::Security => write!(f, "Security"),
599 QualityCategory::Usability => write!(f, "Usability"),
600 QualityCategory::Scalability => write!(f, "Scalability"),
601 QualityCategory::Maintainability => write!(f, "Maintainability"),
602 }
603 }
604}
605
606#[derive(Debug, Clone)]
608pub struct CompiledQualityProperty {
609 pub name: SmolStr,
611 pub value: String,
613}