1use serde::Serialize;
12
13use crate::Span;
14
15#[derive(Debug, Clone, Serialize)]
21pub struct Module {
22 pub span: Span,
23 pub version: Option<u32>,
25 pub declarations: Vec<Decl>,
26}
27
28#[derive(Debug, Clone, Serialize)]
33pub enum Decl {
34 Use(UseDecl),
35 Block(BlockDecl),
36 Default(DefaultDecl),
37 Variant(VariantDecl),
38 Deferred(DeferredDecl),
39 OpenQuestion(OpenQuestionDecl),
40 Invariant(InvariantDecl),
41}
42
43#[derive(Debug, Clone, Serialize)]
45pub struct UseDecl {
46 pub span: Span,
47 pub path: StringLiteral,
48 pub alias: Option<Ident>,
49}
50
51#[derive(Debug, Clone, Serialize)]
53pub struct BlockDecl {
54 pub span: Span,
55 pub kind: BlockKind,
56 pub name: Option<Ident>,
58 pub items: Vec<BlockItem>,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
62pub enum BlockKind {
63 Entity,
64 ExternalEntity,
65 Value,
66 Enum,
67 Given,
68 Config,
69 Rule,
70 Surface,
71 Actor,
72 Contract,
73 Invariant,
74}
75
76#[derive(Debug, Clone, Serialize)]
78pub struct DefaultDecl {
79 pub span: Span,
80 pub type_name: Option<Ident>,
81 pub name: Ident,
82 pub value: Expr,
83}
84
85#[derive(Debug, Clone, Serialize)]
87pub struct VariantDecl {
88 pub span: Span,
89 pub name: Ident,
90 pub base: Expr,
91 pub items: Vec<BlockItem>,
92}
93
94#[derive(Debug, Clone, Serialize)]
96pub struct DeferredDecl {
97 pub span: Span,
98 pub path: Expr,
99}
100
101#[derive(Debug, Clone, Serialize)]
103pub struct OpenQuestionDecl {
104 pub span: Span,
105 pub text: StringLiteral,
106}
107
108#[derive(Debug, Clone, Serialize)]
110pub struct InvariantDecl {
111 pub span: Span,
112 pub name: Ident,
113 pub body: Expr,
114}
115
116#[derive(Debug, Clone, Serialize)]
122pub struct TransitionEdge {
123 pub span: Span,
124 pub from: Ident,
125 pub to: Ident,
126}
127
128#[derive(Debug, Clone, Serialize)]
130pub struct TransitionGraph {
131 pub span: Span,
132 pub field: Ident,
133 pub edges: Vec<TransitionEdge>,
134 pub terminal: Vec<Ident>,
135}
136
137#[derive(Debug, Clone, Serialize)]
143pub struct WhenClause {
144 pub span: Span,
145 pub status_field: Ident,
146 pub qualifying_states: Vec<Ident>,
147}
148
149#[derive(Debug, Clone, Serialize)]
154pub struct BlockItem {
155 pub span: Span,
156 pub kind: BlockItemKind,
157}
158
159#[derive(Debug, Clone, Serialize)]
160pub enum BlockItemKind {
161 Clause { keyword: String, value: Expr },
163 Assignment { name: Ident, value: Expr },
165 ParamAssignment {
167 name: Ident,
168 params: Vec<Ident>,
169 value: Expr,
170 },
171 Let { name: Ident, value: Expr },
173 EnumVariant { name: Ident, backtick_quoted: bool },
175 ForBlock {
177 binding: ForBinding,
178 collection: Expr,
179 filter: Option<Expr>,
180 items: Vec<BlockItem>,
181 },
182 IfBlock {
184 branches: Vec<CondBlockBranch>,
185 else_items: Option<Vec<BlockItem>>,
186 },
187 PathAssignment { path: Expr, value: Expr },
189 OpenQuestion { text: StringLiteral },
191 ContractsClause {
193 entries: Vec<ContractBinding>,
194 },
195 Annotation(Annotation),
197 InvariantBlock { name: Ident, body: Expr },
199 TransitionsBlock(TransitionGraph),
201 FieldWithWhen {
203 name: Ident,
204 value: Expr,
205 when_clause: WhenClause,
206 },
207}
208
209#[derive(Debug, Clone, Serialize)]
215pub enum ContractDirection {
216 Demands,
217 Fulfils,
218}
219
220#[derive(Debug, Clone, Serialize)]
222pub struct ContractBinding {
223 pub direction: ContractDirection,
224 pub name: Ident,
225 pub span: Span,
226}
227
228#[derive(Debug, Clone, Serialize)]
234pub enum AnnotationKind {
235 Invariant,
236 Guidance,
237 Guarantee,
238}
239
240#[derive(Debug, Clone, Serialize)]
242pub struct Annotation {
243 pub kind: AnnotationKind,
244 pub name: Option<Ident>,
245 pub body: Vec<String>,
246 pub span: Span,
247}
248
249#[derive(Debug, Clone, Serialize)]
254pub enum Expr {
255 Ident(Ident),
257
258 StringLiteral(StringLiteral),
260
261 BacktickLiteral { span: Span, value: String },
263
264 NumberLiteral { span: Span, value: String },
266
267 BoolLiteral { span: Span, value: bool },
269
270 Null { span: Span },
272
273 Now { span: Span },
275
276 This { span: Span },
278
279 Within { span: Span },
281
282 DurationLiteral { span: Span, value: String },
284
285 SetLiteral { span: Span, elements: Vec<Expr> },
287
288 ObjectLiteral { span: Span, fields: Vec<NamedArg> },
290
291 GenericType {
293 span: Span,
294 name: Box<Expr>,
295 args: Vec<Expr>,
296 },
297
298 MemberAccess {
300 span: Span,
301 object: Box<Expr>,
302 field: Ident,
303 },
304
305 OptionalAccess {
307 span: Span,
308 object: Box<Expr>,
309 field: Ident,
310 },
311
312 NullCoalesce {
314 span: Span,
315 left: Box<Expr>,
316 right: Box<Expr>,
317 },
318
319 Call {
321 span: Span,
322 function: Box<Expr>,
323 args: Vec<CallArg>,
324 },
325
326 JoinLookup {
328 span: Span,
329 entity: Box<Expr>,
330 fields: Vec<JoinField>,
331 },
332
333 BinaryOp {
335 span: Span,
336 left: Box<Expr>,
337 op: BinaryOp,
338 right: Box<Expr>,
339 },
340
341 Comparison {
343 span: Span,
344 left: Box<Expr>,
345 op: ComparisonOp,
346 right: Box<Expr>,
347 },
348
349 LogicalOp {
351 span: Span,
352 left: Box<Expr>,
353 op: LogicalOp,
354 right: Box<Expr>,
355 },
356
357 Not { span: Span, operand: Box<Expr> },
359
360 In {
362 span: Span,
363 element: Box<Expr>,
364 collection: Box<Expr>,
365 },
366
367 NotIn {
369 span: Span,
370 element: Box<Expr>,
371 collection: Box<Expr>,
372 },
373
374 Exists { span: Span, operand: Box<Expr> },
376
377 NotExists { span: Span, operand: Box<Expr> },
379
380 Where {
382 span: Span,
383 source: Box<Expr>,
384 condition: Box<Expr>,
385 },
386
387 With {
389 span: Span,
390 source: Box<Expr>,
391 predicate: Box<Expr>,
392 },
393
394 Pipe {
396 span: Span,
397 left: Box<Expr>,
398 right: Box<Expr>,
399 },
400
401 Lambda {
403 span: Span,
404 param: Box<Expr>,
405 body: Box<Expr>,
406 },
407
408 Conditional {
410 span: Span,
411 branches: Vec<CondBranch>,
412 else_body: Option<Box<Expr>>,
413 },
414
415 For {
417 span: Span,
418 binding: ForBinding,
419 collection: Box<Expr>,
420 filter: Option<Box<Expr>>,
421 body: Box<Expr>,
422 },
423
424 ProjectionMap {
426 span: Span,
427 source: Box<Expr>,
428 field: Ident,
429 },
430
431 TransitionsTo {
433 span: Span,
434 subject: Box<Expr>,
435 new_state: Box<Expr>,
436 },
437
438 Becomes {
440 span: Span,
441 subject: Box<Expr>,
442 new_state: Box<Expr>,
443 },
444
445 Binding {
447 span: Span,
448 name: Ident,
449 value: Box<Expr>,
450 },
451
452 WhenGuard {
454 span: Span,
455 action: Box<Expr>,
456 condition: Box<Expr>,
457 },
458
459 TypeOptional {
461 span: Span,
462 inner: Box<Expr>,
463 },
464
465 LetExpr {
467 span: Span,
468 name: Ident,
469 value: Box<Expr>,
470 },
471
472 QualifiedName(QualifiedName),
474
475 Block { span: Span, items: Vec<Expr> },
477
478}
479
480impl Expr {
481 pub fn span(&self) -> Span {
482 match self {
483 Expr::Ident(id) => id.span,
484 Expr::StringLiteral(s) => s.span,
485 Expr::BacktickLiteral { span, .. }
486 | Expr::NumberLiteral { span, .. }
487 | Expr::BoolLiteral { span, .. }
488 | Expr::Null { span }
489 | Expr::Now { span }
490 | Expr::This { span }
491 | Expr::Within { span }
492 | Expr::DurationLiteral { span, .. }
493 | Expr::SetLiteral { span, .. }
494 | Expr::ObjectLiteral { span, .. }
495 | Expr::GenericType { span, .. }
496 | Expr::MemberAccess { span, .. }
497 | Expr::OptionalAccess { span, .. }
498 | Expr::NullCoalesce { span, .. }
499 | Expr::Call { span, .. }
500 | Expr::JoinLookup { span, .. }
501 | Expr::BinaryOp { span, .. }
502 | Expr::Comparison { span, .. }
503 | Expr::LogicalOp { span, .. }
504 | Expr::Not { span, .. }
505 | Expr::In { span, .. }
506 | Expr::NotIn { span, .. }
507 | Expr::Exists { span, .. }
508 | Expr::NotExists { span, .. }
509 | Expr::Where { span, .. }
510 | Expr::With { span, .. }
511 | Expr::Pipe { span, .. }
512 | Expr::Lambda { span, .. }
513 | Expr::Conditional { span, .. }
514 | Expr::For { span, .. }
515 | Expr::ProjectionMap { span, .. }
516 | Expr::TransitionsTo { span, .. }
517 | Expr::Becomes { span, .. }
518 | Expr::Binding { span, .. }
519 | Expr::WhenGuard { span, .. }
520 | Expr::TypeOptional { span, .. }
521 | Expr::LetExpr { span, .. }
522 | Expr::Block { span, .. } => *span,
523 Expr::QualifiedName(q) => q.span,
524 }
525 }
526}
527
528#[derive(Debug, Clone, Serialize)]
529pub struct CondBranch {
530 pub span: Span,
531 pub condition: Expr,
532 pub body: Expr,
533}
534
535#[derive(Debug, Clone, Serialize)]
537pub struct CondBlockBranch {
538 pub span: Span,
539 pub condition: Expr,
540 pub items: Vec<BlockItem>,
541}
542
543#[derive(Debug, Clone, Serialize)]
546pub enum ForBinding {
547 Single(Ident),
548 Destructured(Vec<Ident>, Span),
549}
550
551#[derive(Debug, Clone, Serialize)]
556pub struct Ident {
557 pub span: Span,
558 pub name: String,
559}
560
561#[derive(Debug, Clone, Serialize)]
562pub struct QualifiedName {
563 pub span: Span,
564 pub qualifier: Option<String>,
565 pub name: String,
566}
567
568#[derive(Debug, Clone, Serialize)]
569pub struct StringLiteral {
570 pub span: Span,
571 pub parts: Vec<StringPart>,
572}
573
574#[derive(Debug, Clone, Serialize)]
575pub enum StringPart {
576 Text(String),
577 Interpolation(Ident),
578}
579
580#[derive(Debug, Clone, Serialize)]
581pub struct NamedArg {
582 pub span: Span,
583 pub name: Ident,
584 pub value: Expr,
585}
586
587#[derive(Debug, Clone, Serialize)]
588pub enum CallArg {
589 Positional(Expr),
590 Named(NamedArg),
591}
592
593#[derive(Debug, Clone, Serialize)]
594pub struct JoinField {
595 pub span: Span,
596 pub field: Ident,
597 pub value: Option<Expr>,
599}
600
601#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
602pub enum BinaryOp {
603 Add,
604 Sub,
605 Mul,
606 Div,
607}
608
609#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
610pub enum ComparisonOp {
611 Eq,
612 NotEq,
613 Lt,
614 LtEq,
615 Gt,
616 GtEq,
617}
618
619#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
620pub enum LogicalOp {
621 And,
622 Or,
623 Implies,
624}