feat: partial func (WIP)
This commit is contained in:
@@ -1,21 +1,16 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use derive_more::Constructor;
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use crate::env::Env;
|
||||
|
||||
use crate::ir;
|
||||
pub struct Func<'gc> {
|
||||
pub func: &'gc ir::Func,
|
||||
pub env: Rc<Env>,
|
||||
}
|
||||
|
||||
impl<'gc> Func<'gc> {
|
||||
pub fn new(func: &'gc ir::Func, env: Rc<Env>) -> Self {
|
||||
Self { func, env }
|
||||
}
|
||||
}
|
||||
use super::Value;
|
||||
|
||||
impl PartialEq for Func<'_> {
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
#[derive(Debug, Clone, Constructor)]
|
||||
pub struct PartialFunc {
|
||||
pub idx: usize,
|
||||
pub args: Vec<Value>,
|
||||
pub cache: HashMap<usize, Value>
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::rc::Rc;
|
||||
|
||||
use derive_more::{IsVariant, Unwrap};
|
||||
use ecow::EcoString;
|
||||
use func::PartialFunc;
|
||||
use hashbrown::HashSet;
|
||||
use replace_with::replace_with_or_abort;
|
||||
|
||||
@@ -37,7 +38,7 @@ pub enum Value {
|
||||
PrimOp(Rc<PrimOp>),
|
||||
PartialPrimOp(Rc<PartialPrimOp>),
|
||||
Func(usize),
|
||||
PartialFunc(usize, Vec<Value>),
|
||||
PartialFunc(Rc<PartialFunc>)
|
||||
}
|
||||
|
||||
impl Hash for Value {
|
||||
@@ -97,7 +98,7 @@ pub enum ValueAsRef<'v> {
|
||||
PrimOp(&'v PrimOp),
|
||||
PartialPrimOp(&'v PartialPrimOp),
|
||||
Func(usize),
|
||||
PartialFunc(usize, &'v Vec<Value>),
|
||||
PartialFunc(&'v PartialFunc),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
@@ -117,7 +118,7 @@ impl Value {
|
||||
PrimOp(x) => R::PrimOp(x),
|
||||
PartialPrimOp(x) => R::PartialPrimOp(x),
|
||||
Func(x) => R::Func(*x),
|
||||
PartialFunc(x, args) => R::PartialFunc(*x, args),
|
||||
PartialFunc(x) => R::PartialFunc(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,14 +165,15 @@ impl Value {
|
||||
*self = match self {
|
||||
PrimOp(func) => func.call(args, engine),
|
||||
PartialPrimOp(func) => func.call(args, engine),
|
||||
PartialFunc(idx, old) => {
|
||||
PartialFunc(func) => {
|
||||
let self::PartialFunc { idx, args: old_args, cache } = Rc::make_mut(func);
|
||||
let idx = *idx;
|
||||
let len = args.len() + old.len();
|
||||
let len = args.len() + old_args.len();
|
||||
env.reserve_args(len);
|
||||
env.enter_args(std::mem::take(old));
|
||||
env.enter_cache_level(|env| {
|
||||
let mut args = args.into_iter().peekable();
|
||||
env.enter_arg(args.next().unwrap());
|
||||
env.enter_args(std::mem::take(old_args));
|
||||
let mut args = args.into_iter().peekable();
|
||||
env.enter_arg(args.next().unwrap());
|
||||
let (ret, cache) = env.enter_cache_level(|env| {
|
||||
let mut ret = engine.eval_thunk(idx, env)?;
|
||||
while args.peek().is_some() {
|
||||
match ret {
|
||||
@@ -190,22 +192,24 @@ impl Value {
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
let args = env.pop_args(len);
|
||||
if let Value::Func(idx) = ret {
|
||||
ret = Value::PartialFunc(idx, args)
|
||||
} else if let Value::PartialFunc(_, old) = &mut ret {
|
||||
old.extend(args);
|
||||
}
|
||||
ret.ok()
|
||||
})
|
||||
});
|
||||
let mut ret = ret?;
|
||||
let args = env.pop_args(len);
|
||||
if let Value::Func(idx) = ret {
|
||||
ret = PartialFunc(self::PartialFunc::new(idx, args, cache).into());
|
||||
} else if let Value::PartialFunc(func) = &mut ret {
|
||||
Rc::make_mut(func).args.extend(args);
|
||||
}
|
||||
ret.ok()
|
||||
}
|
||||
&mut Func(idx) => {
|
||||
let len = args.len();
|
||||
let mut args = args.into_iter().peekable();
|
||||
env.reserve_args(len);
|
||||
env.enter_cache_level(|env| {
|
||||
env.enter_arg(args.next().unwrap());
|
||||
let (ret, cache) = env.enter_cache_level(|env| {
|
||||
let mut ret = engine.eval_thunk(idx, env)?;
|
||||
env.enter_arg(args.next().unwrap());
|
||||
while args.peek().is_some() {
|
||||
match ret {
|
||||
Value::Func(func) => {
|
||||
@@ -223,14 +227,16 @@ impl Value {
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
let args = env.pop_args(len);
|
||||
if let Value::Func(idx) = ret {
|
||||
ret = Value::PartialFunc(idx, args)
|
||||
} else if let Value::PartialFunc(_, old) = &mut ret {
|
||||
old.extend(args);
|
||||
}
|
||||
ret.ok()
|
||||
})
|
||||
});
|
||||
let mut ret = ret?;
|
||||
let args = env.pop_args(len);
|
||||
if let Value::Func(idx) = ret {
|
||||
ret = Value::PartialFunc(self::PartialFunc::new(idx, args, cache).into())
|
||||
} else if let Value::PartialFunc(func) = &mut ret {
|
||||
Rc::make_mut(func).args.extend(args);
|
||||
}
|
||||
ret.ok()
|
||||
}
|
||||
Catchable(_) => return Ok(()),
|
||||
other => todo!("{}", other.typename()),
|
||||
|
||||
Reference in New Issue
Block a user