1use paste::paste;
2use rue_parser::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T};
3
4pub trait AstNode {
5 fn cast(node: SyntaxNode) -> Option<Self>
6 where
7 Self: Sized;
8
9 fn syntax(&self) -> &SyntaxNode;
10}
11
12macro_rules! ast_nodes {
13 ($( $kind:ident),+ $(,)?) => { paste! { $(
14 #[derive(Debug, Clone)]
15 pub struct [< Ast $kind >](SyntaxNode);
16
17 impl AstNode for [< Ast $kind >] {
18 fn cast(node: SyntaxNode) -> Option<Self> {
19 match node.kind() {
20 SyntaxKind::$kind => Some(Self(node)),
21 _ => None,
22 }
23 }
24
25 fn syntax(&self) -> &SyntaxNode {
26 &self.0
27 }
28 }
29 )+ } };
30}
31
32macro_rules! ast_enum {
33 ($name:ident, $( $kind:ident ),+ $(,)? ) => { paste! {
34 #[derive(Debug, Clone)]
35 pub enum [< Ast $name >] {
36 $( $kind([< Ast $kind >]), )+
37 }
38
39 impl AstNode for [< Ast $name >] {
40 fn cast(node: SyntaxNode) -> Option<Self> {
41 $( if let Some(node) = [< Ast $kind >]::cast(node.clone()) {
42 return Some(Self::$kind(node));
43 } )+
44 None
45 }
46
47 fn syntax(&self) -> &SyntaxNode {
48 match self {
49 $( Self::$kind(node) => node.syntax(), )+
50 }
51 }
52 }
53 } };
54}
55
56ast_nodes!(
57 Document,
58 ModuleItem,
59 FunctionItem,
60 FunctionParameter,
61 ConstantItem,
62 TypeAliasItem,
63 StructItem,
64 StructField,
65 GenericParameters,
66 GenericArguments,
67 LiteralType,
68 PathType,
69 UnionType,
70 GroupType,
71 PairType,
72 ListType,
73 ListTypeItem,
74 LambdaType,
75 LambdaParameter,
76 Block,
77 LetStmt,
78 ExprStmt,
79 IfStmt,
80 ReturnStmt,
81 AssertStmt,
82 RaiseStmt,
83 DebugStmt,
84 PathExpr,
85 PathSegment,
86 LeadingPathSeparator,
87 StructInitializerExpr,
88 StructInitializerField,
89 LiteralExpr,
90 GroupExpr,
91 PairExpr,
92 ListExpr,
93 ListItem,
94 PrefixExpr,
95 BinaryExpr,
96 FunctionCallExpr,
97 IfExpr,
98 GuardExpr,
99 CastExpr,
100 FieldAccessExpr,
101 LambdaExpr,
102 NamedBinding,
103 PairBinding,
104 ListBinding,
105 ListBindingItem,
106 StructBinding,
107 StructFieldBinding,
108);
109
110ast_enum!(Item, TypeItem, SymbolItem);
111ast_enum!(TypeItem, TypeAliasItem, StructItem);
112ast_enum!(SymbolItem, ModuleItem, FunctionItem, ConstantItem);
113ast_enum!(
114 Stmt, LetStmt, ExprStmt, IfStmt, ReturnStmt, AssertStmt, RaiseStmt, DebugStmt
115);
116ast_enum!(StmtOrExpr, Stmt, Expr);
117ast_enum!(
118 Expr,
119 PathExpr,
120 StructInitializerExpr,
121 LiteralExpr,
122 GroupExpr,
123 PairExpr,
124 ListExpr,
125 PrefixExpr,
126 BinaryExpr,
127 FunctionCallExpr,
128 Block,
129 IfExpr,
130 GuardExpr,
131 CastExpr,
132 FieldAccessExpr,
133 LambdaExpr,
134);
135ast_enum!(
136 Type,
137 LiteralType,
138 PathType,
139 UnionType,
140 GroupType,
141 PairType,
142 ListType,
143 LambdaType,
144);
145ast_enum!(
146 Binding,
147 NamedBinding,
148 PairBinding,
149 ListBinding,
150 StructBinding,
151);
152
153impl AstDocument {
154 pub fn items(&self) -> impl Iterator<Item = AstItem> {
155 self.syntax().children().filter_map(AstItem::cast)
156 }
157}
158
159impl AstModuleItem {
160 pub fn export(&self) -> Option<SyntaxToken> {
161 self.syntax()
162 .children_with_tokens()
163 .filter_map(SyntaxElement::into_token)
164 .find(|token| token.kind() == T![export])
165 }
166
167 pub fn name(&self) -> Option<SyntaxToken> {
168 self.syntax()
169 .children_with_tokens()
170 .filter_map(SyntaxElement::into_token)
171 .find(|token| token.kind() == SyntaxKind::Ident)
172 }
173
174 pub fn items(&self) -> impl Iterator<Item = AstItem> {
175 self.syntax().children().filter_map(AstItem::cast)
176 }
177}
178
179impl AstFunctionItem {
180 pub fn export(&self) -> Option<SyntaxToken> {
181 self.syntax()
182 .children_with_tokens()
183 .filter_map(SyntaxElement::into_token)
184 .find(|token| token.kind() == T![export])
185 }
186
187 pub fn extern_kw(&self) -> Option<SyntaxToken> {
188 self.syntax()
189 .children_with_tokens()
190 .filter_map(SyntaxElement::into_token)
191 .find(|token| token.kind() == T![extern])
192 }
193
194 pub fn inline(&self) -> Option<SyntaxToken> {
195 self.syntax()
196 .children_with_tokens()
197 .filter_map(SyntaxElement::into_token)
198 .find(|token| token.kind() == T![inline])
199 }
200
201 pub fn test(&self) -> Option<SyntaxToken> {
202 self.syntax()
203 .children_with_tokens()
204 .filter_map(SyntaxElement::into_token)
205 .find(|token| token.kind() == T![test])
206 }
207
208 pub fn name(&self) -> Option<SyntaxToken> {
209 self.syntax()
210 .children_with_tokens()
211 .filter_map(SyntaxElement::into_token)
212 .find(|token| token.kind() == SyntaxKind::Ident)
213 }
214
215 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
216 self.syntax()
217 .children()
218 .find_map(AstGenericParameters::cast)
219 }
220
221 pub fn parameters(&self) -> impl Iterator<Item = AstFunctionParameter> {
222 self.syntax()
223 .children()
224 .filter_map(AstFunctionParameter::cast)
225 }
226
227 pub fn return_type(&self) -> Option<AstType> {
228 self.syntax().children().find_map(AstType::cast)
229 }
230
231 pub fn body(&self) -> Option<AstBlock> {
232 self.syntax().children().find_map(AstBlock::cast)
233 }
234}
235
236impl AstConstantItem {
237 pub fn export(&self) -> Option<SyntaxToken> {
238 self.syntax()
239 .children_with_tokens()
240 .filter_map(SyntaxElement::into_token)
241 .find(|token| token.kind() == T![export])
242 }
243
244 pub fn inline(&self) -> Option<SyntaxToken> {
245 self.syntax()
246 .children_with_tokens()
247 .filter_map(SyntaxElement::into_token)
248 .find(|token| token.kind() == T![inline])
249 }
250
251 pub fn name(&self) -> Option<SyntaxToken> {
252 self.syntax()
253 .children_with_tokens()
254 .filter_map(SyntaxElement::into_token)
255 .find(|token| token.kind() == SyntaxKind::Ident)
256 }
257
258 pub fn ty(&self) -> Option<AstType> {
259 self.syntax().children().find_map(AstType::cast)
260 }
261
262 pub fn value(&self) -> Option<AstExpr> {
263 self.syntax().children().find_map(AstExpr::cast)
264 }
265}
266
267impl AstTypeAliasItem {
268 pub fn export(&self) -> Option<SyntaxToken> {
269 self.syntax()
270 .children_with_tokens()
271 .filter_map(SyntaxElement::into_token)
272 .find(|token| token.kind() == T![export])
273 }
274
275 pub fn name(&self) -> Option<SyntaxToken> {
276 self.syntax()
277 .children_with_tokens()
278 .filter_map(SyntaxElement::into_token)
279 .find(|token| token.kind() == SyntaxKind::Ident)
280 }
281
282 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
283 self.syntax()
284 .children()
285 .find_map(AstGenericParameters::cast)
286 }
287
288 pub fn ty(&self) -> Option<AstType> {
289 self.syntax().children().find_map(AstType::cast)
290 }
291}
292
293impl AstStructItem {
294 pub fn export(&self) -> Option<SyntaxToken> {
295 self.syntax()
296 .children_with_tokens()
297 .filter_map(SyntaxElement::into_token)
298 .find(|token| token.kind() == T![export])
299 }
300
301 pub fn name(&self) -> Option<SyntaxToken> {
302 self.syntax()
303 .children_with_tokens()
304 .filter_map(SyntaxElement::into_token)
305 .find(|token| token.kind() == SyntaxKind::Ident)
306 }
307
308 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
309 self.syntax()
310 .children()
311 .find_map(AstGenericParameters::cast)
312 }
313
314 pub fn fields(&self) -> impl Iterator<Item = AstStructField> {
315 self.syntax().children().filter_map(AstStructField::cast)
316 }
317}
318
319impl AstStructField {
320 pub fn spread(&self) -> Option<SyntaxToken> {
321 self.syntax()
322 .children_with_tokens()
323 .filter_map(SyntaxElement::into_token)
324 .find(|token| token.kind() == T![...])
325 }
326
327 pub fn name(&self) -> Option<SyntaxToken> {
328 self.syntax()
329 .children_with_tokens()
330 .filter_map(SyntaxElement::into_token)
331 .find(|token| token.kind() == SyntaxKind::Ident)
332 }
333
334 pub fn ty(&self) -> Option<AstType> {
335 self.syntax().children().find_map(AstType::cast)
336 }
337
338 pub fn expr(&self) -> Option<AstExpr> {
339 self.syntax().children().find_map(AstExpr::cast)
340 }
341}
342
343impl AstFunctionParameter {
344 pub fn spread(&self) -> Option<SyntaxToken> {
345 self.syntax()
346 .children_with_tokens()
347 .filter_map(SyntaxElement::into_token)
348 .find(|token| token.kind() == T![...])
349 }
350
351 pub fn binding(&self) -> Option<AstBinding> {
352 self.syntax().children().find_map(AstBinding::cast)
353 }
354
355 pub fn ty(&self) -> Option<AstType> {
356 self.syntax().children().find_map(AstType::cast)
357 }
358}
359
360impl AstGenericParameters {
361 pub fn names(&self) -> impl Iterator<Item = SyntaxToken> {
362 self.syntax()
363 .children_with_tokens()
364 .filter_map(SyntaxElement::into_token)
365 .filter(|token| token.kind() == SyntaxKind::Ident)
366 }
367}
368
369impl AstGenericArguments {
370 pub fn types(&self) -> impl Iterator<Item = AstType> {
371 self.syntax().children().filter_map(AstType::cast)
372 }
373}
374
375impl AstBlock {
376 pub fn items(&self) -> impl Iterator<Item = AstStmtOrExpr> {
377 self.syntax().children().filter_map(AstStmtOrExpr::cast)
378 }
379}
380
381impl AstLetStmt {
382 pub fn inline(&self) -> Option<SyntaxToken> {
383 self.syntax()
384 .children_with_tokens()
385 .filter_map(SyntaxElement::into_token)
386 .find(|token| token.kind() == T![inline])
387 }
388
389 pub fn binding(&self) -> Option<AstBinding> {
390 self.syntax().children().find_map(AstBinding::cast)
391 }
392
393 pub fn ty(&self) -> Option<AstType> {
394 self.syntax().children().find_map(AstType::cast)
395 }
396
397 pub fn value(&self) -> Option<AstExpr> {
398 self.syntax().children().find_map(AstExpr::cast)
399 }
400}
401
402impl AstExprStmt {
403 pub fn expr(&self) -> Option<AstExpr> {
404 self.syntax().children().find_map(AstExpr::cast)
405 }
406}
407
408impl AstIfStmt {
409 pub fn inline(&self) -> Option<SyntaxToken> {
410 self.syntax()
411 .children_with_tokens()
412 .filter_map(SyntaxElement::into_token)
413 .find(|token| token.kind() == T![inline])
414 }
415
416 pub fn condition(&self) -> Option<AstExpr> {
417 self.syntax().children().find_map(AstExpr::cast)
418 }
419
420 pub fn then_block(&self) -> Option<AstBlock> {
421 self.syntax()
422 .children()
423 .filter(|node| AstExpr::cast(node.clone()).is_some())
424 .nth(1)
425 .and_then(AstBlock::cast)
426 }
427}
428
429impl AstReturnStmt {
430 pub fn expr(&self) -> Option<AstExpr> {
431 self.syntax().children().find_map(AstExpr::cast)
432 }
433}
434
435impl AstAssertStmt {
436 pub fn expr(&self) -> Option<AstExpr> {
437 self.syntax().children().find_map(AstExpr::cast)
438 }
439}
440
441impl AstRaiseStmt {
442 pub fn expr(&self) -> Option<AstExpr> {
443 self.syntax().children().find_map(AstExpr::cast)
444 }
445}
446
447impl AstDebugStmt {
448 pub fn expr(&self) -> Option<AstExpr> {
449 self.syntax().children().find_map(AstExpr::cast)
450 }
451}
452
453impl AstPathExpr {
454 pub fn segments(&self) -> impl Iterator<Item = AstPathSegment> {
455 self.syntax().children().filter_map(AstPathSegment::cast)
456 }
457}
458
459impl AstPathSegment {
460 pub fn initial_separator(&self) -> Option<AstLeadingPathSeparator> {
461 self.syntax()
462 .children()
463 .find_map(AstLeadingPathSeparator::cast)
464 }
465
466 pub fn name(&self) -> Option<SyntaxToken> {
467 self.syntax()
468 .children_with_tokens()
469 .filter_map(SyntaxElement::into_token)
470 .find(|token| token.kind() == SyntaxKind::Ident)
471 }
472
473 pub fn generic_arguments(&self) -> Option<AstGenericArguments> {
474 self.syntax().children().find_map(AstGenericArguments::cast)
475 }
476}
477
478impl AstStructInitializerExpr {
479 pub fn path(&self) -> Option<AstPathExpr> {
480 self.syntax().children().find_map(AstPathExpr::cast)
481 }
482
483 pub fn fields(&self) -> impl Iterator<Item = AstStructInitializerField> {
484 self.syntax()
485 .children()
486 .filter_map(AstStructInitializerField::cast)
487 }
488}
489
490impl AstStructInitializerField {
491 pub fn name(&self) -> Option<SyntaxToken> {
492 self.syntax()
493 .children_with_tokens()
494 .filter_map(SyntaxElement::into_token)
495 .find(|token| token.kind() == SyntaxKind::Ident)
496 }
497
498 pub fn expr(&self) -> Option<AstExpr> {
499 self.syntax().children().find_map(AstExpr::cast)
500 }
501}
502
503impl AstLiteralExpr {
504 pub fn value(&self) -> Option<SyntaxToken> {
505 self.syntax()
506 .children_with_tokens()
507 .filter_map(SyntaxElement::into_token)
508 .find(|token| SyntaxKind::LITERAL.contains(&token.kind()))
509 }
510}
511
512impl AstGroupExpr {
513 pub fn expr(&self) -> Option<AstExpr> {
514 self.syntax().children().find_map(AstExpr::cast)
515 }
516}
517
518impl AstPairExpr {
519 pub fn first(&self) -> Option<AstExpr> {
520 self.syntax().children().find_map(AstExpr::cast)
521 }
522
523 pub fn rest(&self) -> Option<AstExpr> {
524 self.syntax().children().filter_map(AstExpr::cast).nth(1)
525 }
526}
527
528impl AstListExpr {
529 pub fn items(&self) -> impl Iterator<Item = AstListItem> {
530 self.syntax().children().filter_map(AstListItem::cast)
531 }
532}
533
534impl AstListItem {
535 pub fn spread(&self) -> Option<SyntaxToken> {
536 self.syntax()
537 .children_with_tokens()
538 .filter_map(SyntaxElement::into_token)
539 .find(|token| token.kind() == T![...])
540 }
541
542 pub fn expr(&self) -> Option<AstExpr> {
543 self.syntax().children().find_map(AstExpr::cast)
544 }
545}
546
547impl AstPrefixExpr {
548 pub fn op(&self) -> Option<SyntaxToken> {
549 self.syntax()
550 .children_with_tokens()
551 .filter_map(SyntaxElement::into_token)
552 .find(|token| SyntaxKind::PREFIX_OPS.contains(&token.kind()))
553 }
554
555 pub fn expr(&self) -> Option<AstExpr> {
556 self.syntax().children().find_map(AstExpr::cast)
557 }
558}
559
560impl AstBinaryExpr {
561 pub fn op(&self) -> Option<SyntaxToken> {
562 self.syntax()
563 .children_with_tokens()
564 .filter_map(SyntaxElement::into_token)
565 .find(|token| SyntaxKind::BINARY_OPS.contains(&token.kind()))
566 }
567
568 pub fn left(&self) -> Option<AstExpr> {
569 self.syntax().children().find_map(AstExpr::cast)
570 }
571
572 pub fn right(&self) -> Option<AstExpr> {
573 self.syntax().children().filter_map(AstExpr::cast).nth(1)
574 }
575}
576
577impl AstFunctionCallExpr {
578 pub fn expr(&self) -> Option<AstExpr> {
579 self.syntax().children().find_map(AstExpr::cast)
580 }
581
582 pub fn args(&self) -> impl Iterator<Item = AstListItem> {
583 self.syntax().children().filter_map(AstListItem::cast)
584 }
585}
586
587impl AstIfExpr {
588 pub fn inline(&self) -> Option<SyntaxToken> {
589 self.syntax()
590 .children_with_tokens()
591 .filter_map(SyntaxElement::into_token)
592 .find(|token| token.kind() == T![inline])
593 }
594
595 pub fn condition(&self) -> Option<AstExpr> {
596 self.syntax().children().find_map(AstExpr::cast)
597 }
598
599 pub fn then_expr(&self) -> Option<AstExpr> {
600 self.syntax().children().filter_map(AstExpr::cast).nth(1)
601 }
602
603 pub fn else_expr(&self) -> Option<AstExpr> {
604 self.syntax().children().filter_map(AstExpr::cast).nth(2)
605 }
606}
607
608impl AstGuardExpr {
609 pub fn expr(&self) -> Option<AstExpr> {
610 self.syntax().children().find_map(AstExpr::cast)
611 }
612
613 pub fn ty(&self) -> Option<AstType> {
614 self.syntax().children().find_map(AstType::cast)
615 }
616}
617
618impl AstCastExpr {
619 pub fn expr(&self) -> Option<AstExpr> {
620 self.syntax().children().find_map(AstExpr::cast)
621 }
622
623 pub fn ty(&self) -> Option<AstType> {
624 self.syntax().children().find_map(AstType::cast)
625 }
626}
627
628impl AstFieldAccessExpr {
629 pub fn expr(&self) -> Option<AstExpr> {
630 self.syntax().children().find_map(AstExpr::cast)
631 }
632
633 pub fn field(&self) -> Option<SyntaxToken> {
634 self.syntax()
635 .children_with_tokens()
636 .filter_map(SyntaxElement::into_token)
637 .find(|token| token.kind() == SyntaxKind::Ident)
638 }
639}
640
641impl AstLambdaExpr {
642 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
643 self.syntax()
644 .children()
645 .find_map(AstGenericParameters::cast)
646 }
647
648 pub fn parameters(&self) -> impl Iterator<Item = AstFunctionParameter> {
649 self.syntax()
650 .children()
651 .filter_map(AstFunctionParameter::cast)
652 }
653
654 pub fn ty(&self) -> Option<AstType> {
655 self.syntax().children().find_map(AstType::cast)
656 }
657
658 pub fn body(&self) -> Option<AstExpr> {
659 self.syntax().children().find_map(AstExpr::cast)
660 }
661}
662
663impl AstLiteralType {
664 pub fn value(&self) -> Option<SyntaxToken> {
665 self.syntax()
666 .children_with_tokens()
667 .filter_map(SyntaxElement::into_token)
668 .find(|token| SyntaxKind::LITERAL.contains(&token.kind()))
669 }
670}
671
672impl AstPathType {
673 pub fn segments(&self) -> impl Iterator<Item = AstPathSegment> {
674 self.syntax().children().filter_map(AstPathSegment::cast)
675 }
676}
677
678impl AstUnionType {
679 pub fn types(&self) -> impl Iterator<Item = AstType> {
680 self.syntax().children().filter_map(AstType::cast)
681 }
682}
683
684impl AstGroupType {
685 pub fn ty(&self) -> Option<AstType> {
686 self.syntax().children().find_map(AstType::cast)
687 }
688}
689
690impl AstPairType {
691 pub fn first(&self) -> Option<AstType> {
692 self.syntax().children().find_map(AstType::cast)
693 }
694
695 pub fn rest(&self) -> Option<AstType> {
696 self.syntax().children().filter_map(AstType::cast).nth(1)
697 }
698}
699
700impl AstListType {
701 pub fn items(&self) -> impl Iterator<Item = AstListTypeItem> {
702 self.syntax().children().filter_map(AstListTypeItem::cast)
703 }
704}
705
706impl AstListTypeItem {
707 pub fn spread(&self) -> Option<SyntaxToken> {
708 self.syntax()
709 .children_with_tokens()
710 .filter_map(SyntaxElement::into_token)
711 .find(|token| token.kind() == T![...])
712 }
713
714 pub fn ty(&self) -> Option<AstType> {
715 self.syntax().children().find_map(AstType::cast)
716 }
717}
718
719impl AstLambdaType {
720 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
721 self.syntax()
722 .children()
723 .find_map(AstGenericParameters::cast)
724 }
725
726 pub fn parameters(&self) -> impl Iterator<Item = AstLambdaParameter> {
727 self.syntax()
728 .children()
729 .filter_map(AstLambdaParameter::cast)
730 }
731
732 pub fn return_type(&self) -> Option<AstType> {
733 self.syntax().children().find_map(AstType::cast)
734 }
735}
736
737impl AstLambdaParameter {
738 pub fn spread(&self) -> Option<SyntaxToken> {
739 self.syntax()
740 .children_with_tokens()
741 .filter_map(SyntaxElement::into_token)
742 .find(|token| token.kind() == T![...])
743 }
744
745 pub fn ty(&self) -> Option<AstType> {
746 self.syntax().children().find_map(AstType::cast)
747 }
748}
749
750impl AstNamedBinding {
751 pub fn name(&self) -> Option<SyntaxToken> {
752 self.syntax()
753 .children_with_tokens()
754 .filter_map(SyntaxElement::into_token)
755 .find(|token| token.kind() == SyntaxKind::Ident)
756 }
757}
758
759impl AstPairBinding {
760 pub fn first(&self) -> Option<AstBinding> {
761 self.syntax().children().find_map(AstBinding::cast)
762 }
763
764 pub fn rest(&self) -> Option<AstBinding> {
765 self.syntax().children().filter_map(AstBinding::cast).nth(1)
766 }
767}
768
769impl AstListBinding {
770 pub fn items(&self) -> impl Iterator<Item = AstListBindingItem> {
771 self.syntax()
772 .children()
773 .filter_map(AstListBindingItem::cast)
774 }
775}
776
777impl AstListBindingItem {
778 pub fn spread(&self) -> Option<SyntaxToken> {
779 self.syntax()
780 .children_with_tokens()
781 .filter_map(SyntaxElement::into_token)
782 .find(|token| token.kind() == T![...])
783 }
784
785 pub fn binding(&self) -> Option<AstBinding> {
786 self.syntax().children().find_map(AstBinding::cast)
787 }
788}
789
790impl AstStructBinding {
791 pub fn fields(&self) -> impl Iterator<Item = AstStructFieldBinding> {
792 self.syntax()
793 .children()
794 .filter_map(AstStructFieldBinding::cast)
795 }
796}
797
798impl AstStructFieldBinding {
799 pub fn name(&self) -> Option<SyntaxToken> {
800 self.syntax()
801 .children_with_tokens()
802 .filter_map(SyntaxElement::into_token)
803 .find(|token| token.kind() == SyntaxKind::Ident)
804 }
805
806 pub fn binding(&self) -> Option<AstBinding> {
807 self.syntax().children().find_map(AstBinding::cast)
808 }
809}