tinymist_analysis/ty/
mutate.rs

1use crate::ty::def::*;
2
3/// A trait to mutate a type.
4pub trait TyMutator {
5    /// Mutates the given type.
6    fn mutate(&mut self, ty: &Ty, pol: bool) -> Option<Ty> {
7        self.mutate_rec(ty, pol)
8    }
9
10    /// Mutates the given type recursively.
11    fn mutate_rec(&mut self, ty: &Ty, pol: bool) -> Option<Ty> {
12        use Ty::*;
13        match ty {
14            Value(..) | Any | Boolean(..) | Builtin(..) => None,
15            Union(v) => Some(Union(self.mutate_vec(v, pol)?)),
16            Var(..) | Let(..) => None,
17            Array(arr) => Some(Array(self.mutate(arr, pol)?.into())),
18            Dict(dict) => Some(Dict(self.mutate_record(dict, pol)?.into())),
19            Tuple(tup) => Some(Tuple(self.mutate_vec(tup, pol)?)),
20            Func(func) => Some(Func(self.mutate_func(func, pol)?.into())),
21            Args(args) => Some(Args(self.mutate_func(args, pol)?.into())),
22            Pattern(pat) => Some(Pattern(self.mutate_func(pat, pol)?.into())),
23            Param(param) => Some(Param(self.mutate_param(param, pol)?.into())),
24            Select(sel) => Some(Select(self.mutate_select(sel, pol)?.into())),
25            With(sig) => Some(With(self.mutate_with_sig(sig, pol)?.into())),
26            Unary(unary) => Some(Unary(self.mutate_unary(unary, pol)?.into())),
27            Binary(binary) => Some(Binary(self.mutate_binary(binary, pol)?.into())),
28            If(if_expr) => Some(If(self.mutate_if(if_expr, pol)?.into())),
29        }
30    }
31
32    /// Mutates the given vector of types.
33    fn mutate_vec(&mut self, ty: &[Ty], pol: bool) -> Option<Interned<Vec<Ty>>> {
34        let mut mutated = false;
35
36        let mut types = Vec::with_capacity(ty.len());
37        for ty in ty.iter() {
38            match self.mutate(ty, pol) {
39                Some(ty) => {
40                    types.push(ty);
41                    mutated = true;
42                }
43                None => types.push(ty.clone()),
44            }
45        }
46
47        if mutated { Some(types.into()) } else { None }
48    }
49
50    /// Mutates the given option of type.
51    fn mutate_option(&mut self, ty: Option<&Ty>, pol: bool) -> Option<Option<Ty>> {
52        match ty {
53            Some(ty) => self.mutate(ty, pol).map(Some),
54            None => None,
55        }
56    }
57
58    /// Mutates the given function signature.
59    fn mutate_func(&mut self, ty: &Interned<SigTy>, pol: bool) -> Option<SigTy> {
60        let types = self.mutate_vec(&ty.inputs, pol);
61        let ret = self.mutate_option(ty.body.as_ref(), pol);
62
63        if types.is_none() && ret.is_none() {
64            return None;
65        }
66
67        let sig = ty.as_ref().clone();
68        let types = types.unwrap_or_else(|| ty.inputs.clone());
69        let ret = ret.unwrap_or_else(|| ty.body.clone());
70        Some(SigTy {
71            inputs: types,
72            body: ret,
73            ..sig
74        })
75    }
76
77    /// Mutates the given parameter type.
78    fn mutate_param(&mut self, param: &Interned<ParamTy>, pol: bool) -> Option<ParamTy> {
79        let ty = self.mutate(&param.ty, pol)?;
80        let mut param = param.as_ref().clone();
81        param.ty = ty;
82        Some(param)
83    }
84
85    /// Mutates the given record type.
86    fn mutate_record(&mut self, record: &Interned<RecordTy>, pol: bool) -> Option<RecordTy> {
87        let types = self.mutate_vec(&record.types, pol)?;
88
89        let rec = record.as_ref().clone();
90        Some(RecordTy { types, ..rec })
91    }
92
93    /// Mutates the given function signature with type.
94    fn mutate_with_sig(&mut self, ty: &Interned<SigWithTy>, pol: bool) -> Option<SigWithTy> {
95        let sig = self.mutate(ty.sig.as_ref(), pol);
96        let with = self.mutate_func(&ty.with, pol);
97
98        if sig.is_none() && with.is_none() {
99            return None;
100        }
101
102        let sig = sig.map(Interned::new).unwrap_or_else(|| ty.sig.clone());
103        let with = with.map(Interned::new).unwrap_or_else(|| ty.with.clone());
104
105        Some(SigWithTy { sig, with })
106    }
107
108    /// Mutates the given unary type.
109    fn mutate_unary(&mut self, ty: &Interned<TypeUnary>, pol: bool) -> Option<TypeUnary> {
110        let lhs = self.mutate(&ty.lhs, pol)?;
111
112        Some(TypeUnary { lhs, op: ty.op })
113    }
114
115    /// Mutates the given binary type.
116    fn mutate_binary(&mut self, ty: &Interned<TypeBinary>, pol: bool) -> Option<TypeBinary> {
117        let (lhs, rhs) = &ty.operands;
118
119        let x = self.mutate(lhs, pol);
120        let y = self.mutate(rhs, pol);
121
122        if x.is_none() && y.is_none() {
123            return None;
124        }
125
126        let lhs = x.unwrap_or_else(|| lhs.clone());
127        let rhs = y.unwrap_or_else(|| rhs.clone());
128
129        Some(TypeBinary {
130            operands: (lhs, rhs),
131            op: ty.op,
132        })
133    }
134
135    /// Mutates the given if type.
136    fn mutate_if(&mut self, ty: &Interned<IfTy>, pol: bool) -> Option<IfTy> {
137        let cond = self.mutate(ty.cond.as_ref(), pol);
138        let then = self.mutate(ty.then.as_ref(), pol);
139        let else_ = self.mutate(ty.else_.as_ref(), pol);
140
141        if cond.is_none() && then.is_none() && else_.is_none() {
142            return None;
143        }
144
145        let cond = cond.map(Interned::new).unwrap_or_else(|| ty.cond.clone());
146        let then = then.map(Interned::new).unwrap_or_else(|| ty.then.clone());
147        let else_ = else_.map(Interned::new).unwrap_or_else(|| ty.else_.clone());
148
149        Some(IfTy { cond, then, else_ })
150    }
151
152    /// Mutates the given select type.
153    fn mutate_select(&mut self, ty: &Interned<SelectTy>, pol: bool) -> Option<SelectTy> {
154        let target = self.mutate(ty.ty.as_ref(), pol)?.into();
155
156        Some(SelectTy {
157            ty: target,
158            select: ty.select.clone(),
159        })
160    }
161}
162
163impl<T> TyMutator for T
164where
165    T: FnMut(&Ty, bool) -> Option<Ty>,
166{
167    fn mutate(&mut self, ty: &Ty, pol: bool) -> Option<Ty> {
168        self(ty, pol)
169    }
170}
171
172impl Ty {
173    /// Mutates the given type.
174    pub fn mutate(&self, pol: bool, checker: &mut impl TyMutator) -> Option<Ty> {
175        checker.mutate(self, pol)
176    }
177}