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,20 +1,17 @@
use std::rc::Rc;
use derive_more::Constructor;
use gc_arena::Collect;
use gc_arena::Mutation;
use crate::error::Result;
use crate::vm::VM;
use super::Value;
#[derive(Debug, Clone, Constructor, Collect)]
#[collect(require_static)]
#[derive(Debug, Clone, Constructor)]
pub struct PrimOp {
pub name: &'static str,
arity: usize,
func: for<'gc> fn(Vec<Value<'gc>>, &VM, &Mutation<'gc>) -> Result<Value<'gc>>,
func: for<'gc> fn(Vec<Value<'gc>>, &VM) -> Result<Value<'gc>>,
}
impl PartialEq for PrimOp {
@@ -24,21 +21,19 @@ impl PartialEq for PrimOp {
}
impl PrimOp {
pub fn call<'gc>(&self, arg: Value<'gc>, vm: &VM, mc: &Mutation<'gc>) -> Result<Value<'gc>> {
pub fn call<'gc>(&self, arg: Value<'gc>, vm: &VM) -> Result<Value<'gc>> {
let mut args = Vec::with_capacity(self.arity);
args.push(arg);
if self.arity > 1 {
Value::PartialPrimOp(Rc::new(
PartialPrimOp {
name: self.name,
arity: self.arity - 1,
args,
func: self.func,
},
))
Value::PartialPrimOp(Rc::new(PartialPrimOp {
name: self.name,
arity: self.arity - 1,
args,
func: self.func,
}))
.ok()
} else {
(self.func)(args, vm, mc)
(self.func)(args, vm)
}
}
}
@@ -48,15 +43,7 @@ pub struct PartialPrimOp<'gc> {
pub name: &'static str,
arity: usize,
args: Vec<Value<'gc>>,
func: fn(Vec<Value<'gc>>, &VM, &Mutation<'gc>) -> Result<Value<'gc>>,
}
unsafe impl<'gc> Collect<'gc> for PartialPrimOp<'gc> {
fn trace<Tr: gc_arena::collect::Trace<'gc>>(&self, cc: &mut Tr) {
for v in self.args.iter() {
v.trace(cc);
}
}
func: fn(Vec<Value<'gc>>, &VM) -> Result<Value<'gc>>,
}
impl PartialEq for PartialPrimOp<'_> {
@@ -66,19 +53,14 @@ impl PartialEq for PartialPrimOp<'_> {
}
impl<'gc> PartialPrimOp<'gc> {
pub fn call(
self: &mut Rc<Self>,
arg: Value<'gc>,
vm: &VM,
mc: &Mutation<'gc>,
) -> Result<Value<'gc>> {
pub fn call(self: &mut Rc<Self>, arg: Value<'gc>, vm: &VM) -> Result<Value<'gc>> {
let func = self.func;
let Some(ret) = ({
let self_mut = Rc::make_mut(self);
self_mut.args.push(arg);
self_mut.arity -= 1;
if self_mut.arity == 0 {
Some(func(std::mem::take(&mut self_mut.args), vm, mc))
Some(func(std::mem::take(&mut self_mut.args), vm))
} else {
None
}