Renamed all the type-related types

This commit is contained in:
greg 2017-10-10 02:17:07 -07:00
parent 57536e6399
commit d9e8178a90
1 changed files with 52 additions and 38 deletions

View File

@ -20,32 +20,37 @@ use schala_lang::parsing::{AST, Statement, Declaration, Signature, Expression, E
// typeInfer :: Expr a -> Matching (Type a) // typeInfer :: Expr a -> Matching (Type a)
// unify :: Type a -> Type b -> Matching (Type c) // unify :: Type a -> Type b -> Matching (Type c)
#[derive(Debug, PartialEq, Clone)]
pub enum Type {
TVar(TypeVar),
TConst(TypeConst),
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum TypeVariable { pub enum TypeVar {
Univ(UVar), Univ(String),
Exist(u64), Exist(u64),
} }
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum UVar { pub enum TypeConst {
Integer, Integer,
Float, Float,
String, StringT,
Boolean, Boolean,
Unit, Unit,
Function(Box<TypeVariable>, Box<TypeVariable>), FunctionT(Box<Type>, Box<Type>),
Bottom, Bottom,
} }
type TypeCheckResult = Result<TypeVariable, String>; type TypeCheckResult = Result<Type, String>;
#[derive(Debug, PartialEq, Eq, Hash)] #[derive(Debug, PartialEq, Eq, Hash)]
struct PathSpecifier(Rc<String>); struct PathSpecifier(Rc<String>);
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
struct TypeContextEntry { struct TypeContextEntry {
type_var: TypeVariable, type_var: Type,
constant: bool constant: bool
} }
@ -99,46 +104,51 @@ impl TypeContext {
pub fn debug_symbol_table(&self) -> String { pub fn debug_symbol_table(&self) -> String {
format!("Symbol table:\n {:?}", self.symbol_table) format!("Symbol table:\n {:?}", self.symbol_table)
} }
fn get_existential_type(&mut self) -> TypeVariable { fn get_existential_type(&mut self) -> Type {
let ret = TypeVariable::Exist(self.existential_type_label_count); let ret = Type::TVar(TypeVar::Exist(self.existential_type_label_count));
self.existential_type_label_count += 1; self.existential_type_label_count += 1;
ret ret
} }
fn from_anno(&mut self, anno: &TypeName) -> TypeVariable { fn from_anno(&mut self, anno: &TypeName) -> Type {
use self::TypeVariable::*; use self::Type::*;
use self::UVar::*; use self::TypeConst::*;
match anno { match anno {
&TypeName::Singleton { ref name, .. } => { &TypeName::Singleton { ref name, .. } => {
match name.as_ref().as_ref() { match name.as_ref().as_ref() {
"Int" => Univ(Integer), "Int" => TConst(Integer),
"Bool" => Univ(Boolean), "Bool" => TConst(Boolean),
_ => self.get_existential_type() _ => self.get_existential_type()
} }
}, },
_ => Univ(Bottom), _ => TConst(Bottom)
} }
} }
fn from_signature(&mut self, sig: &Signature) -> TypeVariable { fn from_signature(&mut self, sig: &Signature) -> Type {
use self::TypeVariable::Univ; use self::Type::*;
use self::UVar::{Unit, Function}; use self::TypeConst::*;
let return_type = sig.type_anno.as_ref().map(|anno| self.from_anno(&anno)).unwrap_or_else(|| { self.get_existential_type() }); let return_type = sig.type_anno.as_ref().map(|anno| self.from_anno(&anno)).unwrap_or_else(|| { self.get_existential_type() });
if sig.params.len() == 0 { if sig.params.len() == 0 {
Univ(Function(Box::new(Univ(Unit)), Box::new(return_type))) TConst(FunctionT(Box::new(TConst(Unit)), Box::new(return_type)))
} else { } else {
let mut output_type = return_type; let mut output_type = return_type;
for p in sig.params.iter() { for p in sig.params.iter() {
let p_type = p.1.as_ref().map(|anno| self.from_anno(anno)).unwrap_or_else(|| { self.get_existential_type() }); let p_type = p.1.as_ref().map(|anno| self.from_anno(anno)).unwrap_or_else(|| { self.get_existential_type() });
output_type = Univ(Function(Box::new(p_type), Box::new(output_type))); output_type = TConst(FunctionT(Box::new(p_type), Box::new(output_type)));
} }
output_type output_type
} }
} }
pub fn type_check(&mut self, ast: &AST) -> TypeCheckResult { pub fn type_check(&mut self, ast: &AST) -> TypeCheckResult {
let mut last = TypeVariable::Univ(UVar::Unit); use self::Type::*;
use self::TypeConst::*;
let mut last = TConst(Unit);
for statement in ast.0.iter() { for statement in ast.0.iter() {
match statement { match statement {
&Statement::Declaration(ref _decl) => { &Statement::Declaration(ref _decl) => {
@ -154,17 +164,18 @@ impl TypeContext {
fn infer(&mut self, expr: &Expression) -> TypeCheckResult { fn infer(&mut self, expr: &Expression) -> TypeCheckResult {
use self::ExpressionType::*; use self::ExpressionType::*;
use self::TypeVariable::*; use self::Type::*;
use self::TypeConst::*;
Ok(match (&expr.0, &expr.1) { Ok(match (&expr.0, &expr.1) {
(ref _t, &Some(ref anno)) => { (ref _t, &Some(ref anno)) => {
//TODO make this better, //TODO make this better,
self.from_anno(anno) self.from_anno(anno)
}, },
(&IntLiteral(_), _) => Univ(UVar::Integer), (&IntLiteral(_), _) => TConst(Integer),
(&FloatLiteral(_), _) => Univ(UVar::Float), (&FloatLiteral(_), _) => TConst(Float),
(&StringLiteral(_), _) => Univ(UVar::String), (&StringLiteral(_), _) => TConst(StringT),
(&BoolLiteral(_), _) => Univ(UVar::Boolean), (&BoolLiteral(_), _) => TConst(Boolean),
(&Variable(ref name), _) => self.lookup(name).map(|entry| entry.type_var) (&Variable(ref name), _) => self.lookup(name).map(|entry| entry.type_var)
.ok_or(format!("Couldn't find {}", name))?, .ok_or(format!("Couldn't find {}", name))?,
(&BinExp(ref op, box ref lhs, box ref rhs), _) => { (&BinExp(ref op, box ref lhs, box ref rhs), _) => {
@ -177,31 +188,33 @@ impl TypeContext {
let f_type = self.infer(&*f)?; let f_type = self.infer(&*f)?;
let arg_type = self.infer(arguments.get(0).unwrap())?; // TODO fix later let arg_type = self.infer(arguments.get(0).unwrap())?; // TODO fix later
match f_type { match f_type {
Univ(UVar::Function(box t1, box ret_type)) => { TConst(FunctionT(box t1, box ret_type)) => {
let _ = self.unify(&t1, &arg_type)?; let _ = self.unify(&t1, &arg_type)?;
ret_type ret_type
}, },
_ => return Err(format!("Type error")) _ => return Err(format!("Type error"))
} }
}, },
_ => Univ(UVar::Unit), _ => TConst(Unit)
}) })
} }
fn infer_op(&mut self, _op: &Operation) -> TypeCheckResult { fn infer_op(&mut self, _op: &Operation) -> TypeCheckResult {
use self::TypeVariable::*; use self::Type::*;
use self::TypeConst::*;
Ok( Ok(
Univ(UVar::Function( TConst(FunctionT(
Box::new(Univ(UVar::Integer)), Box::new(TConst(Integer)),
Box::new(Univ(UVar::Function( Box::new(TConst(FunctionT(
Box::new(Univ(UVar::Integer)), Box::new(TConst(Integer)),
Box::new(Univ(UVar::Integer)) Box::new(TConst(Integer))
))) )))
)) ))
) )
} }
fn unify(&mut self, t1: &TypeVariable, t2: &TypeVariable) -> TypeCheckResult { fn unify(&mut self, t1: &Type, t2: &Type) -> TypeCheckResult {
if t1 == t2 { if t1 == t2 {
Ok(t1.clone()) Ok(t1.clone())
} else { } else {
@ -212,8 +225,9 @@ impl TypeContext {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{TypeContext, TypeVariable, UVar}; use super::{Type, TypeVar, TypeConst, TypeContext};
use super::TypeVariable::*; use super::Type::*;
use super::TypeConst::*;
use schala_lang::parsing::{parse, tokenize}; use schala_lang::parsing::{parse, tokenize};
macro_rules! type_test { macro_rules! type_test {
@ -228,7 +242,7 @@ mod tests {
#[test] #[test]
fn basic_inference() { fn basic_inference() {
type_test!("30", Univ(UVar::Integer)) type_test!("30", TConst(Integer));
} }
} }