summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2017-11-05 09:33:03 -0500
committerDavid Li <li.davidm96@gmail.com>2017-11-05 09:33:03 -0500
commit1c62effe91b5e50d1dbbc79c01655abfb3c17e16 (patch)
tree24ede24d8a65c56f7419d3ec2e24a886a08aaada
parentb0711ef63501b7c29cb7c2014f3ceeaa399e3481 (diff)
Check types in add expressions
-rw-r--r--src/semantic/translate.rs43
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),