diff options
author | David Li <li.davidm96@gmail.com> | 2017-11-05 09:27:10 -0500 |
---|---|---|
committer | David Li <li.davidm96@gmail.com> | 2017-11-05 09:27:10 -0500 |
commit | b0711ef63501b7c29cb7c2014f3ceeaa399e3481 (patch) | |
tree | eb1cf61610517a7479e3f78a30b4bff37dd44708 | |
parent | 9f393b2eb7b3fb8f1924e80095bad3384049cc67 (diff) |
Add stubbed out type checker
-rw-r--r-- | src/ast.rs | 18 | ||||
-rw-r--r-- | src/main.rs | 7 | ||||
-rw-r--r-- | src/semantic/environment.rs | 33 | ||||
-rw-r--r-- | src/semantic/mod.rs | 3 | ||||
-rw-r--r-- | src/semantic/translate.rs | 39 | ||||
-rw-r--r-- | src/semantic/types.rs | 7 |
6 files changed, 99 insertions, 8 deletions
@@ -1,32 +1,36 @@ #[derive(Debug)] pub struct WithLocation<T> { - value: T, - location: (usize, usize), + pub value: T, + pub start: usize, + pub end: usize, } impl<T> WithLocation<T> { pub fn new(value: T, start: usize, end: usize) -> WithLocation<T> { WithLocation { value: value, - location: (start, end), + start: start, + end: end, } } pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> WithLocation<U> { WithLocation { value: f(self.value), - location: self.location, + start: self.start, + end: self.end, } } pub fn join_map<U, V, F>(self, other: WithLocation<U>, f: F) -> WithLocation<V> where F: FnOnce(WithLocation<T>, WithLocation<U>) -> V { - let loc1 = self.location; - let loc2 = other.location; + let start = self.start; + let end = other.end; WithLocation { value: f(self, other), - location: (loc1.0, loc2.1), + start: start, + end: end, } } } diff --git a/src/main.rs b/src/main.rs index 8976597..8264f97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ pub mod ast; +pub mod semantic; pub mod taiga; use std::io::{self, BufRead, Write}; @@ -12,7 +13,11 @@ fn main() { io::stdout().flush().unwrap(); if let Ok(n) = handle.read_line(&mut input) { if n == 0 { break; } - println!("{:?}", taiga::parse_Program(&input)); + let program = taiga::parse_Program(&input); + println!("{:?}", program); + if let Ok(program) = program { + println!("{:?}", semantic::translate::translate(&program)); + } } else { break; diff --git a/src/semantic/environment.rs b/src/semantic/environment.rs new file mode 100644 index 0000000..fab16b3 --- /dev/null +++ b/src/semantic/environment.rs @@ -0,0 +1,33 @@ +use std::collections::HashMap; +use std::hash::Hash; + +pub struct Environment<'a, T: 'a, U: 'a> { + pub parent: Option<&'a Environment<'a, T, U>>, + pub bindings: HashMap<T, U>, +} + +impl<'a, T: 'a, U: 'a> Environment<'a, T, U> + where T: Eq + Hash { + pub fn new(parent: Option<&'a Environment<'a, T, U>>) -> Environment<'a, T, U> { + Environment { + parent: parent, + bindings: HashMap::new(), + } + } + + pub fn add_binding(&mut self, key: T, value: U) { + self.bindings.insert(key, value); + } + + pub fn lookup(&self, key: &T) -> Option<&U> { + if let Some(v) = self.bindings.get(key) { + Some(v) + } + else if let Some(p) = self.parent { + p.lookup(key) + } + else { + None + } + } +} diff --git a/src/semantic/mod.rs b/src/semantic/mod.rs new file mode 100644 index 0000000..433a196 --- /dev/null +++ b/src/semantic/mod.rs @@ -0,0 +1,3 @@ +pub mod environment; +pub mod translate; +pub mod types; diff --git a/src/semantic/translate.rs b/src/semantic/translate.rs new file mode 100644 index 0000000..7bcd646 --- /dev/null +++ b/src/semantic/translate.rs @@ -0,0 +1,39 @@ +use ::ast::{self, WithLocation}; +use super::environment; +use super::types::Ty; + +#[derive(Debug)] +pub enum TypeError { + Unimplemented, +} + +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) +} + +fn trans_exp<'a>(venv: TypeEnvironment<'a>, exp: &WithLocation<ast::Expression>) -> 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) => { + 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)) + }, + } +} diff --git a/src/semantic/types.rs b/src/semantic/types.rs new file mode 100644 index 0000000..2d76387 --- /dev/null +++ b/src/semantic/types.rs @@ -0,0 +1,7 @@ +#[derive(Debug)] +pub enum Ty { + Int, + String, + Nil, + Unit, +} |