From 1df5d052392da6ef9cd8bf993d59d1a20806ddad Mon Sep 17 00:00:00 2001 From: J Henry Waugh Date: Sat, 8 Aug 2020 09:31:15 -0500 Subject: [PATCH] export_fn: allow duplicate Rust names --- codegen/src/function.rs | 9 +++++-- codegen/src/lib.rs | 15 ++++++++++-- codegen/tests/test_functions.rs | 42 ++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 88ff685d..f2e0ab11 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -4,7 +4,7 @@ use syn::{parse::Parse, parse::ParseStream, spanned::Spanned}; #[derive(Debug, Default)] pub(crate) struct ExportedFnParams { - name: Option, + pub name: Option, } impl Parse for ExportedFnParams { @@ -238,7 +238,12 @@ impl ExportedFn { } pub fn generate_impl(&self, on_type_name: &str) -> proc_macro2::TokenStream { - let name: syn::Ident = self.name().clone(); + let name: syn::Ident = if let Some(ref name) = self.params.name { + syn::Ident::new(name, self.name().span()) + } else { + self.name().clone() + }; + let arg_count = self.arg_count(); let is_method_call = self.mutable_receiver(); diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 167bd0fb..8cc5bbd4 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -67,7 +67,7 @@ //! ``` //! -use quote::{quote, quote_spanned}; +use quote::{quote, quote_spanned, ToTokens}; use syn::{parse::Parser, parse_macro_input, spanned::Spanned}; mod function; @@ -79,9 +79,20 @@ pub fn export_fn( args: proc_macro::TokenStream, input: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let mut output = proc_macro2::TokenStream::from(input.clone()); + let output = proc_macro2::TokenStream::from(input.clone()); + let parsed_params = parse_macro_input!(args as function::ExportedFnParams); let function_def = parse_macro_input!(input as function::ExportedFn); + + let mut output = if let Some(ref rename) = parsed_params.name { + // If it wasn't a function, it wouldn't have parsed earlier, so unwrap() is fine. + let mut output_fn: syn::ItemFn = syn::parse2(output.clone()).unwrap(); + let new_name = syn::Ident::new(rename, output_fn.sig.ident.span()); + output_fn.sig.ident = new_name; + output_fn.into_token_stream() + } else { + output + }; output.extend(function_def.generate_with_params(parsed_params)); proc_macro::TokenStream::from(output) } diff --git a/codegen/tests/test_functions.rs b/codegen/tests/test_functions.rs index 24dba324..85fcede7 100644 --- a/codegen/tests/test_functions.rs +++ b/codegen/tests/test_functions.rs @@ -1,5 +1,5 @@ use rhai::module_resolvers::*; -use rhai::{Engine, EvalAltResult, Module, RegisterFn, FLOAT, INT}; +use rhai::{Array, Engine, EvalAltResult, Module, RegisterFn, FLOAT}; pub mod raw_fn { use rhai::plugin::*; @@ -190,3 +190,43 @@ fn rename_fn_test() -> Result<(), Box> { ); Ok(()) } + +mod duplicate_fn_rename { + use rhai::plugin::*; + use rhai::{FLOAT, INT}; + + #[export_fn(name = "add_float")] + pub fn add(f1: FLOAT, f2: FLOAT) -> FLOAT { + f1 + f2 + } + + #[export_fn(name = "add_int")] + pub fn add(i1: INT, i2: INT) -> INT { + i1 + i2 + } +} + +#[test] +fn duplicate_fn_rename_test() -> Result<(), Box> { + let mut engine = Engine::new(); + engine.register_fn("get_mystic_number", || 42 as FLOAT); + let mut m = Module::new(); + rhai::register_exported_fn!(m, "add_two_floats", duplicate_fn_rename::add_float); + rhai::register_exported_fn!(m, "add_two_ints", duplicate_fn_rename::add_int); + let mut r = StaticModuleResolver::new(); + r.insert("Math::Advanced".to_string(), m); + engine.set_module_resolver(Some(r)); + + let output_array = engine.eval::( + r#"import "Math::Advanced" as math; + let fx = get_mystic_number(); + let fy = math::add_two_floats(fx, 1.0); + let ix = 42; + let iy = math::add_two_ints(ix, 1); + [fy, iy] + "# + )?; + assert_eq!(&output_array[0].as_float().unwrap(), &43.0); + assert_eq!(&output_array[1].as_int().unwrap(), &43); + Ok(()) +}