diff options
Diffstat (limited to 'src/type/conversion.rs')
-rw-r--r-- | src/type/conversion.rs | 94 |
1 files changed, 85 insertions, 9 deletions
diff --git a/src/type/conversion.rs b/src/type/conversion.rs index 36e2038..37ebc46 100644 --- a/src/type/conversion.rs +++ b/src/type/conversion.rs @@ -21,6 +21,18 @@ impl Type { /// assert!(List(vec![Boolean, Boolean, Boolean]).aka(&vecof(vt("T")))); /// ``` /// + /// Also, because quotes and vectors have their operators hanging + /// with them, having a conversion (Vector/Quote X) -> X is convenient. + /// ```rust + /// use myslip::r#type::{Type::*, util::*}; + /// assert!( + /// List(vec![QuoteTy, List(vec![Integer, Integer])]).aka(&vecof(Integer)), + /// ); + /// assert!( + /// List(vec![List(vec![QuoteTy, List(vec![Integer, Integer])])]).aka(&vecof(Integer)), + /// ); + /// ``` + /// /// But of course it also should know when to fail: /// ```rust /// use myslip::r#type::{Type::*, util::*}; @@ -82,6 +94,18 @@ impl Type { (vt(name), ctx) }, + (List(v), b) if v.len() == 1 && *&v[0].aka(b) => (b.clone(), ctx), + + (List(v1), x) if !x.is_quoted_or_vectored_list() + && (v1.get(0) == Some(&VecType) || v1.get(0) == Some(&QuoteTy)) + && v1.get(1) != None => + { + match (v1.get(1), x) { + (Some(a), b) => a.lgst_ctx(&b, ctx), + _ => panic!("unreachable") + } + }, + (Arrow(a1, a2), Arrow(b1, b2)) => { let (t1, newctx) = a1.lgst_ctx(b1, ctx); ctx = newctx; @@ -90,10 +114,6 @@ impl Type { (arr(t1, t2), ctx) }, - //(VecOf(a), VecOf(b)) => { - // let (res, ctx) = a.lgst_ctx(b, ctx); - // (vecof(res), ctx) - //}, (List(v1), List(v2)) if v1.len() == v2.len() => { let mut res = vec![]; @@ -137,8 +157,6 @@ impl Type { (vecof(res), ctx) }, - (List(v), b) if v.len() == 1 && *&v[0].aka(b) => (b.clone(), ctx), - _ => (vt("T"), ctx) } @@ -176,6 +194,20 @@ impl Type { /// assert_eq!(List(vec![Integer]).into_type(&Integer), Ok(Integer)); /// ``` /// + /// Also, because quotes and vectors have their operators hanging + /// with them, having a conversion (Vector/Quote X) -> X is convenient. + /// ```rust + /// use myslip::r#type::{Type::*, util::*}; + /// assert_eq!( + /// List(vec![VecType, vecof(Integer)]).into_type(&vecof(Integer)), + /// Ok(vecof(Integer)) + /// ); + /// assert_eq!( + /// List(vec![List(vec![VecType, vecof(Integer)])]).into_type(&vecof(Integer)), + /// Ok(vecof(Integer)) + /// ); + /// ``` + /// /// Now this also needs to be able to hand generics: /// ```rust /// use myslip::r#type::{Type::*, util::*}; @@ -221,19 +253,28 @@ impl Type { (_, VarType(_)) => Ok(self), + (List(x), b) if x.len() == 1 && *&x[0].aka(b) => Ok(x[0].clone().into_type(b)?), + (Arrow(a1, a2), Arrow(b1, b2)) => { let t1 = a1.clone().into_type(b1)?; let t2 = a2.clone().into_type(b2)?; Ok(arr(t1, t2)) }, + (List(v), x) if !x.is_quoted_or_vectored_list() + && (v.get(0) == Some(&VecType) || v.get(0) == Some(&QuoteTy)) + && v.get(1) != None => + { + v[1].clone().into_type(x) + }, + (List(v1), List(v2)) if v1.len() == v2.len() => { let mut res = vec![]; for (t1, t2) in v1.into_iter().zip(v2) { res.push(t1.clone().into_type(&t2)?); } Ok(List(res)) - } + }, (List(v), VecOf(b)) => match v.get(0) { Some(first) => { @@ -251,8 +292,6 @@ impl Type { Err(()) }, }, - - (List(x), b) if x.len() == 1 && *&x[0].aka(b) => Ok(x[0].clone()), _ => Err(()) @@ -327,6 +366,43 @@ mod tests { } #[test] + fn test_removing_quote_and_vec() { + assert_eq!( + List(vec![List(vec![VecType, NilType])]).least_general_supertype(&NilType), + NilType + ); + assert_eq!( + List(vec![VecType, NilType]).least_general_supertype(&NilType), + NilType + ); + assert_eq!( + List(vec![QuoteTy, NilType]).least_general_supertype(&NilType), + NilType + ); + assert_eq!( + List(vec![VecType, vecof(Boolean)]) + .least_general_supertype( + &vecof(Boolean) + ), + vecof(Boolean) + ); + assert_eq!( + List(vec![List(vec![VecType, vecof(Boolean)])]) + .least_general_supertype( + &vecof(Boolean) + ), + vecof(Boolean) + ); + assert_eq!( + List(vec![QuoteTy, List(vec![Integer, Boolean])]) + .least_general_supertype( + &List(vec![Integer, Boolean]) + ), + List(vec![Integer, Boolean]) + ); + } + + #[test] fn test_conversion_in_general_supertypes() { assert_eq!( |