diff --git a/src/borrow.rs b/src/borrow.rs
index d0e990af6b854921198d365ca8265e53084c8a73..55306c43ee3195dfbed5ea65b20b78906b19f580 100644
--- a/src/borrow.rs
+++ b/src/borrow.rs
@@ -17,7 +17,15 @@ enum Val {
     RefMut(Id),
 }
 
-type IdVal = HashMap<Id, (bool, Val)>;
+#[derive(Debug, Clone)]
+pub enum Bc {
+    Fresh,              // Not yet accessed
+    Owned,              // accessed as owned, eg let mut a = 4; _ = a + 1;
+    SharedRef(Vec<Id>), // accessed through shared ref, e.g. let b = &a, _ = *b;
+    UniqueRef(Id),      // accessed through unique ref, e.g. let c = &mut a, _ = *c;
+}
+
+type IdVal = HashMap<Id, (bool, Val, Bc)>;
 
 #[derive(Debug)]
 struct Mem(VecDeque<IdVal>);
@@ -29,7 +37,7 @@ impl Mem {
 
     fn get(&self, id: String) -> Option<&Val> {
         self.0.iter().find_map(|hm| match hm.get(id.as_str()) {
-            Some((_, v)) => Some(v), // always ok to go from mut to non mut
+            Some((_, v, _)) => Some(v), // always ok to go from mut to non mut
             _ => None,
         })
     }
@@ -38,8 +46,8 @@ impl Mem {
         self.0
             .iter_mut()
             .find_map(|hm| match hm.get_mut(id.as_str()) {
-                Some((true, v)) => Some(v), // a mut reference
-                Some((_, v)) => {
+                Some((true, v, _)) => Some(v), // a mut reference
+                Some((_, v, _)) => {
                     match v {
                         Val::Uninitialized => Some(v), // an uninitialized
                         Val::RefMut(_) => {
@@ -58,7 +66,7 @@ impl Mem {
         let hm = self.0.front_mut().unwrap();
         println!("insert id {:?}, in scope {:?}", id, hm);
 
-        hm.insert(id, (is_mut, Val::Uninitialized));
+        hm.insert(id, (is_mut, Val::Uninitialized, Bc::Owned));
     }
 
     fn update(&mut self, id: String, val: Val) {
@@ -315,7 +323,7 @@ fn eval_fn(id: &str, args: &Vec<Val>, m: &mut Mem, fn_env: &FnEnv) -> Val {
         let p_id_arg: Vec<(&(bool, String), &Val)> = p_id.iter().zip(args).collect();
         let p_id_arg: IdVal = p_id_arg
             .into_iter()
-            .map(|(s, v)| (s.1.clone(), (s.0, v.clone())))
+            .map(|(s, v)| (s.1.clone(), (s.0, v.clone(), Bc::Fresh)))
             .collect();
 
         println!("args {:?}", args);
@@ -347,9 +355,15 @@ fn test_deref() {
     let mut m: Mem = Mem::new();
     let mut hm = IdVal::new();
 
-    hm.insert("a".to_string(), (false, Val::Num(7)));
-    hm.insert("b".to_string(), (false, Val::Ref("a".to_string())));
-    hm.insert("c".to_string(), (false, Val::Ref("b".to_string())));
+    hm.insert("a".to_string(), (false, Val::Num(7), Bc::Fresh));
+    hm.insert(
+        "b".to_string(),
+        (false, Val::Ref("a".to_string()), Bc::Fresh),
+    );
+    hm.insert(
+        "c".to_string(),
+        (false, Val::Ref("b".to_string()), Bc::Fresh),
+    );
     m.push_param_scope(hm);
     println!("mem {:?}", m);
     let e: Expr = Expr::Id("a".to_string());