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

View File

@ -250,7 +250,7 @@ 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 f = match op.get_type() {
Ok(ty) => ty, 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)?; 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> { 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> { fn handle_apply(&mut self, tf: Type, tx: Type) -> InferResult<Type> {
Ok(match tf { Ok(match tf {
Type::Arrow(ref t1, ref t2) => { Type::Arrow(box ref t1, box ref t2) => {
let _ = self.unify(*t1.clone(), tx)?; let _ = self.unify(t1.clone(), tx)?;
*t2.clone() t2.clone()
}, },
_ => return TypeError::new(format!("Not a function")) _ => return TypeError::new(format!("Not a function"))
}) })
@ -348,4 +356,10 @@ mod typechecking_tests {
assert_type_in_fresh_context!("-1", ty!(Int)); 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));
}
} }