Refactor Arrow; add general handle_apply
This commit is contained in:
parent
b709cfd51a
commit
0e9b3229e9
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user