From a382754b2f0a167993229a636587b9852db24b38 Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Thu, 17 Sep 2020 21:49:12 +0200
Subject: [PATCH] passes w1_2

---
 examples/w1_2.rs    |  9 ++++-----
 src/check.rs        | 21 ++++++++++++---------
 src/grammar.lalrpop |  3 ++-
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/examples/w1_2.rs b/examples/w1_2.rs
index fcf5cd9..83df078 100644
--- a/examples/w1_2.rs
+++ b/examples/w1_2.rs
@@ -16,12 +16,11 @@ fn c(x: i32, y: i32) -> i32 {
     -a - (-b) * y // here we have prefix operator "-"
 }
 
-
 // More advanced statements
 
 // a function taking two bool arguments returning the bool type
 // with some let statements and function calls
-fn a(x: bool, y: bool) -> bool {
+fn a1(x: bool, y: bool) -> bool {
     if x && y {
         let a: bool = true;
         y || a
@@ -32,8 +31,8 @@ fn a(x: bool, y: bool) -> bool {
 
 // a function taking two bool arguments returning the i32 type
 // with some let statements and function calls
-fn b(x: bool, y: bool) -> i32 {
-    let a: bool = a(x, y || false);
+fn b1(x: bool, y: bool) -> i32 {
+    let a: bool = a1(x, y || false);
     let mut b: i32 = 0;
     if a && y {
         let a: bool = true; // shadowing
@@ -50,7 +49,7 @@ fn b(x: bool, y: bool) -> i32 {
 
 // a function taking two bool arguments returning the i32 type
 // while
-fn c(x: bool, y: bool) -> i32 {
+fn c1(x: bool, y: bool) -> i32 {
     let mut b: i32 = 0;
     let mut c: i32 = 1;
     while (b < 10) {
diff --git a/src/check.rs b/src/check.rs
index 46c2d2a..9bda67b 100644
--- a/src/check.rs
+++ b/src/check.rs
@@ -45,6 +45,8 @@ fn expr_type(
 ) -> Result<Type, Error> {
     use Expr::*;
     trace!("expr_type {}", e);
+    trace!("var_env {:?}", var_env);
+
     match e {
         Num(_) => Ok(Type::I32),
         Bool(_) => Ok(Type::Bool),
@@ -57,15 +59,16 @@ fn expr_type(
 
             use Op::*;
             match op {
-                // Arithmetic and Boolean
+                // Arithmetic and Boolen
                 Add | Mul | Div | Sub | And | Or => {
-                    // check if op and args are of i32
-                    if lt == Type::I32 && rt == Type::I32 {
-                        Ok(Type::I32)
+                    // check if op and args are compliant
+                    let opt = op.get_type();
+                    if lt == opt && rt == opt {
+                        Ok(opt)
                     } else {
                         Err(format!(
-                            "Num operation requires i32, left {}  right {}",
-                            lt, rt
+                            "Expected type {}, found, left {}: {}, {:?}  right {}: {}, {:?}",
+                            opt, l, lt, lt, r, rt, rt
                         ))
                     }
                 }
@@ -373,7 +376,7 @@ pub fn check(p: &Program) -> Result<(), Error> {
     trace!("Input program \n{}", &p);
 
     for fd in p.fn_decls.iter() {
-        trace!("function id {}", fd.id);
+        trace!("check function\n{}", fd);
         let mut var_env = VarEnv::new();
 
         // build a scope for the arguments
@@ -390,9 +393,9 @@ pub fn check(p: &Program) -> Result<(), Error> {
         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!("result {}: {:?}", fd.id, &stmt_type);
 
-        let stmt_type = stmt_type?;
+        let stmt_type = strip_mut(stmt_type?);
 
         if stmt_type != fd.result {
             Err(format!(
diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop
index eaa7f05..239904f 100644
--- a/src/grammar.lalrpop
+++ b/src/grammar.lalrpop
@@ -150,9 +150,10 @@ Stmt : Stmt = {
 
 
 Type : Type = {
-    Id => Type::Named(<>),
+    "bool" => Type::Bool,
     "()" => Type::Unit,
     "i32" => Type::I32, // this should likely be a paratrized Num type later
+    Id => Type::Named(<>),
     "&" <Type> => Type::Ref(Box::new(<>)),
     "&" "mut" <Type> => Type::Ref(Box::new(Type::Mut(Box::new(<>)))),
 }
-- 
GitLab