diff --git a/examples/borrow_err.rs b/examples/borrow_err.rs new file mode 100644 index 0000000000000000000000000000000000000000..63157b53b2008d714818be0fa0c16f510968c76c --- /dev/null +++ b/examples/borrow_err.rs @@ -0,0 +1,7 @@ +fn main() { + let mut a = 5; + let b = &mut a; + //let q = *b; + let c = a; + println!("b {:?}", *b); +} diff --git a/src/check.rs b/src/check.rs index 97c8248f8d98a0f9b2306fee53442682fee15048..f8532f716b007ce601a6d32bb183020f36bc2ab3 100644 --- a/src/check.rs +++ b/src/check.rs @@ -5,7 +5,7 @@ use log::{trace, LevelFilter}; use std::convert::From; use crate::ast::*; -use crate::env::{new_fn_env, new_type_env, Error, FnEnv, IdType, TypeEnv, VarEnv}; +use crate::env::{new_fn_env, new_type_env, Borrow, Error, FnEnv, IdType, TypeEnv, VarEnv}; // type check @@ -150,7 +150,7 @@ fn expr_type( } } - Id(id) => match var_env.get(id.to_string()) { + Id(id) => match var_env.get_type(id.to_string()) { Some((_, t)) => Ok(t.clone()), None => Err(format!("variable not found {}", id)), }, @@ -205,7 +205,7 @@ fn lexpr_type<'a>( trace!("var_env {:?}", var_env); match e { - Id(id) => match var_env.get_mut(id.to_string()) { + Id(id) => match var_env.get_mut_type(id.to_string()) { Some(t) => Ok(t), None => Err(format!("variable not found {}", id)), }, @@ -229,6 +229,26 @@ fn lexpr_type<'a>( } } +#[test] +// trace and assert +fn borrow_test() { + use Type::*; + let var_env = &mut VarEnv::new(); + let fn_env = &mut FnEnv::new(); + let type_env = &TypeEnv::new(); + var_env.push_empty_scope(); + var_env.new_id("a".to_owned(), Type::Ref(Box::new(Type::I32))); + let e = Expr::DeRef(Box::new(Expr::Id("a".to_string()))); + let lh = lexpr_type(&e, fn_env, type_env, var_env); + + println!("lh {:?}", lh); + // let (_, t) = var_env.get("a".to_string()).unwrap(); + + // var_env.borrow("a".to_string(), t); + + println!("{:?}", var_env); +} + // strip a "mut T" to a T fn strip_mut(t: Type) -> Type { match t { @@ -427,7 +447,7 @@ pub fn check(p: &Program) -> Result<(), Error> { true => Type::Mut(Box::new(ty.clone())), _ => ty.clone(), }; - arg_ty.insert(id.to_owned(), ty); + arg_ty.insert(id.to_owned(), (Borrow::Free, ty)); } var_env.push_param_scope(arg_ty); diff --git a/src/env.rs b/src/env.rs index 1b48063dad27b07099d8ed10fb4c1cbc289a6d6c..2539edd67ad95524870c3484b0494085d2d3c7ef 100644 --- a/src/env.rs +++ b/src/env.rs @@ -22,46 +22,65 @@ pub fn new_fn_env(v: &Vec<FnDecl>) -> FnEnv { HashMap::from_iter(i) } -pub type IdType = HashMap<Id, Type>; +#[derive(Debug, PartialEq)] +pub enum Borrow { + Free, // or maybe owned + Unique, + Shared(Vec<String>), +} +pub type Address = i32; type Scope = i32; +pub type IdType = HashMap<Id, (Borrow, Type)>; #[derive(Debug)] -pub struct VarEnv(VecDeque<IdType>); +pub struct VarEnv { + env: VecDeque<IdType>, +} impl VarEnv { pub fn new() -> Self { - VarEnv(VecDeque::new()) + VarEnv { + env: VecDeque::<IdType>::new(), + } } - pub fn get(&self, id: String) -> Option<(Scope, &Type)> { - self.0.iter().enumerate().find_map(|(scope, hm)| { + pub fn get(&self, id: String) -> Option<(Scope, &(Borrow, Type))> { + self.env.iter().enumerate().find_map(|(scope, hm)| { hm.get(id.as_str()) - .map(|t| ((self.0.len() - scope) as Scope, t)) + .map(|t| ((self.env.len() - scope) as Scope, t)) }) } - pub fn get_mut(&mut self, id: String) -> Option<&mut Type> { - self.0.iter_mut().find_map(|hm| hm.get_mut(id.as_str())) + pub fn get_type(&self, id: String) -> Option<(Scope, &Type)> { + self.get(id).map(|(s, t)| (s, &t.1)) + } + + pub fn get_mut(&mut self, id: String) -> Option<&mut (Borrow, Type)> { + self.env.iter_mut().find_map(|hm| hm.get_mut(id.as_str())) + } + + pub fn get_mut_type(&mut self, id: String) -> Option<&mut Type> { + self.get_mut(id).map(|(_, t)| t) } pub fn new_id(&mut self, id: String, ty: Type) { - let hm = self.0.front_mut().unwrap(); - println!("insert id {:?}, in scope {:?}", id, hm); + let hm = self.env.front_mut().unwrap(); + println!("insert id {:?}, in scope {:?}", &id, hm); - hm.insert(id, ty); + hm.insert(id, (Borrow::Free, ty)); } pub fn update(&mut self, id: String, ty: Type) -> Result<(), Error> { println!("env: update"); match self.get_mut(id.clone()) { Some(ot) => match ot { - Type::Unknown => { + (_, Type::Unknown) => { // no type assigned - *ot = ty; + (*ot).1 = ty; Ok(()) } - t => match *t == ty { + (_, t) => match *t == ty { true => Ok(()), false => Err(format!("types differ {} <> {}", t, ty)), }, @@ -71,77 +90,93 @@ impl VarEnv { } pub fn push_empty_scope(&mut self) { - self.0.push_front(HashMap::new()); + self.env.push_front(HashMap::new()); } pub fn push_param_scope(&mut self, args: IdType) { - self.0.push_front(args) + self.env.push_front(args) } pub fn pop_scope(&mut self) { - self.0.pop_front(); + self.env.pop_front(); } } #[test] // trace and assert -fn type_env_test() { +fn borrow_test() { use Type::*; let mut var_env = VarEnv::new(); var_env.push_empty_scope(); - var_env.new_id("a".to_owned(), Type::Unknown); - println!("{:?}", var_env); + var_env.new_id("a".to_owned(), Type::Ref(Box::new(Type::I32))); + var_env.new_id("b".to_owned(), Type::Ref(Box::new(Type::I32))); - 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((1, &I32))); - println!("update a {:?}", var_env.update("a".to_owned(), I32)); - assert!(var_env.update("a".to_owned(), I32).is_ok()); + // let (_, t) = var_env.get("a".to_string()).unwrap(); - println!("update a {:?}", var_env.update("a".to_owned(), Bool)); - assert!(var_env.update("a".to_owned(), Bool).is_err()); + // var_env.borrow("a".to_string(), t); - println!("get b {:?}", var_env.get("b".to_owned())); - assert_eq!(var_env.get("b".to_owned()), None); - - println!("update b {:?}", var_env.update("b".to_owned(), Bool)); - assert!(var_env.update("b".to_owned(), Bool).is_err()); - - var_env.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)); - assert!(var_env.update("a".to_owned(), I32).is_ok()); - - 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((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((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!("\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((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)); - assert!(var_env.update("a".to_owned(), I32).is_ok()); - - println!("get b {:?}", var_env.get("b".to_owned())); - assert_eq!(var_env.get("b".to_owned()), None); + println!("{:?}", var_env); } +// #[test] +// // trace and assert +// fn type_env_test() { +// use Type::*; +// let mut var_env = VarEnv::new(); +// var_env.push_empty_scope(); +// var_env.new_id("a".to_owned(), Type::Unknown); +// println!("{:?}", var_env); + +// println!("update a {:?}", var_env.update("a".to_owned(), I32)); +// println!("get a {:?}", var_env.get("a".to_owned())); +// assert_eq!(var_env.get_type("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()); + +// println!("update a {:?}", var_env.update("a".to_owned(), Bool)); +// assert!(var_env.update("a".to_owned(), Bool).is_err()); + +// println!("get_type b {:?}", var_env.get_type("b".to_owned())); +// assert_eq!(var_env.get_type("b".to_owned()), None); + +// println!("update b {:?}", var_env.update("b".to_owned(), Bool)); +// assert!(var_env.update("b".to_owned(), Bool).is_err()); + +// var_env.push_empty_scope(); +// println!("\n -- push empty scope\n"); +// assert_eq!(var_env.get_type("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)); +// assert!(var_env.update("a".to_owned(), I32).is_ok()); + +// var_env.new_id("a".to_owned(), Unknown); +// println!("get_type a {:?}", var_env.get_type("a".to_owned())); +// assert_eq!(var_env.get_type("a".to_owned()), Some((2, &Unknown))); +// println!("update a {:?}", var_env.update("a".to_owned(), Bool)); +// println!("get_type a {:?}", var_env.get_type("a".to_owned())); +// assert_eq!(var_env.get_type("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!("\n -- pop scope\n"); +// var_env.pop_scope(); +// println!("get_type a {:?}", var_env.get_type("a".to_owned())); +// assert_eq!(var_env.get_type("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)); +// assert!(var_env.update("a".to_owned(), I32).is_ok()); + +// println!("get_type b {:?}", var_env.get_type("b".to_owned())); +// assert_eq!(var_env.get_type("b".to_owned()), None); +// } + pub type TypeEnv<'a> = HashMap<&'a str, &'a TypeDecl>; impl TypeDecl {