forked from M-Labs/nac3
1
0
Fork 0

most of unification...

This commit is contained in:
pca006132 2021-07-14 17:20:12 +08:00
parent 97fe450a0b
commit 1df3f4e757
1 changed files with 71 additions and 25 deletions

View File

@ -2,7 +2,7 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
use generational_arena::{Arena, Index}; use generational_arena::{Arena, Index};
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::iter::{empty, once, Iterator}; use std::iter::once;
use std::mem::swap; use std::mem::swap;
use std::rc::Rc; use std::rc::Rc;
@ -155,7 +155,7 @@ struct Unifier {
} }
impl Unifier { impl Unifier {
fn unify(&self, a: Type, b: Type) -> Result<(), String> { fn unify(&self, mut a: Type, mut b: Type) -> Result<(), String> {
let (mut i_a, mut i_b) = { let (mut i_a, mut i_b) = {
let mut table = self.unification_table.borrow_mut(); let mut table = self.unification_table.borrow_mut();
(table.probe_value(a), table.probe_value(b)) (table.probe_value(a), table.probe_value(b))
@ -165,7 +165,7 @@ impl Unifier {
return Ok(()); return Ok(());
} }
let (ty_a_cell, ty_b_cell) = { let (mut ty_a_cell, mut ty_b_cell) = {
let arena = self.type_arena.borrow(); let arena = self.type_arena.borrow();
( (
arena.get(i_a.0).unwrap().clone(), arena.get(i_a.0).unwrap().clone(),
@ -173,15 +173,17 @@ impl Unifier {
) )
}; };
let mut ty_a = ty_a_cell.borrow(); let (ty_a, ty_b) = {
let mut ty_b = ty_b_cell.borrow();
// simplify our pattern matching... // simplify our pattern matching...
if ty_a.kind_le(&ty_b) { if ty_a_cell.borrow().kind_le(&ty_b_cell.borrow()) {
swap(&mut a, &mut b);
swap(&mut i_a, &mut i_b); swap(&mut i_a, &mut i_b);
swap(&mut ty_a, &mut ty_b); swap(&mut ty_a_cell, &mut ty_b_cell);
} }
(ty_a_cell.borrow(), ty_b_cell.borrow())
};
self.occur_check(i_a, b)?;
match &*ty_a { match &*ty_a {
TypeEnum::TVar { .. } => { TypeEnum::TVar { .. } => {
match *ty_b { match *ty_b {
@ -195,12 +197,11 @@ impl Unifier {
} else { } else {
i_a i_a
} }
} };
.0; self.type_arena.borrow_mut().remove(old.0);
self.type_arena.borrow_mut().remove(old);
} }
_ => { _ => {
// TODO: type variables bound check and occur check // TODO: type variables bound check
self.set_a_to_b(a, b); self.set_a_to_b(a, b);
} }
} }
@ -208,7 +209,6 @@ impl Unifier {
TypeEnum::TSeq { map: map1 } => { TypeEnum::TSeq { map: map1 } => {
match &*ty_b { match &*ty_b {
TypeEnum::TSeq { map: map2 } => { TypeEnum::TSeq { map: map2 } => {
self.set_a_to_b(a, b);
drop(ty_a); drop(ty_a);
if let TypeEnum::TSeq { map: map1 } = &mut *ty_a_cell.as_ref().borrow_mut() if let TypeEnum::TSeq { map: map1 } = &mut *ty_a_cell.as_ref().borrow_mut()
{ {
@ -223,9 +223,9 @@ impl Unifier {
} else { } else {
unreachable!() unreachable!()
} }
self.set_a_to_b(a, b);
} }
TypeEnum::TTuple { ty: types } => { TypeEnum::TTuple { ty: types } => {
self.set_a_to_b(a, b);
let len = types.len() as u32; let len = types.len() as u32;
for (k, v) in map1.iter() { for (k, v) in map1.iter() {
if *k >= len { if *k >= len {
@ -237,12 +237,13 @@ impl Unifier {
} }
self.unify(*v, types[*k as usize])?; self.unify(*v, types[*k as usize])?;
} }
self.set_a_to_b(a, b);
} }
TypeEnum::TList { ty } => { TypeEnum::TList { ty } => {
self.set_a_to_b(a, b);
for v in map1.values() { for v in map1.values() {
self.unify(*v, *ty)?; self.unify(*v, *ty)?;
} }
self.set_a_to_b(a, b);
} }
_ => { _ => {
return self.report_kind_error(&*ty_a, &*ty_b); return self.report_kind_error(&*ty_a, &*ty_b);
@ -258,26 +259,25 @@ impl Unifier {
ty2.len() ty2.len()
)); ));
} }
self.set_a_to_b(a, b); for (x, y) in ty1.iter().zip(ty2.iter()) {
for (a, b) in ty1.iter().zip(ty2.iter()) { self.unify(*x, *y)?;
self.unify(*a, *b)?;
} }
self.set_a_to_b(a, b);
} else { } else {
return self.report_kind_error(&*ty_a, &*ty_b); return self.report_kind_error(&*ty_a, &*ty_b);
} }
} }
TypeEnum::TList { ty: ty1 } => { TypeEnum::TList { ty: ty1 } => {
if let TypeEnum::TList { ty: ty2 } = *ty_b { if let TypeEnum::TList { ty: ty2 } = *ty_b {
self.set_a_to_b(a, b);
self.unify(*ty1, ty2)?; self.unify(*ty1, ty2)?;
self.set_a_to_b(a, b);
} else { } else {
return self.report_kind_error(&*ty_a, &*ty_b); return self.report_kind_error(&*ty_a, &*ty_b);
} }
} }
TypeEnum::TRecord { .. } => { TypeEnum::TRecord { fields: fields1 } => {
match &*ty_b { match &*ty_b {
TypeEnum::TRecord { fields: fields2 } => { TypeEnum::TRecord { fields: fields2 } => {
self.set_a_to_b(a, b);
drop(ty_a); drop(ty_a);
if let TypeEnum::TRecord { fields: fields1 } = if let TypeEnum::TRecord { fields: fields1 } =
&mut *ty_a_cell.as_ref().borrow_mut() &mut *ty_a_cell.as_ref().borrow_mut()
@ -292,13 +292,59 @@ impl Unifier {
} else { } else {
unreachable!() unreachable!()
} }
self.set_a_to_b(a, b);
}
TypeEnum::TObj {
fields: fields2, ..
} => {
for (key, value) in fields1.iter() {
if let Some(ty) = fields2.get(key) {
self.unify(*ty, *value)?;
} else {
return Err(format!("No such attribute {}", key));
}
}
self.set_a_to_b(a, b);
}
TypeEnum::TVirtual { ty } => {
// not sure if this is correct...
self.unify(a, *ty)?;
self.set_a_to_b(a, b);
} }
// obj...
_ => { _ => {
return self.report_kind_error(&*ty_a, &*ty_b); return self.report_kind_error(&*ty_a, &*ty_b);
} }
} }
} }
TypeEnum::TObj {
obj_id: id1,
params: params1,
..
} => {
if let TypeEnum::TObj {
obj_id: id2,
params: params2,
..
} = &*ty_b
{
if id1 != id2 {
return Err(format!("Cannot unify objects with ID {} and {}", id1, id2));
}
for (x, y) in params1.values().zip(params2.values()) {
self.unify(*x, *y)?;
}
self.set_a_to_b(a, b);
} else {
return self.report_kind_error(&*ty_a, &*ty_b);
}
}
TypeEnum::TVirtual { ty: ty1 } => {
if let TypeEnum::TVirtual { ty: ty2 } = &*ty_b {
self.unify(*ty1, *ty2)?;
} else {
return self.report_kind_error(&*ty_a, &*ty_b);
}
}
_ => unimplemented!(), _ => unimplemented!(),
} }
Ok(()) Ok(())