2018-02-21 02:31:28 -08:00
|
|
|
use std::rc::Rc;
|
|
|
|
|
2019-01-07 13:00:37 -08:00
|
|
|
use crate::ast::*;
|
|
|
|
use crate::util::ScopeStack;
|
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
|
|
|
|
2018-11-08 20:30:17 -08:00
|
|
|
pub struct TypeContext<'a> {
|
2019-02-09 00:25:12 -08:00
|
|
|
variable_map: ScopeStack<'a, Rc<String>, ()>,
|
2019-02-10 05:33:55 -08:00
|
|
|
//evar_count: u32
|
2018-11-06 13:44:52 -08:00
|
|
|
}
|
|
|
|
|
2018-11-11 18:04:44 -08:00
|
|
|
/// `InferResult` is the monad in which type inference takes place.
|
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)]
|
2018-11-08 02:26:02 -08:00
|
|
|
struct TypeError { msg: String }
|
|
|
|
|
|
|
|
impl TypeError {
|
|
|
|
fn new<A>(msg: &str) -> InferResult<A> {
|
|
|
|
Err(TypeError { msg: msg.to_string() })
|
|
|
|
}
|
|
|
|
}
|
2018-11-06 16:47:34 -08:00
|
|
|
|
2019-02-10 04:30:37 -08:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Type {
|
|
|
|
Const(TypeConst),
|
|
|
|
Arrow(Box<Type>, Box<Type>)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum TypeConst {
|
|
|
|
Unit,
|
|
|
|
Nat,
|
|
|
|
Int,
|
|
|
|
Float,
|
|
|
|
StringT,
|
|
|
|
Bool,
|
|
|
|
Order,
|
|
|
|
UserDefined
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Type {
|
2019-02-10 05:31:58 -08:00
|
|
|
fn to_string(&self) -> String {
|
|
|
|
use self::Type::*;
|
|
|
|
use self::TypeConst::*;
|
|
|
|
match self {
|
|
|
|
Const(Unit) => format!("()"),
|
|
|
|
Const(Nat) => format!("Nat"),
|
|
|
|
Const(Int) => format!("Int"),
|
|
|
|
Const(Float) => format!("Float"),
|
|
|
|
Const(StringT) => format!("String"),
|
|
|
|
Const(Bool) => format!("Bool"),
|
|
|
|
Const(Order) => format!("Order"),
|
|
|
|
_ => format!("UNKNOWN TYPE"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-10 04:30:37 -08:00
|
|
|
|
2019-02-09 00:25:12 -08:00
|
|
|
/*
|
2018-11-11 18:04:44 -08:00
|
|
|
/// `Type` is parameterized by whether the type variables can be just universal, or universal or
|
|
|
|
/// existential.
|
2018-11-07 13:44:28 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2018-11-09 02:50:29 -08:00
|
|
|
enum Type<A> {
|
|
|
|
Var(A),
|
2018-11-07 15:39:40 -08:00
|
|
|
Const(TConst),
|
2018-11-09 02:50:29 -08:00
|
|
|
Arrow(Box<Type<A>>, Box<Type<A>>),
|
|
|
|
}
|
|
|
|
|
2018-11-10 16:33:42 -08:00
|
|
|
#[derive(Debug, Clone)]
|
2018-11-09 02:50:29 -08:00
|
|
|
enum TVar {
|
2018-11-10 16:33:42 -08:00
|
|
|
Univ(UVar),
|
2018-11-10 14:11:29 -08:00
|
|
|
Exist(ExistentialVar)
|
2018-11-08 02:26:02 -08:00
|
|
|
}
|
|
|
|
|
2018-11-10 16:33:42 -08:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct UVar(Rc<String>);
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
2018-11-09 02:50:29 -08:00
|
|
|
struct ExistentialVar(u32);
|
|
|
|
|
2018-11-10 16:33:42 -08:00
|
|
|
impl Type<UVar> {
|
|
|
|
fn to_tvar(&self) -> Type<TVar> {
|
|
|
|
match self {
|
|
|
|
Type::Var(UVar(name)) => Type::Var(TVar::Univ(UVar(name.clone()))),
|
|
|
|
Type::Const(ref c) => Type::Const(c.clone()),
|
|
|
|
Type::Arrow(a, b) => Type::Arrow(
|
|
|
|
Box::new(a.to_tvar()),
|
|
|
|
Box::new(b.to_tvar())
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Type<TVar> {
|
|
|
|
fn skolemize(&self) -> Type<UVar> {
|
|
|
|
match self {
|
|
|
|
Type::Var(TVar::Univ(uvar)) => Type::Var(uvar.clone()),
|
2018-11-13 02:39:02 -08:00
|
|
|
Type::Var(TVar::Exist(_)) => Type::Var(UVar(Rc::new(format!("sk")))),
|
2018-11-10 16:33:42 -08:00
|
|
|
Type::Const(ref c) => Type::Const(c.clone()),
|
|
|
|
Type::Arrow(a, b) => Type::Arrow(
|
|
|
|
Box::new(a.skolemize()),
|
|
|
|
Box::new(b.skolemize())
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-08 02:26:02 -08:00
|
|
|
impl TypeIdentifier {
|
2018-11-10 16:33:42 -08:00
|
|
|
fn to_monotype(&self) -> Type<UVar> {
|
2018-11-08 20:30:17 -08:00
|
|
|
match self {
|
2018-11-13 02:39:02 -08:00
|
|
|
TypeIdentifier::Tuple(_) => Type::Const(TConst::Nat),
|
2018-11-08 20:30:17 -08:00
|
|
|
TypeIdentifier::Singleton(TypeSingletonName { name, .. }) => {
|
|
|
|
match &name[..] {
|
2018-11-09 02:05:59 -08:00
|
|
|
"Nat" => Type::Const(TConst::Nat),
|
|
|
|
"Int" => Type::Const(TConst::Int),
|
|
|
|
"Float" => Type::Const(TConst::Float),
|
|
|
|
"Bool" => Type::Const(TConst::Bool),
|
|
|
|
"String" => Type::Const(TConst::StringT),
|
2018-11-13 02:39:02 -08:00
|
|
|
_ => Type::Const(TConst::Nat),
|
2018-11-08 20:30:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-08 02:26:02 -08:00
|
|
|
}
|
2018-11-07 03:39:31 -08:00
|
|
|
}
|
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-08 02:12:01 -08:00
|
|
|
Bool,
|
2018-11-07 15:39:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TConst {
|
|
|
|
fn user(name: &str) -> TConst {
|
|
|
|
TConst::User(Rc::new(name.to_string()))
|
|
|
|
}
|
|
|
|
}
|
2019-02-09 00:25:12 -08:00
|
|
|
*/
|
2018-11-07 15:39:40 -08:00
|
|
|
|
2018-11-08 20:30:17 -08:00
|
|
|
impl<'a> TypeContext<'a> {
|
|
|
|
pub fn new() -> TypeContext<'a> {
|
|
|
|
TypeContext {
|
|
|
|
variable_map: ScopeStack::new(None),
|
2019-02-10 05:33:55 -08:00
|
|
|
//evar_count: 0
|
2018-11-08 20:30:17 -08:00
|
|
|
}
|
2018-11-06 13:44:52 -08:00
|
|
|
}
|
|
|
|
|
2018-11-07 13:44:28 -08:00
|
|
|
pub fn typecheck(&mut self, ast: &AST) -> Result<String, String> {
|
2019-02-10 05:15:57 -08:00
|
|
|
let mut returned_type = Type::Const(TypeConst::Unit);
|
2019-02-10 04:42:30 -08:00
|
|
|
for statement in ast.0.iter() {
|
2019-02-10 05:15:57 -08:00
|
|
|
returned_type = self.typecheck_statement(statement.node()).map_err(|err| { err.msg })?
|
2019-02-10 04:42:30 -08:00
|
|
|
}
|
2019-02-10 05:31:58 -08:00
|
|
|
Ok(returned_type.to_string())
|
2019-02-10 04:42:30 -08:00
|
|
|
}
|
|
|
|
|
2019-02-10 05:15:57 -08:00
|
|
|
fn typecheck_statement(&mut self, statement: &Statement) -> InferResult<Type> {
|
2019-02-10 04:42:30 -08:00
|
|
|
match statement {
|
|
|
|
Statement::ExpressionStatement(e) => self.typecheck_expr(e.node()),
|
|
|
|
Statement::Declaration(decl) => self.typecheck_decl(decl),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-10 05:31:58 -08:00
|
|
|
fn typecheck_decl(&mut self, _decl: &Declaration) -> InferResult<Type> {
|
2019-02-10 05:15:57 -08:00
|
|
|
Ok(Type::Const(TypeConst::Unit))
|
2019-02-10 04:42:30 -08:00
|
|
|
}
|
|
|
|
|
2019-02-10 05:15:57 -08:00
|
|
|
fn typecheck_expr(&mut self, expr: &Expression) -> InferResult<Type> {
|
|
|
|
match expr {
|
|
|
|
Expression(expr_type, Some(_anno)) => {
|
|
|
|
//TODO here
|
|
|
|
self.typecheck_expr_type(expr_type)
|
|
|
|
},
|
|
|
|
Expression(expr_type, None) => self.typecheck_expr_type(expr_type)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn typecheck_expr_type(&mut self, expr: &ExpressionType) -> InferResult<Type> {
|
2019-02-10 05:31:58 -08:00
|
|
|
use self::ExpressionType::*;
|
|
|
|
Ok(match expr {
|
|
|
|
NatLiteral(_) => Type::Const(TypeConst::Nat),
|
|
|
|
BoolLiteral(_) => Type::Const(TypeConst::Bool),
|
2019-02-10 05:33:55 -08:00
|
|
|
FloatLiteral(_) => Type::Const(TypeConst::Float),
|
|
|
|
StringLiteral(_) => Type::Const(TypeConst::StringT),
|
2019-02-10 05:31:58 -08:00
|
|
|
_ => Type::Const(TypeConst::Unit)
|
|
|
|
})
|
2018-11-06 13:44:52 -08:00
|
|
|
}
|
|
|
|
}
|