forked from M-Labs/nac3
cleanup: we don't actually need arena
This commit is contained in:
parent
c2d00aa762
commit
62736bd4bf
|
@ -75,12 +75,6 @@ version = "1.0.68"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
|
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "0.1.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -115,7 +109,7 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"dirs-sys-next",
|
"dirs-sys-next",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -151,22 +145,13 @@ version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generational-arena"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
@ -177,7 +162,7 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
@ -280,7 +265,7 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -386,7 +371,7 @@ version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -400,7 +385,6 @@ name = "nac3core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ena",
|
"ena",
|
||||||
"generational-arena",
|
|
||||||
"indoc 1.0.3",
|
"indoc 1.0.3",
|
||||||
"inkwell",
|
"inkwell",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
@ -499,7 +483,7 @@ version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"instant",
|
"instant",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
|
@ -852,7 +836,7 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b114ece25254e97bf48dd4bfc2a12bad0647adacfe4cae1247a9ca6ad302cec"
|
checksum = "3b114ece25254e97bf48dd4bfc2a12bad0647adacfe4cae1247a9ca6ad302cec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
|
|
|
@ -10,7 +10,6 @@ num-traits = "0.2"
|
||||||
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm10-0"] }
|
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm10-0"] }
|
||||||
rustpython-parser = { git = "https://github.com/RustPython/RustPython", branch = "master" }
|
rustpython-parser = { git = "https://github.com/RustPython/RustPython", branch = "master" }
|
||||||
indoc = "1.0"
|
indoc = "1.0"
|
||||||
generational-arena = "0.2"
|
|
||||||
ena = "0.14"
|
ena = "0.14"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -5,7 +5,6 @@ extern crate num_bigint;
|
||||||
extern crate inkwell;
|
extern crate inkwell;
|
||||||
extern crate rustpython_parser;
|
extern crate rustpython_parser;
|
||||||
extern crate indoc;
|
extern crate indoc;
|
||||||
extern crate generational_arena;
|
|
||||||
extern crate ena;
|
extern crate ena;
|
||||||
|
|
||||||
mod typecheck;
|
mod typecheck;
|
||||||
|
|
|
@ -1,29 +1,20 @@
|
||||||
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
||||||
use generational_arena::{Arena, Index};
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// Order:
|
|
||||||
// TVar
|
|
||||||
// |--> TSeq
|
|
||||||
// | |--> TTuple
|
|
||||||
// | `--> TList
|
|
||||||
// |--> TRecord
|
|
||||||
// | |--> TObj
|
|
||||||
// | `--> TVirtual
|
|
||||||
// `--> TCall
|
|
||||||
// `--> TFunc
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
/// Handle for a type, implementated as a key in the unification table.
|
||||||
pub struct Type(u32);
|
pub struct Type(u32);
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone)]
|
||||||
pub struct TypeIndex(Index);
|
pub struct TypeCell(Rc<RefCell<TypeEnum>>);
|
||||||
|
|
||||||
impl UnifyValue for TypeIndex {
|
impl UnifyValue for TypeCell {
|
||||||
type Error = NoError;
|
type Error = NoError;
|
||||||
fn unify_values(_: &Self, value2: &Self) -> Result<Self, Self::Error> {
|
fn unify_values(_: &Self, value2: &Self) -> Result<Self, Self::Error> {
|
||||||
// WARN: depends on the implementation details of ena.
|
// WARN: depends on the implementation details of ena.
|
||||||
|
@ -31,12 +22,12 @@ impl UnifyValue for TypeIndex {
|
||||||
// and assign the type by `union_value(key, new_value)`, which set the
|
// and assign the type by `union_value(key, new_value)`, which set the
|
||||||
// value as `unify_values(key.value, new_value)`. So, we need to return
|
// value as `unify_values(key.value, new_value)`. So, we need to return
|
||||||
// the right one.
|
// the right one.
|
||||||
Ok(*value2)
|
Ok(value2.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnifyKey for Type {
|
impl UnifyKey for Type {
|
||||||
type Value = TypeIndex;
|
type Value = TypeCell;
|
||||||
fn index(&self) -> u32 {
|
fn index(&self) -> u32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
@ -48,6 +39,14 @@ impl UnifyKey for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for TypeCell {
|
||||||
|
type Target = Rc<RefCell<TypeEnum>>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &<Self as Deref>::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type Mapping<K, V = Type> = HashMap<K, V>;
|
pub type Mapping<K, V = Type> = HashMap<K, V>;
|
||||||
pub type VarMap = Mapping<u32>;
|
pub type VarMap = Mapping<u32>;
|
||||||
|
|
||||||
|
@ -104,18 +103,63 @@ pub enum TypeEnum {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Order:
|
||||||
|
// TVar
|
||||||
|
// |--> TSeq
|
||||||
|
// | |--> TTuple
|
||||||
|
// | `--> TList
|
||||||
|
// |--> TRecord
|
||||||
|
// | |--> TObj
|
||||||
|
// | `--> TVirtual
|
||||||
|
// `--> TCall
|
||||||
|
// `--> TFunc
|
||||||
|
|
||||||
|
// We encode the types as natural numbers, and subtyping relation as divisibility.
|
||||||
|
// If a | b, b <: a.
|
||||||
|
// We assign unique prime numbers (1 to TVar, everything is a subtype of it) to each type:
|
||||||
|
// TVar = 1
|
||||||
|
// |--> TSeq = 2
|
||||||
|
// | |--> TTuple = 3
|
||||||
|
// | `--> TList = 5
|
||||||
|
// |--> TRecord = 7
|
||||||
|
// | |--> TObj = 11
|
||||||
|
// | `--> TVirtual = 13
|
||||||
|
// `--> TCall = 17
|
||||||
|
// `--> TFunc = 21
|
||||||
|
//
|
||||||
|
// And then, based on the subtyping relation, multiply them together...
|
||||||
|
// TVar = 1
|
||||||
|
// |--> TSeq = 2 * TVar
|
||||||
|
// | |--> TTuple = 3 * TSeq * TVar
|
||||||
|
// | `--> TList = 5 * TSeq * TVar
|
||||||
|
// |--> TRecord = 7 * TVar
|
||||||
|
// | |--> TObj = 11 * TRecord * TVar
|
||||||
|
// | `--> TVirtual = 13 * TRecord * TVar
|
||||||
|
// `--> TCall = 17 * TVar
|
||||||
|
// `--> TFunc = 21 * TCall * TVar
|
||||||
|
|
||||||
impl TypeEnum {
|
impl TypeEnum {
|
||||||
fn get_int(&self) -> i32 {
|
fn get_int(&self) -> i32 {
|
||||||
|
const TVAR: i32 = 1;
|
||||||
|
const TSEQ: i32 = 2;
|
||||||
|
const TTUPLE: i32 = 3;
|
||||||
|
const TLIST: i32 = 5;
|
||||||
|
const TRECORD: i32 = 7;
|
||||||
|
const TOBJ: i32 = 11;
|
||||||
|
const TVIRTUAL: i32 = 13;
|
||||||
|
const TCALL: i32 = 17;
|
||||||
|
const TFUNC: i32 = 21;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
TypeEnum::TVar { .. } => 1,
|
TypeEnum::TVar { .. } => TVAR,
|
||||||
TypeEnum::TSeq { .. } => 5,
|
TypeEnum::TSeq { .. } => TSEQ * TVAR,
|
||||||
TypeEnum::TTuple { .. } => 10,
|
TypeEnum::TTuple { .. } => TTUPLE * TSEQ * TVAR,
|
||||||
TypeEnum::TList { .. } => 15,
|
TypeEnum::TList { .. } => TLIST * TSEQ * TVAR,
|
||||||
TypeEnum::TRecord { .. } => 7,
|
TypeEnum::TRecord { .. } => TRECORD * TVAR,
|
||||||
TypeEnum::TObj { .. } => 14,
|
TypeEnum::TObj { .. } => TOBJ * TRECORD * TVAR,
|
||||||
TypeEnum::TVirtual { .. } => 21,
|
TypeEnum::TVirtual { .. } => TVIRTUAL * TRECORD * TVAR,
|
||||||
TypeEnum::TCall { .. } => 11,
|
TypeEnum::TCall { .. } => TCALL * TVAR,
|
||||||
TypeEnum::TFunc { .. } => 22,
|
TypeEnum::TFunc { .. } => TFUNC * TCALL * TVAR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +170,7 @@ impl TypeEnum {
|
||||||
(a % b) == 0
|
(a % b) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_kind_name(&self) -> &'static str {
|
pub fn get_type_name(&self) -> &'static str {
|
||||||
// this function is for debugging only...
|
// this function is for debugging only...
|
||||||
// a proper to_str implementation requires the context
|
// a proper to_str implementation requires the context
|
||||||
match self {
|
match self {
|
||||||
|
@ -143,6 +187,12 @@ impl TypeEnum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for TypeCell {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(&self.borrow().get_type_name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ObjDef {
|
pub struct ObjDef {
|
||||||
name: String,
|
name: String,
|
||||||
fields: Mapping<String>,
|
fields: Mapping<String>,
|
||||||
|
@ -150,7 +200,6 @@ pub struct ObjDef {
|
||||||
|
|
||||||
pub struct Unifier {
|
pub struct Unifier {
|
||||||
unification_table: RefCell<InPlaceUnificationTable<Type>>,
|
unification_table: RefCell<InPlaceUnificationTable<Type>>,
|
||||||
type_arena: RefCell<Arena<Rc<RefCell<TypeEnum>>>>,
|
|
||||||
obj_def_table: Vec<ObjDef>,
|
obj_def_table: Vec<ObjDef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,53 +207,43 @@ impl Unifier {
|
||||||
pub fn new() -> Unifier {
|
pub fn new() -> Unifier {
|
||||||
Unifier {
|
Unifier {
|
||||||
unification_table: RefCell::new(InPlaceUnificationTable::new()),
|
unification_table: RefCell::new(InPlaceUnificationTable::new()),
|
||||||
type_arena: RefCell::new(Arena::new()),
|
|
||||||
obj_def_table: Vec::new(),
|
obj_def_table: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register a type to the unifier.
|
||||||
|
/// Returns a key in the unification_table.
|
||||||
pub fn add_ty(&self, a: TypeEnum) -> Type {
|
pub fn add_ty(&self, a: TypeEnum) -> Type {
|
||||||
let index = self.type_arena.borrow_mut().insert(Rc::new(a.into()));
|
|
||||||
self.unification_table
|
self.unification_table
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.new_key(TypeIndex(index))
|
.new_key(TypeCell(Rc::new(a.into())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the TypeEnum of a type.
|
||||||
pub fn get_ty(&self, a: Type) -> Rc<RefCell<TypeEnum>> {
|
pub fn get_ty(&self, a: Type) -> Rc<RefCell<TypeEnum>> {
|
||||||
let mut table = self.unification_table.borrow_mut();
|
let mut table = self.unification_table.borrow_mut();
|
||||||
let arena = self.type_arena.borrow();
|
table.probe_value(a).0
|
||||||
arena.get(table.probe_value(a).0).unwrap().clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unify(&self, mut a: Type, mut b: Type) -> Result<(), String> {
|
pub fn unify(&self, mut a: Type, mut b: Type) -> Result<(), String> {
|
||||||
let (mut i_a, mut i_b) = {
|
let (mut ty_a_cell, mut ty_b_cell) = {
|
||||||
let mut table = self.unification_table.borrow_mut();
|
let mut table = self.unification_table.borrow_mut();
|
||||||
(table.probe_value(a), table.probe_value(b))
|
if table.unioned(a, b) {
|
||||||
};
|
|
||||||
|
|
||||||
if i_a == i_b {
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
(table.probe_value(a), table.probe_value(b))
|
||||||
let (mut ty_a_cell, mut ty_b_cell) = {
|
|
||||||
let arena = self.type_arena.borrow();
|
|
||||||
(
|
|
||||||
arena.get(i_a.0).unwrap().clone(),
|
|
||||||
arena.get(i_b.0).unwrap().clone(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (ty_a, ty_b) = {
|
let (ty_a, ty_b) = {
|
||||||
// simplify our pattern matching...
|
// simplify our pattern matching...
|
||||||
if ty_a_cell.borrow().kind_le(&ty_b_cell.borrow()) {
|
if ty_a_cell.borrow().kind_le(&ty_b_cell.borrow()) {
|
||||||
swap(&mut a, &mut b);
|
swap(&mut a, &mut b);
|
||||||
swap(&mut i_a, &mut i_b);
|
|
||||||
swap(&mut ty_a_cell, &mut ty_b_cell);
|
swap(&mut ty_a_cell, &mut ty_b_cell);
|
||||||
}
|
}
|
||||||
(ty_a_cell.borrow(), ty_b_cell.borrow())
|
(ty_a_cell.borrow(), ty_b_cell.borrow())
|
||||||
};
|
};
|
||||||
|
|
||||||
self.occur_check(i_a, b)?;
|
self.occur_check(a, b)?;
|
||||||
match &*ty_a {
|
match &*ty_a {
|
||||||
TypeEnum::TVar { .. } => {
|
TypeEnum::TVar { .. } => {
|
||||||
// TODO: type variables bound check...
|
// TODO: type variables bound check...
|
||||||
|
@ -356,30 +395,26 @@ impl Unifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_a_to_b(&self, a: Type, b: Type) {
|
fn set_a_to_b(&self, a: Type, b: Type) {
|
||||||
// unify a and b together, and set the value to b's value this would
|
// unify a and b together, and set the value to b's value.
|
||||||
// also deallocate a's previous value in the arena to save space...
|
|
||||||
let mut table = self.unification_table.borrow_mut();
|
let mut table = self.unification_table.borrow_mut();
|
||||||
let i_a = table.probe_value(a);
|
let ty_b = table.probe_value(b);
|
||||||
let i_b = table.probe_value(b);
|
|
||||||
table.union(a, b);
|
table.union(a, b);
|
||||||
table.union_value(a, i_b);
|
table.union_value(a, ty_b);
|
||||||
self.type_arena.borrow_mut().remove(i_a.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_kind_error(&self, a: &TypeEnum, b: &TypeEnum) -> Result<(), String> {
|
fn report_kind_error(&self, a: &TypeEnum, b: &TypeEnum) -> Result<(), String> {
|
||||||
Err(format!(
|
Err(format!(
|
||||||
"Cannot unify {} with {}",
|
"Cannot unify {} with {}",
|
||||||
a.get_kind_name(),
|
a.get_type_name(),
|
||||||
b.get_kind_name()
|
b.get_type_name()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn occur_check(&self, a: TypeIndex, b: Type) -> Result<(), String> {
|
fn occur_check(&self, a: Type, b: Type) -> Result<(), String> {
|
||||||
let i_b = self.unification_table.borrow_mut().probe_value(b);
|
if self.unification_table.borrow_mut().unioned(a, b) {
|
||||||
if a == i_b {
|
|
||||||
return Err("Recursive type is prohibited.".to_owned());
|
return Err("Recursive type is prohibited.".to_owned());
|
||||||
}
|
}
|
||||||
let ty = self.type_arena.borrow().get(i_b.0).unwrap().clone();
|
let ty = self.unification_table.borrow_mut().probe_value(b);
|
||||||
let ty = ty.borrow();
|
let ty = ty.borrow();
|
||||||
|
|
||||||
match &*ty {
|
match &*ty {
|
||||||
|
@ -433,11 +468,7 @@ impl Unifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subst(&self, a: Type, mapping: &VarMap) -> Option<Type> {
|
pub fn subst(&self, a: Type, mapping: &VarMap) -> Option<Type> {
|
||||||
let index = self.unification_table.borrow_mut().probe_value(a);
|
let ty_cell = self.unification_table.borrow_mut().probe_value(a);
|
||||||
let ty_cell = {
|
|
||||||
let arena = self.type_arena.borrow();
|
|
||||||
arena.get(index.0).unwrap().clone()
|
|
||||||
};
|
|
||||||
let ty = ty_cell.borrow();
|
let ty = ty_cell.borrow();
|
||||||
// this function would only be called when we instantiate functions.
|
// this function would only be called when we instantiate functions.
|
||||||
// function type signature should ONLY contain concrete types and type
|
// function type signature should ONLY contain concrete types and type
|
||||||
|
@ -445,15 +476,9 @@ impl Unifier {
|
||||||
// should be safe to not implement the substitution for those variants.
|
// should be safe to not implement the substitution for those variants.
|
||||||
match &*ty {
|
match &*ty {
|
||||||
TypeEnum::TVar { id } => mapping.get(&id).cloned(),
|
TypeEnum::TVar { id } => mapping.get(&id).cloned(),
|
||||||
TypeEnum::TSeq { map } => self.subst_map(map, mapping).map(|m| {
|
TypeEnum::TSeq { map } => self
|
||||||
let index = self
|
.subst_map(map, mapping)
|
||||||
.type_arena
|
.map(|m| self.add_ty(TypeEnum::TSeq { map: m })),
|
||||||
.borrow_mut()
|
|
||||||
.insert(Rc::new(TypeEnum::TSeq { map: m }.into()));
|
|
||||||
self.unification_table
|
|
||||||
.borrow_mut()
|
|
||||||
.new_key(TypeIndex(index))
|
|
||||||
}),
|
|
||||||
TypeEnum::TTuple { ty } => {
|
TypeEnum::TTuple { ty } => {
|
||||||
let mut new_ty = None;
|
let mut new_ty = None;
|
||||||
for (i, t) in ty.iter().enumerate() {
|
for (i, t) in ty.iter().enumerate() {
|
||||||
|
@ -482,9 +507,7 @@ impl Unifier {
|
||||||
// parameter list, we don't need to substitute the fields.
|
// parameter list, we don't need to substitute the fields.
|
||||||
// This is also used to prevent infinite substitution...
|
// This is also used to prevent infinite substitution...
|
||||||
let need_subst = params.values().any(|v| {
|
let need_subst = params.values().any(|v| {
|
||||||
let index = self.unification_table.borrow_mut().probe_value(*v);
|
let ty_cell = self.unification_table.borrow_mut().probe_value(*v);
|
||||||
let arena = self.type_arena.borrow();
|
|
||||||
let ty_cell = arena.get(index.0).unwrap();
|
|
||||||
let ty = ty_cell.borrow();
|
let ty = ty_cell.borrow();
|
||||||
if let TypeEnum::TVar { id } = &*ty {
|
if let TypeEnum::TVar { id } = &*ty {
|
||||||
mapping.contains_key(id)
|
mapping.contains_key(id)
|
||||||
|
@ -558,21 +581,12 @@ impl Unifier {
|
||||||
if a == b {
|
if a == b {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let (i_a, i_b) = {
|
let (ty_a, ty_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))
|
if table.unioned(a, b) {
|
||||||
};
|
|
||||||
|
|
||||||
if i_a == i_b {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
(table.probe_value(a), table.probe_value(b))
|
||||||
let (ty_a, ty_b) = {
|
|
||||||
let arena = self.type_arena.borrow();
|
|
||||||
(
|
|
||||||
arena.get(i_a.0).unwrap().clone(),
|
|
||||||
arena.get(i_b.0).unwrap().clone(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty_a = ty_a.borrow();
|
let ty_a = ty_a.borrow();
|
||||||
|
|
Loading…
Reference in New Issue