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