feat: get rid of gc and cyclic thunk

This commit is contained in:
2025-06-05 16:43:47 +08:00
parent 51f8df9cca
commit 484cfa4610
17 changed files with 342 additions and 595 deletions

View File

@@ -1,42 +1,34 @@
use std::hash::Hash;
use std::rc::Rc;
use gc_arena::{Collect, Gc, Mutation};
use hashbrown::HashMap;
use crate::{ir::Ir, ty::internal::Value};
#[derive(Collect)]
#[collect(no_drop)]
pub struct Env<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
let_: Gc<'gc, LetEnv<'gc, V>>,
with: Gc<'gc, With<'gc, K, V>>,
pub struct Env<K: Hash + Eq, V> {
let_: Rc<LetEnv<V>>,
with: Rc<With<K, V>>,
args: Vec<V>,
jit_store: Vec<Box<V>>,
last: Option<Gc<'gc, Env<'gc, K, V>>>,
last: Option<Rc<Env<K, V>>>,
}
#[derive(Collect)]
#[collect(no_drop)]
pub struct LetEnv<'gc, V: Collect<'gc>> {
pub struct LetEnv<V> {
map: Vec<V>,
last: Option<Gc<'gc, LetEnv<'gc, V>>>,
last: Option<Rc<LetEnv<V>>>,
}
pub type VmEnv<'gc> = Env<'gc, usize, Value<'gc>>;
pub type IrEnv<'gc> = Env<'gc, usize, Ir>;
pub type VmEnv<'gc> = Env<usize, Value<'gc>>;
pub type IrEnv<'gc> = Env<usize, Ir>;
#[derive(Default, Clone, Collect)]
#[collect(no_drop)]
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(Default, Clone)]
pub struct With<K: Hash + Eq, V> {
map: Option<Rc<HashMap<K, V>>>,
last: Option<Rc<With<K, V>>>,
}
#[derive(Collect)]
#[collect(no_drop)]
enum LetNode<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
Let(Gc<'gc, HashMap<K, V>>),
MultiArg(Gc<'gc, HashMap<K, V>>),
enum LetNode<K: Hash + Eq, V> {
Let(Rc<HashMap<K, V>>),
MultiArg(Rc<HashMap<K, V>>),
}
#[derive(Clone, Copy)]
@@ -46,24 +38,17 @@ pub enum Type {
With,
}
impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc, K, V> {
pub fn new(map: Vec<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,
},
),
args: Vec::new(),
jit_store: Vec::new(),
impl<K: Hash + Eq + Clone, V: Clone> Env<K, V> {
pub fn new(map: Vec<V>) -> Rc<Self> {
Rc::new(Self {
let_: LetEnv::new(map),
with: Rc::new(With {
map: None,
last: None,
},
)
}),
args: Vec::new(),
last: None,
})
}
pub fn lookup_arg(&self, level: usize) -> &V {
@@ -83,109 +68,64 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
}
#[must_use]
pub fn enter_arg(self: Gc<'gc, Self>, val: V, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
pub fn enter_arg(self: Rc<Self>, val: V) -> Rc<Self> {
let mut args = self.args.clone();
args.push(val);
Gc::new(
mc,
Env {
let_: self.let_,
with: self.with,
last: Some(self),
jit_store: Vec::new(),
args
},
)
Rc::new(Self {
let_: self.let_.clone(),
with: self.with.clone(),
last: Some(self),
args,
})
}
#[must_use]
pub fn enter_let(
self: Gc<'gc, Self>,
map: Vec<V>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
let_: self.let_.enter_let(map, mc),
with: self.with,
args: self.args.clone(),
jit_store: Vec::new(),
last: Some(self),
},
)
pub fn enter_let(self: Rc<Self>, map: Vec<V>) -> Rc<Self> {
Rc::new(Self {
let_: self.let_.clone().enter_let(map),
with: self.with.clone(),
args: self.args.clone(),
last: Some(self),
})
}
#[must_use]
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),
args: self.args.clone(),
jit_store: Vec::new(),
last: Some(self),
},
)
pub fn enter_with(self: Rc<Self>, map: Rc<HashMap<K, V>>) -> Rc<Self> {
Rc::new(Self {
let_: self.let_.clone(),
with: self.with.clone().enter(map),
args: self.args.clone(),
last: Some(self),
})
}
#[inline]
pub fn jit_store(&'gc mut self, val: V) -> &'gc V {
self.jit_store.push(Box::new(val));
&self.jit_store[self.jit_store.len() - 1]
}
#[inline]
pub fn jit_stored(&self) -> usize {
self.jit_store.len()
}
pub fn leave(&self) -> Gc<'gc, Self> {
self.last.unwrap()
pub fn leave(&self) -> Rc<Self> {
self.last.clone().unwrap()
}
}
impl<'gc, V: Clone + Collect<'gc>> LetEnv<'gc, V> {
pub fn new(map: Vec<V>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
map,
last: None,
},
)
impl<V: Clone> LetEnv<V> {
pub fn new(map: Vec<V>) -> Rc<Self> {
Rc::new(Self { map, last: None })
}
pub fn lookup(&self, level: usize, idx: usize) -> &V {
let mut cur = self;
for _ in 0..level {
let last = cur.last.unwrap();
cur = last.as_ref();
cur = cur.last.as_ref().unwrap();
}
&cur.map[idx]
}
pub fn enter_let(
self: Gc<'gc, Self>,
map: Vec<V>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
map,
last: Some(self),
},
)
pub fn enter_let(self: Rc<Self>, map: Vec<V>) -> Rc<Self> {
Rc::new(Self {
map,
last: Some(self),
})
}
}
impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> With<'gc, K, V> {
impl<K: Hash + Eq + Clone, V: Clone> With<K, V> {
pub fn lookup(&self, symbol: &K) -> Option<&V> {
if let Some(val) = self.map.as_ref()?.get(symbol) {
return Some(val);
@@ -193,17 +133,10 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> With<'gc
self.last.as_ref().and_then(|env| env.lookup(symbol))
}
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),
},
)
pub fn enter(self: Rc<Self>, map: Rc<HashMap<K, V>>) -> Rc<Self> {
Rc::new(Self {
map: Some(map),
last: Some(self),
})
}
}