fmt, fixes and additions

This commit is contained in:
timurgordon
2025-06-19 13:18:10 +03:00
parent 6b3cbfc4b2
commit e91a44ce37
86 changed files with 5292 additions and 2844 deletions

View File

@@ -1,23 +1,23 @@
use proc_macro::TokenStream;
use quote::{quote, format_ident};
use syn::{parse_macro_input, ItemFn, FnArg, Pat, PatType, ReturnType, parse_quote};
use quote::{format_ident, quote};
use syn::{parse_macro_input, parse_quote, FnArg, ItemFn, Pat, PatType, ReturnType};
/// Procedural macro that generates a Rhai client function for a Rust function.
///
///
/// When applied to a Rust function, it generates a corresponding function with a '_rhai_client' suffix
/// that calls the original function through the Rhai engine.
///
///
/// # Example
///
///
/// ```rust
/// #[rhai]
/// fn hello(name: String) -> String {
/// format!("Hello, {}!", name)
/// }
/// ```
///
///
/// This will generate:
///
///
/// ```rust
/// fn hello_rhai_client(engine: &rhai::Engine, name: String) -> String {
/// let script = format!("hello(\"{}\")", name.replace("\"", "\\\""));
@@ -27,7 +27,7 @@ use syn::{parse_macro_input, ItemFn, FnArg, Pat, PatType, ReturnType, parse_quot
/// })
/// }
/// ```
///
///
/// Note: The macro handles type conversions between Rust and Rhai types,
/// particularly for integer types (Rhai uses i64 internally).
#[proc_macro_attribute]
@@ -36,15 +36,15 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input_fn = parse_macro_input!(item as ItemFn);
let fn_name = &input_fn.sig.ident;
let fn_name_str = fn_name.to_string();
// Create the client function name (original + _rhai_client)
let client_fn_name = format_ident!("{}_rhai_client", fn_name);
// Extract function parameters
let mut param_names = Vec::new();
let mut param_types = Vec::new();
let mut param_declarations = Vec::new();
for arg in &input_fn.sig.inputs {
match arg {
FnArg::Typed(PatType { pat, ty, .. }) => {
@@ -61,48 +61,55 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
}
}
// Determine return type
let return_type = match &input_fn.sig.output {
ReturnType::Default => parse_quote!(()),
ReturnType::Type(_, ty) => ty.clone(),
};
// Generate parameter formatting for the Rhai script
let param_format_strings = param_names.iter().zip(param_types.iter()).map(|(name, ty)| {
let type_str = quote! { #ty }.to_string();
// Handle different parameter types
if type_str.contains("String") {
quote! {
format!("\"{}\"" , #name.replace("\"", "\\\""))
let param_format_strings = param_names
.iter()
.zip(param_types.iter())
.map(|(name, ty)| {
let type_str = quote! { #ty }.to_string();
// Handle different parameter types
if type_str.contains("String") {
quote! {
format!("\"{}\"" , #name.replace("\"", "\\\""))
}
} else if type_str.contains("bool") {
quote! {
format!("{}", #name)
}
} else if type_str.contains("i32") || type_str.contains("u32") {
// Convert smaller integer types to i64 for Rhai
quote! {
format!("{}", #name as i64)
}
} else if type_str.contains("i64")
|| type_str.contains("u64")
|| type_str.contains("f32")
|| type_str.contains("f64")
{
// Other numeric types
quote! {
format!("{}", #name)
}
} else {
// For complex types, just pass the variable name
// The Rhai engine will handle the conversion
quote! {
#name.to_string()
}
}
} else if type_str.contains("bool") {
quote! {
format!("{}", #name)
}
} else if type_str.contains("i32") || type_str.contains("u32") {
// Convert smaller integer types to i64 for Rhai
quote! {
format!("{}", #name as i64)
}
} else if type_str.contains("i64") || type_str.contains("u64") || type_str.contains("f32") || type_str.contains("f64") {
// Other numeric types
quote! {
format!("{}", #name)
}
} else {
// For complex types, just pass the variable name
// The Rhai engine will handle the conversion
quote! {
#name.to_string()
}
}
});
});
// Determine if the return type needs conversion
let return_type_str = quote! { #return_type }.to_string();
// Generate the client function with appropriate type conversions
let client_fn = if return_type_str.contains("i32") || return_type_str.contains("u32") {
// For integer return types that need conversion
@@ -113,7 +120,7 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
#fn_name_str,
&[#(#param_format_strings),*].join(", ")
);
match engine.eval::<i64>(&script) {
Ok(result) => result as #return_type,
Err(err) => {
@@ -132,7 +139,7 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
#fn_name_str,
&[#(#param_format_strings),*].join(", ")
);
match engine.eval::<#return_type>(&script) {
Ok(result) => result,
Err(err) => {
@@ -151,7 +158,7 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
#fn_name_str,
&[#(#param_format_strings),*].join(", ")
);
match engine.eval::<#return_type>(&script) {
Ok(result) => result,
Err(err) => {
@@ -170,7 +177,7 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
#fn_name_str,
&[#(#param_format_strings),*].join(", ")
);
match engine.eval::<#return_type>(&script) {
Ok(result) => result,
Err(err) => {
@@ -181,19 +188,19 @@ pub fn rhai(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
}
};
// Combine the original function and the generated client function
let output = quote! {
#input_fn
#client_fn
};
output.into()
}
/// A more advanced version of the rhai macro that handles different parameter types better.
///
///
/// This version properly escapes strings and handles different parameter types more accurately.
/// It's recommended to use this version for more complex functions.
#[proc_macro_attribute]
@@ -202,15 +209,15 @@ pub fn rhai_advanced(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input_fn = parse_macro_input!(item as ItemFn);
let fn_name = &input_fn.sig.ident;
let fn_name_str = fn_name.to_string();
// Create the client function name (original + _rhai_client)
let client_fn_name = format_ident!("{}_rhai_client", fn_name);
// Extract function parameters
let mut param_names = Vec::new();
let mut param_types = Vec::new();
let mut param_declarations = Vec::new();
for arg in &input_fn.sig.inputs {
match arg {
FnArg::Typed(PatType { pat, ty, .. }) => {
@@ -227,48 +234,53 @@ pub fn rhai_advanced(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
}
}
// Determine return type
let return_type = match &input_fn.sig.output {
ReturnType::Default => parse_quote!(()),
ReturnType::Type(_, ty) => ty.clone(),
};
// Generate parameter formatting for the Rhai script
let param_format_expressions = param_names.iter().zip(param_types.iter()).map(|(name, ty)| {
let type_str = quote! { #ty }.to_string();
// Handle different parameter types
if type_str.contains("String") {
quote! {
format!("\"{}\"", #name.replace("\"", "\\\""))
let param_format_expressions = param_names
.iter()
.zip(param_types.iter())
.map(|(name, ty)| {
let type_str = quote! { #ty }.to_string();
// Handle different parameter types
if type_str.contains("String") {
quote! {
format!("\"{}\"", #name.replace("\"", "\\\""))
}
} else if type_str.contains("bool") {
quote! {
format!("{}", #name)
}
} else if type_str.contains("i32") || type_str.contains("u32") {
// Convert smaller integer types to i64 for Rhai
quote! {
format!("{}", #name as i64)
}
} else if type_str.contains("i") || type_str.contains("u") || type_str.contains("f") {
// Other numeric types
quote! {
format!("{}", #name)
}
} else {
// Default for other types
quote! {
format!("{:?}", #name)
}
}
} else if type_str.contains("bool") {
quote! {
format!("{}", #name)
}
} else if type_str.contains("i32") || type_str.contains("u32") {
// Convert smaller integer types to i64 for Rhai
quote! {
format!("{}", #name as i64)
}
} else if type_str.contains("i") || type_str.contains("u") || type_str.contains("f") {
// Other numeric types
quote! {
format!("{}", #name)
}
} else {
// Default for other types
quote! {
format!("{:?}", #name)
}
}
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
// Determine if the return type needs conversion
let return_type_str = quote! { #return_type }.to_string();
let needs_return_conversion = return_type_str.contains("i32") || return_type_str.contains("u32");
let needs_return_conversion =
return_type_str.contains("i32") || return_type_str.contains("u32");
// Generate the client function with appropriate type conversions
let client_fn = if needs_return_conversion {
quote! {
@@ -278,7 +290,7 @@ pub fn rhai_advanced(_attr: TokenStream, item: TokenStream) -> TokenStream {
#fn_name_str,
&[#(#param_format_expressions),*].join(", ")
);
match engine.eval::<i64>(&script) {
Ok(result) => result as #return_type,
Err(err) => {
@@ -296,7 +308,7 @@ pub fn rhai_advanced(_attr: TokenStream, item: TokenStream) -> TokenStream {
#fn_name_str,
&[#(#param_format_expressions),*].join(", ")
);
match engine.eval::<#return_type>(&script) {
Ok(result) => result,
Err(err) => {
@@ -307,19 +319,19 @@ pub fn rhai_advanced(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
}
};
// Combine the original function and the generated client function
let output = quote! {
#input_fn
#client_fn
};
output.into()
}
/// Macro that generates a module with Rhai client functions for all functions in scope.
///
///
/// This macro should be used at the module level to generate Rhai client functions for all
/// functions marked with the #[rhai] attribute.
#[proc_macro]
@@ -329,20 +341,20 @@ pub fn generate_rhai_module(_item: TokenStream) -> TokenStream {
// client functions for all of them.
//
// For simplicity, we'll just return a placeholder implementation
let output = quote! {
/// Register all functions marked with #[rhai] in this module with the Rhai engine.
///
///
/// This function handles type conversions between Rust and Rhai types automatically.
/// For example, it converts between Rust's i32 and Rhai's i64 types.
pub fn register_rhai_functions(engine: &mut rhai::Engine) {
// This would be generated based on the functions in the module
println!("Registering Rhai functions...");
// In a real implementation, this would iterate through all functions
// marked with #[rhai] and register them with the engine.
}
};
output.into()
}