cl_ast/ast_impl/
convert.rs

1//! Converts between major enums and enum variants
2use super::*;
3
4impl<T: AsRef<str>> From<T> for PathPart {
5    fn from(value: T) -> Self {
6        match value.as_ref() {
7            "super" => PathPart::SuperKw,
8            ident => PathPart::Ident(ident.into()),
9        }
10    }
11}
12
13macro impl_from ($(impl From for $T:ty {$($from:ty => $to:expr),*$(,)?})*) {$($(
14    impl From<$from> for $T {
15        fn from(value: $from) -> Self {
16            $to(value.into()) // Uses *tuple constructor*
17        }
18    }
19    impl From<Box<$from>> for $T {
20        fn from(value: Box<$from>) -> Self {
21            $to((*value).into())
22        }
23    }
24)*)*}
25
26impl_from! {
27    impl From for ItemKind {
28        Alias => ItemKind::Alias,
29        Const => ItemKind::Const,
30        Static => ItemKind::Static,
31        Module => ItemKind::Module,
32        Function => ItemKind::Function,
33        Struct => ItemKind::Struct,
34        Enum => ItemKind::Enum,
35        Impl => ItemKind::Impl,
36        Use => ItemKind::Use,
37    }
38    impl From for StructKind {
39        Vec<Ty> => StructKind::Tuple,
40        // TODO: Struct members in struct
41    }
42    impl From for TyKind {
43        Path => TyKind::Path,
44        TyTuple => TyKind::Tuple,
45        TyRef => TyKind::Ref,
46        TyPtr => TyKind::Ptr,
47        TyFn => TyKind::Fn,
48    }
49    impl From for StmtKind {
50        Item => StmtKind::Item,
51        Expr => StmtKind::Expr,
52    }
53    impl From for ExprKind {
54        Let => ExprKind::Let,
55        Closure => ExprKind::Closure,
56        Quote => ExprKind::Quote,
57        Match => ExprKind::Match,
58        Assign => ExprKind::Assign,
59        Modify => ExprKind::Modify,
60        Binary => ExprKind::Binary,
61        Unary => ExprKind::Unary,
62        Cast => ExprKind::Cast,
63        Member => ExprKind::Member,
64        Index => ExprKind::Index,
65        Path => ExprKind::Path,
66        Literal => ExprKind::Literal,
67        Array => ExprKind::Array,
68        ArrayRep => ExprKind::ArrayRep,
69        AddrOf => ExprKind::AddrOf,
70        Block => ExprKind::Block,
71        Group => ExprKind::Group,
72        Tuple => ExprKind::Tuple,
73        While => ExprKind::While,
74        If => ExprKind::If,
75        For => ExprKind::For,
76        Break => ExprKind::Break,
77        Return => ExprKind::Return,
78    }
79    impl From for Literal {
80        bool => Literal::Bool,
81        char => Literal::Char,
82        u128 => Literal::Int,
83        String => Literal::String,
84    }
85}
86
87impl From<Option<Expr>> for Else {
88    fn from(value: Option<Expr>) -> Self {
89        Self { body: value.map(Into::into) }
90    }
91}
92impl From<Expr> for Else {
93    fn from(value: Expr) -> Self {
94        Self { body: Some(value.into()) }
95    }
96}
97
98impl TryFrom<Expr> for Pattern {
99    type Error = Expr;
100
101    /// Performs the conversion. On failure, returns the *first* non-pattern subexpression.
102    fn try_from(value: Expr) -> Result<Self, Self::Error> {
103        Ok(match value.kind {
104            ExprKind::Literal(literal) => Pattern::Literal(literal),
105            ExprKind::Path(Path { absolute: false, ref parts }) => match parts.as_slice() {
106                [PathPart::Ident(name)] => Pattern::Name(*name),
107                _ => Err(value)?,
108            },
109            ExprKind::Empty => Pattern::Tuple(vec![]),
110            ExprKind::Group(Group { expr }) => Pattern::Tuple(vec![Pattern::try_from(*expr)?]),
111            ExprKind::Tuple(Tuple { exprs }) => Pattern::Tuple(
112                exprs
113                    .into_iter()
114                    .map(Pattern::try_from)
115                    .collect::<Result<_, _>>()?,
116            ),
117            ExprKind::AddrOf(AddrOf { mutable, expr }) => {
118                Pattern::Ref(mutable, Box::new(Pattern::try_from(*expr)?))
119            }
120            ExprKind::Array(Array { values }) => Pattern::Array(
121                values
122                    .into_iter()
123                    .map(Pattern::try_from)
124                    .collect::<Result<_, _>>()?,
125            ),
126            ExprKind::Binary(Binary { kind: BinaryKind::Call, parts }) => {
127                let (Expr { kind: ExprKind::Path(path), .. }, args) = *parts else {
128                    return Err(parts.0);
129                };
130                match args.kind {
131                    ExprKind::Empty | ExprKind::Tuple(_) => {}
132                    _ => return Err(args),
133                }
134                let Pattern::Tuple(args) = Pattern::try_from(args)? else {
135                    unreachable!("Arguments should be convertible to pattern!")
136                };
137                Pattern::TupleStruct(path, args)
138            }
139            ExprKind::Binary(Binary { kind: BinaryKind::RangeExc, parts }) => {
140                let (head, tail) = (Pattern::try_from(parts.0)?, Pattern::try_from(parts.1)?);
141                Pattern::RangeExc(head.into(), tail.into())
142            }
143            ExprKind::Binary(Binary { kind: BinaryKind::RangeInc, parts }) => {
144                let (head, tail) = (Pattern::try_from(parts.0)?, Pattern::try_from(parts.1)?);
145                Pattern::RangeInc(head.into(), tail.into())
146            }
147            ExprKind::Unary(Unary { kind: UnaryKind::RangeExc, tail }) => {
148                Pattern::Rest(Some(Pattern::try_from(*tail)?.into()))
149            }
150            ExprKind::Structor(Structor { to, init }) => {
151                let fields = init
152                    .into_iter()
153                    .map(|Fielder { name, init }| {
154                        Ok((name, init.map(|i| Pattern::try_from(*i)).transpose()?))
155                    })
156                    .collect::<Result<_, Self::Error>>()?;
157                Pattern::Struct(to, fields)
158            }
159            _ => Err(value)?,
160        })
161    }
162}