use ::ast::{self, WithLocation}; use super::environment; 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>; pub fn translate(program: &ast::Program) -> Result { let mut env = TypeEnvironment::new(None); trans_exp(&mut env, &*program.0) } fn trans_exp<'a>(venv: &mut TypeEnvironment<'a>, exp: &WithLocation) -> Result { use ast::Expression::*; match &exp.value { &Let(ref decls, ref body) => { Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) }, &UnaryOp(ref op, ref operand) => { Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) }, &BinOp(ref op, ref left, ref right) => { 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), &Name(ref name) => { Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) }, &Nil => { Err(WithLocation::new(TypeError::Unimplemented, exp.start, exp.end)) }, } }