Typechecking operators
This commit is contained in:
parent
2be55958f4
commit
03793e08d3
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user