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        TyFn => TyKind::Fn,
47    }
48    impl From for StmtKind {
49        Item => StmtKind::Item,
50        Expr => StmtKind::Expr,
51    }
52    impl From for ExprKind {
53        Let => ExprKind::Let,
54        Closure => ExprKind::Closure,
55        Quote => ExprKind::Quote,
56        Match => ExprKind::Match,
57        Assign => ExprKind::Assign,
58        Modify => ExprKind::Modify,
59        Binary => ExprKind::Binary,
60        Unary => ExprKind::Unary,
61        Cast => ExprKind::Cast,
62        Member => ExprKind::Member,
63        Index => ExprKind::Index,
64        Path => ExprKind::Path,
65        Literal => ExprKind::Literal,
66        Array => ExprKind::Array,
67        ArrayRep => ExprKind::ArrayRep,
68        AddrOf => ExprKind::AddrOf,
69        Block => ExprKind::Block,
70        Group => ExprKind::Group,
71        Tuple => ExprKind::Tuple,
72        While => ExprKind::While,
73        If => ExprKind::If,
74        For => ExprKind::For,
75        Break => ExprKind::Break,
76        Return => ExprKind::Return,
77    }
78    impl From for Literal {
79        bool => Literal::Bool,
80        char => Literal::Char,
81        u128 => Literal::Int,
82        String => Literal::String,
83    }
84}
85
86impl From<Option<Expr>> for Else {
87    fn from(value: Option<Expr>) -> Self {
88        Self { body: value.map(Into::into) }
89    }
90}
91impl From<Expr> for Else {
92    fn from(value: Expr) -> Self {
93        Self { body: Some(value.into()) }
94    }
95}
96
97impl TryFrom<Expr> for Pattern {
98    type Error = Expr;
99
100    /// Performs the conversion. On failure, returns the *first* non-pattern subexpression.
101    fn try_from(value: Expr) -> Result<Self, Self::Error> {
102        Ok(match value.kind {
103            ExprKind::Literal(literal) => Pattern::Literal(literal),
104            ExprKind::Path(Path { absolute: false, ref parts }) => match parts.as_slice() {
105                [PathPart::Ident(name)] => Pattern::Name(*name),
106                _ => Err(value)?,
107            },
108            ExprKind::Empty => Pattern::Tuple(vec![]),
109            ExprKind::Group(Group { expr }) => Pattern::Tuple(vec![Pattern::try_from(*expr)?]),
110            ExprKind::Tuple(Tuple { exprs }) => Pattern::Tuple(
111                exprs
112                    .into_iter()
113                    .map(Pattern::try_from)
114                    .collect::<Result<_, _>>()?,
115            ),
116            ExprKind::AddrOf(AddrOf { mutable, expr }) => {
117                Pattern::Ref(mutable, Box::new(Pattern::try_from(*expr)?))
118            }
119            ExprKind::Array(Array { values }) => Pattern::Array(
120                values
121                    .into_iter()
122                    .map(Pattern::try_from)
123                    .collect::<Result<_, _>>()?,
124            ),
125            ExprKind::Binary(Binary { kind: BinaryKind::Call, parts }) => {
126                let (Expr { kind: ExprKind::Path(path), .. }, args) = *parts else {
127                    return Err(parts.0);
128                };
129                match args.kind {
130                    ExprKind::Empty | ExprKind::Tuple(_) => {}
131                    _ => return Err(args),
132                }
133                let Pattern::Tuple(args) = Pattern::try_from(args)? else {
134                    unreachable!("Arguments should be convertible to pattern!")
135                };
136                Pattern::TupleStruct(path, args)
137            }
138            ExprKind::Binary(Binary { kind: BinaryKind::RangeExc, parts }) => {
139                let (head, tail) = (Pattern::try_from(parts.0)?, Pattern::try_from(parts.1)?);
140                Pattern::RangeExc(head.into(), tail.into())
141            }
142            ExprKind::Binary(Binary { kind: BinaryKind::RangeInc, parts }) => {
143                let (head, tail) = (Pattern::try_from(parts.0)?, Pattern::try_from(parts.1)?);
144                Pattern::RangeInc(head.into(), tail.into())
145            }
146            ExprKind::Unary(Unary { kind: UnaryKind::RangeExc, tail }) => {
147                Pattern::Rest(Some(Pattern::try_from(*tail)?.into()))
148            }
149            ExprKind::Structor(Structor { to, init }) => {
150                let fields = init
151                    .into_iter()
152                    .map(|Fielder { name, init }| {
153                        Ok((name, init.map(|i| Pattern::try_from(*i)).transpose()?))
154                    })
155                    .collect::<Result<_, Self::Error>>()?;
156                Pattern::Struct(to, fields)
157            }
158            _ => Err(value)?,
159        })
160    }
161}