Typechecking operators

This commit is contained in:
greg 2019-02-20 03:27:46 -08:00
parent 2be55958f4
commit 03793e08d3
2 changed files with 21 additions and 7 deletions

View File

@ -30,12 +30,12 @@ impl BinOp {
};
Some(BinOp::from_sigil(s))
}
/*
pub fn get_type(&self) -> Result<Type, String> {
let s = self.sigil.as_str();
BINOPS.get(s).map(|x| x.0.clone()).ok_or(format!("Binop {} not found", s))
}
*/
pub fn min_precedence() -> i32 {
i32::min_value()
}

View File

@ -250,7 +250,7 @@ impl<'a> TypeContext<'a> {
fn prefix(&mut self, op: &PrefixOp, expr: &Expression) -> InferResult<Type> {
let f = match op.get_type() {
Ok(ty) => ty,
Err(e) => return TypeError::new("Couldn't find a type for this prefix op")
Err(e) => return TypeError::new(e)
};
let x = self.expr(expr)?;
@ -258,14 +258,22 @@ impl<'a> TypeContext<'a> {
}
fn binexp(&mut self, op: &BinOp, lhs: &Expression, rhs: &Expression) -> InferResult<Type> {
Ok(ty!(Unit))
let tf = match op.get_type() {
Ok(ty) => ty,
Err(e) => return TypeError::new(e),
};
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)
}
fn handle_apply(&mut self, tf: Type, tx: Type) -> InferResult<Type> {
Ok(match tf {
Type::Arrow(ref t1, ref t2) => {
let _ = self.unify(*t1.clone(), tx)?;
*t2.clone()
Type::Arrow(box ref t1, box ref t2) => {
let _ = self.unify(t1.clone(), tx)?;
t2.clone()
},
_ => return TypeError::new(format!("Not a function"))
})
@ -348,4 +356,10 @@ mod typechecking_tests {
assert_type_in_fresh_context!("-1", ty!(Int));
}
#[test]
fn operators() {
assert_type_in_fresh_context!("1 + 2", ty!(Nat));
assert_type_in_fresh_context!("-2", ty!(Int));
assert_type_in_fresh_context!("!true", ty!(Bool));
}
}