diff options
author | David Li <li.davidm96@gmail.com> | 2017-11-06 20:49:04 -0500 |
---|---|---|
committer | David Li <li.davidm96@gmail.com> | 2017-11-06 20:49:04 -0500 |
commit | b1ef87bc10b662d6e37f929fa86db7a20b44e7dd (patch) | |
tree | b443fea62396032fc656655e0a56b6697bdbbe69 | |
parent | d087fd4fb4a1f35dcb40623b22558cefc79b38cc (diff) |
Typecheck function declarations
-rw-r--r-- | src/semantic/translate.rs | 26 |
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, ¶m.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) |