use crate::ns::*;
pub struct TypeSubstitution<'a>(pub &'a SemanticHost);
impl<'a> TypeSubstitution<'a> {
pub fn exec(&mut self, thing: &Thingy, type_params: &SharedArray<Thingy>, substitute_types: &SharedArray<Thingy>) -> Thingy {
if thing.is::<UnresolvedThingy>() {
return thing.clone();
} else if thing.is::<Type>() {
if thing.is::<FunctionType>() {
let result_type = thing.result_type().type_substitution(self.0, type_params, substitute_types);
let mut params: Vec<Rc<SemanticFunctionTypeParameter>> = 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::<NullableType>() {
let base = &thing.base().type_substitution(self.0, type_params, substitute_types);
return self.0.factory().create_nullable_type(base);
} else if thing.is::<NonNullableType>() {
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::<TupleType>() {
let el: Vec<Thingy> = 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::<TypeAfterSubstitution>() {
let new_substitute_types: SharedArray<Thingy> = 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::<TypeParameterType>() {
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::<VariableSlot>() {
self.0.factory().create_variable_slot_after_substitution(thing, type_params, substitute_types)
} else if thing.is::<VirtualSlot>() {
self.0.factory().create_virtual_slot_after_substitution(thing, type_params, substitute_types)
} else if thing.is::<MethodSlot>() {
self.0.factory().create_method_slot_after_substitution(thing, type_params, substitute_types)
} else {
panic!()
}
}
}