diff options
Diffstat (limited to 'src/type/conversion.rs')
-rw-r--r-- | src/type/conversion.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/type/conversion.rs b/src/type/conversion.rs index a819409..3be2874 100644 --- a/src/type/conversion.rs +++ b/src/type/conversion.rs @@ -71,6 +71,60 @@ impl Type { } + /// Tries to convert this type into a subtype of the other. + /// + /// ```rust + /// use myslip::r#type::{Type::*, util::*}; + /// + /// assert_eq!(Integer.into_type(&Boolean), Err(())); + /// assert_eq!(Integer.into_type(&Integer), Ok(Integer)); + /// assert_eq!(Integer.into_type(&vt("T")), Ok(Integer)); + /// assert_eq!( + /// List(vec![Integer, Integer]).into_type(&vecof(Integer)), + /// Ok(vecof(Integer)) + /// ); + /// assert_eq!( + /// List(vec![Integer, Integer]).into_type(&vecof(vt("T"))), + /// Ok(vecof(Integer)) + /// ); + /// assert_eq!( + /// List(vec![Integer, Boolean]).into_type(&vecof(vt("T"))), + /// Ok(vecof(vt("T"))) + /// ); + /// ``` + pub fn into_type(self, other: &Type) -> Result<Type, ()> { + if !self.aka(other) { + return Err(()); + } + + match (&self, other) { + + (a, b) if a == b => Ok(self), + + (_, VarType(_)) => Ok(self), + + (List(v), VecOf(b)) => match v.get(0) { + Some(first) => { + let cand = v.into_iter() + .fold(first.clone(), |a, b| a.least_general_supertype(b)); + if cand.aka(b) { + Ok(vecof(cand)) + } else { + Err(()) + } + }, + None => if NilType.aka(b) { + Ok(vecof(NilType)) + } else { + Err(()) + }, + }, + + _ => Err(()) + + } + } + } #[cfg(test)] |