Refactor Arrow; add general handle_apply
This commit is contained in:
parent
b709cfd51a
commit
0e9b3229e9
@ -49,7 +49,10 @@ impl TypeError {
|
|||||||
pub enum Type {
|
pub enum Type {
|
||||||
Const(TypeConst),
|
Const(TypeConst),
|
||||||
Var(TypeVar),
|
Var(TypeVar),
|
||||||
Arrow(Box<Type>, Box<Type>),
|
Arrow {
|
||||||
|
params: Vec<Type>,
|
||||||
|
ret: Box<Type>
|
||||||
|
},
|
||||||
Compound {
|
Compound {
|
||||||
ty_name: String,
|
ty_name: String,
|
||||||
args:Vec<Type>
|
args:Vec<Type>
|
||||||
@ -82,8 +85,8 @@ impl EqUnifyValue for TypeConst { }
|
|||||||
|
|
||||||
macro_rules! ty {
|
macro_rules! ty {
|
||||||
($type_name:ident) => { Type::Const(TypeConst::$type_name) };
|
($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) => { Type::Arrow { params: vec![ty!($t1)], ret: box ty!($t2) } };
|
||||||
($t1:ident -> $t2:ident -> $t3:ident) => { Type::Arrow(Box::new(ty!($t1)), Box::new(ty!($t2 -> $t3))) };
|
($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
|
//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> {
|
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,
|
Ok(ty) => ty,
|
||||||
Err(e) => return TypeError::new(e)
|
Err(e) => return TypeError::new(e)
|
||||||
};
|
};
|
||||||
|
|
||||||
let x = self.expr(expr)?;
|
let tx = self.expr(expr)?;
|
||||||
self.handle_apply(f, x)
|
self.handle_apply(tf, vec![tx])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> InferResult<Type> {
|
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_lhs = self.expr(lhs)?;
|
||||||
let t_curried = self.handle_apply(tf, t_lhs)?;
|
let t_rhs = self.expr(rhs)?; //TODO is this order a problem? not sure
|
||||||
let t_rhs = self.expr(rhs)?;
|
|
||||||
self.handle_apply(t_curried, t_rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_apply(&mut self, tf: Type, tx: Type) -> InferResult<Type> {
|
self.handle_apply(tf, vec![t_lhs, t_rhs])
|
||||||
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"))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn if_expr(&mut self, discriminator: &Discriminator, body: &IfExpressionBody) -> InferResult<Type> {
|
fn if_expr(&mut self, discriminator: &Discriminator, body: &IfExpressionBody) -> InferResult<Type> {
|
||||||
@ -352,6 +345,19 @@ impl<'a> TypeContext<'a> {
|
|||||||
Ok(ty!(UserDefined))
|
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> {
|
fn block(&mut self, block: &Block) -> InferResult<Type> {
|
||||||
let mut output = ty!(Unit);
|
let mut output = ty!(Unit);
|
||||||
for s in block.iter() {
|
for s in block.iter() {
|
||||||
|
Loading…
Reference in New Issue
Block a user