2018-02-21 02:31:28 -08:00
|
|
|
use std::rc::Rc;
|
|
|
|
|
2018-11-06 16:47:34 -08:00
|
|
|
use ast::*;
|
2018-11-06 13:44:52 -08:00
|
|
|
|
2018-05-27 02:44:06 -07:00
|
|
|
pub type TypeName = Rc<String>;
|
2018-11-06 13:44:52 -08:00
|
|
|
|
|
|
|
pub struct TypeContext {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-07 17:01:07 -08:00
|
|
|
type InferResult<T> = Result<T, TypeError>;
|
2018-11-06 16:47:34 -08:00
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct TypeError { }
|
|
|
|
|
2018-11-07 13:44:28 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2018-11-07 03:39:31 -08:00
|
|
|
enum MonoType {
|
|
|
|
Var(Rc<String>),
|
2018-11-07 15:39:40 -08:00
|
|
|
Const(TConst),
|
2018-11-07 03:39:31 -08:00
|
|
|
Arrow(Rc<String>)
|
|
|
|
}
|
2018-11-06 16:47:34 -08:00
|
|
|
|
2018-11-07 15:39:40 -08:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
enum TConst {
|
|
|
|
User(Rc<String>),
|
|
|
|
Unit,
|
|
|
|
Nat,
|
2018-11-07 16:39:32 -08:00
|
|
|
Int,
|
|
|
|
Float,
|
|
|
|
StringT,
|
2018-11-07 15:39:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TConst {
|
|
|
|
fn user(name: &str) -> TConst {
|
|
|
|
TConst::User(Rc::new(name.to_string()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-07 13:44:28 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2018-11-07 03:39:31 -08:00
|
|
|
struct PolyType {
|
|
|
|
vars: Vec<Rc<String>>,
|
|
|
|
ty: MonoType
|
2018-11-06 16:47:34 -08:00
|
|
|
}
|
|
|
|
|
2018-11-06 13:44:52 -08:00
|
|
|
impl TypeContext {
|
|
|
|
pub fn new() -> TypeContext {
|
|
|
|
TypeContext { }
|
|
|
|
}
|
|
|
|
|
2018-11-07 13:44:28 -08:00
|
|
|
pub fn typecheck(&mut self, ast: &AST) -> Result<String, String> {
|
2018-11-06 16:47:34 -08:00
|
|
|
match self.infer_ast(ast) {
|
2018-11-07 13:44:28 -08:00
|
|
|
Ok(t) => Ok(format!("{:?}", t)),
|
2018-11-06 16:47:34 -08:00
|
|
|
Err(err) => Err(format!("Type error: {:?}", err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TypeContext {
|
2018-11-07 17:01:07 -08:00
|
|
|
fn infer_ast(&mut self, ast: &AST) -> InferResult<MonoType> {
|
2018-11-07 15:39:40 -08:00
|
|
|
let mut output = MonoType::Const(TConst::Unit);
|
2018-11-07 03:39:31 -08:00
|
|
|
for statement in ast.0.iter() {
|
2018-11-07 13:44:28 -08:00
|
|
|
output = match statement {
|
2018-11-07 03:39:31 -08:00
|
|
|
Statement::ExpressionStatement(ref expr) => self.infer_expr(expr)?,
|
|
|
|
Statement::Declaration(ref decl) => self.infer_decl(decl)?,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
Ok(output)
|
|
|
|
}
|
|
|
|
|
2018-11-07 17:01:07 -08:00
|
|
|
fn infer_expr(&mut self, expr: &Expression) -> InferResult<MonoType> {
|
2018-11-07 03:39:31 -08:00
|
|
|
match expr {
|
|
|
|
Expression(expr_type, Some(type_anno)) => unimplemented!(),
|
|
|
|
Expression(expr_type, None) => self.infer_expr_type(expr_type)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-07 17:01:07 -08:00
|
|
|
fn infer_decl(&mut self, expr: &Declaration) -> InferResult<MonoType> {
|
2018-11-07 15:39:40 -08:00
|
|
|
Ok(MonoType::Const(TConst::user("unimplemented")))
|
2018-11-06 16:47:34 -08:00
|
|
|
}
|
2018-11-07 03:39:31 -08:00
|
|
|
|
2018-11-07 17:01:07 -08:00
|
|
|
fn infer_expr_type(&mut self, expr_type: &ExpressionType) -> InferResult<MonoType> {
|
2018-11-07 03:39:31 -08:00
|
|
|
use self::ExpressionType::*;
|
|
|
|
match expr_type {
|
2018-11-07 15:39:40 -08:00
|
|
|
NatLiteral(_) => Ok(MonoType::Const(TConst::Nat)),
|
2018-11-07 16:39:32 -08:00
|
|
|
FloatLiteral(_) => Ok(MonoType::Const(TConst::Float)),
|
|
|
|
StringLiteral(_) => Ok(MonoType::Const(TConst::StringT)),
|
2018-11-07 15:39:40 -08:00
|
|
|
_ => Ok(MonoType::Const(TConst::user("unimplemented")))
|
2018-11-07 03:39:31 -08:00
|
|
|
}
|
|
|
|
}
|
2018-11-06 16:47:34 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2018-11-07 16:39:32 -08:00
|
|
|
|
|
|
|
fn parse(input: &str) -> AST {
|
|
|
|
let tokens: Vec<::tokenizing::Token> = ::tokenizing::tokenize(input);
|
|
|
|
let mut parser = ::parsing::Parser::new(tokens);
|
|
|
|
parser.parse().unwrap()
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! type_test {
|
|
|
|
($input:expr, $correct:expr) => {
|
|
|
|
{
|
|
|
|
let mut tc = TypeContext::new();
|
|
|
|
let ast = parse($input);
|
|
|
|
tc.add_symbols(&ast);
|
|
|
|
assert_eq!($correct, tc.type_check(&ast).unwrap())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-11-06 16:47:34 -08:00
|
|
|
#[test]
|
|
|
|
fn basic_inference() {
|
|
|
|
|
2018-11-06 13:44:52 -08:00
|
|
|
}
|
|
|
|
}
|