export_fn: add "name" parameter
This commit is contained in:
parent
1de13b7a03
commit
7410f40c92
@ -2,12 +2,45 @@
|
|||||||
use quote::{quote, quote_spanned};
|
use quote::{quote, quote_spanned};
|
||||||
use syn::{parse::Parse, parse::ParseStream, spanned::Spanned};
|
use syn::{parse::Parse, parse::ParseStream, spanned::Spanned};
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub(crate) struct ExportedFnParams {
|
||||||
|
name: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for ExportedFnParams {
|
||||||
|
fn parse(args: ParseStream) -> syn::Result<Self> {
|
||||||
|
if args.is_empty() {
|
||||||
|
return Ok(ExportedFnParams::default());
|
||||||
|
}
|
||||||
|
let assignment: syn::ExprAssign = args.parse()?;
|
||||||
|
|
||||||
|
let attr_name: syn::Ident = match assignment.left.as_ref() {
|
||||||
|
syn::Expr::Path(syn::ExprPath { path: attr_path, .. }) => attr_path.get_ident().cloned()
|
||||||
|
.ok_or_else(|| syn::Error::new(attr_path.span(), "expecting attribute name"))?,
|
||||||
|
x => return Err(syn::Error::new(x.span(), "expecting attribute name")),
|
||||||
|
};
|
||||||
|
if &attr_name != "name" {
|
||||||
|
return Err(syn::Error::new(attr_name.span(), format!("unknown attribute '{}'", &attr_name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let attr_value: String = match assignment.right.as_ref() {
|
||||||
|
syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(string), .. }) => string.value(),
|
||||||
|
x => return Err(syn::Error::new(x.span(), "expecting string literal value")),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ExportedFnParams {
|
||||||
|
name: Some(attr_value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct ExportedFn {
|
pub(crate) struct ExportedFn {
|
||||||
entire_span: proc_macro2::Span,
|
entire_span: proc_macro2::Span,
|
||||||
signature: syn::Signature,
|
signature: syn::Signature,
|
||||||
is_public: bool,
|
is_public: bool,
|
||||||
mut_receiver: bool,
|
mut_receiver: bool,
|
||||||
|
params: ExportedFnParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ExportedFn {
|
impl Parse for ExportedFn {
|
||||||
@ -111,6 +144,7 @@ impl Parse for ExportedFn {
|
|||||||
signature: fn_all.sig,
|
signature: fn_all.sig,
|
||||||
is_public,
|
is_public,
|
||||||
mut_receiver,
|
mut_receiver,
|
||||||
|
params: ExportedFnParams::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,11 +182,20 @@ impl ExportedFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn generate_with_params(mut self,
|
||||||
|
mut params: ExportedFnParams) -> proc_macro2::TokenStream {
|
||||||
|
self.params = params;
|
||||||
|
self.generate()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate(self) -> proc_macro2::TokenStream {
|
pub fn generate(self) -> proc_macro2::TokenStream {
|
||||||
let name: syn::Ident = syn::Ident::new(
|
let name_str = if let Some(ref name) = self.params.name {
|
||||||
&format!("rhai_fn_{}", self.name().to_string()),
|
name.clone()
|
||||||
self.name().span(),
|
} else {
|
||||||
);
|
self.name().to_string()
|
||||||
|
};
|
||||||
|
let name: syn::Ident = syn::Ident::new(&format!("rhai_fn_{}", name_str),
|
||||||
|
self.name().span());
|
||||||
let impl_block = self.generate_impl("Token");
|
let impl_block = self.generate_impl("Token");
|
||||||
let callable_block = self.generate_callable("Token");
|
let callable_block = self.generate_callable("Token");
|
||||||
let input_types_block = self.generate_input_types("Token");
|
let input_types_block = self.generate_input_types("Token");
|
||||||
|
@ -76,12 +76,13 @@ mod rhai_module;
|
|||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn export_fn(
|
pub fn export_fn(
|
||||||
_args: proc_macro::TokenStream,
|
args: proc_macro::TokenStream,
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
let mut output = proc_macro2::TokenStream::from(input.clone());
|
let mut 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 function_def = parse_macro_input!(input as function::ExportedFn);
|
||||||
output.extend(function_def.generate());
|
output.extend(function_def.generate_with_params(parsed_params));
|
||||||
proc_macro::TokenStream::from(output)
|
proc_macro::TokenStream::from(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,3 +158,35 @@ fn mut_opaque_ref_test() -> Result<(), Box<EvalAltResult>> {
|
|||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod rename_fn {
|
||||||
|
use rhai::plugin::*;
|
||||||
|
use rhai::FLOAT;
|
||||||
|
|
||||||
|
#[export_fn(name = "add_float")]
|
||||||
|
pub fn add(f1: FLOAT, f2: FLOAT) -> FLOAT {
|
||||||
|
f1 + f2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rename_fn_test() -> Result<(), Box<EvalAltResult>> {
|
||||||
|
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", rename_fn::add_float);
|
||||||
|
let mut r = StaticModuleResolver::new();
|
||||||
|
r.insert("Math::Advanced".to_string(), m);
|
||||||
|
engine.set_module_resolver(Some(r));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<FLOAT>(
|
||||||
|
r#"import "Math::Advanced" as math;
|
||||||
|
let x = get_mystic_number();
|
||||||
|
let y = math::add_two_floats(x, 1.0);
|
||||||
|
y"#
|
||||||
|
)?,
|
||||||
|
43.0
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
24
codegen/ui_tests/export_fn_bad_attr.rs
Normal file
24
codegen/ui_tests/export_fn_bad_attr.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use rhai::plugin::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Point {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_fn(unknown = true)]
|
||||||
|
pub fn test_fn(input: Point) -> bool {
|
||||||
|
input.x > input.y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let n = Point {
|
||||||
|
x: 0.0,
|
||||||
|
y: 10.0,
|
||||||
|
};
|
||||||
|
if test_fn(n) {
|
||||||
|
println!("yes");
|
||||||
|
} else {
|
||||||
|
println!("no");
|
||||||
|
}
|
||||||
|
}
|
11
codegen/ui_tests/export_fn_bad_attr.stderr
Normal file
11
codegen/ui_tests/export_fn_bad_attr.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error: unknown attribute 'unknown'
|
||||||
|
--> $DIR/export_fn_bad_attr.rs:9:13
|
||||||
|
|
|
||||||
|
9 | #[export_fn(unknown = true)]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error[E0425]: cannot find function `test_fn` in this scope
|
||||||
|
--> $DIR/export_fn_bad_attr.rs:19:8
|
||||||
|
|
|
||||||
|
19 | if test_fn(n) {
|
||||||
|
| ^^^^^^^ not found in this scope
|
24
codegen/ui_tests/export_fn_bad_value.rs
Normal file
24
codegen/ui_tests/export_fn_bad_value.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use rhai::plugin::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Point {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_fn(name = true)]
|
||||||
|
pub fn test_fn(input: Point) -> bool {
|
||||||
|
input.x > input.y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let n = Point {
|
||||||
|
x: 0.0,
|
||||||
|
y: 10.0,
|
||||||
|
};
|
||||||
|
if test_fn(n) {
|
||||||
|
println!("yes");
|
||||||
|
} else {
|
||||||
|
println!("no");
|
||||||
|
}
|
||||||
|
}
|
11
codegen/ui_tests/export_fn_bad_value.stderr
Normal file
11
codegen/ui_tests/export_fn_bad_value.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error: expecting string literal value
|
||||||
|
--> $DIR/export_fn_bad_value.rs:9:20
|
||||||
|
|
|
||||||
|
9 | #[export_fn(name = true)]
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
|
error[E0425]: cannot find function `test_fn` in this scope
|
||||||
|
--> $DIR/export_fn_bad_value.rs:19:8
|
||||||
|
|
|
||||||
|
19 | if test_fn(n) {
|
||||||
|
| ^^^^^^^ not found in this scope
|
24
codegen/ui_tests/export_fn_junk_arg.rs
Normal file
24
codegen/ui_tests/export_fn_junk_arg.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use rhai::plugin::*;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Point {
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[export_fn("wheeeee")]
|
||||||
|
pub fn test_fn(input: Point) -> bool {
|
||||||
|
input.x > input.y
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let n = Point {
|
||||||
|
x: 0.0,
|
||||||
|
y: 10.0,
|
||||||
|
};
|
||||||
|
if test_fn(n) {
|
||||||
|
println!("yes");
|
||||||
|
} else {
|
||||||
|
println!("no");
|
||||||
|
}
|
||||||
|
}
|
11
codegen/ui_tests/export_fn_junk_arg.stderr
Normal file
11
codegen/ui_tests/export_fn_junk_arg.stderr
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
error: expected assignment expression
|
||||||
|
--> $DIR/export_fn_junk_arg.rs:9:13
|
||||||
|
|
|
||||||
|
9 | #[export_fn("wheeeee")]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0425]: cannot find function `test_fn` in this scope
|
||||||
|
--> $DIR/export_fn_junk_arg.rs:19:8
|
||||||
|
|
|
||||||
|
19 | if test_fn(n) {
|
||||||
|
| ^^^^^^^ not found in this scope
|
Loading…
Reference in New Issue
Block a user