feat(env): Rc
This commit is contained in:
@@ -5,8 +5,8 @@ use rpds::HashTrieMap;
|
|||||||
use crate::ty::internal::{AttrSet, Const, PrimOp, Value};
|
use crate::ty::internal::{AttrSet, Const, PrimOp, Value};
|
||||||
use crate::vm::{Env, VM};
|
use crate::vm::{Env, VM};
|
||||||
|
|
||||||
pub fn env<'vm>(vm: &'vm VM) -> Rc<Env<'vm>> {
|
pub fn env<'vm>(vm: &'vm VM) -> Env<'vm> {
|
||||||
let env = Rc::new(Env::empty());
|
let mut env = Env::empty();
|
||||||
env.insert(vm.new_sym("true"), Value::Const(Const::Bool(true)));
|
env.insert(vm.new_sym("true"), Value::Const(Const::Bool(true)));
|
||||||
env.insert(vm.new_sym("false"), Value::Const(Const::Bool(false)));
|
env.insert(vm.new_sym("false"), Value::Const(Const::Bool(false)));
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use derive_more::Constructor;
|
use derive_more::Constructor;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
@@ -43,7 +42,7 @@ impl<'vm> AttrSet<'vm> {
|
|||||||
self.data.get(&sym).is_some()
|
self.data.get(&sym).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn capture(&mut self, env: &Rc<Env<'vm>>) {
|
pub fn capture(&mut self, env: &Env<'vm>) {
|
||||||
self.data.iter().for_each(|(_, v)| match v.clone() {
|
self.data.iter().for_each(|(_, v)| match v.clone() {
|
||||||
Value::Thunk(ref thunk) => {
|
Value::Thunk(ref thunk) => {
|
||||||
thunk.capture(env.clone());
|
thunk.capture(env.clone());
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use derive_more::Constructor;
|
use derive_more::Constructor;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
@@ -46,7 +43,7 @@ pub type JITFunc<'vm> =
|
|||||||
#[derive(Debug, Clone, Constructor)]
|
#[derive(Debug, Clone, Constructor)]
|
||||||
pub struct Func<'vm> {
|
pub struct Func<'vm> {
|
||||||
pub func: &'vm BFunc,
|
pub func: &'vm BFunc,
|
||||||
pub env: Rc<Env<'vm>>,
|
pub env: Env<'vm>,
|
||||||
pub compiled: Option<JITFunc<'vm>>,
|
pub compiled: Option<JITFunc<'vm>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +51,10 @@ impl<'vm> Func<'vm> {
|
|||||||
pub fn call(&self, vm: &'vm VM<'_>, arg: Value<'vm>) -> Result<Value<'vm>> {
|
pub fn call(&self, vm: &'vm VM<'_>, arg: Value<'vm>) -> Result<Value<'vm>> {
|
||||||
use Param::*;
|
use Param::*;
|
||||||
|
|
||||||
let env = Rc::new(self.env.as_ref().clone());
|
let mut env = self.env.clone();
|
||||||
|
|
||||||
match self.func.param.clone() {
|
match self.func.param.clone() {
|
||||||
Ident(ident) => env.enter([(ident.into(), arg)].into_iter()),
|
Ident(ident) => env = env.enter([(ident.into(), arg)].into_iter()),
|
||||||
Formals {
|
Formals {
|
||||||
formals,
|
formals,
|
||||||
ellipsis,
|
ellipsis,
|
||||||
@@ -88,7 +85,7 @@ impl<'vm> Func<'vm> {
|
|||||||
if let Some(alias) = alias {
|
if let Some(alias) = alias {
|
||||||
new.push((alias.clone().into(), Value::AttrSet(arg)));
|
new.push((alias.clone().into(), Value::AttrSet(arg)));
|
||||||
}
|
}
|
||||||
env.enter(new.into_iter());
|
env = env.enter(new.into_iter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -466,7 +466,7 @@ pub struct Thunk<'vm> {
|
|||||||
|
|
||||||
#[derive(Debug, IsVariant, Unwrap, Clone)]
|
#[derive(Debug, IsVariant, Unwrap, Clone)]
|
||||||
pub enum _Thunk<'vm> {
|
pub enum _Thunk<'vm> {
|
||||||
Code(&'vm OpCodes, OnceCell<Rc<Env<'vm>>>),
|
Code(&'vm OpCodes, OnceCell<Env<'vm>>),
|
||||||
SuspendedFrom(*const Thunk<'vm>),
|
SuspendedFrom(*const Thunk<'vm>),
|
||||||
Value(Value<'vm>),
|
Value(Value<'vm>),
|
||||||
}
|
}
|
||||||
@@ -478,7 +478,7 @@ impl<'vm> Thunk<'vm> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn capture(&self, env: Rc<Env<'vm>>) {
|
pub fn capture(&self, env: Env<'vm>) {
|
||||||
if let _Thunk::Code(_, envcell) = &*self.thunk.borrow() {
|
if let _Thunk::Code(_, envcell) = &*self.thunk.borrow() {
|
||||||
envcell.get_or_init(|| env);
|
envcell.get_or_init(|| env);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,13 @@
|
|||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use rpds::HashTrieMap;
|
use rpds::HashTrieMap;
|
||||||
|
|
||||||
use crate::ty::internal::{AttrSet, Value};
|
use crate::ty::internal::{AttrSet, Value};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct Env<'vm> {
|
pub struct Env<'vm> {
|
||||||
last: RefCell<Option<Rc<Env<'vm>>>>,
|
last: Option<Rc<Env<'vm>>>,
|
||||||
map: RefCell<HashTrieMap<usize, Value<'vm>>>,
|
map: HashTrieMap<usize, Value<'vm>>,
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for Env<'_> {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
Env {
|
|
||||||
last: RefCell::new(
|
|
||||||
self.last
|
|
||||||
.borrow()
|
|
||||||
.clone()
|
|
||||||
.map(|e| Rc::new(e.as_ref().clone())),
|
|
||||||
),
|
|
||||||
map: RefCell::new(self.map.borrow().clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'vm> Env<'vm> {
|
impl<'vm> Env<'vm> {
|
||||||
@@ -31,28 +16,30 @@ impl<'vm> Env<'vm> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup(&self, symbol: usize) -> Option<Value<'vm>> {
|
pub fn lookup(&self, symbol: usize) -> Option<Value<'vm>> {
|
||||||
self.map.borrow().get(&symbol).cloned()
|
self.map.get(&symbol).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&self, symbol: usize, value: Value<'vm>) {
|
pub fn insert(&mut self, symbol: usize, value: Value<'vm>) {
|
||||||
self.map.borrow_mut().insert_mut(symbol, value);
|
self.map.insert_mut(symbol, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter(&self, new: impl Iterator<Item = (usize, Value<'vm>)>) {
|
pub fn enter(self, new: impl Iterator<Item = (usize, Value<'vm>)>) -> Self {
|
||||||
let mut map = self.map.borrow().clone();
|
let mut map = self.map.clone();
|
||||||
for (k, v) in new {
|
for (k, v) in new {
|
||||||
map.insert_mut(k, v);
|
map.insert_mut(k, v);
|
||||||
}
|
}
|
||||||
let last = Env {
|
let last = Some(
|
||||||
last: self.last.clone(),
|
Env {
|
||||||
map: self.map.clone(),
|
last: self.last,
|
||||||
};
|
map: self.map,
|
||||||
*self.last.borrow_mut() = Some(Rc::new(last));
|
}
|
||||||
*self.map.borrow_mut() = map;
|
.into(),
|
||||||
|
);
|
||||||
|
Env { last, map }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter_with(&self, new: Rc<AttrSet<'vm>>) {
|
pub fn enter_with(self, new: Rc<AttrSet<'vm>>) -> Self {
|
||||||
let mut map = self.map.borrow().clone();
|
let mut map = self.map.clone();
|
||||||
for (k, v) in new.as_inner().iter() {
|
for (k, v) in new.as_inner().iter() {
|
||||||
let v = if let Value::Builtins = v {
|
let v = if let Value::Builtins = v {
|
||||||
Value::AttrSet(new.clone())
|
Value::AttrSet(new.clone())
|
||||||
@@ -61,18 +48,17 @@ impl<'vm> Env<'vm> {
|
|||||||
};
|
};
|
||||||
map.insert_mut(k.clone(), v);
|
map.insert_mut(k.clone(), v);
|
||||||
}
|
}
|
||||||
let last = Env {
|
let last = Some(
|
||||||
|
Env {
|
||||||
last: self.last.clone(),
|
last: self.last.clone(),
|
||||||
map: self.map.clone(),
|
map: self.map.clone(),
|
||||||
};
|
}
|
||||||
*self.last.borrow_mut() = Some(Rc::new(last));
|
.into(),
|
||||||
*self.map.borrow_mut() = map;
|
);
|
||||||
|
Env { last, map }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leave(&self) {
|
pub fn leave(self) -> Self {
|
||||||
let last = (*self.last.borrow_mut()).take().unwrap();
|
self.last.unwrap().as_ref().clone()
|
||||||
let _ = std::mem::replace(&mut *self.last.borrow_mut(), last.last.borrow().clone());
|
|
||||||
let map = last.map.borrow().clone();
|
|
||||||
*self.map.borrow_mut() = map;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::builtins::env;
|
use crate::builtins::env;
|
||||||
use crate::bytecode::{BinOp, Func as F, OpCode, OpCodes, Program, UnOp};
|
use crate::bytecode::{BinOp, Func as F, OpCode, OpCodes, Program, UnOp};
|
||||||
@@ -80,12 +79,12 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
|||||||
pub fn eval(
|
pub fn eval(
|
||||||
&'vm self,
|
&'vm self,
|
||||||
opcodes: impl Iterator<Item = OpCode>,
|
opcodes: impl Iterator<Item = OpCode>,
|
||||||
env: Rc<Env<'vm>>,
|
mut env: Env<'vm>,
|
||||||
) -> Result<Value<'vm>> {
|
) -> Result<Value<'vm>> {
|
||||||
let mut stack = Stack::<_, STACK_SIZE>::new();
|
let mut stack = Stack::<_, STACK_SIZE>::new();
|
||||||
let mut iter = opcodes.into_iter();
|
let mut iter = opcodes.into_iter();
|
||||||
while let Some(opcode) = iter.next() {
|
while let Some(opcode) = iter.next() {
|
||||||
let jmp = self.single_op(opcode, &mut stack, &env)?;
|
let jmp = self.single_op(opcode, &mut stack, &mut env)?;
|
||||||
for _ in 0..jmp {
|
for _ in 0..jmp {
|
||||||
iter.next().unwrap();
|
iter.next().unwrap();
|
||||||
}
|
}
|
||||||
@@ -101,7 +100,7 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
|||||||
&'vm self,
|
&'vm self,
|
||||||
opcode: OpCode,
|
opcode: OpCode,
|
||||||
stack: &'s mut Stack<Value<'vm>, CAP>,
|
stack: &'s mut Stack<Value<'vm>, CAP>,
|
||||||
env: &Rc<Env<'vm>>,
|
env: &mut Env<'vm>,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
match opcode {
|
match opcode {
|
||||||
OpCode::Illegal => panic!("illegal opcode"),
|
OpCode::Illegal => panic!("illegal opcode"),
|
||||||
@@ -187,7 +186,7 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
|||||||
stack.push(Value::AttrSet(AttrSet::empty().into()))?;
|
stack.push(Value::AttrSet(AttrSet::empty().into()))?;
|
||||||
}
|
}
|
||||||
OpCode::FinalizeRec => {
|
OpCode::FinalizeRec => {
|
||||||
env.enter(
|
let env = env.clone().enter(
|
||||||
stack
|
stack
|
||||||
.tos()?
|
.tos()?
|
||||||
.clone()
|
.clone()
|
||||||
@@ -196,7 +195,7 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| (k.clone(), v.clone())),
|
.map(|(k, v)| (k.clone(), v.clone())),
|
||||||
);
|
);
|
||||||
stack.tos_mut()?.as_mut().unwrap_attr_set().capture(env);
|
stack.tos_mut()?.as_mut().unwrap_attr_set().capture(&env);
|
||||||
}
|
}
|
||||||
OpCode::PushStaticAttr { name } => {
|
OpCode::PushStaticAttr { name } => {
|
||||||
let val = stack.pop();
|
let val = stack.pop();
|
||||||
@@ -252,13 +251,11 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
|||||||
})?)?;
|
})?)?;
|
||||||
}
|
}
|
||||||
OpCode::EnterEnv => match stack.pop() {
|
OpCode::EnterEnv => match stack.pop() {
|
||||||
Value::AttrSet(attrs) => env.enter_with(attrs),
|
Value::AttrSet(attrs) => *env = env.clone().enter_with(attrs),
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
OpCode::LeaveEnv => {
|
OpCode::LeaveEnv => *env = env.clone().leave(),
|
||||||
env.leave();
|
|
||||||
}
|
|
||||||
OpCode::Assert => {
|
OpCode::Assert => {
|
||||||
if !stack.pop().unwrap_const().unwrap_bool() {
|
if !stack.pop().unwrap_const().unwrap_bool() {
|
||||||
todo!()
|
todo!()
|
||||||
|
|||||||
Reference in New Issue
Block a user