Add gen_fn_siguatures API.

This commit is contained in:
Stephen Chung
2020-11-22 17:21:34 +08:00
parent 739dce72e3
commit 07fe132e1a
17 changed files with 400 additions and 83 deletions

View File

@@ -12,7 +12,7 @@ use std::format;
use std::borrow::Cow;
use quote::{quote, quote_spanned};
use quote::{quote, quote_spanned, ToTokens};
use syn::{
parse::{Parse, ParseStream, Parser},
spanned::Spanned,
@@ -83,6 +83,10 @@ pub(crate) fn flatten_type_groups(ty: &syn::Type) -> &syn::Type {
}
}
pub(crate) fn print_type(ty: &syn::Type) -> String {
ty.to_token_stream().to_string().replace("& ", "&")
}
#[derive(Debug, Default)]
pub(crate) struct ExportedFnParams {
pub name: Option<Vec<String>>,
@@ -576,6 +580,7 @@ impl ExportedFn {
syn::Ident::new(&format!("rhai_fn_{}", self.name()), self.name().span());
let impl_block = self.generate_impl("Token");
let callable_block = self.generate_callable("Token");
let input_names_block = self.generate_input_names("Token");
let input_types_block = self.generate_input_types("Token");
let dyn_result_fn_block = self.generate_dynamic_fn();
quote! {
@@ -585,6 +590,7 @@ impl ExportedFn {
struct Token();
#impl_block
#callable_block
#input_names_block
#input_types_block
#dyn_result_fn_block
}
@@ -655,6 +661,19 @@ impl ExportedFn {
}
}
pub fn generate_input_names(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let input_names_fn_name: syn::Ident = syn::Ident::new(
format!("{}_input_names", on_type_name.to_lowercase()).as_str(),
self.name().span(),
);
quote! {
pub fn #input_names_fn_name() -> Box<[&'static str]> {
#token_name().input_names()
}
}
}
pub fn generate_input_types(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let input_types_fn_name: syn::Ident = syn::Ident::new(
@@ -680,6 +699,7 @@ impl ExportedFn {
let mut unpack_stmts: Vec<syn::Stmt> = Vec::new();
let mut unpack_exprs: Vec<syn::Expr> = Vec::new();
let mut input_type_names: Vec<String> = Vec::new();
let mut input_type_exprs: Vec<syn::Expr> = Vec::new();
let skip_first_arg;
@@ -693,8 +713,9 @@ impl ExportedFn {
let first_arg = self.arg_list().next().unwrap();
let var = syn::Ident::new("arg0", proc_macro2::Span::call_site());
match first_arg {
syn::FnArg::Typed(pattern) => {
let arg_type = match flatten_type_groups(pattern.ty.as_ref()) {
syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
let arg_name = format!("{}: {}", pat.to_token_stream(), print_type(ty));
let arg_type = match flatten_type_groups(ty.as_ref()) {
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
p => p,
};
@@ -706,6 +727,7 @@ impl ExportedFn {
})
.unwrap(),
);
input_type_names.push(arg_name);
input_type_exprs.push(
syn::parse2::<syn::Expr>(quote_spanned!(
arg_type.span()=> TypeId::of::<#arg_type>()
@@ -731,9 +753,10 @@ impl ExportedFn {
let is_string;
let is_ref;
match arg {
syn::FnArg::Typed(pattern) => {
let arg_type = pattern.ty.as_ref();
let downcast_span = match flatten_type_groups(pattern.ty.as_ref()) {
syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => {
let arg_name = format!("{}: {}", pat.to_token_stream(), print_type(ty));
let arg_type = ty.as_ref();
let downcast_span = match flatten_type_groups(arg_type) {
syn::Type::Reference(syn::TypeReference {
mutability: None,
ref elem,
@@ -767,6 +790,7 @@ impl ExportedFn {
})
.unwrap(),
);
input_type_names.push(arg_name);
if !is_string {
input_type_exprs.push(
syn::parse2::<syn::Expr>(quote_spanned!(
@@ -837,6 +861,9 @@ impl ExportedFn {
fn is_method_call(&self) -> bool { #is_method_call }
fn is_variadic(&self) -> bool { false }
fn clone_boxed(&self) -> Box<dyn PluginFunction> { Box::new(#type_name()) }
fn input_names(&self) -> Box<[&'static str]> {
new_vec![#(#input_type_names),*].into_boxed_slice()
}
fn input_types(&self) -> Box<[TypeId]> {
new_vec![#(#input_type_exprs),*].into_boxed_slice()
}