1use crate::Span;
12
13#[derive(Debug, Clone)]
19pub struct Module {
20 pub span: Span,
21 pub version: Option<u32>,
23 pub declarations: Vec<Decl>,
24}
25
26#[derive(Debug, Clone)]
31pub enum Decl {
32 Use(UseDecl),
33 Block(BlockDecl),
34 Default(DefaultDecl),
35 Variant(VariantDecl),
36 Deferred(DeferredDecl),
37 OpenQuestion(OpenQuestionDecl),
38}
39
40#[derive(Debug, Clone)]
42pub struct UseDecl {
43 pub span: Span,
44 pub path: StringLiteral,
45 pub alias: Option<Ident>,
46}
47
48#[derive(Debug, Clone)]
50pub struct BlockDecl {
51 pub span: Span,
52 pub kind: BlockKind,
53 pub name: Option<Ident>,
55 pub items: Vec<BlockItem>,
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum BlockKind {
60 Entity,
61 ExternalEntity,
62 Value,
63 Enum,
64 Given,
65 Config,
66 Rule,
67 Surface,
68 Actor,
69}
70
71#[derive(Debug, Clone)]
73pub struct DefaultDecl {
74 pub span: Span,
75 pub type_name: Option<Ident>,
76 pub name: Ident,
77 pub value: Expr,
78}
79
80#[derive(Debug, Clone)]
82pub struct VariantDecl {
83 pub span: Span,
84 pub name: Ident,
85 pub base: Expr,
86 pub items: Vec<BlockItem>,
87}
88
89#[derive(Debug, Clone)]
91pub struct DeferredDecl {
92 pub span: Span,
93 pub path: Expr,
94}
95
96#[derive(Debug, Clone)]
98pub struct OpenQuestionDecl {
99 pub span: Span,
100 pub text: StringLiteral,
101}
102
103#[derive(Debug, Clone)]
108pub struct BlockItem {
109 pub span: Span,
110 pub kind: BlockItemKind,
111}
112
113#[derive(Debug, Clone)]
114pub enum BlockItemKind {
115 Clause { keyword: String, value: Expr },
117 Assignment { name: Ident, value: Expr },
119 ParamAssignment {
121 name: Ident,
122 params: Vec<Ident>,
123 value: Expr,
124 },
125 Let { name: Ident, value: Expr },
127 EnumVariant { name: Ident },
129 ForBlock {
131 binding: ForBinding,
132 collection: Expr,
133 filter: Option<Expr>,
134 items: Vec<BlockItem>,
135 },
136 IfBlock {
138 branches: Vec<CondBlockBranch>,
139 else_items: Option<Vec<BlockItem>>,
140 },
141 PathAssignment { path: Expr, value: Expr },
143 OpenQuestion { text: StringLiteral },
145}
146
147#[derive(Debug, Clone)]
152pub enum Expr {
153 Ident(Ident),
155
156 StringLiteral(StringLiteral),
158
159 NumberLiteral { span: Span, value: String },
161
162 BoolLiteral { span: Span, value: bool },
164
165 Null { span: Span },
167
168 Now { span: Span },
170
171 This { span: Span },
173
174 Within { span: Span },
176
177 DurationLiteral { span: Span, value: String },
179
180 SetLiteral { span: Span, elements: Vec<Expr> },
182
183 ListLiteral { span: Span, elements: Vec<Expr> },
185
186 ObjectLiteral { span: Span, fields: Vec<NamedArg> },
188
189 GenericType {
191 span: Span,
192 name: Box<Expr>,
193 args: Vec<Expr>,
194 },
195
196 MemberAccess {
198 span: Span,
199 object: Box<Expr>,
200 field: Ident,
201 },
202
203 OptionalAccess {
205 span: Span,
206 object: Box<Expr>,
207 field: Ident,
208 },
209
210 NullCoalesce {
212 span: Span,
213 left: Box<Expr>,
214 right: Box<Expr>,
215 },
216
217 Call {
219 span: Span,
220 function: Box<Expr>,
221 args: Vec<CallArg>,
222 },
223
224 JoinLookup {
226 span: Span,
227 entity: Box<Expr>,
228 fields: Vec<JoinField>,
229 },
230
231 BinaryOp {
233 span: Span,
234 left: Box<Expr>,
235 op: BinaryOp,
236 right: Box<Expr>,
237 },
238
239 Comparison {
241 span: Span,
242 left: Box<Expr>,
243 op: ComparisonOp,
244 right: Box<Expr>,
245 },
246
247 LogicalOp {
249 span: Span,
250 left: Box<Expr>,
251 op: LogicalOp,
252 right: Box<Expr>,
253 },
254
255 Not { span: Span, operand: Box<Expr> },
257
258 In {
260 span: Span,
261 element: Box<Expr>,
262 collection: Box<Expr>,
263 },
264
265 NotIn {
267 span: Span,
268 element: Box<Expr>,
269 collection: Box<Expr>,
270 },
271
272 Exists { span: Span, operand: Box<Expr> },
274
275 NotExists { span: Span, operand: Box<Expr> },
277
278 Where {
280 span: Span,
281 source: Box<Expr>,
282 condition: Box<Expr>,
283 },
284
285 With {
287 span: Span,
288 source: Box<Expr>,
289 predicate: Box<Expr>,
290 },
291
292 Pipe {
294 span: Span,
295 left: Box<Expr>,
296 right: Box<Expr>,
297 },
298
299 Lambda {
301 span: Span,
302 param: Box<Expr>,
303 body: Box<Expr>,
304 },
305
306 Conditional {
308 span: Span,
309 branches: Vec<CondBranch>,
310 else_body: Option<Box<Expr>>,
311 },
312
313 For {
315 span: Span,
316 binding: ForBinding,
317 collection: Box<Expr>,
318 filter: Option<Box<Expr>>,
319 body: Box<Expr>,
320 },
321
322 ProjectionMap {
324 span: Span,
325 source: Box<Expr>,
326 field: Ident,
327 },
328
329 TransitionsTo {
331 span: Span,
332 subject: Box<Expr>,
333 new_state: Box<Expr>,
334 },
335
336 Becomes {
338 span: Span,
339 subject: Box<Expr>,
340 new_state: Box<Expr>,
341 },
342
343 Binding {
345 span: Span,
346 name: Ident,
347 value: Box<Expr>,
348 },
349
350 WhenGuard {
352 span: Span,
353 action: Box<Expr>,
354 condition: Box<Expr>,
355 },
356
357 TypeOptional {
359 span: Span,
360 inner: Box<Expr>,
361 },
362
363 LetExpr {
365 span: Span,
366 name: Ident,
367 value: Box<Expr>,
368 },
369
370 QualifiedName(QualifiedName),
372
373 Block { span: Span, items: Vec<Expr> },
375
376}
377
378impl Expr {
379 pub fn span(&self) -> Span {
380 match self {
381 Expr::Ident(id) => id.span,
382 Expr::StringLiteral(s) => s.span,
383 Expr::NumberLiteral { span, .. }
384 | Expr::BoolLiteral { span, .. }
385 | Expr::Null { span }
386 | Expr::Now { span }
387 | Expr::This { span }
388 | Expr::Within { span }
389 | Expr::DurationLiteral { span, .. }
390 | Expr::SetLiteral { span, .. }
391 | Expr::ListLiteral { span, .. }
392 | Expr::ObjectLiteral { span, .. }
393 | Expr::GenericType { span, .. }
394 | Expr::MemberAccess { span, .. }
395 | Expr::OptionalAccess { span, .. }
396 | Expr::NullCoalesce { span, .. }
397 | Expr::Call { span, .. }
398 | Expr::JoinLookup { span, .. }
399 | Expr::BinaryOp { span, .. }
400 | Expr::Comparison { span, .. }
401 | Expr::LogicalOp { span, .. }
402 | Expr::Not { span, .. }
403 | Expr::In { span, .. }
404 | Expr::NotIn { span, .. }
405 | Expr::Exists { span, .. }
406 | Expr::NotExists { span, .. }
407 | Expr::Where { span, .. }
408 | Expr::With { span, .. }
409 | Expr::Pipe { span, .. }
410 | Expr::Lambda { span, .. }
411 | Expr::Conditional { span, .. }
412 | Expr::For { span, .. }
413 | Expr::ProjectionMap { span, .. }
414 | Expr::TransitionsTo { span, .. }
415 | Expr::Becomes { span, .. }
416 | Expr::Binding { span, .. }
417 | Expr::WhenGuard { span, .. }
418 | Expr::TypeOptional { span, .. }
419 | Expr::LetExpr { span, .. }
420 | Expr::Block { span, .. } => *span,
421 Expr::QualifiedName(q) => q.span,
422 }
423 }
424}
425
426#[derive(Debug, Clone)]
427pub struct CondBranch {
428 pub span: Span,
429 pub condition: Expr,
430 pub body: Expr,
431}
432
433#[derive(Debug, Clone)]
435pub struct CondBlockBranch {
436 pub span: Span,
437 pub condition: Expr,
438 pub items: Vec<BlockItem>,
439}
440
441#[derive(Debug, Clone)]
444pub enum ForBinding {
445 Single(Ident),
446 Destructured(Vec<Ident>, Span),
447}
448
449#[derive(Debug, Clone)]
454pub struct Ident {
455 pub span: Span,
456 pub name: String,
457}
458
459#[derive(Debug, Clone)]
460pub struct QualifiedName {
461 pub span: Span,
462 pub qualifier: Option<String>,
463 pub name: String,
464}
465
466#[derive(Debug, Clone)]
467pub struct StringLiteral {
468 pub span: Span,
469 pub parts: Vec<StringPart>,
470}
471
472#[derive(Debug, Clone)]
473pub enum StringPart {
474 Text(String),
475 Interpolation(Ident),
476}
477
478#[derive(Debug, Clone)]
479pub struct NamedArg {
480 pub span: Span,
481 pub name: Ident,
482 pub value: Expr,
483}
484
485#[derive(Debug, Clone)]
486pub enum CallArg {
487 Positional(Expr),
488 Named(NamedArg),
489}
490
491#[derive(Debug, Clone)]
492pub struct JoinField {
493 pub span: Span,
494 pub field: Ident,
495 pub value: Option<Expr>,
497}
498
499#[derive(Debug, Clone, Copy, PartialEq, Eq)]
500pub enum BinaryOp {
501 Add,
502 Sub,
503 Mul,
504 Div,
505}
506
507#[derive(Debug, Clone, Copy, PartialEq, Eq)]
508pub enum ComparisonOp {
509 Eq,
510 NotEq,
511 Lt,
512 LtEq,
513 Gt,
514 GtEq,
515}
516
517#[derive(Debug, Clone, Copy, PartialEq, Eq)]
518pub enum LogicalOp {
519 And,
520 Or,
521}