From b0711ef63501b7c29cb7c2014f3ceeaa399e3481 Mon Sep 17 00:00:00 2001 From: David Li Date: Sun, 5 Nov 2017 09:27:10 -0500 Subject: Add stubbed out type checker --- src/ast.rs | 18 +++++++++++------- src/main.rs | 7 ++++++- src/semantic/environment.rs | 33 +++++++++++++++++++++++++++++++++ src/semantic/mod.rs | 3 +++ src/semantic/translate.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/semantic/types.rs | 7 +++++++ 6 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 src/semantic/environment.rs create mode 100644 src/semantic/mod.rs create mode 100644 src/semantic/translate.rs create mode 100644 src/semantic/types.rs (limited to 'src') diff --git a/src/ast.rs b/src/ast.rs index 7edf9c7..c3925b0 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,32 +1,36 @@ #[derive(Debug)] pub struct WithLocation { - value: T, - location: (usize, usize), + pub value: T, + pub start: usize, + pub end: usize, } impl WithLocation { pub fn new(value: T, start: usize, end: usize) -> WithLocation { WithLocation { value: value, - location: (start, end), + start: start, + end: end, } } pub fn map U>(self, f: F) -> WithLocation { WithLocation { value: f(self.value), - location: self.location, + start: self.start, + end: self.end, } } pub fn join_map(self, other: WithLocation, f: F) -> WithLocation where F: FnOnce(WithLocation, WithLocation) -> 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, +} + +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>; + +pub fn translate(program: &ast::Program) -> Result { + trans_exp(TypeEnvironment::new(None), &*program.0) +} + +fn trans_exp<'a>(venv: 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) => { + 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, +} -- cgit v1.2.3