Add ena crate for unification

This commit is contained in:
greg 2019-02-23 00:34:44 -08:00
parent f041cc17d2
commit 00a0de4431
3 changed files with 34 additions and 6 deletions

View File

@ -10,6 +10,7 @@ take_mut = "0.1.3"
maplit = "*"
lazy_static = "0.2.8"
failure = "0.1.2"
ena = "0.11.0"
schala-lang-codegen = { path = "../codegen" }

View File

@ -17,6 +17,7 @@ extern crate schala_repl;
extern crate schala_repl_codegen;
#[macro_use]
extern crate schala_lang_codegen;
extern crate ena;
use std::cell::RefCell;
use std::rc::Rc;

View File

@ -4,10 +4,16 @@ use std::rc::Rc;
// -nope, ghc deliberately does typechecking before desugaring to core
// cf. a history of haskell, peyton-jones
use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable};
use crate::ast::*;
use crate::util::ScopeStack;
use crate::builtin::{PrefixOp, BinOp};
use std::collections::HashMap;
use std::hash::Hash;
#[derive(Debug, Clone, PartialEq)]
pub struct TypeData {
ty: Option<Type>
@ -23,6 +29,7 @@ pub type TypeName = Rc<String>;
pub struct TypeContext<'a> {
variable_map: ScopeStack<'a, Rc<String>, Type>,
unification_table: InPlaceUnificationTable<TypeVar>,
//evar_count: u32
}
@ -49,8 +56,15 @@ pub enum Type {
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeVar(String);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeVar(usize);
impl UnifyKey for TypeVar {
type Value = ();
fn index(&self) -> u32 { self.0 as u32 }
fn from_index(u: u32) -> TypeVar { TypeVar(u as usize) }
fn tag() -> &'static str { "TypeVar" }
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypeConst {
@ -190,6 +204,7 @@ impl<'a> TypeContext<'a> {
pub fn new() -> TypeContext<'a> {
TypeContext {
variable_map: ScopeStack::new(None),
unification_table: UnificationTable::new(),
//evar_count: 0
}
}
@ -315,6 +330,7 @@ impl<'a> TypeContext<'a> {
}
fn lambda(&mut self, params: &Vec<FormalParam>, type_anno: &Option<TypeIdentifier>, body: &Block) -> InferResult<Type> {
Ok(ty!(Unit))
}
@ -336,10 +352,20 @@ impl<'a> TypeContext<'a> {
fn unify(&mut self, t1: Type, t2: Type) -> InferResult<Type> {
use self::Type::*;
Ok(match (t1, t2) {
(Const(ref c1), Const(ref c2)) if c1 == c2 => Const(c1.clone()), //choice of c1 is arbitrary I *think*
(a, b) => return TypeError::new(format!("{:?} and {:?} do not unify", a, b)),
})
use std::collections::hash_map::Entry;
match (t1, t2) {
(Const(ref c1), Const(ref c2)) if c1 == c2 => Ok(Const(c1.clone())), //choice of c1 is arbitrary I *think*
(Const(ref c1), Var(ref v2)) => {
//TODO flesh this out!
Ok(Const(c1.clone()))
},
(a @ Var(_), b @ Const(_)) => self.unify(b, a),
(Var(v1), Var(v2)) => {
panic!()
},
(a, b) => TypeError::new(format!("{:?} and {:?} do not unify", a, b)),
}
}
}