75 lines
2.0 KiB
Rust
75 lines
2.0 KiB
Rust
use std::rc::Rc;
|
|
|
|
use derive_more::Constructor;
|
|
|
|
use crate::error::Result;
|
|
use crate::vm::VM;
|
|
|
|
use super::Value;
|
|
|
|
#[derive(Debug, Clone, Constructor)]
|
|
pub struct PrimOp<'jit: 'vm, 'vm> {
|
|
pub name: &'static str,
|
|
arity: usize,
|
|
func: fn(&'vm VM<'jit>, Vec<Value<'jit, 'vm>>) -> Result<Value<'jit, 'vm>>,
|
|
}
|
|
|
|
impl PartialEq for PrimOp<'_, '_> {
|
|
fn eq(&self, _: &Self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
impl<'jit, 'vm> PrimOp<'jit, 'vm> {
|
|
pub fn call(&self, vm: &'vm VM<'jit>, args: Vec<Value<'jit, 'vm>>) -> Result<Value<'jit, 'vm>> {
|
|
if (args.len()) < self.arity {
|
|
Value::PartialPrimOp(
|
|
PartialPrimOp {
|
|
name: self.name,
|
|
arity: self.arity - args.len(),
|
|
args,
|
|
func: self.func,
|
|
}
|
|
.into(),
|
|
)
|
|
.ok()
|
|
} else if args.len() == self.arity {
|
|
(self.func)(vm, args)
|
|
} else {
|
|
unimplemented!()
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PartialPrimOp<'jit: 'vm, 'vm> {
|
|
pub name: &'static str,
|
|
arity: usize,
|
|
args: Vec<Value<'jit, 'vm>>,
|
|
func: fn(&'vm VM<'jit>, Vec<Value<'jit, 'vm>>) -> Result<Value<'jit, 'vm>>,
|
|
}
|
|
|
|
impl PartialEq for PartialPrimOp<'_, '_> {
|
|
fn eq(&self, _: &Self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
impl<'jit: 'vm, 'vm> PartialPrimOp<'jit, 'vm> {
|
|
pub fn call(self: &Rc<Self>, vm: &'vm VM<'jit>, args: Vec<Value<'jit, 'vm>>) -> Result<Value<'jit, 'vm>> {
|
|
let len = args.len();
|
|
let mut self_clone = self.clone();
|
|
let self_mut = Rc::make_mut(&mut self_clone);
|
|
self_mut.args.extend(args);
|
|
self_mut.arity -= len;
|
|
if self_mut.arity > 0 {
|
|
Value::PartialPrimOp(self_clone).ok()
|
|
} else if self_mut.arity == 0 {
|
|
let args = std::mem::replace(&mut self_mut.args, Vec::new());
|
|
(self.func)(vm, args)
|
|
} else {
|
|
unimplemented!()
|
|
}
|
|
}
|
|
}
|