diff options
-rw-r--r-- | src/semantic/translate.rs | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/src/semantic/translate.rs b/src/semantic/translate.rs index 7bcd646..d3ebd2c 100644 --- a/src/semantic/translate.rs +++ b/src/semantic/translate.rs @@ -5,16 +5,21 @@ use super::types::Ty; #[derive(Debug)] pub enum TypeError { Unimplemented, + Mismatch { + expected: Ty, + actual: Ty, + }, } type TypeEnvironment<'a> = environment::Environment<'a, String, Ty>; pub type Result = ::std::result::Result<Ty, WithLocation<TypeError>>; pub fn translate(program: &ast::Program) -> Result { - trans_exp(TypeEnvironment::new(None), &*program.0) + let mut env = TypeEnvironment::new(None); + trans_exp(&mut env, &*program.0) } -fn trans_exp<'a>(venv: TypeEnvironment<'a>, exp: &WithLocation<ast::Expression>) -> Result { +fn trans_exp<'a>(venv: &mut TypeEnvironment<'a>, exp: &WithLocation<ast::Expression>) -> Result { use ast::Expression::*; match &exp.value { @@ -25,7 +30,39 @@ fn trans_exp<'a>(venv: TypeEnvironment<'a>, exp: &WithLocation<ast::Expression>) Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) }, &BinOp(ref op, ref left, ref right) => { - Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) + use ast::BinOp::*; + match op { + &Add => { + let left = trans_exp(venv, left)?; + let right = trans_exp(venv, right)?; + match (left, right) { + (Ty::Int, Ty::Int) => { + Ok(Ty::Int) + } + (Ty::String, Ty::String) => { + Ok(Ty::String) + } + (Ty::Int, other) => { + Err(WithLocation::new(TypeError::Mismatch { + expected: Ty::Int, + actual: other, + }, exp.start, exp.end)) + } + (Ty::String, other) => { + Err(WithLocation::new(TypeError::Mismatch { + expected: Ty::String, + actual: other, + }, exp.start, exp.end)) + } + _ => { + Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) + } + } + } + _ => { + Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) + } + } }, &Number(_) => Ok(Ty::Int), &String(_) => Ok(Ty::String), |