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)]
121pub struct BlockItem {
122 pub span: Span,
123 pub kind: BlockItemKind,
124}
125
126#[derive(Debug, Clone, Serialize)]
127pub enum BlockItemKind {
128 Clause { keyword: String, value: Expr },
130 Assignment { name: Ident, value: Expr },
132 ParamAssignment {
134 name: Ident,
135 params: Vec<Ident>,
136 value: Expr,
137 },
138 Let { name: Ident, value: Expr },
140 EnumVariant { name: Ident },
142 ForBlock {
144 binding: ForBinding,
145 collection: Expr,
146 filter: Option<Expr>,
147 items: Vec<BlockItem>,
148 },
149 IfBlock {
151 branches: Vec<CondBlockBranch>,
152 else_items: Option<Vec<BlockItem>>,
153 },
154 PathAssignment { path: Expr, value: Expr },
156 OpenQuestion { text: StringLiteral },
158 ContractsClause {
160 entries: Vec<ContractBinding>,
161 },
162 Annotation(Annotation),
164 InvariantBlock { name: Ident, body: Expr },
166}
167
168#[derive(Debug, Clone, Serialize)]
174pub enum ContractDirection {
175 Demands,
176 Fulfils,
177}
178
179#[derive(Debug, Clone, Serialize)]
181pub struct ContractBinding {
182 pub direction: ContractDirection,
183 pub name: Ident,
184 pub span: Span,
185}
186
187#[derive(Debug, Clone, Serialize)]
193pub enum AnnotationKind {
194 Invariant,
195 Guidance,
196 Guarantee,
197}
198
199#[derive(Debug, Clone, Serialize)]
201pub struct Annotation {
202 pub kind: AnnotationKind,
203 pub name: Option<Ident>,
204 pub body: Vec<String>,
205 pub span: Span,
206}
207
208#[derive(Debug, Clone, Serialize)]
213pub enum Expr {
214 Ident(Ident),
216
217 StringLiteral(StringLiteral),
219
220 NumberLiteral { span: Span, value: String },
222
223 BoolLiteral { span: Span, value: bool },
225
226 Null { span: Span },
228
229 Now { span: Span },
231
232 This { span: Span },
234
235 Within { span: Span },
237
238 DurationLiteral { span: Span, value: String },
240
241 SetLiteral { span: Span, elements: Vec<Expr> },
243
244 ObjectLiteral { span: Span, fields: Vec<NamedArg> },
246
247 GenericType {
249 span: Span,
250 name: Box<Expr>,
251 args: Vec<Expr>,
252 },
253
254 MemberAccess {
256 span: Span,
257 object: Box<Expr>,
258 field: Ident,
259 },
260
261 OptionalAccess {
263 span: Span,
264 object: Box<Expr>,
265 field: Ident,
266 },
267
268 NullCoalesce {
270 span: Span,
271 left: Box<Expr>,
272 right: Box<Expr>,
273 },
274
275 Call {
277 span: Span,
278 function: Box<Expr>,
279 args: Vec<CallArg>,
280 },
281
282 JoinLookup {
284 span: Span,
285 entity: Box<Expr>,
286 fields: Vec<JoinField>,
287 },
288
289 BinaryOp {
291 span: Span,
292 left: Box<Expr>,
293 op: BinaryOp,
294 right: Box<Expr>,
295 },
296
297 Comparison {
299 span: Span,
300 left: Box<Expr>,
301 op: ComparisonOp,
302 right: Box<Expr>,
303 },
304
305 LogicalOp {
307 span: Span,
308 left: Box<Expr>,
309 op: LogicalOp,
310 right: Box<Expr>,
311 },
312
313 Not { span: Span, operand: Box<Expr> },
315
316 In {
318 span: Span,
319 element: Box<Expr>,
320 collection: Box<Expr>,
321 },
322
323 NotIn {
325 span: Span,
326 element: Box<Expr>,
327 collection: Box<Expr>,
328 },
329
330 Exists { span: Span, operand: Box<Expr> },
332
333 NotExists { span: Span, operand: Box<Expr> },
335
336 Where {
338 span: Span,
339 source: Box<Expr>,
340 condition: Box<Expr>,
341 },
342
343 With {
345 span: Span,
346 source: Box<Expr>,
347 predicate: Box<Expr>,
348 },
349
350 Pipe {
352 span: Span,
353 left: Box<Expr>,
354 right: Box<Expr>,
355 },
356
357 Lambda {
359 span: Span,
360 param: Box<Expr>,
361 body: Box<Expr>,
362 },
363
364 Conditional {
366 span: Span,
367 branches: Vec<CondBranch>,
368 else_body: Option<Box<Expr>>,
369 },
370
371 For {
373 span: Span,
374 binding: ForBinding,
375 collection: Box<Expr>,
376 filter: Option<Box<Expr>>,
377 body: Box<Expr>,
378 },
379
380 ProjectionMap {
382 span: Span,
383 source: Box<Expr>,
384 field: Ident,
385 },
386
387 TransitionsTo {
389 span: Span,
390 subject: Box<Expr>,
391 new_state: Box<Expr>,
392 },
393
394 Becomes {
396 span: Span,
397 subject: Box<Expr>,
398 new_state: Box<Expr>,
399 },
400
401 Binding {
403 span: Span,
404 name: Ident,
405 value: Box<Expr>,
406 },
407
408 WhenGuard {
410 span: Span,
411 action: Box<Expr>,
412 condition: Box<Expr>,
413 },
414
415 TypeOptional {
417 span: Span,
418 inner: Box<Expr>,
419 },
420
421 LetExpr {
423 span: Span,
424 name: Ident,
425 value: Box<Expr>,
426 },
427
428 QualifiedName(QualifiedName),
430
431 Block { span: Span, items: Vec<Expr> },
433
434}
435
436impl Expr {
437 pub fn span(&self) -> Span {
438 match self {
439 Expr::Ident(id) => id.span,
440 Expr::StringLiteral(s) => s.span,
441 Expr::NumberLiteral { span, .. }
442 | Expr::BoolLiteral { span, .. }
443 | Expr::Null { span }
444 | Expr::Now { span }
445 | Expr::This { span }
446 | Expr::Within { span }
447 | Expr::DurationLiteral { span, .. }
448 | Expr::SetLiteral { span, .. }
449 | Expr::ObjectLiteral { span, .. }
450 | Expr::GenericType { span, .. }
451 | Expr::MemberAccess { span, .. }
452 | Expr::OptionalAccess { span, .. }
453 | Expr::NullCoalesce { span, .. }
454 | Expr::Call { span, .. }
455 | Expr::JoinLookup { span, .. }
456 | Expr::BinaryOp { span, .. }
457 | Expr::Comparison { span, .. }
458 | Expr::LogicalOp { span, .. }
459 | Expr::Not { span, .. }
460 | Expr::In { span, .. }
461 | Expr::NotIn { span, .. }
462 | Expr::Exists { span, .. }
463 | Expr::NotExists { span, .. }
464 | Expr::Where { span, .. }
465 | Expr::With { span, .. }
466 | Expr::Pipe { span, .. }
467 | Expr::Lambda { span, .. }
468 | Expr::Conditional { span, .. }
469 | Expr::For { span, .. }
470 | Expr::ProjectionMap { span, .. }
471 | Expr::TransitionsTo { span, .. }
472 | Expr::Becomes { span, .. }
473 | Expr::Binding { span, .. }
474 | Expr::WhenGuard { span, .. }
475 | Expr::TypeOptional { span, .. }
476 | Expr::LetExpr { span, .. }
477 | Expr::Block { span, .. } => *span,
478 Expr::QualifiedName(q) => q.span,
479 }
480 }
481}
482
483#[derive(Debug, Clone, Serialize)]
484pub struct CondBranch {
485 pub span: Span,
486 pub condition: Expr,
487 pub body: Expr,
488}
489
490#[derive(Debug, Clone, Serialize)]
492pub struct CondBlockBranch {
493 pub span: Span,
494 pub condition: Expr,
495 pub items: Vec<BlockItem>,
496}
497
498#[derive(Debug, Clone, Serialize)]
501pub enum ForBinding {
502 Single(Ident),
503 Destructured(Vec<Ident>, Span),
504}
505
506#[derive(Debug, Clone, Serialize)]
511pub struct Ident {
512 pub span: Span,
513 pub name: String,
514}
515
516#[derive(Debug, Clone, Serialize)]
517pub struct QualifiedName {
518 pub span: Span,
519 pub qualifier: Option<String>,
520 pub name: String,
521}
522
523#[derive(Debug, Clone, Serialize)]
524pub struct StringLiteral {
525 pub span: Span,
526 pub parts: Vec<StringPart>,
527}
528
529#[derive(Debug, Clone, Serialize)]
530pub enum StringPart {
531 Text(String),
532 Interpolation(Ident),
533}
534
535#[derive(Debug, Clone, Serialize)]
536pub struct NamedArg {
537 pub span: Span,
538 pub name: Ident,
539 pub value: Expr,
540}
541
542#[derive(Debug, Clone, Serialize)]
543pub enum CallArg {
544 Positional(Expr),
545 Named(NamedArg),
546}
547
548#[derive(Debug, Clone, Serialize)]
549pub struct JoinField {
550 pub span: Span,
551 pub field: Ident,
552 pub value: Option<Expr>,
554}
555
556#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
557pub enum BinaryOp {
558 Add,
559 Sub,
560 Mul,
561 Div,
562}
563
564#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
565pub enum ComparisonOp {
566 Eq,
567 NotEq,
568 Lt,
569 LtEq,
570 Gt,
571 GtEq,
572}
573
574#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
575pub enum LogicalOp {
576 And,
577 Or,
578 Implies,
579}