Skip to content
Snippets Groups Projects
Commit 7e92be3d authored by Per Lindgren's avatar Per Lindgren
Browse files

check binaray and unary ops

parent fb1f90a7
No related branches found
No related tags found
No related merge requests found
fn main() { fn main() {
let mut a = 7; let mut a = 7;
let mut b = &a; let mut b = &mut a;
let c = &mut b; let c = &mut b;
*(*c) = 9; *(*c) = 9;
let d = a; let d = a;
......
...@@ -300,7 +300,7 @@ impl Display for Type { ...@@ -300,7 +300,7 @@ impl Display for Type {
I32 => write!(fmt, "i32"), I32 => write!(fmt, "i32"),
Ref(t) => write!(fmt, "&{}", t), Ref(t) => write!(fmt, "&{}", t),
Mut(t) => write!(fmt, "mut {}", t), Mut(t) => write!(fmt, "mut {}", t),
_ => unimplemented!(), Unknown => write!(fmt, "Unknown"),
} }
} }
} }
......
...@@ -48,93 +48,105 @@ fn expr_type( ...@@ -48,93 +48,105 @@ fn expr_type(
match e { match e {
Num(_) => Ok(Type::I32), Num(_) => Ok(Type::I32),
Bool(_) => Ok(Type::Bool), Bool(_) => Ok(Type::Bool),
// Infix(l, op, r) => { Infix(l, op, r) => {
// let lt = expr_type(l, fn_env, type_env, var_env)?; let lt = expr_type(l, fn_env, type_env, var_env)?;
// let rt = expr_type(r, fn_env, type_env, var_env)?; let rt = expr_type(r, fn_env, type_env, var_env)?;
// use Op::*;
// match op { let lt = strip_mut(lt);
// // Arithmetic and Boolean let rt = strip_mut(rt);
// Add | Mul | Div | Sub | And | Or => {
// let opt = From::from(op); use Op::*;
match op {
// // check if op and args are of same type // Arithmetic and Boolean
// if lt == rt && lt == opt { Add | Mul | Div | Sub | And | Or => {
// Ok((false, opt)) // check if op and args are of i32
// } else { if lt == Type::I32 && rt == Type::I32 {
// Err(format!("left {} op {} right {}", lt, opt, rt)) Ok(Type::I32)
// } } else {
// } Err(format!(
// // Equality "Num operation requires i32, left {} right {}",
// Eq | Neq => { lt, rt
// let opt = From::from(op); ))
}
// // check if op and args are of same type }
// if lt == rt && lt == opt { // Equality
// Ok((false, Type::Bool)) Eq | Neq => {
// } else { // check if args are of same type
// Err(format!("left {} op {} right {}", lt, opt, rt)) if lt == rt {
// } Ok(Type::Bool)
// } } else {
// // Comparison Err(format!(
// Less | Greater | LessEq | GreaterEq => { "Comparison requires operands of same type, left {}, right {}",
// if lt == Type::I32 && rt == Type::I32 { lt, rt
// Ok((false, Type::Bool)) ))
// } else { }
// Err(format!("left {} right {}", lt, rt)) }
// } // Comparison
// } Less | Greater | LessEq | GreaterEq => {
if lt == Type::I32 && rt == Type::I32 {
// _ => panic!("ICE on {}", e), // check if args are of i32
// } Ok(Type::Bool)
// } } else {
// Prefix(op, r) => { Err(format!(
// let rt = expr_type(r, fn_env, type_env, var_env)?; "Comparison requires operands of same type, left {}, right {}",
// let opt = op.get_type(); lt, rt
))
// // check if both of same type }
// if rt == opt { }
// Ok((false, opt)) _ => panic!("ICE on {}", e),
// } else { }
// Err(format!("op {} rt {}", opt, rt)) }
// }
// } Prefix(op, r) => {
// Call(s, args) => { let rt = expr_type(r, fn_env, type_env, var_env)?;
// trace!("call {} with {}", s, args); let opt = op.get_type();
// let argt: Vec<Type> = args // check if both of same type
// .clone() if rt == opt {
// .0 Ok(opt)
// .into_iter() } else {
// .map(|e| expr_type(&*e, fn_env, type_env, var_env)) Err(format!("op {} rt {}", opt, rt))
// .collect::<Result<_, _>>()?; }
}
// trace!("arg types {:?}", argt);
// let f = match fn_env.get(s.as_str()) { Call(s, args) => {
// Some(f) => f, trace!("call {} with {}", s, args);
// None => Err(format!("{} not found", s))?,
// }; let argt: Vec<Type> = args
.clone()
// let part: Vec<Type> = (f.params.0.clone()) .0
// .into_iter() .into_iter()
// .map(|p| From::from(&p)) .map(|e| expr_type(&*e, fn_env, type_env, var_env))
// .collect(); .collect::<Result<_, _>>()?;
// trace!( trace!("arg types {:?}", argt);
// "fn to call {} with params {} and types {:?}", let f = match fn_env.get(s.as_str()) {
// f, Some(f) => f,
// f.params, None => Err(format!("{} not found", s))?,
// part };
// );
let part: Vec<Type> = (f.params.0.clone())
// if argt == part { .into_iter()
// Ok((false, f.result.clone())) .map(|p| From::from(&p))
// } else { .collect();
// Err(format!(
// "arguments types {:?} does not match parameter types {:?}", trace!(
// argt, part "fn to call {} with params {} and types {:?}",
// )) f,
// } f.params,
// } part
);
if argt == part {
Ok(f.result.clone())
} else {
Err(format!(
"arguments types {:?} does not match parameter types {:?}",
argt, part
))
}
}
Id(id) => match var_env.get(id.to_string()) { Id(id) => match var_env.get(id.to_string()) {
Some(t) => Ok(t.clone()), Some(t) => Ok(t.clone()),
None => Err(format!("variable not found {}", id)), None => Err(format!("variable not found {}", id)),
...@@ -172,7 +184,6 @@ fn expr_type( ...@@ -172,7 +184,6 @@ fn expr_type(
_ => Err(format!("cannot deref {} of type {}", e, t)), _ => Err(format!("cannot deref {} of type {}", e, t)),
} }
} }
_ => unimplemented!(),
} }
} }
...@@ -234,7 +245,17 @@ pub fn check_stmts( ...@@ -234,7 +245,17 @@ pub fn check_stmts(
trace!("lh_type {}", &lh_type); trace!("lh_type {}", &lh_type);
if match &lh_type { if match &lh_type {
Type::Mut(t) => **t == e_type, Type::Unknown => {
trace!("assign to unknown");
true
}
Type::Mut(t) => match **t {
Type::Unknown => {
trace!("assign to `mut Unknown`");
true
}
_ => **t == e_type,
},
_ => Err(format!("assignment to immutable"))?, _ => Err(format!("assignment to immutable"))?,
} { } {
......
...@@ -53,7 +53,6 @@ impl VarEnv { ...@@ -53,7 +53,6 @@ impl VarEnv {
} }
pub fn update(&mut self, id: String, ty: Type) -> Result<(), Error> { pub fn update(&mut self, id: String, ty: Type) -> Result<(), Error> {
use Type::*;
match self.get_mut(id.clone()) { match self.get_mut(id.clone()) {
Some(ot) => match ot { Some(ot) => match ot {
Type::Unknown => { Type::Unknown => {
......
...@@ -218,5 +218,5 @@ Num: i32 = { ...@@ -218,5 +218,5 @@ Num: i32 = {
}; };
Id: String = { Id: String = {
r"([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*" => String::from_str(<>).unwrap(), r"([a-z]|[A-Z]|_)([a-z]|[A-Z]|[0-9]|_)*" => String::from_str(<>).unwrap(),
}; };
use erode::check::check; use erode::check::check;
use erode::read_file; use erode::read_file;
#[test]
fn check_w1_2() {
assert!(check(&read_file::parse("examples/w1_2.rs")).is_ok());
}
#[test] #[test]
fn check_prog() { fn check_prog() {
check(&read_file::parse("examples/minimal.rs")).unwrap(); check(&read_file::parse("examples/minimal.rs")).unwrap();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment