diff --git a/src/ast.rs b/src/ast.rs index 3d1a1aaaa8cc12d41a4bb3888038de0cfc713145..c54d740d66ba7eed8e3affc5e191b5b0d04142da 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -76,6 +76,7 @@ pub enum Type { I32, // i32 Ref(Box<Type>), // & mut? Type -- used in parser Mut(Box<Type>), // mut Type + Unknown, // Not yet assigned // RefMut(Box<Type>), // &mut Type -- used in parser } diff --git a/src/check.rs b/src/check.rs index 6b2e6c3a84dba0f2981c56db4278a2930f9824b6..b6dfac2392d18505095c0eaa3ed7228c02fae8ff 100644 --- a/src/check.rs +++ b/src/check.rs @@ -44,6 +44,7 @@ fn expr_type( var_env: &VarEnv, ) -> Result<Type, Error> { use Expr::*; + trace!("expr_type {}", e); match e { Num(_) => Ok(Type::I32), Bool(_) => Ok(Type::Bool), @@ -134,38 +135,38 @@ fn expr_type( // )) // } // } - // Id(id) => match var_env.get(id.to_string()) { - // Some(t) => match t { - // (is_mut, Some(t)) => Ok((*is_mut, t.clone())), - // (_, None) => Err(format!("variable {:?} has no type yet", id)), - // }, - // None => Err(format!("variable not found {}", id)), - // }, + Id(id) => match var_env.get(id.to_string()) { + Some(t) => match t { + // variable bound to type + Some(t) => Ok(t.clone()), + // not yet bound + None => Err(format!("variable {:?} has no type yet", id)), + }, + None => Err(format!("variable not found {}", id)), + }, + As(_e, _t) => unimplemented!("here we implement explicit type cast"), - // for now, allow only references to variables - // should we make recursive call here? - // Ref(ref_e) => { - // let (_, t) = expr_type(ref_e, fn_env, type_env, var_env)?; - // Ok(Type::Ref(Box::new((false, t))) - // } + // Convert Expr::Ref to Type::Ref + Ref(ref_e) => { + let t = expr_type(ref_e, fn_env, type_env, var_env)?; + Ok(Type::Ref(Box::new(t))) + } - // // for now, allow only references to variables - // // should we make recursive call here? - // RefMut(ref_mut_e) => { - // let t = expr_type(ref_mut_e, fn_env, type_env, var_env)?; - // Ok(Type::RefMut(Box::new(t))) - // } + // Convert Expr::Mut to Type::Mut + RefMut(ref_mut_e) => { + let t = expr_type(ref_mut_e, fn_env, type_env, var_env)?; + Ok(Type::Mut(Box::new(t))) + } - // DeRef(deref_e) => { - // let t = expr_type(deref_e, fn_env, type_env, var_env)?; - // trace!("deref_t {}", &t); - // match t { - // Type::Ref(dt) => Ok(*dt), - // Type::RefMut(dt) => Ok(*dt), - // _ => Err(format!("cannot deref {}", e)), - // } - // } + DeRef(deref_e) => { + let t = expr_type(deref_e, fn_env, type_env, var_env)?; + trace!("deref_t {}", &t); + match t { + Type::Ref(dt) => Ok(*dt), + _ => Err(format!("cannot deref {} of type {}", e, t)), + } + } _ => unimplemented!(), } } @@ -342,8 +343,12 @@ pub fn check_stmts( (None, Some(e)) => Some(expr_type(&*e, fn_env, type_env, var_env)?), (ot, None) => ot.clone(), }; - // var_env.new_id(var_id.clone(), *is_mut, ot); - // trace!("var_env {:?}", var_env); + let ot = match is_mut { + true => Type::Mut(Box::new(ot)), + false => ot, + }; + var_env.new_id(var_id.clone(), ot); + trace!("var_env {:?}", var_env); Ok(Type::Unit) } diff --git a/src/env.rs b/src/env.rs index 975c102bd3aa93f2cffd5eab0edd57b0431c6df2..e3d1fc1c8fe26e23625926a23b667212529c8474 100644 --- a/src/env.rs +++ b/src/env.rs @@ -22,8 +22,8 @@ pub fn new_fn_env(v: &Vec<FnDecl>) -> FnEnv { HashMap::from_iter(i) } -// (bool, Option<Type>) -// variable is_mut, +// Option<Type> +// // Some<Type>, variable has a declared type // None, variable has been introduced, but type not yet determined