1use std::{convert::Infallible, mem::replace};
4
5use crate::{
6 At, Bind, BindOp, DefaultTypes, Pat, PatOp,
7 fold::{Fold, Foldable, impl_default_fold},
8};
9
10fn take(At(pat, span): &mut At<Pat>) -> At<Pat> {
11 At(replace(pat, Pat::Ignore), *span)
12}
13
14pub fn bubble_types(pat: At<Pat>, in_enum: bool) -> (At<Pat>, Option<At<Pat>>) {
15 let (op, mut pats, span) = match pat {
17 At(Pat::Op(op, pats), span) => (op, pats, span),
18 _ => return (pat, None),
19 };
20
21 match (op, &mut pats[..]) {
22 (PatOp::Typed, [pat, ty]) => {
23 let (value, _ty2) = bubble_types(take(pat), in_enum);
24 (value, Some(take(ty)))
26 }
27 (PatOp::TypePrefixed, [prefix, pat]) => {
28 let (pat, ty) = bubble_types(take(pat), in_enum);
29 let ty = match (ty, in_enum) {
30 (Some(At(ty, span)), false) => {
31 Pat::Op(op, vec![prefix.clone(), ty.at(span)]).at(span)
32 }
33 (Some(At(ty, span)), true) => {
34 Pat::Op(op, vec![Pat::Ignore.at(span), ty.at(span)]).at(span)
35 }
36 (None, _) => prefix.clone(),
37 };
38 let value = Pat::Op(op, vec![take(prefix), pat]).at(span);
39 (value, Some(ty))
40 }
41 (PatOp::MetaInner | PatOp::MetaOuter, [meta, pat]) => {
42 let (value, ty) = bubble_types(take(pat), in_enum);
43 (Pat::Op(op, vec![take(meta), value]).at(span), ty)
44 }
45 (PatOp::Pub | PatOp::Mut | PatOp::Ref | PatOp::Ptr, [pat]) => {
46 let (value, ty) = bubble_types(take(pat), in_enum);
47 (Pat::Op(op, vec![value]).at(span), ty)
48 }
49 (PatOp::Record, ..) => {
50 let (mut values, mut types) = (vec![], vec![]);
51 for At(pat, span) in pats {
52 let (name, body) = bubble_types(pat.at(span), false);
54
55 if in_enum {
57 values.push(body.unwrap_or_else(|| name.clone()));
58 types.push(name);
59 continue;
60 }
61
62 let body = body.unwrap_or(Pat::Ignore.at(name.1));
64 let (body, ty) = bubble_types(body, false);
65 let ty = ty.unwrap_or(Pat::Ignore.at(body.1));
66
67 values.push(Pat::Op(PatOp::Typed, vec![name.clone(), body]).at(span));
68 types.push(Pat::Op(PatOp::Typed, vec![name, ty]).at(span));
69 }
70 let (value, ty) = (Pat::Op(op, values).at(span), Pat::Op(op, types).at(span));
71 (value, Some(ty))
72 }
73 (PatOp::ArRep, [pat, rep]) => {
74 let (pat, ty) = bubble_types(take(pat), in_enum);
75 let ty = ty.unwrap_or(Pat::Ignore.at(pat.1));
76 (
77 Pat::Op(op, vec![pat, Pat::Ignore.at(span)]).at(span),
78 Some(Pat::Op(op, vec![ty, take(rep)]).at(span)),
79 )
80 }
81 (PatOp::Generic, [pat, ..]) => {
82 let (pat, ty) = bubble_types(take(pat), in_enum);
83 pats[0] = ty.unwrap_or(Pat::Ignore.at(pat.1));
84 (pat, Some(Pat::Op(op, pats).at(span)))
85 }
86 (PatOp::Fn, [arg, ret]) => {
87 let (pat, ty) = bubble_types(take(arg), in_enum);
88 let ty = ty.unwrap_or(Pat::Ignore.at(pat.1));
89 (pat, Some(Pat::Op(op, vec![ty, take(ret)]).at(span)))
90 }
91 _ => {
92 let (mut values, mut tys) = (vec![], vec![]);
93 for pat in pats {
94 let (value, ty) = bubble_types(pat, in_enum);
95 tys.push(ty.unwrap_or(Pat::Ignore.at(value.1)));
96 values.push(value);
97 }
98 let (value, ty) = (Pat::Op(op, values).at(span), Pat::Op(op, tys).at(span));
99 (value, Some(ty))
100 }
101 }
102}
103
104#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
110pub struct Bubbler(pub bool);
111
112impl Fold<DefaultTypes, DefaultTypes> for Bubbler {
113 type Error = Infallible;
114 impl_default_fold!(DefaultTypes, DefaultTypes);
115
116 fn fold_at_pat(
117 &mut self,
118 pat: At<Pat<DefaultTypes>, DefaultTypes>,
119 ) -> Result<At<Pat<DefaultTypes>, DefaultTypes>, Self::Error> {
120 Ok(match bubble_types(pat, self.0) {
121 (value @ At(_, span), Some(ty)) => Pat::Op(PatOp::Typed, vec![value, ty]).at(span),
122 (value, None) => value,
123 })
124 }
125
126 fn fold_bind(&mut self, bind: Bind<DefaultTypes>) -> Result<Bind<DefaultTypes>, Self::Error> {
127 let mut bubbler = Bubbler(bind.0 == BindOp::Enum);
128 bind.children(&mut bubbler)
129 }
130}