use crate::ns::*; /// Type substitution. /// /// In the present, the Compiler codebase is able to perform type substitution on a limited /// set of things and panics for unsupported things: /// /// * Types /// * Classes and interfaces are not substituted by `TypeSubstitution`, but may be in a future version. /// * `UnresolvedThingy` is returned as is /// * Variable slots /// * Virtual slots /// * Method slots /// /// In the future, type substitution may expand to other things if necessary. pub struct TypeSubstitution<'a>(pub &'a SemanticHost); impl<'a> TypeSubstitution<'a> { pub fn exec(&mut self, thing: &Thingy, type_params: &SharedArray, substitute_types: &SharedArray) -> Thingy { if thing.is::() || thing.is::() { return thing.clone(); } else if thing.is::() { if thing.is::() { let result_type = thing.result_type().type_substitution(self.0, type_params, substitute_types); let mut params: Vec> = Vec::new(); for param in thing.params().iter() { params.push(Rc::new(param.type_substitution(self.0, type_params, substitute_types))); } return self.0.factory().create_function_type(params, result_type); } else if thing.is::() { let base = &thing.base().type_substitution(self.0, type_params, substitute_types); return self.0.factory().create_nullable_type(base); } else if thing.is::() { let base = &thing.base().type_substitution(self.0, type_params, substitute_types); return self.0.factory().create_non_nullable_type(base); } else if thing.is::() { let el: Vec = thing.element_types().iter().map(|t| t.type_substitution(self.0, type_params, substitute_types)).collect(); return self.0.factory().create_tuple_type(el); } else if thing.is::() { let new_substitute_types: SharedArray = thing.substitute_types().iter().map(|t| t.type_substitution(self.0, type_params, substitute_types)).collect(); return self.0.factory().create_type_after_substitution(&thing.origin(), &new_substitute_types); } else if thing.is::() { let i = type_params.index_of(&thing); if let Some(i) = i { return substitute_types.get(i).unwrap(); } } return thing.clone(); } else if thing.is::() { self.0.factory().create_variable_slot_after_substitution(thing, type_params, substitute_types) } else if thing.is::() { self.0.factory().create_virtual_slot_after_substitution(thing, type_params, substitute_types) } else if thing.is::() { self.0.factory().create_method_slot_after_substitution(thing, type_params, substitute_types) } else { panic!() } } }