use std::boxed::Box;
use std::cell::RefCell;
use std::rc::Rc;
use crate::LuaEnv;
use crate::LuaValue;
use crate::RuntimeError;
#[derive(Debug, Clone, Copy)]
pub struct FunctionInfo {
pub args: usize,
pub is_variadic: bool,
pub local_variables: usize,
pub address: usize,
}
type LuaFunctionRust = Box<dyn Fn(&mut LuaEnv, usize, Option<usize>) -> Result<(), RuntimeError>>;
pub enum LuaFunction {
LuaFunc(LuaFunctionLua),
RustFunc(LuaFunctionRust),
}
impl std::fmt::Debug for LuaFunction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LuaFunction::LuaFunc(func) => write!(f, "LuaFunctionLua({:?})", func),
LuaFunction::RustFunc(func) => {
write!(f, "LuaFunctionRust({:p})", func.as_ref() as *const _)
}
}
}
}
impl LuaFunction {
pub fn from_func_with_expected(
func: impl Fn(&mut LuaEnv, usize, Option<usize>) -> Result<(), RuntimeError> + 'static,
) -> Self {
LuaFunction::RustFunc(Box::new(func))
}
pub fn from_func(
func: impl Fn(&mut LuaEnv, usize) -> Result<usize, RuntimeError> + 'static,
) -> Self {
Self::from_func_with_expected(move |env, stack_top, expected| {
let ret = func(env, stack_top)?;
if let Some(expected) = expected {
let mut thread_mut = env.borrow_running_thread_mut();
let adjusted = thread_mut.data_stack.len() - ret + expected;
thread_mut
.data_stack
.resize_with(adjusted, Default::default);
}
Ok(())
})
}
}
#[derive(Debug, Clone)]
pub struct LuaFunctionLua {
pub upvalues: Vec<Rc<RefCell<LuaValue>>>,
pub function_id: usize,
}