aboutsummaryrefslogtreecommitdiff
path: root/src/type/conversion.rs
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-16 02:04:09 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-16 02:04:09 +0300
commite35522189f5217987bc455d70c3b9056541ef8c6 (patch)
tree421bcca16938157268eb9bcd4ea181ce0d099133 /src/type/conversion.rs
parenta97fef6f099767924c5203782a2b04b1a559ac6b (diff)
downloadmyslip-e35522189f5217987bc455d70c3b9056541ef8c6.tar.gz
myslip-e35522189f5217987bc455d70c3b9056541ef8c6.zip
feat: type conversion from (Vec/Quote X) -> X and add vec/quote to rest pattern substitutions
Diffstat (limited to 'src/type/conversion.rs')
-rw-r--r--src/type/conversion.rs94
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!(