diff --git a/src/ast.rs b/src/ast.rs index 0b8b2d3e612dc4c0f6e5efb16931fe9ffc25402f..465fbf8ac48b5b044fc5cc77444ed807a5db7c9b 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 0fe868dabb40c4e5a5db5b9eb9b84d98cb17d836..8aed07baa8e6ab69f9d604c1c890c42a253b48a3 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 c2f4abaa7ac69deaa9143c238c378d94c585e2c2..86fdfbe41bcbcc20269d707ef4935c50b943aedb 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 => {