aboutsummaryrefslogtreecommitdiff
path: root/src/type/conversion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/type/conversion.rs')
-rw-r--r--src/type/conversion.rs54
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)]