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 ObjectLiteral { span: Span, fields: Vec<NamedArg> },
185
186 GenericType {
188 span: Span,
189 name: Box<Expr>,
190 args: Vec<Expr>,
191 },
192
193 MemberAccess {
195 span: Span,
196 object: Box<Expr>,
197 field: Ident,
198 },
199
200 OptionalAccess {
202 span: Span,
203 object: Box<Expr>,
204 field: Ident,
205 },
206
207 NullCoalesce {
209 span: Span,
210 left: Box<Expr>,
211 right: Box<Expr>,
212 },
213
214 Call {
216 span: Span,
217 function: Box<Expr>,
218 args: Vec<CallArg>,
219 },
220
221 JoinLookup {
223 span: Span,
224 entity: Box<Expr>,
225 fields: Vec<JoinField>,
226 },
227
228 BinaryOp {
230 span: Span,
231 left: Box<Expr>,
232 op: BinaryOp,
233 right: Box<Expr>,
234 },
235
236 Comparison {
238 span: Span,
239 left: Box<Expr>,
240 op: ComparisonOp,
241 right: Box<Expr>,
242 },
243
244 LogicalOp {
246 span: Span,
247 left: Box<Expr>,
248 op: LogicalOp,
249 right: Box<Expr>,
250 },
251
252 Not { span: Span, operand: Box<Expr> },
254
255 In {
257 span: Span,
258 element: Box<Expr>,
259 collection: Box<Expr>,
260 },
261
262 NotIn {
264 span: Span,
265 element: Box<Expr>,
266 collection: Box<Expr>,
267 },
268
269 Exists { span: Span, operand: Box<Expr> },
271
272 NotExists { span: Span, operand: Box<Expr> },
274
275 Where {
277 span: Span,
278 source: Box<Expr>,
279 condition: Box<Expr>,
280 },
281
282 With {
284 span: Span,
285 source: Box<Expr>,
286 predicate: Box<Expr>,
287 },
288
289 Pipe {
291 span: Span,
292 left: Box<Expr>,
293 right: Box<Expr>,
294 },
295
296 Lambda {
298 span: Span,
299 param: Box<Expr>,
300 body: Box<Expr>,
301 },
302
303 Conditional {
305 span: Span,
306 branches: Vec<CondBranch>,
307 else_body: Option<Box<Expr>>,
308 },
309
310 For {
312 span: Span,
313 binding: ForBinding,
314 collection: Box<Expr>,
315 filter: Option<Box<Expr>>,
316 body: Box<Expr>,
317 },
318
319 ProjectionMap {
321 span: Span,
322 source: Box<Expr>,
323 field: Ident,
324 },
325
326 TransitionsTo {
328 span: Span,
329 subject: Box<Expr>,
330 new_state: Box<Expr>,
331 },
332
333 Becomes {
335 span: Span,
336 subject: Box<Expr>,
337 new_state: Box<Expr>,
338 },
339
340 Binding {
342 span: Span,
343 name: Ident,
344 value: Box<Expr>,
345 },
346
347 WhenGuard {
349 span: Span,
350 action: Box<Expr>,
351 condition: Box<Expr>,
352 },
353
354 TypeOptional {
356 span: Span,
357 inner: Box<Expr>,
358 },
359
360 LetExpr {
362 span: Span,
363 name: Ident,
364 value: Box<Expr>,
365 },
366
367 QualifiedName(QualifiedName),
369
370 Block { span: Span, items: Vec<Expr> },
372
373}
374
375impl Expr {
376 pub fn span(&self) -> Span {
377 match self {
378 Expr::Ident(id) => id.span,
379 Expr::StringLiteral(s) => s.span,
380 Expr::NumberLiteral { span, .. }
381 | Expr::BoolLiteral { span, .. }
382 | Expr::Null { span }
383 | Expr::Now { span }
384 | Expr::This { span }
385 | Expr::Within { span }
386 | Expr::DurationLiteral { span, .. }
387 | Expr::SetLiteral { span, .. }
388 | Expr::ObjectLiteral { span, .. }
389 | Expr::GenericType { span, .. }
390 | Expr::MemberAccess { span, .. }
391 | Expr::OptionalAccess { span, .. }
392 | Expr::NullCoalesce { span, .. }
393 | Expr::Call { span, .. }
394 | Expr::JoinLookup { span, .. }
395 | Expr::BinaryOp { span, .. }
396 | Expr::Comparison { span, .. }
397 | Expr::LogicalOp { span, .. }
398 | Expr::Not { span, .. }
399 | Expr::In { span, .. }
400 | Expr::NotIn { span, .. }
401 | Expr::Exists { span, .. }
402 | Expr::NotExists { span, .. }
403 | Expr::Where { span, .. }
404 | Expr::With { span, .. }
405 | Expr::Pipe { span, .. }
406 | Expr::Lambda { span, .. }
407 | Expr::Conditional { span, .. }
408 | Expr::For { span, .. }
409 | Expr::ProjectionMap { span, .. }
410 | Expr::TransitionsTo { span, .. }
411 | Expr::Becomes { span, .. }
412 | Expr::Binding { span, .. }
413 | Expr::WhenGuard { span, .. }
414 | Expr::TypeOptional { span, .. }
415 | Expr::LetExpr { span, .. }
416 | Expr::Block { span, .. } => *span,
417 Expr::QualifiedName(q) => q.span,
418 }
419 }
420}
421
422#[derive(Debug, Clone)]
423pub struct CondBranch {
424 pub span: Span,
425 pub condition: Expr,
426 pub body: Expr,
427}
428
429#[derive(Debug, Clone)]
431pub struct CondBlockBranch {
432 pub span: Span,
433 pub condition: Expr,
434 pub items: Vec<BlockItem>,
435}
436
437#[derive(Debug, Clone)]
440pub enum ForBinding {
441 Single(Ident),
442 Destructured(Vec<Ident>, Span),
443}
444
445#[derive(Debug, Clone)]
450pub struct Ident {
451 pub span: Span,
452 pub name: String,
453}
454
455#[derive(Debug, Clone)]
456pub struct QualifiedName {
457 pub span: Span,
458 pub qualifier: Option<String>,
459 pub name: String,
460}
461
462#[derive(Debug, Clone)]
463pub struct StringLiteral {
464 pub span: Span,
465 pub parts: Vec<StringPart>,
466}
467
468#[derive(Debug, Clone)]
469pub enum StringPart {
470 Text(String),
471 Interpolation(Ident),
472}
473
474#[derive(Debug, Clone)]
475pub struct NamedArg {
476 pub span: Span,
477 pub name: Ident,
478 pub value: Expr,
479}
480
481#[derive(Debug, Clone)]
482pub enum CallArg {
483 Positional(Expr),
484 Named(NamedArg),
485}
486
487#[derive(Debug, Clone)]
488pub struct JoinField {
489 pub span: Span,
490 pub field: Ident,
491 pub value: Option<Expr>,
493}
494
495#[derive(Debug, Clone, Copy, PartialEq, Eq)]
496pub enum BinaryOp {
497 Add,
498 Sub,
499 Mul,
500 Div,
501}
502
503#[derive(Debug, Clone, Copy, PartialEq, Eq)]
504pub enum ComparisonOp {
505 Eq,
506 NotEq,
507 Lt,
508 LtEq,
509 Gt,
510 GtEq,
511}
512
513#[derive(Debug, Clone, Copy, PartialEq, Eq)]
514pub enum LogicalOp {
515 And,
516 Or,
517}