From 990d4f0f76992503600384586a0571a1e3915b65 Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Fri, 18 Sep 2020 15:24:45 +0200 Subject: [PATCH] all tests pass --- examples/mut.rs | 4 +-- examples/mut2.rs | 4 +-- src/check.rs | 61 ++++++++++++++++++++++++++++++++++++++------- tests/test_check.rs | 15 +++++++++++ tests/test_vm.rs | 4 +++ 5 files changed, 75 insertions(+), 13 deletions(-) diff --git a/examples/mut.rs b/examples/mut.rs index a93ad51..ec2e140 100644 --- a/examples/mut.rs +++ b/examples/mut.rs @@ -1,5 +1,5 @@ -fn main() -> i32 { +fn main() { let mut a = 0; a = 2; - a + let b = a; } diff --git a/examples/mut2.rs b/examples/mut2.rs index 2166959..33fd4af 100644 --- a/examples/mut2.rs +++ b/examples/mut2.rs @@ -1,8 +1,8 @@ -fn main() -> i32 { +fn main() { let mut a = 0; a = 2; let mut b = a; // copy semantics a = 3; b = b + 1; - a + b + let c = a + b; } diff --git a/src/check.rs b/src/check.rs index 1b16944..18d5675 100644 --- a/src/check.rs +++ b/src/check.rs @@ -190,6 +190,41 @@ fn expr_type( } } +fn lexpr_type<'a>( + e: &Expr, + fn_env: &FnEnv, + type_env: &TypeEnv, + var_env: &'a mut VarEnv, +) -> Result<&'a mut Type, Error> { + use Expr::*; + trace!("expr_type {}", e); + trace!("var_env {:?}", var_env); + + match e { + Id(id) => match var_env.get_mut(id.to_string()) { + Some(t) => Ok(t), + None => Err(format!("variable not found {}", id)), + }, + + DeRef(deref_e) => { + let t = lexpr_type(deref_e, fn_env, type_env, var_env)?; + trace!("deref_t {}", &t); + + // strip mut + let t = match t { + Type::Mut(t) => t, + _ => t, + }; + trace!("strip deref_t {}", t); + match t { + Type::Ref(dt) => Ok(dt), + _ => Err(format!("cannot deref {} of type {}", e, t)), + } + } + _ => Err(format!("Illegal left hand expression {}", e)), + } +} + fn strip_mut(t: Type) -> Type { match t { Type::Mut(t) => *t, @@ -228,7 +263,8 @@ pub fn check_stmts( let t: Type = match (ot, oe) { (Some(t), Some(e)) => { let e_type = expr_type(&*e, fn_env, type_env, var_env)?; - match *t == e_type { + let e_type = strip_mut(e_type); + match strip_mut(t.clone()) == e_type { true => t.clone(), false => { trace!("e {}", e); @@ -237,9 +273,9 @@ pub fn check_stmts( } } (None, Some(e)) => { - let et = expr_type(&*e, fn_env, type_env, var_env)?; - match is_known(&et) { - true => et, + let e_type = strip_mut(expr_type(&*e, fn_env, type_env, var_env)?); + match is_known(&e_type) { + true => e_type, _ => Err("reference to unknown type".to_string())?, } } @@ -256,21 +292,28 @@ pub fn check_stmts( } Assign(lh, e) => { + trace!("assign"); + let e_type = expr_type(&*e, fn_env, type_env, var_env)?; - trace!("e_type = {}", e_type); - trace!("lh = {:?}", lh); + trace!("e_type = {}", &e_type); + let e_type = strip_mut(e_type); + trace!("e_type stripped = {}", &e_type); + + trace!("lh expr = {:?}", lh); - let lh_type = expr_type(lh, fn_env, type_env, var_env)?; - trace!("lh_type {}", &lh_type); + let lh_type = lexpr_type(lh, fn_env, type_env, var_env)?; + trace!("lh_type {}", lh_type); - if match &lh_type { + if match lh_type { Type::Unknown => { trace!("assign to unknown"); + *lh_type = e_type.clone(); true } Type::Mut(t) => match **t { Type::Unknown => { trace!("assign to `mut Unknown`"); + *t = Box::new(e_type.clone()); true } _ => **t == e_type, diff --git a/tests/test_check.rs b/tests/test_check.rs index d120948..6334148 100644 --- a/tests/test_check.rs +++ b/tests/test_check.rs @@ -21,6 +21,11 @@ fn check_assign2() { assert!(check(&read_file::parse("examples/assign2.rs")).is_ok()); } +#[test] +fn check_assign3() { + assert!(check(&read_file::parse("examples/assign3.rs")).is_ok()); +} + #[test] fn check_assign_err() { assert!(check(&read_file::parse("examples/assign_err.rs")).is_err()); @@ -154,3 +159,13 @@ fn check_ref_err3() { fn check_ref_err4() { assert!(check(&read_file::parse("examples/ref_err4.rs")).is_err()); } + +#[test] +fn check_scopes() { + assert!(check(&read_file::parse("examples/scopes.rs")).is_ok()); +} + +#[test] +fn check_scopes_err() { + assert!(check(&read_file::parse("examples/scopes_err.rs")).is_err()); +} diff --git a/tests/test_vm.rs b/tests/test_vm.rs index 27086b6..33d7729 100644 --- a/tests/test_vm.rs +++ b/tests/test_vm.rs @@ -35,6 +35,10 @@ fn scopes_test() { eval_prog("examples/scopes.rs"); } +#[test] +fn scopes_err_test() { + eval_prog("examples/scopes_err.rs"); +} #[test] fn vm_test() { eval_prog("examples/vm.rs"); -- GitLab