Refactor Arrow; add general handle_apply

This commit is contained in:
greg 2019-02-23 03:33:56 -08:00
parent b709cfd51a
commit 0e9b3229e9
1 changed files with 24 additions and 18 deletions

View File

@ -49,7 +49,10 @@ impl TypeError {
pub enum Type {
Const(TypeConst),
Var(TypeVar),
Arrow(Box<Type>, Box<Type>),
Arrow {
params: Vec<Type>,
ret: Box<Type>
},
Compound {
ty_name: String,
args:Vec<Type>
@ -82,8 +85,8 @@ impl EqUnifyValue for TypeConst { }
macro_rules! ty {
($type_name:ident) => { Type::Const(TypeConst::$type_name) };
($t1:ident -> $t2:ident) => { Type::Arrow(Box::new(ty!($t1)), Box::new(ty!($t2))) };
($t1:ident -> $t2:ident -> $t3:ident) => { Type::Arrow(Box::new(ty!($t1)), Box::new(ty!($t2 -> $t3))) };
($t1:ident -> $t2:ident) => { Type::Arrow { params: vec![ty!($t1)], ret: box ty!($t2) } };
($t1:ident -> $t2:ident -> $t3:ident) => { Type::Arrow { params: vec![ty!($t1), ty!($t2)], ret: box ty!($t3) } };
}
//TODO find a better way to capture the to/from string logic
@ -281,13 +284,13 @@ impl<'a> TypeContext<'a> {
}
fn prefix(&mut self, op: &PrefixOp, expr: &Expression) -> InferResult<Type> {
let f = match op.get_type() {
let tf = match op.get_type() {
Ok(ty) => ty,
Err(e) => return TypeError::new(e)
};
let x = self.expr(expr)?;
self.handle_apply(f, x)
let tx = self.expr(expr)?;
self.handle_apply(tf, vec![tx])
}
fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> InferResult<Type> {
@ -297,19 +300,9 @@ impl<'a> TypeContext<'a> {
};
let t_lhs = self.expr(lhs)?;
let t_curried = self.handle_apply(tf, t_lhs)?;
let t_rhs = self.expr(rhs)?;
self.handle_apply(t_curried, t_rhs)
}
let t_rhs = self.expr(rhs)?; //TODO is this order a problem? not sure
fn handle_apply(&mut self, tf: Type, tx: Type) -> InferResult<Type> {
Ok(match tf {
Type::Arrow(box ref t1, box ref t2) => {
let _ = self.unify(t1.clone(), tx)?;
t2.clone()
},
_ => return TypeError::new(format!("Not a function"))
})
self.handle_apply(tf, vec![t_lhs, t_rhs])
}
fn if_expr(&mut self, discriminator: &Discriminator, body: &IfExpressionBody) -> InferResult<Type> {
@ -352,6 +345,19 @@ impl<'a> TypeContext<'a> {
Ok(ty!(UserDefined))
}
fn handle_apply(&mut self, tf: Type, args: Vec<Type>) -> InferResult<Type> {
Ok(match tf {
Type::Arrow { ref params, ret: box ref t_ret } if params.len() == args.len() => {
for (t_param, t_arg) in params.iter().zip(args.iter()) {
let _ = self.unify(t_param.clone(), t_arg.clone())?; //TODO I think this needs to reference a sub-scope
}
t_ret.clone()
},
Type::Arrow { .. } => return TypeError::new("Wrong length"),
_ => return TypeError::new(format!("Not a function"))
})
}
fn block(&mut self, block: &Block) -> InferResult<Type> {
let mut output = ty!(Unit);
for s in block.iter() {