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