feat: less env clone

This commit is contained in:
2025-05-22 19:21:14 +08:00
parent dcd22ad1f3
commit c898b577b0
5 changed files with 117 additions and 75 deletions

View File

@@ -3,23 +3,30 @@ use std::{hash::Hash, rc::Rc};
use hashbrown::HashMap;
use crate::ty::internal::{AttrSet, Value};
use crate::ty::internal::Value;
pub struct Env<K: Hash + Eq, V> {
map: Node<K, V>,
last: Option<Rc<Env<K, V>>>,
#[derive(Clone)]
pub struct Env<K: Hash + Eq + Clone, V: Clone> {
let_: Rc<LetEnv<K, V>>,
with: Rc<With<K, V>>,
}
impl<K: Clone + Hash + Eq, V: Clone> Clone for Env<K, V> {
fn clone(&self) -> Self {
Self {
map: self.map.clone(),
last: self.last.clone(),
}
#[derive(Clone)]
pub struct LetEnv<K: Hash + Eq + Clone, V: Clone> {
map: Let<K, V>,
last: Option<Rc<LetEnv<K, V>>>,
}
impl<K: Debug + Hash + Eq + Clone, V: Debug + Clone> Debug for Env<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Env")
.field("let_", &self.let_)
.field("with", &self.with)
.finish()
}
}
impl<K: Debug + Hash + Eq, V: Debug> Debug for Env<K, V> {
impl<K: Debug + Hash + Eq + Clone, V: Debug + Clone> Debug for LetEnv<K, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Env")
.field("map", &self.map)
@@ -31,13 +38,13 @@ impl<K: Debug + Hash + Eq, V: Debug> Debug for Env<K, V> {
pub type VmEnv<'jit, 'vm> = Env<usize, Value<'jit, 'vm>>;
#[derive(Debug, Default, Clone)]
pub struct WithEnv<'jit, 'vm> {
map: Rc<AttrSet<'jit, 'vm>>,
last: Option<Rc<WithEnv<'jit, 'vm>>>,
pub struct With<K: Hash + Eq, V> {
map: Option<Rc<HashMap<K, V>>>,
last: Option<Rc<With<K, V>>>,
}
#[derive(Debug, Clone)]
enum Node<K: Hash + Eq, V> {
enum Let<K: Hash + Eq, V> {
Let(Rc<HashMap<K, V>>),
SingleArg(K, V),
MultiArg(Rc<HashMap<K, V>>),
@@ -50,16 +57,56 @@ pub enum Type {
With,
}
impl<K: Hash + Eq, V> Env<K, V> {
impl<K: Hash + Eq + Clone, V: Clone> Env<K, V> {
pub fn new(map: Rc<HashMap<K, V>>) -> Self {
Self {
map: Node::Let(map),
let_: LetEnv::new(map).into(),
with: With {
map: None,
last: None,
}
.into(),
}
}
pub fn lookup(&self, symbol: &K) -> Option<&V> {
if let Some(val) = self.let_.lookup(symbol) {
return Some(val);
}
self.with.lookup(symbol)
}
pub fn enter_arg(self: &mut Rc<Self>, ident: K, val: V) {
Rc::make_mut(self).let_.enter_arg(ident, val);
}
pub fn enter_let(self: &mut Rc<Self>, map: Rc<HashMap<K, V>>) {
Rc::make_mut(self).let_.enter_let(map);
}
pub fn enter_with(self: &mut Rc<Self>, map: Rc<HashMap<K, V>>) {
Rc::make_mut(self).with.enter(map);
}
pub fn leave_let(self: &mut Rc<Self>) {
Rc::make_mut(self).let_.leave();
}
pub fn leave_with(self: &mut Rc<Self>) {
Rc::make_mut(self).with.leave();
}
}
impl<K: Hash + Eq + Clone, V: Clone> LetEnv<K, V> {
pub fn new(map: Rc<HashMap<K, V>>) -> Self {
Self {
map: Let::Let(map),
last: None,
}
}
pub fn lookup(&self, symbol: &K) -> Option<&V> {
use Node::*;
use self::Let::*;
match &self.map {
Let(map) | MultiArg(map) => {
if let Some(val) = map.get(symbol) {
@@ -75,59 +122,45 @@ impl<K: Hash + Eq, V> Env<K, V> {
self.last.as_ref().and_then(|env| env.lookup(symbol))
}
pub fn enter_arg(self: Rc<Self>, ident: K, val: V) -> Rc<Self> {
let last = Some(self);
let map = Node::SingleArg(ident, val);
Env { last, map }.into()
pub fn enter_arg(self: &mut Rc<Self>, ident: K, val: V) {
let cloned = self.clone();
let mutref = Rc::make_mut(self);
mutref.last = Some(cloned);
mutref.map = Let::SingleArg(ident, val);
}
pub fn enter_attrs(self: Rc<Self>, map: Rc<HashMap<K, V>>) -> Rc<Self> {
let last = Some(self);
let map = Node::Let(map);
Env { last, map }.into()
pub fn enter_let(self: &mut Rc<Self>, map: Rc<HashMap<K, V>>) {
let cloned = self.clone();
let mutref = Rc::make_mut(self);
mutref.last = Some(cloned);
mutref.map = Let::Let(map);
}
pub fn enter_with(self: Rc<Self>, map: Rc<HashMap<K, V>>) -> Rc<Self> {
let map = Node::Let(map);
let last = Some(self);
Env { last, map }.into()
}
pub fn leave(self: Rc<Self>) -> Rc<Self> {
self.last.clone().unwrap()
pub fn leave(self: &mut Rc<Self>) {
let refmut = Rc::make_mut(self);
let last = refmut.last.take().unwrap();
*self = last;
}
}
impl<'jit, 'vm> WithEnv<'jit, 'vm> {
pub fn lookup(&self, symbol: usize) -> Option<Value<'jit, 'vm>> {
if let Some(val) = self.map.select(symbol) {
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);
}
self.last.as_ref().and_then(|env| env.lookup(symbol))
}
pub fn enter_with(self, new: Rc<AttrSet<'jit, 'vm>>) -> Self {
let map = Rc::new(
new.as_inner()
.iter()
.map(|(&k, v)| {
(
k,
if let Value::Builtins(weak) = v {
Value::AttrSet(weak.upgrade().unwrap())
} else {
v.clone()
},
)
})
.collect::<HashMap<_, _>>()
.into(),
);
let last = Some(self.into());
WithEnv { last, map }
pub fn enter(self: &mut Rc<Self>, map: Rc<HashMap<K, V>>) {
let cloned = self.clone();
let mutref = Rc::make_mut(self);
mutref.last = Some(cloned);
mutref.map = Some(map);
}
pub fn leave(self) -> Self {
self.last.unwrap().as_ref().clone()
pub fn leave(self: &mut Rc<Self>) {
let refmut = Rc::make_mut(self);
let last = refmut.last.take().unwrap();
*self = last;
}
}