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());