Add ena crate for unification
This commit is contained in:
parent
f041cc17d2
commit
00a0de4431
@ -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" }
|
||||
|
@ -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;
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user