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.rs55
1 files changed, 50 insertions, 5 deletions
diff --git a/src/type/conversion.rs b/src/type/conversion.rs
index 128d1aa..a819409 100644
--- a/src/type/conversion.rs
+++ b/src/type/conversion.rs
@@ -1,5 +1,5 @@
-use crate::r#type::Type;
+use crate::r#type::{Type, Type::*, util::*};
impl Type {
@@ -27,11 +27,48 @@ impl Type {
/// assert!(!List(vec![Integer, Boolean]).aka(&vecof(Boolean)));
/// ```
pub fn aka(&self, known_as: &Type) -> bool {
- todo!()
+ self.least_general_supertype(known_as) == *known_as
}
fn least_general_supertype(&self, other: &Type) -> Type {
- todo!()
+
+ match (self, other) {
+
+ (a, b) if a == b => a.clone(),
+
+ (VecOf(a), VecOf(b)) => vecof(a.least_general_supertype(b)),
+
+ (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)
+ },
+
+ (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")
+ },
+
+ (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))
+ ),
+
+
+ _ => vt("T")
+
+ }
+
}
}
@@ -44,8 +81,16 @@ mod tests {
#[test]
fn test_basic_general_supertypes() {
- assert_eq!(Integer.least_general_supertype(&Integer), Integer);
- assert_eq!(Integer.least_general_supertype(&Boolean), vt("T"));
+ assert_eq!(
+ Integer.least_general_supertype(&Integer),
+ Integer,
+ "if two types are equal, they get the same supertype"
+ );
+ assert_eq!(
+ Integer.least_general_supertype(&Boolean),
+ vt("T"),
+ "if two types have nothing in common, vt(\"t\") is returned"
+ );
}