Add ena crate for unification
This commit is contained in:
parent
f041cc17d2
commit
00a0de4431
@ -10,6 +10,7 @@ take_mut = "0.1.3"
|
|||||||
maplit = "*"
|
maplit = "*"
|
||||||
lazy_static = "0.2.8"
|
lazy_static = "0.2.8"
|
||||||
failure = "0.1.2"
|
failure = "0.1.2"
|
||||||
|
ena = "0.11.0"
|
||||||
|
|
||||||
|
|
||||||
schala-lang-codegen = { path = "../codegen" }
|
schala-lang-codegen = { path = "../codegen" }
|
||||||
|
@ -17,6 +17,7 @@ extern crate schala_repl;
|
|||||||
extern crate schala_repl_codegen;
|
extern crate schala_repl_codegen;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate schala_lang_codegen;
|
extern crate schala_lang_codegen;
|
||||||
|
extern crate ena;
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -4,10 +4,16 @@ use std::rc::Rc;
|
|||||||
// -nope, ghc deliberately does typechecking before desugaring to core
|
// -nope, ghc deliberately does typechecking before desugaring to core
|
||||||
// cf. a history of haskell, peyton-jones
|
// cf. a history of haskell, peyton-jones
|
||||||
|
|
||||||
|
use ena::unify::{UnifyKey, InPlaceUnificationTable, UnificationTable};
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
use crate::builtin::{PrefixOp, BinOp};
|
use crate::builtin::{PrefixOp, BinOp};
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct TypeData {
|
pub struct TypeData {
|
||||||
ty: Option<Type>
|
ty: Option<Type>
|
||||||
@ -23,6 +29,7 @@ pub type TypeName = Rc<String>;
|
|||||||
|
|
||||||
pub struct TypeContext<'a> {
|
pub struct TypeContext<'a> {
|
||||||
variable_map: ScopeStack<'a, Rc<String>, Type>,
|
variable_map: ScopeStack<'a, Rc<String>, Type>,
|
||||||
|
unification_table: InPlaceUnificationTable<TypeVar>,
|
||||||
//evar_count: u32
|
//evar_count: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,8 +56,15 @@ pub enum Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct TypeVar(String);
|
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)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum TypeConst {
|
pub enum TypeConst {
|
||||||
@ -190,6 +204,7 @@ impl<'a> TypeContext<'a> {
|
|||||||
pub fn new() -> TypeContext<'a> {
|
pub fn new() -> TypeContext<'a> {
|
||||||
TypeContext {
|
TypeContext {
|
||||||
variable_map: ScopeStack::new(None),
|
variable_map: ScopeStack::new(None),
|
||||||
|
unification_table: UnificationTable::new(),
|
||||||
//evar_count: 0
|
//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> {
|
fn lambda(&mut self, params: &Vec<FormalParam>, type_anno: &Option<TypeIdentifier>, body: &Block) -> InferResult<Type> {
|
||||||
|
|
||||||
Ok(ty!(Unit))
|
Ok(ty!(Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,10 +352,20 @@ impl<'a> TypeContext<'a> {
|
|||||||
|
|
||||||
fn unify(&mut self, t1: Type, t2: Type) -> InferResult<Type> {
|
fn unify(&mut self, t1: Type, t2: Type) -> InferResult<Type> {
|
||||||
use self::Type::*;
|
use self::Type::*;
|
||||||
Ok(match (t1, t2) {
|
use std::collections::hash_map::Entry;
|
||||||
(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)),
|
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