From 54da96eca49db7721ec981099a64779996be8483 Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Thu, 17 Sep 2020 00:55:50 +0200 Subject: [PATCH] check call --- src/ast.rs | 1 - src/check.rs | 94 +++++++++++++++++++++++++++++----------------------- src/env.rs | 1 - 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 0b8b2d3..465fbf8 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -47,7 +47,6 @@ pub struct Param { pub id: Id, pub ty: Type, } -// pub bool, pub Id, pub Type); #[derive(Debug, PartialEq)] pub enum TypeDecl { diff --git a/src/check.rs b/src/check.rs index 0fe868d..8aed07b 100644 --- a/src/check.rs +++ b/src/check.rs @@ -98,43 +98,44 @@ fn expr_type( // Err(format!("op {} rt {}", opt, rt)) // } // } - // Call(s, args) => { - // trace!("call {} with {}", s, args); - - // let argt: Vec<Type> = args - // .clone() - // .0 - // .into_iter() - // .map(|e| expr_type(&*e, fn_env, type_env, var_env)) - // .collect::<Result<_, _>>()?; - - // trace!("arg types {:?}", argt); - // let f = match fn_env.get(s.as_str()) { - // Some(f) => f, - // None => Err(format!("{} not found", s))?, - // }; - - // let part: Vec<Type> = (f.params.0.clone()) - // .into_iter() - // .map(|p| From::from(&p)) - // .collect(); - - // trace!( - // "fn to call {} with params {} and types {:?}", - // f, - // f.params, - // part - // ); - - // if argt == part { - // Ok((false, f.result.clone())) - // } else { - // Err(format!( - // "arguments types {:?} does not match parameter types {:?}", - // argt, part - // )) - // } - // } + Call(s, args) => { + trace!("call {} with {}", s, args); + + let arg_t: Vec<Type> = args + .clone() + .0 + .into_iter() + .map(|e| expr_type(&*e, fn_env, type_env, var_env)) + .collect::<Result<_, _>>()?; + + trace!("arg types {:?}", arg_t); + let f = match fn_env.get(s.as_str()) { + Some(f) => f, + None => Err(format!("{} not found", s))?, + }; + + let par_t: Vec<Type> = (f.params.0.clone()) + .into_iter() + .map(|p| From::from(&p)) + .collect(); + + trace!( + "fn to call {} with params {} and types {:?}", + f, + f.params, + par_t + ); + + if arg_t == par_t { + Ok(f.result.clone()) + } else { + Err(format!( + "arguments types {:?} does not match parameter types {:?}", + arg_t, par_t + )) + } + } + Id(id) => match var_env.get(id.to_string()) { Some(t) => Ok(t.clone()), None => Err(format!("variable not found {}", id)), @@ -341,18 +342,27 @@ pub fn check(p: &Program) -> Result<(), Error> { // build a scope for the arguments let mut arg_ty = IdType::new(); + for Param { is_mut, id, ty } in fd.params.0.iter() { - // TODO move is_mut to Type in parser - arg_ty.insert(id.to_owned(), ty.clone()); + let ty = match *is_mut { + true => Type::Mut(Box::new(ty.clone())), + _ => ty.clone(), + }; + arg_ty.insert(id.to_owned(), ty); } var_env.push_param_scope(arg_ty); let stmt_type = check_stmts(&fd.body, &fn_env, &type_env, &mut var_env); - trace!("function id {}: {:?}", fd.id, stmt_type); + trace!("function id {}: {:?}", fd.id, &stmt_type); + + let stmt_type = stmt_type?; - if stmt_type? != fd.result { - Err(format!("return value does not match statements"))?; + if stmt_type != fd.result { + Err(format!( + "return type {} does not match statements type {}", + fd.result, stmt_type + ))?; } } Ok(()) diff --git a/src/env.rs b/src/env.rs index c2f4aba..86fdfbe 100644 --- a/src/env.rs +++ b/src/env.rs @@ -53,7 +53,6 @@ impl VarEnv { } pub fn update(&mut self, id: String, ty: Type) -> Result<(), Error> { - use Type::*; match self.get_mut(id.clone()) { Some(ot) => match ot { Type::Unknown => { -- GitLab