aboutsummaryrefslogtreecommitdiff
path: root/src/bidirectional.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bidirectional.rs')
-rw-r--r--src/bidirectional.rs38
1 files changed, 20 insertions, 18 deletions
diff --git a/src/bidirectional.rs b/src/bidirectional.rs
index 4b34ab2..4e69372 100644
--- a/src/bidirectional.rs
+++ b/src/bidirectional.rs
@@ -26,7 +26,7 @@ impl Context {
},
// Bt-Abs
Expression::Abstraction { param, func } => match target {
- Type::Function { from, to } => {
+ Type::Function(from, to) => {
let mut context = self.clone();
context.insert_term(param, from.default()?);
return context.check(*func, &to);
@@ -65,14 +65,14 @@ impl Context {
},
// Bt-App
Expression::Application { func, arg } => match self.infer(*func)? {
- Type::Function { from, to } => self.check(*arg, &*from).map(|x| *to),
- _ => Err(format!("application abstraction is not a function type").into())
+ Type::Function(from, to) => self.check(*arg, &*from).map(|x| *to),
+ _ => Err("application abstraction is not a function type".into())
},
// inference from an abstraction is always an error
// we could try and infer the func without adding the parameter to scope:
// but this is overwhelmingly likely to be an error, so just report it now.
Expression::Abstraction { param, func } =>
- Err(format!("attempting to infer from an abstraction").into()),
+ Err("attempting to infer from an abstraction".into()),
// idk
Expression::Conditional { if_cond, if_then, if_else } => {
self.check(*if_cond, &Type::Boolean)?;
@@ -91,6 +91,12 @@ impl Context {
/// "is" is a subtype of "of", i.e. "is" can be safely used in any context "of" is expected.
pub fn subtype(&self, is: &Type, of: &Type) -> bool {
match (is, of) {
+ (_, Type::Empty) => true, // top type: every type is a subtype of the empty type (empty as in structurally empty)
+ (Type::Error, _) => true, // bottom type: no type is a subtype of the error type
+ (Type::Natural, Type::Integer) => true, // obviously not, but let's pretend
+ (Type::List(is), Type::Slice(of)) | (Type::Array(is, _), Type::Slice(of)) |
+ (Type::List(is), Type::List(of)) | (Type::Slice(is), Type::Slice(of)) => self.subtype(is, of),
+ (Type::Array(is, is_size), Type::Array(of, of_size)) => self.subtype(is, of) && is_size == of_size,
(Type::Tuple(is_data, is_fields), Type::Tuple(of_data, of_fields)) => {
// length, order, and subtype
if is_data.len() != of_data.len() || is_fields.len() != of_fields.len() {
@@ -131,8 +137,7 @@ impl Context {
}
true
},
- (Type::Function { from: is_from, to: is_to },
- Type::Function { from: of_from, to: of_to }) => {
+ (Type::Function(is_from, is_to), Type::Function(of_from, of_to)) => {
self.subtype(of_from, is_from) && self.subtype(is_to, of_to)
},
(is, Type::Interface(signatures, associated)) => {
@@ -151,12 +156,8 @@ impl Context {
}
true
},
- (Type::List(is), Type::Slice(of)) | (Type::Array(is, _), Type::Slice(of)) |
- (Type::List(is), Type::List(of)) | (Type::Slice(is), Type::Slice(of)) => self.subtype(is, of),
- (Type::Array(is, is_size), Type::Array(of, of_size)) => self.subtype(is, of) && is_size == of_size,
- (Type::Natural, Type::Integer) => true, // obviously not, but let's pretend
- (_, Type::Empty) => true, // top type: every type is a subtype of the empty type (empty as in structurally empty)
- (Type::Error, _) => true, // bottom type: no type is a subtype of the error type
+ (is, Type::Generic(Some(data))) => data.contains(is),
+ (_, Type::Generic(None)) => true,
(_, _) => is == of
}
}
@@ -178,12 +179,13 @@ impl Type {
data.iter().map(|(k, v)| (k.clone(), v.clone().deselfify(replacement))).collect()),
Type::Tuple(data, idents) => Type::Tuple(
data.iter().map(|x| x.clone().deselfify(replacement)).collect(), idents),
- Type::Function { from, to } => Type::Function {
- from: Box::new(from.deselfify(replacement)),
- to: Box::new(to.deselfify(replacement))
- },
- Type::Interface(signatures, associated) =>
- Type::Interface(signatures, associated.map(|x| Box::new(x.deselfify(replacement)))),
+ Type::Function(from, to) => Type::Function(
+ Box::new(from.deselfify(replacement)), Box::new(to.deselfify(replacement))),
+ Type::Interface(signatures, associated) => Type::Interface(signatures,
+ associated.map(|x| Box::new(x.deselfify(replacement)))),
+ Type::Generic(Some(data)) => Type::Generic(
+ Some(data.iter().map(|x| x.clone().deselfify(replacement)).collect())),
+ Type::Generic(None) => Type::Generic(None),
}
}
}