mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-18 22:53:16 +00:00
Handle arguments for lua functions in a better way
This commit is contained in:
parent
66a5a009e2
commit
d62fb39a93
3 changed files with 115 additions and 14 deletions
|
@ -14,6 +14,7 @@ noita_api_macro::generate_components!();
|
|||
|
||||
pub mod raw {
|
||||
use super::{Color, ComponentID, EntityID, Obj};
|
||||
use crate::lua::LuaPutValue;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::lua::LuaState;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod lua_bindings;
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::Cell,
|
||||
ffi::{c_char, c_int, CStr},
|
||||
mem, slice,
|
||||
|
@ -10,6 +11,8 @@ use std::{
|
|||
use eyre::{bail, Context, OptionExt};
|
||||
use lua_bindings::{lua_CFunction, lua_State, Lua51, LUA_GLOBALSINDEX};
|
||||
|
||||
use crate::{Color, ComponentID, EntityID, Obj};
|
||||
|
||||
thread_local! {
|
||||
static CURRENT_LUA_STATE: Cell<Option<LuaState>> = Cell::default();
|
||||
}
|
||||
|
@ -121,6 +124,7 @@ impl LuaState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Used for types that can be returned from functions that were defined in rust to lua.
|
||||
pub trait LuaFnRet {
|
||||
fn do_return(self, lua: LuaState) -> c_int;
|
||||
}
|
||||
|
@ -150,3 +154,93 @@ impl<R: LuaFnRet> LuaFnRet for eyre::Result<R> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for arguments that can be put on lua stack.
|
||||
pub(crate) trait LuaPutValue {
|
||||
fn put(&self, lua: LuaState);
|
||||
fn is_non_empty(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for i32 {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_integer(*self as isize);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for isize {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_integer(*self);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for u32 {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_integer(unsafe { mem::transmute::<_, i32>(*self) as isize });
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for f64 {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_number(*self);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for bool {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_bool(*self);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for Cow<'_, str> {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_string(self.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for str {
|
||||
fn put(&self, lua: LuaState) {
|
||||
lua.push_string(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for EntityID {
|
||||
fn put(&self, lua: LuaState) {
|
||||
self.0.put(lua);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for ComponentID {
|
||||
fn put(&self, lua: LuaState) {
|
||||
self.0.put(lua);
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for Color {
|
||||
fn put(&self, _lua: LuaState) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl LuaPutValue for Obj {
|
||||
fn put(&self, _lua: LuaState) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: LuaPutValue> LuaPutValue for Option<T> {
|
||||
fn put(&self, lua: LuaState) {
|
||||
match self {
|
||||
Some(val) => val.put(lua),
|
||||
None => lua.push_nil(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_non_empty(&self) -> bool {
|
||||
match self {
|
||||
Some(val) => val.is_non_empty(),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -228,19 +228,23 @@ fn generate_code_for_api_fn(api_fn: ApiFn) -> proc_macro2::TokenStream {
|
|||
}
|
||||
});
|
||||
|
||||
let put_args = api_fn.args.iter().map(|arg| {
|
||||
let optional = arg.default.is_some();
|
||||
let put_args_pre = api_fn.args.iter().enumerate().map(|(i, arg)| {
|
||||
let arg_name = format_ident!("{}", arg.name);
|
||||
let arg_push = arg.typ.generate_lua_push(arg_name.clone());
|
||||
if optional {
|
||||
quote! {
|
||||
match #arg_name {
|
||||
Some(#arg_name) => #arg_push,
|
||||
None => lua.push_nil(),
|
||||
}
|
||||
let i = i as i32;
|
||||
quote! {
|
||||
if LuaPutValue::is_non_empty(&#arg_name) {
|
||||
last_non_empty = #i;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let put_args = api_fn.args.iter().enumerate().map(|(i, arg)| {
|
||||
let arg_name = format_ident!("{}", arg.name);
|
||||
let i = i as i32;
|
||||
quote! {
|
||||
if #i <= last_non_empty {
|
||||
LuaPutValue::put(&#arg_name, lua);
|
||||
}
|
||||
} else {
|
||||
arg_push
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -266,7 +270,6 @@ fn generate_code_for_api_fn(api_fn: ApiFn) -> proc_macro2::TokenStream {
|
|||
|
||||
let fn_name_c = name_to_c_literal(api_fn.fn_name);
|
||||
|
||||
let arg_count = api_fn.args.len() as i32;
|
||||
let ret_count = api_fn.rets.len() as i32;
|
||||
|
||||
quote! {
|
||||
|
@ -275,9 +278,12 @@ fn generate_code_for_api_fn(api_fn: ApiFn) -> proc_macro2::TokenStream {
|
|||
let lua = LuaState::current()?;
|
||||
|
||||
lua.get_global(#fn_name_c);
|
||||
#(#put_args;)*
|
||||
|
||||
lua.call(#arg_count, #ret_count);
|
||||
let mut last_non_empty: i32 = -1;
|
||||
#(#put_args_pre)*
|
||||
#(#put_args)*
|
||||
|
||||
lua.call(last_non_empty+1, #ret_count);
|
||||
|
||||
let ret = Ok(#ret_expr);
|
||||
lua.pop_last_n(#ret_count);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue