aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-14 18:46:07 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-14 18:46:07 +0300
commitc411c568d60246cd995ebf6880f4143e458b605f (patch)
tree1d94592b20436a74fa18f586e0005acc4a6f8c74
parente85dae567589181959683f78a783b6a81fb3d01f (diff)
downloadmyslip-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.rs107
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!(