aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-13 01:20:19 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-13 01:20:19 +0300
commit189d06730ae23770fbb970bf37eb0993edb8cd2d (patch)
tree73048265c57176ba27d2b823e09ebe4c1c7328c1
parentec13c45c8ae0f63fa715178308547cfadd8f8c39 (diff)
downloadmyslip-189d06730ae23770fbb970bf37eb0993edb8cd2d.tar.gz
myslip-189d06730ae23770fbb970bf37eb0993edb8cd2d.zip
feat: generic match arms, mostly for functions I guess?
-rw-r--r--src/type/check.rs14
-rw-r--r--src/type/conversion.rs2
-rw-r--r--src/type/display.rs1
-rw-r--r--src/type/mod.rs2
4 files changed, 13 insertions, 6 deletions
diff --git a/src/type/check.rs b/src/type/check.rs
index 7a2d231..f842b4c 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -216,7 +216,14 @@ impl SExp {
/// };
/// ```
pub fn type_check(&self) -> Result<Type, TypeError> {
- self.infer_type(HashMap::new())
+ let res = self.infer_type(HashMap::new());
+ match res {
+ Ok(res) => match res.is_concrete() {
+ Ok(()) => Ok(res),
+ Err(name) => Err(UnboundGeneric(name)),
+ },
+ e => e,
+ }
}
@@ -305,10 +312,7 @@ impl SExp {
}
match &ty {
None => ty = Some(arm.infer_type(newctx)?),
- Some(t) => if arm.infer_type(newctx.clone())? != *t {
- println!("different types: {}, {}", t, arm.infer_list_type(newctx)?);
- return Err(OtherError);
- },
+ Some(t) => ty = Some(t.least_general_supertype(&arm.infer_type(newctx.clone())?)),
}
}
if !has_wildcard {
diff --git a/src/type/conversion.rs b/src/type/conversion.rs
index 0a96790..5d29ba0 100644
--- a/src/type/conversion.rs
+++ b/src/type/conversion.rs
@@ -30,7 +30,7 @@ impl Type {
self.least_general_supertype(known_as) == *known_as
}
- fn least_general_supertype(&self, other: &Type) -> Type {
+ pub fn least_general_supertype(&self, other: &Type) -> Type {
match (self, other) {
diff --git a/src/type/display.rs b/src/type/display.rs
index 290e24e..56b22b6 100644
--- a/src/type/display.rs
+++ b/src/type/display.rs
@@ -122,6 +122,7 @@ impl fmt::Display for TypeError {
letexp
)
},
+ DifferentTypeCaseArms(ty1, ty2) => write!(f, "arms of match have different types, '{ty1}' and '{ty2}'"),
FunAsAtom => write!(f, "'fn' used as atom doesn't make sense"),
CaseAsAtom => write!(f, "'case' used as atom doesn't make sense"),
RestAsAtom => write!(f, "'..[name]' used as atom doesn't make sense"),
diff --git a/src/type/mod.rs b/src/type/mod.rs
index e979595..06b73ac 100644
--- a/src/type/mod.rs
+++ b/src/type/mod.rs
@@ -79,6 +79,8 @@ pub enum TypeError {
NoWildcardInCase(SExp),
+ DifferentTypeCaseArms(Type, Type),
+
OtherError
}