summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2017-11-06 20:49:04 -0500
committerDavid Li <li.davidm96@gmail.com>2017-11-06 20:49:04 -0500
commitb1ef87bc10b662d6e37f929fa86db7a20b44e7dd (patch)
treeb443fea62396032fc656655e0a56b6697bdbbe69
parentd087fd4fb4a1f35dcb40623b22558cefc79b38cc (diff)
Typecheck function declarations
-rw-r--r--src/semantic/translate.rs26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/semantic/translate.rs b/src/semantic/translate.rs
index 7e0d2b8..617c832 100644
--- a/src/semantic/translate.rs
+++ b/src/semantic/translate.rs
@@ -64,8 +64,30 @@ fn trans_decl<'a>(
tenv: &mut TypeEnvironment<'a>,
decl: &WithLocation<ast::Declaration>) -> Result {
match decl.declaration {
- ast::DeclarationBody::Fun { .. } => {
- err!(decl, TypeError::Unimplemented)
+ ast::DeclarationBody::Fun { ref ty, ref params, ref body } => {
+ let declared_ty = if let &Some(ref ty) = ty {
+ Some(ast::WithLocation::new(trans_ty(venv, tenv, &ty)?, ty.start, ty.end))
+ } else { None };
+
+ let mut new_venv = TypeEnvironment::new(Some(venv));
+ let mut new_tenv = TypeEnvironment::new(Some(tenv));
+ for param in params.iter() {
+ let decl_ty = trans_ty(&mut new_venv, &mut new_tenv, &param.ty)?;
+ new_venv.add_binding(param.name.value.clone(), decl_ty);
+ }
+
+ let body_ty = trans_exp(&mut new_venv, &mut new_tenv, &*body)?;
+
+ if let Some(decl_ty) = declared_ty {
+ if &decl_ty.value != &body_ty {
+ return err!(decl_ty, TypeError::Mismatch {
+ expected: decl_ty.value,
+ actual: body_ty,
+ });
+ }
+ }
+
+ Ok(body_ty)
}
ast::DeclarationBody::Ty { ref ty } => {
trans_ty(venv, tenv, ty)