rue_ast/
lib.rs

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}