Skip to main content

skullbrain_parser/ast/
_ast.rs

1use super::*;
2use crate::cst::{CommaSeperated, CstNode, CstToken, IdentToken};
3use crate::{cst, SyntaxKind};
4use cstree::interning::{Resolver, TokenKey};
5use itertools::Itertools;
6use skullbrain_lexer::{Lexer, LiteralKind, ModifierKind};
7
8impl ToAst for IdentToken {
9    type Output = Ident;
10    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
11    where
12        I: Resolver<TokenKey> + ?Sized,
13    {
14        let span = self.token().text_range();
15
16        Some(Ident {
17            span,
18            name: self.token().resolve_text(resolver).to_string(),
19        })
20    }
21}
22
23impl ToAst for cst::LiteralToken {
24    type Output = Literal;
25    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
26    where
27        I: Resolver<TokenKey> + ?Sized,
28    {
29        let text = self.token().resolve_text(resolver);
30        let Some(tok) = Lexer::new(text.chars()).next() else {
31            unreachable!()
32        };
33
34        let Some(lit) = tok.into_kind().literial() else {
35            unreachable!()
36        };
37
38        let value = match lit {
39            LiteralKind::Int { is_empty, .. } if is_empty => return None,
40            LiteralKind::Double { empty_exponent, .. } if empty_exponent => return None,
41            LiteralKind::Str { is_terminated } if is_terminated => return None,
42            LiteralKind::Str { .. } => Value::Str(text.to_string()).into(),
43            LiteralKind::Int { .. } => {
44                let Ok(int) = text.parse() else {
45                    unreachable!()
46                };
47
48                Value::Int(int).into()
49            }
50            LiteralKind::Double { .. } => {
51                let Ok(int) = text.parse() else {
52                    unreachable!()
53                };
54
55                Value::Double(int).into()
56            }
57            LiteralKind::Boolean(value) => Value::Bool(value).into(),
58        };
59
60        let span = self.token().text_range();
61        Some(Literal { span, value })
62    }
63}
64
65impl ToAst for cst::BinaryExpr {
66    type Output = BinaryExpr;
67    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
68    where
69        I: Resolver<TokenKey> + ?Sized,
70    {
71        let lhs = self.lhs()?.to_ast(resolver)?;
72        let rhs = self.rhs()?.to_ast(resolver)?;
73
74        let op = match self.operator().kind() {
75            SyntaxKind::OpEq => BinaryOp::Eq,
76            SyntaxKind::OpNotEq => BinaryOp::NotEq,
77            SyntaxKind::OpLt => BinaryOp::Lt,
78            SyntaxKind::OpGt => BinaryOp::Gt,
79            SyntaxKind::OpLtEq => BinaryOp::LtEq,
80            SyntaxKind::OpGtEq => BinaryOp::GtEq,
81            SyntaxKind::OpMinus => BinaryOp::Sub,
82            SyntaxKind::OpAnd => BinaryOp::And,
83            SyntaxKind::OpOr => BinaryOp::Or,
84            SyntaxKind::OpPlus => BinaryOp::Add,
85            SyntaxKind::OpMul => BinaryOp::Mul,
86            SyntaxKind::OpDivide => BinaryOp::Div,
87            SyntaxKind::OpMod => BinaryOp::Mod,
88            _ => unreachable!(),
89        };
90
91        let operand = Box::new((lhs, rhs));
92        Some(BinaryExpr { op, operand })
93    }
94}
95
96impl ToAst for cst::UnaryExpr {
97    type Output = UnaryExpr;
98    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
99    where
100        I: Resolver<TokenKey> + ?Sized,
101    {
102        let rhs = self.expr()?.to_ast(resolver)?;
103        let expr = Box::new(rhs);
104
105        let op = match self.operator().kind() {
106            SyntaxKind::OpNot => UnaryOp::Not,
107            SyntaxKind::OpMinus => UnaryOp::Minus,
108            _ => unreachable!(),
109        };
110
111        Some(UnaryExpr { op, expr })
112    }
113}
114
115impl ToAst for cst::ChainExpr {
116    type Output = ChainExpr;
117    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
118    where
119        I: Resolver<TokenKey> + ?Sized,
120    {
121        let object = self.object()?.to_ast(resolver)?;
122        let method = self.method()?.to_ast(resolver)?;
123        let data = Box::new((object, method));
124        Some(ChainExpr { data })
125    }
126}
127
128impl ToAst for cst::ParenExpr {
129    type Output = ParenExpr;
130    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
131    where
132        I: Resolver<TokenKey> + ?Sized,
133    {
134        // Verifies syntax
135        let _ = self.open_token()?;
136        let _ = self.close_token()?;
137
138        let expr = self.exprs().exactly_one().ok()?.to_ast(resolver)?;
139        let expr = Box::new(expr);
140
141        let span = self.syntax().text_range();
142
143        Some(ParenExpr { expr, span })
144    }
145}
146
147impl ToAst for cst::BlockExpr {
148    type Output = BlockExpr;
149    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
150    where
151        I: Resolver<TokenKey> + ?Sized,
152    {
153        let _ = self.open_token()?;
154        let _ = self.close_token()?;
155
156        let statements = self
157            .exprs()
158            .map(|expr| expr.to_ast(resolver))
159            .collect::<Option<Box<[_]>>>()?;
160        let span = self.syntax().text_range();
161
162        Some(BlockExpr { statements, span })
163    }
164}
165
166impl ToAst for cst::Break {
167    type Output = Break;
168    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
169    where
170        I: Resolver<TokenKey> + ?Sized,
171    {
172        let value = self.optional_expr()?.to_ast(resolver)?;
173        let value = Box::new(value);
174        let span = self.syntax().text_range();
175
176        Some(Break {
177            value: Some(value),
178            span,
179        })
180    }
181}
182
183impl ToAst for cst::Continue {
184    type Output = Continue;
185    fn to_ast<I>(self, _resolver: &I) -> Option<Self::Output>
186    where
187        I: Resolver<TokenKey> + ?Sized,
188    {
189        let span = self.syntax().text_range();
190        Some(Continue { span })
191    }
192}
193
194impl ToAst for cst::Return {
195    type Output = Return;
196    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
197    where
198        I: Resolver<TokenKey> + ?Sized,
199    {
200        let value = self.optional_expr()?.to_ast(resolver)?;
201        let span = self.syntax().text_range();
202        Some(Return {
203            span,
204            value: Some(Box::new(value)),
205        })
206    }
207}
208
209impl ToAst for cst::Throw {
210    type Output = Throw;
211    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
212    where
213        I: Resolver<TokenKey> + ?Sized,
214    {
215        let value = self.expr()?.to_ast(resolver)?;
216        let span = self.syntax().text_range();
217        Some(Throw {
218            span,
219
220            value: Box::new(value),
221        })
222    }
223}
224
225impl ToAst for cst::While {
226    type Output = While;
227    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
228    where
229        I: Resolver<TokenKey> + ?Sized,
230    {
231        let condition = self.condition()?.to_ast(resolver)?;
232        let body = self.body()?.to_ast(resolver)?;
233        let span = self.syntax().text_range();
234        Some(While {
235            span,
236            condition,
237            body,
238        })
239    }
240}
241
242impl ToAst for cst::ForLoop {
243    type Output = ForLoop;
244    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
245    where
246        I: Resolver<TokenKey> + ?Sized,
247    {
248        let _ = self.open_token()?;
249        let _ = self.close_token()?;
250
251        let iterator = self.iter()?.to_ast(resolver)?;
252        let body = self.body()?.to_ast(resolver)?;
253        let span = self.syntax().text_range();
254        Some(ForLoop {
255            span,
256            iterator,
257            body,
258        })
259    }
260}
261
262impl ToAst for cst::TryCatch {
263    type Output = TryCatch;
264    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
265    where
266        I: Resolver<TokenKey> + ?Sized,
267    {
268        let try_arm = self.try_arm()?;
269        let _ = try_arm.try_token()?;
270        let try_block = try_arm.block()?.to_ast(resolver)?;
271
272        let mut seen_arm_without_ty = false;
273
274        let catch_arms = self
275            .catch_arms()
276            .map(|arm| match arm.catch_ty() {
277                Some(_) if seen_arm_without_ty => None,
278                Some(_) => {
279                    seen_arm_without_ty = true;
280                    arm.to_ast(resolver)
281                }
282                None => arm.to_ast(resolver),
283            })
284            .collect::<Option<Box<[_]>>>();
285
286        let span = self.syntax().text_range();
287
288        Some(TryCatch {
289            span,
290            try_block,
291            catch_arms,
292        })
293    }
294}
295
296impl ToAst for cst::CatchArm {
297    type Output = CatchArm;
298    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
299    where
300        I: Resolver<TokenKey> + ?Sized,
301    {
302        let _ = self.catch_token()?;
303
304        let catch_ty = match self.catch_ty() {
305            Some(ty) => {
306                let _ = ty.colon_token()?;
307                let name = ty.name()?.to_ast(resolver)?;
308                let ty = ty.ty()?.to_ast(resolver)?;
309                let span = ty.span();
310                Some(CatchType { span, ty, name })
311            }
312            None => None,
313        };
314
315        let body = self.block()?.to_ast(resolver)?;
316        let span = self.syntax().text_range();
317
318        Some(CatchArm {
319            span,
320            catch_ty,
321            body,
322        })
323    }
324}
325
326impl ToAst for cst::VariableStmt {
327    type Output = VariableStmt;
328    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
329    where
330        I: Resolver<TokenKey> + ?Sized,
331    {
332        let is_mutable = self.var_token().is_mutable();
333        let modifiers = self.modifiers()?.to_ast(resolver)?;
334        let name = self.name()?.to_ast(resolver)?;
335        let ty_annotation = self.ty()?.to_ast(resolver)?.into();
336        let initializer = self.initialiser()?.to_ast(resolver)?;
337
338        let span = self.syntax().text_range();
339
340        Some(VariableStmt {
341            span,
342            is_mutable,
343            modifiers,
344            name,
345            ty_annotation,
346            initializer,
347        })
348    }
349}
350
351impl ToAst for cst::TypeAlias {
352    type Output = TypeAlias;
353    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
354    where
355        I: Resolver<TokenKey> + ?Sized,
356    {
357        let modifiers = self.modifiers()?.to_ast(resolver)?;
358
359        let _ = self.alias_token()?;
360        let _ = self.assignment_token()?;
361
362        let name = self.name()?.to_ast(resolver)?;
363        let aliased_type = self.aliased()?.to_ast(resolver)?;
364
365        let span = self.syntax().text_range();
366
367        Some(TypeAlias {
368            span,
369            modifiers,
370            name,
371            aliased_type,
372        })
373    }
374}
375
376impl ToAst for cst::Modifiers {
377    type Output = Modifiers;
378    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
379    where
380        I: Resolver<TokenKey> + ?Sized,
381    {
382        let mut flags = Modifiers::empty();
383
384        for item in self.iter() {
385            let kind = item.kind(resolver);
386            let flag = match kind {
387                ModifierKind::VisibilityPublic => Modifiers::Public,
388                ModifierKind::InstanceAccess => Modifiers::InstanceAccess,
389            };
390
391            if flags.contains(flag.clone()) {
392                return None;
393            } else {
394                flags |= flag
395            }
396        }
397
398        Some(flags)
399    }
400}
401impl ToAst for cst::Type {
402    type Output = Type;
403    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
404    where
405        I: Resolver<TokenKey> + ?Sized,
406    {
407        if let Some(ident) = self.ident() {
408            let ident = ident.to_ast(resolver)?;
409            return Some(Type::Ident(ident));
410        }
411
412        if let Some(func) = self.signature() {
413            let ty = func.to_ast(resolver)?;
414            return Some(Type::Function(ty));
415        }
416
417        unreachable!()
418    }
419}
420
421impl ToAst for cst::FunctionSignature {
422    type Output = FunctionSignature;
423    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
424    where
425        I: Resolver<TokenKey> + ?Sized,
426    {
427        let _ = self.return_ty_token()?;
428        let _ = self.open_brace_token()?;
429        let _ = self.close_brace_token()?;
430
431        let parameters = self.parameters()?;
432        let is_valid = parameters
433            .iter()
434            .enumerate()
435            .all(|(i, item)| match (i % 2, item) {
436                // Even indices should be Items
437                (0, CommaSeperated::Item(_)) => true,
438                // Odd indices should be Commas
439                (1, CommaSeperated::Comma(_)) => true,
440                _ => false,
441            });
442
443        if !is_valid {
444            return None;
445        }
446
447        let parameters = parameters
448            .iter()
449            .step_by(2) // Take every other item starting from 0 (the Items)
450            .filter_map(|item| match item {
451                CommaSeperated::Item(param) => Some(param.to_ast(resolver)),
452                _ => None,
453            })
454            .collect::<Option<Box<_>>>()?;
455
456        let return_type = self
457            .return_ty()
458            .and_then(|ty| ty.to_ast(resolver))
459            .map(|ty| Box::new(ty));
460
461        let span = self.syntax().text_range();
462        Some(FunctionSignature {
463            span,
464            parameters,
465            return_type,
466        })
467    }
468}
469
470impl ToAst for cst::Parameter {
471    type Output = Parameter;
472    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
473    where
474        I: Resolver<TokenKey> + ?Sized,
475    {
476        let _ = self.colon_token()?;
477        let name = self.name()?.to_ast(resolver)?;
478        let ty = self.ty()?.to_ast(resolver)?;
479
480        Some(Parameter { name, ty })
481    }
482}
483
484impl ToAst for cst::IfElse {
485    type Output = IfElse;
486    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
487    where
488        I: Resolver<TokenKey> + ?Sized,
489    {
490        let if_arm = self.if_arm()?;
491        let _ = if_arm.if_token()?;
492        let condition = if_arm.condition()?.to_ast(resolver)?;
493        let then_branch = if_arm.body()?.to_ast(resolver)?;
494
495        let mut seen_else_branch = false;
496        let else_branches = self
497            .else_branches()
498            .map(|arm| match arm {
499                crate::cst::ElseBranch::Else(_) if seen_else_branch => None,
500                crate::cst::ElseBranch::Else(_) => {
501                    seen_else_branch = true;
502                    arm.to_ast(resolver)
503                }
504                _ => arm.to_ast(resolver),
505            })
506            .collect::<Option<Box<[_]>>>()?;
507        let span = self.syntax().text_range();
508
509        Some(IfElse {
510            span,
511            condition,
512            then_branch,
513            else_branches: Some(else_branches),
514        })
515    }
516}
517
518impl ToAst for cst::ElseBranch {
519    type Output = ElseBranch;
520    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
521    where
522        I: Resolver<TokenKey> + ?Sized,
523    {
524        let span = self.syntax().text_range();
525
526        let (condition, then_branch) = match self {
527            cst::ElseBranch::Else(else_arm) => {
528                let _ = else_arm.else_token()?;
529                let body = else_arm.body()?.to_ast(resolver)?;
530                (None, body)
531            }
532            cst::ElseBranch::ElseIf(else_if_arm) => {
533                let _ = else_if_arm.contains_else_if()?;
534                let condition = else_if_arm.condition()?.to_ast(resolver)?;
535                let body = else_if_arm.body()?.to_ast(resolver)?;
536
537                (Some(condition), body)
538            }
539        };
540
541        Some(ElseBranch {
542            span,
543            condition,
544            then_branch,
545        })
546    }
547}
548impl ToAst for cst::Match {
549    type Output = Match;
550    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
551    where
552        I: Resolver<TokenKey> + ?Sized,
553    {
554        let _ = self.body_open_token();
555        let _ = self.body_close_token();
556        if self.disallowed_exprs()?.next().is_some() {
557            return None;
558        }
559
560        let expr = self.expr()?.to_ast(resolver)?;
561
562        let arms = self
563            .match_arms()?
564            .map(|arm| arm.to_ast(resolver))
565            .collect::<Option<Box<_>>>()?;
566
567        // Ensures no duplicate default arms
568        let mut iter = arms.iter();
569
570        if iter.find(|arm| arm.pat.is_none()).is_some()
571            && iter.find(|arm| arm.pat.is_none()).is_some()
572        {
573            return None;
574        }
575
576        let span = self.syntax().text_range();
577        Some(Match { span, expr, arms })
578    }
579}
580
581impl ToAst for cst::MatchArm {
582    type Output = MatchArm;
583    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
584    where
585        I: Resolver<TokenKey> + ?Sized,
586    {
587        let res = match self {
588            cst::MatchArm::WithCondition(arm) => MatchArm {
589                pat: Some(arm.pat()?.to_ast(resolver)?),
590                body: arm.body()?.to_ast(resolver)?,
591            },
592            cst::MatchArm::Default(arm) => MatchArm {
593                pat: None,
594                body: arm.body()?.to_ast(resolver)?,
595            },
596        };
597
598        Some(res)
599    }
600}
601
602impl ToAst for cst::MatchPat {
603    type Output = MatchPat;
604    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
605    where
606        I: Resolver<TokenKey> + ?Sized,
607    {
608        let pat = if let Some(ident) = self.ident() {
609            MatchPat::Ident(ident.to_ast(resolver)?)
610        } else if let Some(lit) = self.lit() {
611            MatchPat::Literal(lit.to_ast(resolver)?)
612        } else {
613            todo!()
614        };
615
616        Some(pat)
617    }
618}
619
620impl ToAst for cst::ImportStmt {
621    type Output = ImportStmt;
622    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
623    where
624        I: Resolver<TokenKey> + ?Sized,
625    {
626        let _ = self.import_token()?;
627        let _ = self.alias_token()?;
628        let _ = self.alias_token()?;
629
630        let source = {
631            let source = self.source()?;
632
633            match source.ident() {
634                Some(ident) => ident.to_ast(resolver)?.name,
635                None => match source.path() {
636                    Some(path) => path.token().resolve_text(resolver).to_string(),
637                    _ => unreachable!(),
638                },
639            }
640        };
641
642        let item_idents = self.items()?;
643
644        let open = item_idents.open_token();
645        let close = item_idents.close_token();
646
647        let is_both = open.is_some() && close.is_some();
648        let is_neither = open.is_none() && close.is_none();
649
650        let items = item_idents
651            .idents()
652            .map(|i| i.to_ast(resolver))
653            .collect::<Option<Box<_>>>()?;
654
655        // if len is 0 -> return false
656        // if len is 1 -> (if both | neither -> ok else return false)
657        // if len > 1 -> (if both -> ok else return false)
658        match items.len() {
659            0 => return None,
660            1 => {
661                if !(is_both || is_neither) {
662                    return None;
663                }
664            }
665            _ => {
666                if !is_both {
667                    return None;
668                }
669            }
670        }
671        let span = self.syntax().text_range();
672
673        Some(ImportStmt {
674            span,
675            source,
676            items,
677        })
678    }
679}
680
681impl ToAst for cst::Function {
682    type Output = Function;
683    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
684    where
685        I: Resolver<TokenKey> + ?Sized,
686    {
687        let modifiers = self.modifiers()?.to_ast(resolver)?;
688        let name = self.name()?.to_ast(resolver)?;
689        let signature = self.signature()?.to_ast(resolver)?;
690        let body = self.body()?.to_ast(resolver)?;
691        let span = self.syntax().text_range();
692
693        Some(Function {
694            span,
695            modifiers,
696            name,
697            signature,
698            body,
699        })
700    }
701}
702
703impl ToAst for cst::FunctionItem {
704    type Output = FunctionItem;
705    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
706    where
707        I: Resolver<TokenKey> + ?Sized,
708    {
709        let span = self.syntax().text_range();
710
711        let modifiers = self.modifiers()?.to_ast(resolver)?;
712        let name = self.name()?.to_ast(resolver)?;
713        let signature = self.signature()?.to_ast(resolver)?;
714        let body = match self {
715            cst::FunctionItem::Full(function) => Some(function.body()?.to_ast(resolver)?),
716            cst::FunctionItem::Partial(_) => None,
717        };
718
719        Some(FunctionItem {
720            span,
721            modifiers,
722            name,
723            signature,
724            body,
725        })
726    }
727}
728
729impl ToAst for cst::Enum {
730    type Output = Enum;
731    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
732    where
733        I: Resolver<TokenKey> + ?Sized,
734    {
735        let _ = self.body_open_tok()?;
736        let _ = self.body_close_tok()?;
737
738        let modifiers = self.modifiers()?.to_ast(resolver)?;
739        let name = self.name()?.to_ast(resolver)?;
740        let variants = self
741            .variants()
742            .map(|variant| variant.to_ast(resolver))
743            .collect::<Option<Box<_>>>()?;
744
745        let nested_impls = self
746            .nested_impls()?
747            .map(|_impl| _impl.to_ast(resolver))
748            .collect::<Option<Box<_>>>()?;
749
750        let members = MemberConstructions::from_cst(
751            resolver,
752            self.methods(),
753            self.variables(),
754            self.ty_aliasz(),
755            self.implicit_init_exprs(),
756        )?;
757
758        let span = self.syntax().text_range();
759
760        Some(Enum {
761            span,
762            modifiers,
763            name,
764            variants,
765            members,
766            nested_impls,
767        })
768    }
769}
770
771impl ToAst for cst::EnumVariant {
772    type Output = EnumVariant;
773    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
774    where
775        I: Resolver<TokenKey> + ?Sized,
776    {
777        let name = self.name()?.to_ast(resolver)?;
778        let fields = self.fields()?.map(|field| field.to_ast(resolver)).collect();
779        Some(EnumVariant { name, fields })
780    }
781}
782
783impl ToAst for cst::EnumVariantField {
784    type Output = EnumVariantField;
785    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
786    where
787        I: Resolver<TokenKey> + ?Sized,
788    {
789        let _ = self.colon_token()?;
790        let name = self.name()?.to_ast(resolver)?;
791        let ty = self.ty()?.to_ast(resolver)?;
792
793        Some(EnumVariantField { name, ty })
794    }
795}
796
797impl<T> MemberConstructions<T> {
798    fn from_cst<I, A>(
799        resolver: &I,
800        methods: Option<impl Iterator<Item = A>>,
801        fields: Option<impl Iterator<Item = cst::VariableStmt>>,
802        aliasz: Option<impl Iterator<Item = cst::TypeAlias>>,
803        implicit_inits: Option<impl Iterator<Item = cst::Expr>>,
804    ) -> Option<Self>
805    where
806        I: Resolver<TokenKey> + ?Sized,
807        A: ToAst<Output = T>,
808    {
809        let methods = methods?
810            .map(|func| func.to_ast(resolver))
811            .collect::<Option<Box<_>>>()?;
812
813        let fields = fields?
814            .map(|var| var.to_ast(resolver))
815            .collect::<Option<Box<_>>>()?;
816
817        let aliasz = aliasz?
818            .map(|var| var.to_ast(resolver))
819            .collect::<Option<Box<_>>>()?;
820
821        let implicit_inits = implicit_inits?
822            .map(|expr| expr.to_ast(resolver))
823            .collect::<Option<Box<_>>>()?;
824
825        Some(Self {
826            implicit_inits,
827            methods,
828            fields,
829            aliasz,
830        })
831    }
832}
833
834impl ToAst for cst::Class {
835    type Output = Class;
836    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
837    where
838        I: Resolver<TokenKey> + ?Sized,
839    {
840        let _ = self.body_open_tok()?;
841        let _ = self.body_close_tok()?;
842
843        let modifiers = self.modifiers()?.to_ast(resolver)?;
844        let name = self.name()?.to_ast(resolver)?;
845
846        let nested_impls = self
847            .nested_impls()?
848            .map(|_impl| _impl.to_ast(resolver))
849            .collect::<Option<Box<_>>>()?;
850
851        let members = MemberConstructions::from_cst(
852            resolver,
853            self.methods(),
854            self.variables(),
855            self.ty_aliasz(),
856            self.implicit_init_exprs(),
857        )?;
858        let span = self.syntax().text_range();
859
860        Some(Class {
861            span,
862            modifiers,
863            name,
864            members,
865            nested_impls,
866        })
867    }
868}
869
870impl ToAst for cst::TraitImpl {
871    type Output = TraitImpl;
872    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
873    where
874        I: Resolver<TokenKey> + ?Sized,
875    {
876        let _ = self.body_open_tok()?;
877        let _ = self.body_close_tok()?;
878
879        let members = MemberConstructions::from_cst(
880            resolver,
881            self.methods(),
882            self.var_decls(),
883            self.type_aliases(),
884            self.implicit_init_exprs(),
885        )?;
886
887        let span = self.syntax().text_range();
888
889        Some(TraitImpl { span, members })
890    }
891}
892
893impl ToAst for cst::Trait {
894    type Output = Trait;
895    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
896    where
897        I: Resolver<TokenKey> + ?Sized,
898    {
899        let _ = self.open_brace_token()?;
900        let _ = self.close_brace_token()?;
901
902        let modifiers = self.modifiers()?.to_ast(resolver)?;
903        let name = self.name()?.to_ast(resolver)?;
904        let members = MemberConstructions::from_cst(
905            resolver,
906            self.functions(),
907            self.var_decls(),
908            self.type_aliases(),
909            self.implicit_init_exprs(),
910        )?;
911
912        let span = self.syntax().text_range();
913
914        Some(Trait {
915            span,
916            modifiers,
917            name,
918            members,
919        })
920    }
921}
922
923impl ToAst for cst::Expr {
924    type Output = Expr;
925    fn to_ast<I>(self, resolver: &I) -> Option<Self::Output>
926    where
927        I: Resolver<TokenKey> + ?Sized,
928    {
929        let res: Expr = match self {
930            cst::Expr::Literal(literal_token) => literal_token.to_ast(resolver)?.into(),
931            cst::Expr::Ident(ident_token) => ident_token.to_ast(resolver)?.into(),
932            cst::Expr::Paren(parenthesis_expr) => parenthesis_expr.to_ast(resolver)?.into(),
933            cst::Expr::Block(block_expr) => block_expr.to_ast(resolver)?.into(),
934            cst::Expr::Binary(binary_op) => binary_op.to_ast(resolver)?.into(),
935            cst::Expr::Unary(unary_op) => unary_op.to_ast(resolver)?.into(),
936            cst::Expr::Chain(chain) => chain.to_ast(resolver)?.into(),
937            cst::Expr::Break(break_expr) => break_expr.to_ast(resolver)?.into(),
938            cst::Expr::Continue(continue_expr) => continue_expr.to_ast(resolver)?.into(),
939            cst::Expr::Return(return_expr) => return_expr.to_ast(resolver)?.into(),
940            cst::Expr::Throw(throw_expr) => throw_expr.to_ast(resolver)?.into(),
941            cst::Expr::While(while_loop) => while_loop.to_ast(resolver)?.into(),
942            cst::Expr::For(for_loop) => for_loop.to_ast(resolver)?.into(),
943            cst::Expr::TryCatch(try_catch) => try_catch.to_ast(resolver)?.into(),
944            cst::Expr::IfElse(if_else) => if_else.to_ast(resolver)?.into(),
945            cst::Expr::Match(match_expr) => match_expr.to_ast(resolver)?.into(),
946            cst::Expr::Variable(variable_decl) => variable_decl.to_ast(resolver)?.into(),
947            cst::Expr::Import(import_expr) => import_expr.to_ast(resolver)?.into(),
948            cst::Expr::TypeAlias(type_alias_decl) => type_alias_decl.to_ast(resolver)?.into(),
949            cst::Expr::Function(function_decl) => function_decl.to_ast(resolver)?.into(),
950            cst::Expr::Trait(trait_decl) => trait_decl.to_ast(resolver)?.into(),
951            cst::Expr::TraitImpl(trait_impl_decl) => trait_impl_decl.to_ast(resolver)?.into(),
952            cst::Expr::Class(class_decl) => class_decl.to_ast(resolver)?.into(),
953            cst::Expr::Enum(enum_decl) => enum_decl.to_ast(resolver)?.into(),
954            cst::Expr::Fragment(_) => return None,
955        };
956
957        Some(res)
958    }
959}
960
961impl From<Literal> for Expr {
962    fn from(value: Literal) -> Self {
963        Expr::Literal(value)
964    }
965}
966
967impl From<Ident> for Expr {
968    fn from(value: Ident) -> Self {
969        Expr::Ident(value)
970    }
971}
972
973// Operators
974impl From<BinaryExpr> for Expr {
975    fn from(value: BinaryExpr) -> Self {
976        Expr::Binary(value)
977    }
978}
979
980impl From<UnaryExpr> for Expr {
981    fn from(value: UnaryExpr) -> Self {
982        Expr::Unary(value)
983    }
984}
985
986// Method chaining
987impl From<ChainExpr> for Expr {
988    fn from(value: ChainExpr) -> Self {
989        Expr::Chain(value)
990    }
991}
992
993// Grouping
994impl From<ParenExpr> for Expr {
995    fn from(value: ParenExpr) -> Self {
996        Expr::Paren(value)
997    }
998}
999
1000impl From<BlockExpr> for Expr {
1001    fn from(value: BlockExpr) -> Self {
1002        Expr::Block(value)
1003    }
1004}
1005
1006// Control flow
1007impl From<Break> for Expr {
1008    fn from(value: Break) -> Self {
1009        Expr::Break(value)
1010    }
1011}
1012
1013impl From<Continue> for Expr {
1014    fn from(value: Continue) -> Self {
1015        Expr::Continue(value)
1016    }
1017}
1018
1019impl From<Return> for Expr {
1020    fn from(value: Return) -> Self {
1021        Expr::Return(value)
1022    }
1023}
1024
1025impl From<Throw> for Expr {
1026    fn from(value: Throw) -> Self {
1027        Expr::Throw(value)
1028    }
1029}
1030
1031// Loops
1032impl From<While> for Expr {
1033    fn from(value: While) -> Self {
1034        Expr::While(value)
1035    }
1036}
1037
1038impl From<ForLoop> for Expr {
1039    fn from(value: ForLoop) -> Self {
1040        Expr::For(value)
1041    }
1042}
1043
1044// Conditionals
1045impl From<IfElse> for Expr {
1046    fn from(value: IfElse) -> Self {
1047        Expr::If(value)
1048    }
1049}
1050
1051impl From<Match> for Expr {
1052    fn from(value: Match) -> Self {
1053        Expr::Match(value)
1054    }
1055}
1056
1057// Try/catch
1058impl From<TryCatch> for Expr {
1059    fn from(value: TryCatch) -> Self {
1060        Expr::TryCatch(value)
1061    }
1062}
1063
1064// Declarations (when used as expressions)
1065impl From<VariableStmt> for Expr {
1066    fn from(value: VariableStmt) -> Self {
1067        Expr::Variable(value)
1068    }
1069}
1070
1071impl From<Function> for Expr {
1072    fn from(value: Function) -> Self {
1073        Expr::Function(value)
1074    }
1075}
1076
1077impl From<Class> for Expr {
1078    fn from(value: Class) -> Self {
1079        Expr::Class(value)
1080    }
1081}
1082
1083impl From<Trait> for Expr {
1084    fn from(value: Trait) -> Self {
1085        Expr::Trait(value)
1086    }
1087}
1088
1089impl From<TraitImpl> for Expr {
1090    fn from(value: TraitImpl) -> Self {
1091        Expr::TraitImpl(value)
1092    }
1093}
1094
1095impl From<Enum> for Expr {
1096    fn from(value: Enum) -> Self {
1097        Expr::Enum(value)
1098    }
1099}
1100
1101impl From<TypeAlias> for Expr {
1102    fn from(value: TypeAlias) -> Self {
1103        Expr::TypeAlias(value)
1104    }
1105}
1106
1107impl From<ImportStmt> for Expr {
1108    fn from(value: ImportStmt) -> Self {
1109        Expr::Import(value)
1110    }
1111}