From 53a6eeba234e4e4cf771df2ea64cc99ff5c89558 Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Thu, 24 Sep 2020 15:48:52 +0200
Subject: [PATCH] borrow check, (scopes) wip1

---
 .vscode/settings.json |  1 +
 src/check.rs          |  4 ++--
 src/env.rs            | 27 ++++++++++++++-------------
 3 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 802fdcf..6a7f202 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,6 +5,7 @@
         "deque",
         "ifmt",
         "lalrpop",
+        "lexpr",
         "stmts",
         "typedecls",
         "vec",
diff --git a/src/check.rs b/src/check.rs
index 6dc0f9e..9a0fac4 100644
--- a/src/check.rs
+++ b/src/check.rs
@@ -59,7 +59,7 @@ fn expr_type(
 
             use Op::*;
             match op {
-                // Arithmetic and Boolen
+                // Arithmetic and Boolean
                 Add | Mul | Div | Sub | And | Or => {
                     // check if op and args are compliant
                     let opt = op.get_type();
@@ -151,7 +151,7 @@ fn expr_type(
         }
 
         Id(id) => match var_env.get(id.to_string()) {
-            Some(t) => Ok(t.clone()),
+            Some((_, t)) => Ok(t.clone()),
             None => Err(format!("variable not found {}", id)),
         },
 
diff --git a/src/env.rs b/src/env.rs
index f7a0d92..03f3ddc 100644
--- a/src/env.rs
+++ b/src/env.rs
@@ -22,12 +22,8 @@ pub fn new_fn_env(v: &Vec<FnDecl>) -> FnEnv {
     HashMap::from_iter(i)
 }
 
-// Option<Type>
-//
-// Some<Type>, variable has a declared type
-// None, variable has been introduced, but type not yet determined
-
 pub type IdType = HashMap<Id, Type>;
+type Scope = i32;
 
 #[derive(Debug)]
 pub struct VarEnv(VecDeque<IdType>);
@@ -37,8 +33,11 @@ impl VarEnv {
         VarEnv(VecDeque::new())
     }
 
-    pub fn get(&self, id: String) -> Option<&Type> {
-        self.0.iter().find_map(|hm| hm.get(id.as_str()))
+    pub fn get(&self, id: String) -> Option<(Scope, &Type)> {
+        self.0.iter().enumerate().find_map(|(scope, hm)| {
+            hm.get(id.as_str())
+                .map(|t| ((self.0.len() - scope) as Scope, t))
+        })
     }
 
     pub fn get_mut(&mut self, id: String) -> Option<&mut Type> {
@@ -94,7 +93,7 @@ fn type_env_test() {
 
     println!("update a {:?}", var_env.update("a".to_owned(), I32));
     println!("get a {:?}", var_env.get("a".to_owned()));
-    assert_eq!(var_env.get("a".to_owned()), Some(&I32));
+    assert_eq!(var_env.get("a".to_owned()), Some((1, &I32)));
     println!("update a {:?}", var_env.update("a".to_owned(), I32));
     assert!(var_env.update("a".to_owned(), I32).is_ok());
 
@@ -108,7 +107,9 @@ fn type_env_test() {
     assert!(var_env.update("b".to_owned(), Bool).is_err());
 
     var_env.push_empty_scope();
-    println!("push empty scope");
+    println!("\n -- push empty scope\n");
+    assert_eq!(var_env.get("a".to_owned()), Some((1, &I32)));
+
     println!("update a {:?}", var_env.update("a".to_owned(), Bool));
     assert!(var_env.update("a".to_owned(), Bool).is_err());
     println!("update a {:?}", var_env.update("a".to_owned(), I32));
@@ -116,20 +117,20 @@ fn type_env_test() {
 
     var_env.new_id("a".to_owned(), Unknown);
     println!("get a {:?}", var_env.get("a".to_owned()));
-    assert_eq!(var_env.get("a".to_owned()), Some(&Unknown));
+    assert_eq!(var_env.get("a".to_owned()), Some((2, &Unknown)));
     println!("update a {:?}", var_env.update("a".to_owned(), Bool));
     println!("get a {:?}", var_env.get("a".to_owned()));
-    assert_eq!(var_env.get("a".to_owned()), Some(&Bool));
+    assert_eq!(var_env.get("a".to_owned()), Some((2, &Bool)));
 
     println!("update a {:?}", var_env.update("a".to_owned(), Bool));
     assert!(var_env.update("a".to_owned(), Bool).is_ok());
     println!("update a {:?}", var_env.update("a".to_owned(), Type::I32));
     assert!(var_env.update("a".to_owned(), I32).is_err());
 
-    println!("pop_scope");
+    println!("\n -- pop scope\n");
     var_env.pop_scope();
     println!("get a {:?}", var_env.get("a".to_owned()));
-    assert_eq!(var_env.get("a".to_owned()), Some(&I32));
+    assert_eq!(var_env.get("a".to_owned()), Some((1, &I32)));
 
     println!("update a {:?}", var_env.update("a".to_owned(), Bool));
     assert!(var_env.update("a".to_owned(), Bool).is_err());
-- 
GitLab