feat: gc (does compile, but WIP)

This commit is contained in:
2025-05-27 21:08:59 +08:00
parent 319c12c1f4
commit c3ace28af1
20 changed files with 696 additions and 575 deletions

View File

@@ -1,13 +1,13 @@
use std::hash::Hash;
use gc_arena::{Collect, Gc, Mutation};
use hashbrown::HashMap;
use crate::ty::internal::Value;
use crate::ty::common::Map;
#[derive(Collect)]
#[collect(no_drop)]
pub struct Env<'gc, K: Hash + Eq + Collect, V: Collect> {
pub struct Env<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
let_: Gc<'gc, LetEnv<'gc, K, V>>,
with: Gc<'gc, With<'gc, K, V>>,
last: Option<Gc<'gc, Env<'gc, K, V>>>,
@@ -15,7 +15,7 @@ pub struct Env<'gc, K: Hash + Eq + Collect, V: Collect> {
#[derive(Collect)]
#[collect(no_drop)]
pub struct LetEnv<'gc, K: Hash + Eq + Collect, V: Collect> {
pub struct LetEnv<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
map: LetNode<'gc, K, V>,
last: Option<Gc<'gc, LetEnv<'gc, K, V>>>,
}
@@ -24,17 +24,17 @@ pub type VmEnv<'gc> = Env<'gc, usize, Value<'gc>>;
#[derive(Default, Clone, Collect)]
#[collect(no_drop)]
pub struct With<'gc, K: Hash + Eq + Collect, V: Collect> {
map: Option<Gc<'gc, Map<K, V>>>,
pub struct With<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
map: Option<Gc<'gc, HashMap<K, V>>>,
last: Option<Gc<'gc, With<'gc, K, V>>>,
}
#[derive(Collect)]
#[collect(no_drop)]
enum LetNode<'gc, K: Hash + Eq + Collect, V: Collect> {
Let(Gc<'gc, Map<K, V>>),
enum LetNode<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
Let(Gc<'gc, HashMap<K, V>>),
SingleArg(K, V),
MultiArg(Gc<'gc, Map<K, V>>),
MultiArg(Gc<'gc, HashMap<K, V>>),
}
#[derive(Clone, Copy)]
@@ -44,19 +44,25 @@ pub enum Type {
With,
}
impl<'gc, K: Hash + Eq + Clone + Collect, V: Clone + Collect> Env<'gc, K, V> {
pub fn new(map: Gc<'gc, Map<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Self {
let_: LetEnv::new(map, mc),
with: Gc::new(mc, With {
map: None,
impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc, K, V> {
pub fn new(map: Gc<'gc, HashMap<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
let_: LetEnv::new(map, mc),
with: Gc::new(
mc,
With {
map: None,
last: None,
},
),
last: None,
}),
last: None,
})
},
)
}
pub fn lookup(&'gc self, symbol: &K) -> Option<&'gc V> {
pub fn lookup(&self, symbol: &K) -> Option<&V> {
if let Some(val) = self.let_.lookup(symbol) {
return Some(val);
}
@@ -64,27 +70,44 @@ impl<'gc, K: Hash + Eq + Clone + Collect, V: Clone + Collect> Env<'gc, K, V> {
}
pub fn enter_arg(self: Gc<'gc, Self>, ident: K, val: V, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Env {
let_: self.let_.enter_arg(ident, val, mc),
with: self.with,
last: Some(self),
})
Gc::new(
mc,
Env {
let_: self.let_.enter_arg(ident, val, mc),
with: self.with,
last: Some(self),
},
)
}
pub fn enter_let(self: Gc<'gc, Self>, map: Gc<'gc, Map<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Self {
let_: self.let_.enter_let(map, mc),
with: self.with,
last: Some(self),
})
pub fn enter_let(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
let_: self.let_.enter_let(map, mc),
with: self.with,
last: Some(self),
},
)
}
pub fn enter_with(self: Gc<'gc, Self>, map: Gc<'gc, Map<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Env {
let_: self.let_,
with: self.with.enter(map, mc),
last: Some(self),
})
pub fn enter_with(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Env {
let_: self.let_,
with: self.with.enter(map, mc),
last: Some(self),
},
)
}
pub fn leave(&self) -> Gc<'gc, Self> {
@@ -92,12 +115,15 @@ impl<'gc, K: Hash + Eq + Clone + Collect, V: Clone + Collect> Env<'gc, K, V> {
}
}
impl<'gc, K: Hash + Eq + Clone + Collect, V: Clone + Collect> LetEnv<'gc, K, V> {
pub fn new(map: Gc<'gc, Map<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc,Self {
map: LetNode::Let(map),
last: None,
})
impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> LetEnv<'gc, K, V> {
pub fn new(map: Gc<'gc, HashMap<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
map: LetNode::Let(map),
last: None,
},
)
}
pub fn lookup(&self, symbol: &K) -> Option<&V> {
@@ -118,32 +144,49 @@ impl<'gc, K: Hash + Eq + Clone + Collect, V: Clone + Collect> LetEnv<'gc, K, V>
}
pub fn enter_arg(self: Gc<'gc, Self>, ident: K, val: V, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Self {
map: LetNode::SingleArg(ident, val),
last: Some(self),
})
Gc::new(
mc,
Self {
map: LetNode::SingleArg(ident, val),
last: Some(self),
},
)
}
pub fn enter_let(self: Gc<'gc, Self>, map: Gc<'gc, Map<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Self {
map: LetNode::Let(map),
last: Some(self),
})
pub fn enter_let(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
map: LetNode::Let(map),
last: Some(self),
},
)
}
}
impl<'gc, K: Hash + Eq + Clone + Collect, V: Clone + Collect> With<'gc, K, V> {
pub fn lookup(&'gc self, symbol: &K) -> Option<&'gc V> {
impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> With<'gc, K, V> {
pub fn lookup(&self, symbol: &K) -> Option<&V> {
if let Some(val) = self.map.as_ref()?.get(symbol) {
return Some(val);
}
self.last.as_ref().and_then(|env| env.lookup(symbol))
}
pub fn enter(self: Gc<'gc, Self>, map: Gc<'gc, Map<K, V>>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(mc, Self {
map: Some(map),
last: Some(self),
})
pub fn enter(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
map: Some(map),
last: Some(self),
},
)
}
}