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_alias: Option<Ident>,
82 pub type_name: Option<Ident>,
83 pub name: Ident,
84 pub value: Expr,
85}
86
87#[derive(Debug, Clone, Serialize)]
89pub struct VariantDecl {
90 pub span: Span,
91 pub name: Ident,
92 pub base: Expr,
93 pub items: Vec<BlockItem>,
94}
95
96#[derive(Debug, Clone, Serialize)]
104pub struct DeferredDecl {
105 pub span: Span,
106 pub path: Expr,
107 pub location_hint: Option<StringLiteral>,
108}
109
110#[derive(Debug, Clone, Serialize)]
112pub struct OpenQuestionDecl {
113 pub span: Span,
114 pub text: StringLiteral,
115}
116
117#[derive(Debug, Clone, Serialize)]
119pub struct InvariantDecl {
120 pub span: Span,
121 pub name: Ident,
122 pub body: Expr,
123}
124
125#[derive(Debug, Clone, Serialize)]
131pub struct TransitionEdge {
132 pub span: Span,
133 pub from: Ident,
134 pub to: Ident,
135}
136
137#[derive(Debug, Clone, Serialize)]
139pub struct TransitionGraph {
140 pub span: Span,
141 pub field: Ident,
142 pub edges: Vec<TransitionEdge>,
143 pub terminal: Vec<Ident>,
144}
145
146#[derive(Debug, Clone, Serialize)]
152pub struct WhenClause {
153 pub span: Span,
154 pub status_field: Ident,
155 pub qualifying_states: Vec<Ident>,
156}
157
158#[derive(Debug, Clone, Serialize)]
163pub struct BlockItem {
164 pub span: Span,
165 pub kind: BlockItemKind,
166}
167
168#[derive(Debug, Clone, Serialize)]
169pub enum BlockItemKind {
170 Clause { keyword: String, value: Expr },
172 Assignment { name: Ident, value: Expr },
174 ParamAssignment {
176 name: Ident,
177 params: Vec<Ident>,
178 value: Expr,
179 },
180 Let { name: Ident, value: Expr },
182 EnumVariant { name: Ident, backtick_quoted: bool },
184 ForBlock {
186 binding: ForBinding,
187 collection: Expr,
188 filter: Option<Expr>,
189 items: Vec<BlockItem>,
190 },
191 IfBlock {
193 branches: Vec<CondBlockBranch>,
194 else_items: Option<Vec<BlockItem>>,
195 },
196 PathAssignment { path: Expr, value: Expr },
198 OpenQuestion { text: StringLiteral },
200 ContractsClause {
202 entries: Vec<ContractBinding>,
203 },
204 Annotation(Annotation),
206 InvariantBlock { name: Ident, body: Expr },
208 TransitionsBlock(TransitionGraph),
210 FieldWithWhen {
212 name: Ident,
213 value: Expr,
214 when_clause: WhenClause,
215 },
216}
217
218#[derive(Debug, Clone, Serialize)]
224pub enum ContractDirection {
225 Demands,
226 Fulfils,
227}
228
229#[derive(Debug, Clone, Serialize)]
231pub struct ContractBinding {
232 pub direction: ContractDirection,
233 pub qualifier: Option<String>,
236 pub name: Ident,
237 pub span: Span,
238}
239
240#[derive(Debug, Clone, Serialize)]
246pub enum AnnotationKind {
247 Invariant,
248 Guidance,
249 Guarantee,
250}
251
252#[derive(Debug, Clone, Serialize)]
254pub struct Annotation {
255 pub kind: AnnotationKind,
256 pub name: Option<Ident>,
257 pub body: Vec<String>,
258 pub span: Span,
259}
260
261#[derive(Debug, Clone, Serialize)]
266pub enum Expr {
267 Ident(Ident),
269
270 StringLiteral(StringLiteral),
272
273 BacktickLiteral { span: Span, value: String },
275
276 NumberLiteral { span: Span, value: String },
278
279 BoolLiteral { span: Span, value: bool },
281
282 Null { span: Span },
284
285 Now { span: Span },
287
288 This { span: Span },
290
291 Within { span: Span },
293
294 DurationLiteral { span: Span, value: String },
296
297 SetLiteral { span: Span, elements: Vec<Expr> },
299
300 ListLiteral { span: Span, elements: Vec<Expr> },
302
303 ObjectLiteral { span: Span, fields: Vec<NamedArg> },
305
306 GenericType {
308 span: Span,
309 name: Box<Expr>,
310 args: Vec<Expr>,
311 },
312
313 MemberAccess {
315 span: Span,
316 object: Box<Expr>,
317 field: Ident,
318 },
319
320 OptionalAccess {
322 span: Span,
323 object: Box<Expr>,
324 field: Ident,
325 },
326
327 NullCoalesce {
329 span: Span,
330 left: Box<Expr>,
331 right: Box<Expr>,
332 },
333
334 Call {
336 span: Span,
337 function: Box<Expr>,
338 args: Vec<CallArg>,
339 },
340
341 JoinLookup {
343 span: Span,
344 entity: Box<Expr>,
345 fields: Vec<JoinField>,
346 },
347
348 BinaryOp {
350 span: Span,
351 left: Box<Expr>,
352 op: BinaryOp,
353 right: Box<Expr>,
354 },
355
356 Comparison {
358 span: Span,
359 left: Box<Expr>,
360 op: ComparisonOp,
361 right: Box<Expr>,
362 },
363
364 LogicalOp {
366 span: Span,
367 left: Box<Expr>,
368 op: LogicalOp,
369 right: Box<Expr>,
370 },
371
372 Not { span: Span, operand: Box<Expr> },
374
375 In {
377 span: Span,
378 element: Box<Expr>,
379 collection: Box<Expr>,
380 },
381
382 NotIn {
384 span: Span,
385 element: Box<Expr>,
386 collection: Box<Expr>,
387 },
388
389 Exists { span: Span, operand: Box<Expr> },
391
392 NotExists { span: Span, operand: Box<Expr> },
394
395 Where {
397 span: Span,
398 source: Box<Expr>,
399 condition: Box<Expr>,
400 },
401
402 With {
404 span: Span,
405 source: Box<Expr>,
406 predicate: Box<Expr>,
407 },
408
409 Pipe {
411 span: Span,
412 left: Box<Expr>,
413 right: Box<Expr>,
414 },
415
416 Lambda {
418 span: Span,
419 param: Box<Expr>,
420 body: Box<Expr>,
421 },
422
423 Conditional {
425 span: Span,
426 branches: Vec<CondBranch>,
427 else_body: Option<Box<Expr>>,
428 },
429
430 For {
432 span: Span,
433 binding: ForBinding,
434 collection: Box<Expr>,
435 filter: Option<Box<Expr>>,
436 body: Box<Expr>,
437 },
438
439 ProjectionMap {
441 span: Span,
442 source: Box<Expr>,
443 field: Ident,
444 },
445
446 TransitionsTo {
448 span: Span,
449 subject: Box<Expr>,
450 new_state: Box<Expr>,
451 },
452
453 Becomes {
455 span: Span,
456 subject: Box<Expr>,
457 new_state: Box<Expr>,
458 },
459
460 Binding {
462 span: Span,
463 name: Ident,
464 value: Box<Expr>,
465 },
466
467 WhenGuard {
469 span: Span,
470 action: Box<Expr>,
471 condition: Box<Expr>,
472 },
473
474 TypeOptional {
476 span: Span,
477 inner: Box<Expr>,
478 },
479
480 LetExpr {
482 span: Span,
483 name: Ident,
484 value: Box<Expr>,
485 },
486
487 QualifiedName(QualifiedName),
489
490 Block { span: Span, items: Vec<Expr> },
492
493}
494
495impl Expr {
496 pub fn span(&self) -> Span {
497 match self {
498 Expr::Ident(id) => id.span,
499 Expr::StringLiteral(s) => s.span,
500 Expr::BacktickLiteral { span, .. }
501 | Expr::NumberLiteral { span, .. }
502 | Expr::BoolLiteral { span, .. }
503 | Expr::Null { span }
504 | Expr::Now { span }
505 | Expr::This { span }
506 | Expr::Within { span }
507 | Expr::DurationLiteral { span, .. }
508 | Expr::SetLiteral { span, .. }
509 | Expr::ListLiteral { span, .. }
510 | Expr::ObjectLiteral { span, .. }
511 | Expr::GenericType { span, .. }
512 | Expr::MemberAccess { span, .. }
513 | Expr::OptionalAccess { span, .. }
514 | Expr::NullCoalesce { span, .. }
515 | Expr::Call { span, .. }
516 | Expr::JoinLookup { span, .. }
517 | Expr::BinaryOp { span, .. }
518 | Expr::Comparison { span, .. }
519 | Expr::LogicalOp { span, .. }
520 | Expr::Not { span, .. }
521 | Expr::In { span, .. }
522 | Expr::NotIn { span, .. }
523 | Expr::Exists { span, .. }
524 | Expr::NotExists { span, .. }
525 | Expr::Where { span, .. }
526 | Expr::With { span, .. }
527 | Expr::Pipe { span, .. }
528 | Expr::Lambda { span, .. }
529 | Expr::Conditional { span, .. }
530 | Expr::For { span, .. }
531 | Expr::ProjectionMap { span, .. }
532 | Expr::TransitionsTo { span, .. }
533 | Expr::Becomes { span, .. }
534 | Expr::Binding { span, .. }
535 | Expr::WhenGuard { span, .. }
536 | Expr::TypeOptional { span, .. }
537 | Expr::LetExpr { span, .. }
538 | Expr::Block { span, .. } => *span,
539 Expr::QualifiedName(q) => q.span,
540 }
541 }
542}
543
544#[derive(Debug, Clone, Serialize)]
545pub struct CondBranch {
546 pub span: Span,
547 pub condition: Expr,
548 pub body: Expr,
549}
550
551#[derive(Debug, Clone, Serialize)]
553pub struct CondBlockBranch {
554 pub span: Span,
555 pub condition: Expr,
556 pub items: Vec<BlockItem>,
557}
558
559#[derive(Debug, Clone, Serialize)]
562pub enum ForBinding {
563 Single(Ident),
564 Destructured(Vec<Ident>, Span),
565}
566
567#[derive(Debug, Clone, Serialize)]
572pub struct Ident {
573 pub span: Span,
574 pub name: String,
575}
576
577#[derive(Debug, Clone, Serialize)]
578pub struct QualifiedName {
579 pub span: Span,
580 pub qualifier: Option<String>,
581 pub name: String,
582}
583
584#[derive(Debug, Clone, Serialize)]
585pub struct StringLiteral {
586 pub span: Span,
587 pub parts: Vec<StringPart>,
588}
589
590impl StringLiteral {
591 pub fn text(&self) -> String {
595 let mut s = String::new();
596 for part in &self.parts {
597 if let StringPart::Text(t) = part {
598 s.push_str(t);
599 }
600 }
601 s
602 }
603}
604
605#[derive(Debug, Clone, Serialize)]
606pub enum StringPart {
607 Text(String),
608 Interpolation(Ident),
609}
610
611#[derive(Debug, Clone, Serialize)]
612pub struct NamedArg {
613 pub span: Span,
614 pub name: Ident,
615 pub value: Expr,
616}
617
618#[derive(Debug, Clone, Serialize)]
619pub enum CallArg {
620 Positional(Expr),
621 Named(NamedArg),
622}
623
624#[derive(Debug, Clone, Serialize)]
625pub struct JoinField {
626 pub span: Span,
627 pub field: Ident,
628 pub value: Option<Expr>,
630}
631
632#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
633pub enum BinaryOp {
634 Add,
635 Sub,
636 Mul,
637 Div,
638}
639
640#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
641pub enum ComparisonOp {
642 Eq,
643 NotEq,
644 Lt,
645 LtEq,
646 Gt,
647 GtEq,
648}
649
650#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
651pub enum LogicalOp {
652 And,
653 Or,
654 Implies,
655}