Merge branch 'master' of mzhang.io:school/csci8980-f23
This commit is contained in:
commit
3ca96544de
4 changed files with 65 additions and 22 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
@ -19,6 +19,7 @@ name = "bidir"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"dashmap",
|
||||||
"im",
|
"im",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
@ -46,6 +47,25 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dashmap"
|
||||||
|
version = "5.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"hashbrown",
|
||||||
|
"lock_api",
|
||||||
|
"once_cell",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "im"
|
name = "im"
|
||||||
version = "15.1.0"
|
version = "15.1.0"
|
||||||
|
@ -82,6 +102,12 @@ dependencies = [
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.18.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
|
dashmap = "5.5.3"
|
||||||
im = "15.1.0"
|
im = "15.1.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
|
|
|
@ -2,11 +2,8 @@ use anyhow::{bail, Result};
|
||||||
|
|
||||||
use crate::DEPTH;
|
use crate::DEPTH;
|
||||||
|
|
||||||
use crate::data::{FreeVar, Monotype};
|
use crate::data::{Context, ContextEntry, FreeVar, Monotype, Term, Type};
|
||||||
use crate::{
|
use crate::gensym::gensym_existential;
|
||||||
data::{Context, ContextEntry, Term, Type},
|
|
||||||
gensym::gensym_prefix,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Figure 8. Applying a context, as a substitution, to a type
|
// Figure 8. Applying a context, as a substitution, to a type
|
||||||
|
|
||||||
|
@ -31,8 +28,8 @@ pub fn app_ctx(ctx: &Context, ty: &Type) -> Result<Type> {
|
||||||
|
|
||||||
/// Under input context Γ , type A is a subtype of B, with output context ∆
|
/// Under input context Γ , type A is a subtype of B, with output context ∆
|
||||||
#[trace]
|
#[trace]
|
||||||
pub fn subtype(ctx: &Context, a: &Type, b: &Type) -> Result<Context> {
|
pub fn subtype(ctx: &Context, left: &Type, right: &Type) -> Result<Context> {
|
||||||
match (a, b) {
|
match (left, right) {
|
||||||
// <:Unit rule
|
// <:Unit rule
|
||||||
(Type::Unit, Type::Unit) => Ok(ctx.clone()),
|
(Type::Unit, Type::Unit) => Ok(ctx.clone()),
|
||||||
|
|
||||||
|
@ -47,7 +44,9 @@ pub fn subtype(ctx: &Context, a: &Type, b: &Type) -> Result<Context> {
|
||||||
}
|
}
|
||||||
|
|
||||||
(Type::Existential(a), ty_a)
|
(Type::Existential(a), ty_a)
|
||||||
if !b.free_vars().contains(&FreeVar::Existential(a.to_string()))
|
if !right
|
||||||
|
.free_vars()
|
||||||
|
.contains(&FreeVar::Existential(a.to_string()))
|
||||||
&& ctx.lookup_existential(a).is_some() =>
|
&& ctx.lookup_existential(a).is_some() =>
|
||||||
{
|
{
|
||||||
let ctx_delta = instantiate_left(ctx, a, ty_a)?;
|
let ctx_delta = instantiate_left(ctx, a, ty_a)?;
|
||||||
|
@ -68,7 +67,7 @@ pub fn subtype(ctx: &Context, a: &Type, b: &Type) -> Result<Context> {
|
||||||
(Type::Arrow(_, _), Type::Polytype(_, _)) => todo!(),
|
(Type::Arrow(_, _), Type::Polytype(_, _)) => todo!(),
|
||||||
(Type::Arrow(_, _), Type::Arrow(_, _)) => todo!(),
|
(Type::Arrow(_, _), Type::Arrow(_, _)) => todo!(),
|
||||||
|
|
||||||
_ => bail!("subtyping relation failed between {a:?} and {b:?} (ctx = {ctx:?})"),
|
_ => bail!("subtyping relation failed between {left:?} and {right:?} (ctx = {ctx:?})"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,8 +159,8 @@ pub fn synthesize(ctx: &Context, term: &Term) -> Result<(Type, Context)> {
|
||||||
// > not place a marker before ^α, because ^α and ^β appear in the output type
|
// > not place a marker before ^α, because ^α and ^β appear in the output type
|
||||||
// > (λx. e ⇒ ^α → ^β).
|
// > (λx. e ⇒ ^α → ^β).
|
||||||
Term::Lam(x, e) => {
|
Term::Lam(x, e) => {
|
||||||
let ex_a_s = gensym_prefix("ex");
|
let ex_a_s = gensym_existential();
|
||||||
let ex_b_s = gensym_prefix("ex");
|
let ex_b_s = gensym_existential();
|
||||||
let ex_a = Type::Existential(ex_a_s.clone());
|
let ex_a = Type::Existential(ex_a_s.clone());
|
||||||
let ex_b = Type::Existential(ex_b_s.clone());
|
let ex_b = Type::Existential(ex_b_s.clone());
|
||||||
let aug_ctx = ctx.add(vec![
|
let aug_ctx = ctx.add(vec![
|
||||||
|
|
|
@ -1,18 +1,35 @@
|
||||||
|
use dashmap::DashMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use parking_lot::Mutex;
|
|
||||||
|
|
||||||
lazy_static! {
|
thread_local! {
|
||||||
static ref CTR: Mutex<usize> = Mutex::new(0);
|
static CTRMAP: DashMap<&'static str, usize> = DashMap::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gensym() -> String {
|
const EXISTENTIALS: [&'static str; 24] = [
|
||||||
gensym_prefix("var")
|
"α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ",
|
||||||
|
"υ", "φ", "χ", "ψ", "ω",
|
||||||
|
];
|
||||||
|
|
||||||
|
const TYPEVARS: [&'static str; 26] = [
|
||||||
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
|
||||||
|
"T", "U", "V", "W", "X", "Y", "Z",
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn gensym_existential() -> String {
|
||||||
|
let result = idx("existential");
|
||||||
|
format!("{}\u{0302}", EXISTENTIALS[result])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gensym_prefix(prefix: impl AsRef<str>) -> String {
|
pub fn gensym_type() -> String {
|
||||||
let mut g = CTR.lock();
|
let result = idx("existential");
|
||||||
let ctr = *g;
|
format!("{}\u{0302}", TYPEVARS[result])
|
||||||
*g += 1;
|
}
|
||||||
drop(g);
|
|
||||||
format!("{}{}", prefix.as_ref(), ctr)
|
fn idx(ty: &'static str) -> usize {
|
||||||
|
CTRMAP.with(|ctrmap| {
|
||||||
|
let mut g = ctrmap.entry(ty).or_insert(0);
|
||||||
|
let ctr = *g;
|
||||||
|
*g += 1;
|
||||||
|
ctr
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue