diff options
author | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-14 18:46:07 +0300 |
---|---|---|
committer | Joel Kronqvist <joel.kronqvist@iki.fi> | 2025-08-14 18:46:07 +0300 |
commit | c411c568d60246cd995ebf6880f4143e458b605f (patch) | |
tree | 1d94592b20436a74fa18f586e0005acc4a6f8c74 | |
parent | e85dae567589181959683f78a783b6a81fb3d01f (diff) | |
download | myslip-c411c568d60246cd995ebf6880f4143e458b605f.tar.gz myslip-c411c568d60246cd995ebf6880f4143e458b605f.zip |
fix: made conversion work according to updated tests:
* implemented conversion of arrow types
* fixed (Int Bool) into (T T) succeeding
* now vectors have to be of one type only even if generic
* maybe something else too
-rw-r--r-- | src/type/conversion.rs | 107 |
1 files changed, 81 insertions, 26 deletions
diff --git a/src/type/conversion.rs b/src/type/conversion.rs index d0bc1dd..36e2038 100644 --- a/src/type/conversion.rs +++ b/src/type/conversion.rs @@ -1,5 +1,6 @@ use crate::r#type::{Type, Type::*, util::*}; +use std::collections::HashMap; impl Type { @@ -7,7 +8,7 @@ impl Type { /// ie. checks if there exists an implicit conversion from /// one to the other. /// - /// Currently this is only needed for list to vec conversions. + /// This is needed for list to vec conversions. /// ```rust /// use myslip::r#type::{Type::*, util::*}; /// assert!(List(vec![Integer, Integer, Integer]).aka(&vecof(Integer))); @@ -54,43 +55,91 @@ impl Type { } pub fn least_general_supertype(&self, other: &Type) -> Type { + let (ty, ctx) = self.lgst_ctx(other, Vec::new()); + let mut checks = HashMap::new(); + for (name, ty1) in ctx { + if let Some(ty2) = checks.insert(name, ty1.clone()) { + if ty2 != ty1 { + return vt("?"); + } + } + } + ty + } + + fn lgst_ctx( + &self, + other: &Type, + mut ctx: Vec<(String, Type)> + ) -> (Type, Vec<(String, Type)>) { match (self, other) { - (a, b) if a == b => a.clone(), + (a, b) if a == b => (a.clone(), ctx), - (List(v), b) if v.len() == 1 && &v[0] == b => b.clone(), + (a, VarType(name)) => { + ctx.push((name.clone(), a.clone())); + (vt(name), ctx) + }, - (VecOf(a), VecOf(b)) => vecof(a.least_general_supertype(b)), + (Arrow(a1, a2), Arrow(b1, b2)) => { + let (t1, newctx) = a1.lgst_ctx(b1, ctx); + ctx = newctx; + let (t2, newctx) = a2.lgst_ctx(b2, ctx); + ctx = newctx; + (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![]; - for (a, b) in v1.into_iter().zip(v2) { - res.push(a.least_general_supertype(b)); - } - List(res) + let mut res = vec![]; + for (a, b) in v1.into_iter().zip(v2) { + let (ty, newctx) = a.lgst_ctx(b, ctx.clone()); + res.push(ty); + ctx = newctx; + } + (List(res), ctx) }, (List(v1), List(v2)) => match v1.get(0).or(v2.get(0)) { - Some(first) => vecof( - v1.into_iter() - .chain(v2) - .fold(first.clone(), |a, b| a.least_general_supertype(b)) - ), - None => panic!("unreachable - types would be equal") + Some(first) => { + let mut res = first.clone(); + for ty in v1.into_iter().chain(v2) { + let (ty, newctx) = res.lgst_ctx(ty, ctx.clone()); + res = ty; + ctx = newctx; + } + (vecof(res), ctx) + }, + None => panic!("unreachable - types would be equal") }, - (List(v), VecOf(b)) => vecof( - v.into_iter() - .fold(*b.clone(), |a, b| a.least_general_supertype(b)) - ), - (VecOf(b), List(v)) => vecof( - v.into_iter() - .fold(*b.clone(), |a, b| a.least_general_supertype(b)) - ), + (List(v), VecOf(b)) => { + let mut res = *b.clone(); + for ty in v { + let (ty, newctx) = res.lgst_ctx(ty, ctx.clone()); + res = ty; + ctx = newctx; + } + (vecof(res), ctx) + }, + (VecOf(b), List(v)) => { + let mut res = *b.clone(); + for ty in v { + let (ty, newctx) = res.lgst_ctx(ty, ctx.clone()); + res = ty; + ctx = newctx; + } + (vecof(res), ctx) + }, + (List(v), b) if v.len() == 1 && *&v[0].aka(b) => (b.clone(), ctx), - _ => vt("T") + _ => (vt("T"), ctx) } @@ -172,7 +221,11 @@ impl Type { (_, VarType(_)) => Ok(self), - (List(x), b) if x.len() == 1 && &x[0] == b => Ok(x[0].clone()), + (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(v1), List(v2)) if v1.len() == v2.len() => { let mut res = vec![]; @@ -198,6 +251,8 @@ impl Type { Err(()) }, }, + + (List(x), b) if x.len() == 1 && *&x[0].aka(b) => Ok(x[0].clone()), _ => Err(()) @@ -259,7 +314,7 @@ mod tests { .least_general_supertype( &vecof(Boolean) ), - vecof(vt("T")) + vt("T") ); assert_eq!( |