Skip to main content

duchess_reflect/
substitution.rs

1use std::iter::FromIterator;
2use std::{collections::BTreeMap, sync::Arc};
3
4use crate::class_info::{ClassRef, Id, RefType, Type};
5
6pub struct Substitution<'s> {
7    map: BTreeMap<&'s Id, &'s RefType>,
8}
9
10impl<'s> FromIterator<(&'s Id, &'s RefType)> for Substitution<'s> {
11    fn from_iter<T: IntoIterator<Item = (&'s Id, &'s RefType)>>(iter: T) -> Self {
12        Substitution {
13            map: iter.into_iter().collect(),
14        }
15    }
16}
17
18pub trait Substitute {
19    fn substitute(&self, subst: &Substitution<'_>) -> Self;
20}
21
22impl Substitute for RefType {
23    fn substitute(&self, subst: &Substitution<'_>) -> Self {
24        match self {
25            RefType::Class(c) => RefType::Class(c.substitute(subst)),
26            RefType::Array(a) => RefType::Array(a.substitute(subst)),
27            RefType::TypeParameter(id) => match subst.map.get(&id) {
28                Some(v) => RefType::clone(v),
29                None => self.clone(),
30            },
31            RefType::Extends(e) => RefType::Extends(e.substitute(subst)),
32            RefType::Super(e) => RefType::Super(e.substitute(subst)),
33            RefType::Wildcard => RefType::Wildcard,
34        }
35    }
36}
37
38impl Substitute for Type {
39    fn substitute(&self, subst: &Substitution<'_>) -> Self {
40        match self {
41            Type::Ref(r) => Type::Ref(r.substitute(subst)),
42            Type::Scalar(_) => self.clone(),
43            Type::Repeat(r) => Type::Repeat(r.substitute(subst)),
44        }
45    }
46}
47
48impl Substitute for ClassRef {
49    fn substitute(&self, subst: &Substitution<'_>) -> Self {
50        let ClassRef { name, generics } = self;
51        ClassRef {
52            name: name.clone(),
53            generics: generics.substitute(subst),
54        }
55    }
56}
57
58impl<F> Substitute for Vec<F>
59where
60    F: Substitute,
61{
62    fn substitute(&self, subst: &Substitution<'_>) -> Self {
63        self.iter().map(|e| e.substitute(subst)).collect()
64    }
65}
66
67impl<F> Substitute for Arc<F>
68where
69    F: Substitute,
70{
71    fn substitute(&self, subst: &Substitution<'_>) -> Self {
72        Arc::new(F::substitute(self, subst))
73    }
74}