feat: lookup at downgrade time

works, but leaks memory
This commit is contained in:
2025-06-01 09:20:04 +08:00
parent 7d6168fdae
commit 20b2b6f1ef
20 changed files with 762 additions and 651 deletions

View File

@@ -8,16 +8,17 @@ 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, K, V>>,
let_: Gc<'gc, LetEnv<'gc, V>>,
with: Gc<'gc, With<'gc, K, V>>,
args: Vec<V>,
last: Option<Gc<'gc, Env<'gc, K, V>>>,
}
#[derive(Collect)]
#[collect(no_drop)]
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>>>,
pub struct LetEnv<'gc, V: Collect<'gc>> {
map: Vec<V>,
last: Option<Gc<'gc, LetEnv<'gc, V>>>,
}
pub type VmEnv<'gc> = Env<'gc, usize, Value<'gc>>;
@@ -34,7 +35,6 @@ pub struct With<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
#[collect(no_drop)]
enum LetNode<'gc, K: Hash + Eq + Collect<'gc>, V: Collect<'gc>> {
Let(Gc<'gc, HashMap<K, V>>),
SingleArg(K, V),
MultiArg(Gc<'gc, HashMap<K, V>>),
}
@@ -46,7 +46,7 @@ pub enum Type {
}
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> {
pub fn new(map: Vec<V>, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
@@ -58,20 +58,18 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
last: None,
},
),
args: Vec::new(),
last: None,
},
)
}
pub fn lookup_slow(&self, symbol: &K) -> Option<&V> {
if let Some(val) = self.let_.lookup(symbol) {
return Some(val);
}
self.with.lookup(symbol)
pub fn lookup_arg(&self, level: usize) -> V {
self.args[self.args.len() - level - 1].clone()
}
pub fn lookup_let(&self, symbol: &K) -> Option<&V> {
self.let_.lookup(symbol)
pub fn lookup_let(&self, level: usize, idx: usize) -> V {
self.let_.lookup(level, idx)
}
pub fn lookup_with(&self, symbol: &K) -> Option<&V> {
@@ -82,20 +80,25 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
self.with.map.is_some()
}
pub fn enter_arg(self: Gc<'gc, Self>, ident: K, val: V, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
#[must_use]
pub fn enter_arg(self: Gc<'gc, Self>, val: V, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
let mut args = self.args.clone();
args.push(val);
Gc::new(
mc,
Env {
let_: self.let_.enter_arg(ident, val, mc),
let_: self.let_,
with: self.with,
last: Some(self),
args
},
)
}
#[must_use]
pub fn enter_let(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
map: Vec<V>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
@@ -103,11 +106,13 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
Self {
let_: self.let_.enter_let(map, mc),
with: self.with,
args: self.args.clone(),
last: Some(self),
},
)
}
#[must_use]
pub fn enter_with(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
@@ -118,6 +123,7 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
Env {
let_: self.let_,
with: self.with.enter(map, mc),
args: self.args.clone(),
last: Some(self),
},
)
@@ -128,53 +134,35 @@ impl<'gc, K: Hash + Eq + Clone + Collect<'gc>, V: Clone + Collect<'gc>> Env<'gc,
}
}
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> {
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: LetNode::Let(map),
map,
last: None,
},
)
}
pub fn lookup(&self, symbol: &K) -> Option<&V> {
use self::LetNode::*;
match &self.map {
Let(map) | MultiArg(map) => {
if let Some(val) = map.get(symbol) {
return Some(val);
}
}
SingleArg(sym, val) => {
if sym == symbol {
return Some(val);
}
}
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();
}
self.last.as_ref().and_then(|env| env.lookup(symbol))
}
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),
},
)
cur.map[idx].clone()
}
pub fn enter_let(
self: Gc<'gc, Self>,
map: Gc<'gc, HashMap<K, V>>,
map: Vec<V>,
mc: &Mutation<'gc>,
) -> Gc<'gc, Self> {
Gc::new(
mc,
Self {
map: LetNode::Let(map),
map,
last: Some(self),
},
)