diff --git a/examples/borrow2.rs b/examples/borrow2.rs index f99b6d5d921895510c27eb954e2386a448e89a95..cd3cb1a687ed14d42222f6933df0b90be543830e 100644 --- a/examples/borrow2.rs +++ b/examples/borrow2.rs @@ -17,6 +17,6 @@ fn main() { // this is can be solved by "alpha renaming" // in a function f(x, ...) = x ... -// x can be "renamed" to a new name y +// x can be "renamed" to a new name y // by changing all appearances of x to y -// (as long as y don't appear in f) \ No newline at end of file +// (as long as y don't appear in f) diff --git a/examples/borrow6.rs b/examples/borrow6.rs new file mode 100644 index 0000000000000000000000000000000000000000..ae873f98d0238e0b2af23985325240c53ca6a70f --- /dev/null +++ b/examples/borrow6.rs @@ -0,0 +1,13 @@ +fn g(b: &mut bool) { + let c = b; + *c = true; +} + +fn f(b: &mut bool) { + let c = b; + g(c); +} +fn main() { + let mut b = false; + f(&mut b); +} diff --git a/examples/borrow7.rs b/examples/borrow7.rs new file mode 100644 index 0000000000000000000000000000000000000000..b7085b296ef4b4003ea2fd262e7dd823cba9c746 --- /dev/null +++ b/examples/borrow7.rs @@ -0,0 +1,14 @@ +fn g(b: &mut i32) { + let c = b; + *c = 1; +} + +fn f(b: &mut i32) { + let c = b; + g(c); + *c = 2; +} +fn main() { + let mut b = 0; + f(&mut b); +} diff --git a/src/borrow.rs b/src/borrow.rs index 29bfa3524f264b4fa2ec7f8ced5df4cdebce7795..3bca22ff1c1d96598e15f570753d3b1000e98eb2 100644 --- a/src/borrow.rs +++ b/src/borrow.rs @@ -52,23 +52,32 @@ impl Mem { } fn get_mut(&mut self, scope: Scope, id: String) -> Option<&mut Val> { + println!("--- get_mut {:?} in scope # {}", id, scope); + let nr_scopes = self.0.len(); self.0 .iter_mut() .enumerate() - .find_map(|(i, hm)| match hm.get_mut(id.as_str()) { - Some((true, v, _)) => Some(v), // a mut reference - Some((_, v, _)) => { - match v { - Val::Uninitialized => Some(v), // an uninitialized - Val::RefMut(_, _) => { - // a ref mut - println!("get &mut {:?}", v); - Some(v) + .find_map(|(i, hm)| match nr_scopes - i <= scope { + true => { + // search in this scope + println!("i {}, hm {:?} ", i, hm); + match hm.get_mut(id.as_str()) { + Some((true, v, _)) => Some(v), // a mut reference + Some((_, v, _)) => { + match v { + Val::Uninitialized => Some(v), // an uninitialized + Val::RefMut(_, _) => { + // a ref mut + println!("get &mut {:?}", v); + Some(v) + } + _ => panic!("cannot access as mutable"), + } } - _ => panic!("cannot access as mutable"), + _ => None, } } - _ => None, + false => None, // skip this scope }) } @@ -83,7 +92,7 @@ impl Mem { // println!("before mem {:?}", self); match self.get_mut(scope, id.clone()) { Some(v_ref) => { - println!("found"); + println!("update v_ref {:?} = val {:?}", v_ref, val); *v_ref = val; } None => { @@ -211,25 +220,25 @@ fn eval_expr(e: &Expr, m: &mut Mem, fn_env: &FnEnv) -> Val { } } -fn eval_left_expr(e: &Expr, m: &Mem, fn_env: &FnEnv) -> Id { +fn eval_left_expr(e: &Expr, m: &Mem, fn_env: &FnEnv, scope: Scope) -> (Scope, Id) { println!("eval_left_expr {}", e); match e { - Expr::Id(id) => id.to_owned(), + Expr::Id(id) => (scope, id.to_owned()), Expr::DeRef(e) => { println!("eval_left deref e {:?}", e); - let ev = eval_left_expr(e, m, fn_env); - println!("eval_left {:?}", ev); + let (sc, ev) = eval_left_expr(e, m, fn_env, scope); + println!("eval_left {:?}, sc {}", ev, sc); match m.get(ev) { Some((_, Val::Ref(s, id))) => { println!("Ref id {} in scope {}", id, s); - id.clone() + (*s, id.clone()) } Some((_, Val::RefMut(s, id))) => { println!("RefMut id {} in scope {}", id, s); - id.clone() + (*s, id.clone()) } _ => panic!("deref failed"), } @@ -271,10 +280,12 @@ fn eval_stmts(stmts: &Stmts, m: &mut Mem, fn_env: &FnEnv) -> Val { m.update(m.get_scope(), id.to_owned(), v) } _ => { - let lv = eval_left_expr(ev, m, fn_env); - println!("lv {:?}", lv); + let cur_scope = m.get_scope(); + println!("cur_scope {}", cur_scope); + let (scope, id) = eval_left_expr(ev, m, fn_env, cur_scope); + println!("scope {} id {:?}", scope, id); let v = eval_expr(e, m, fn_env); - m.update(m.get_scope(), lv, v) + m.update(scope, id, v) } }; Val::Unit diff --git a/tests/test_borrow.rs b/tests/test_borrow.rs index 16dba2cf7e5fadc27a22ebbdf371711f0add0f5f..af4b05eccf5a02a0557a1aa83e988c71acf1df49 100644 --- a/tests/test_borrow.rs +++ b/tests/test_borrow.rs @@ -118,3 +118,23 @@ fn borrow() { fn borrow2() { eval_prog("examples/borrow2.rs"); } + +#[test] +fn borrow4() { + eval_prog("examples/borrow4.rs"); +} + +#[test] +fn borrow5() { + eval_prog("examples/borrow5.rs"); +} + +#[test] +fn borrow6() { + eval_prog("examples/borrow6.rs"); +} + +#[test] +fn borrow7() { + eval_prog("examples/borrow7.rs"); +}