extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro2::Span;
extern crate syn;
use syn::spanned::Spanned;
use syn::*;
use std::result::Result;
pub struct FunctionInfo {
pub name: Ident,
pub has_return: bool,
}
pub fn get_declared_helper_functions(
attribute_args: AttributeArgs,
) -> Result<Vec<Ident>, Vec<syn::Error>> {
let mut declared_helper_functions = vec![];
let mut errors = vec![];
for attribute_arg in attribute_args {
if let NestedMeta::Meta(meta) = attribute_arg {
if let Meta::Path(path) = meta {
if let Some(ident) = path.get_ident() {
declared_helper_functions.push((*ident).clone());
} else {
errors.push(syn::Error::new(
path.span(),
"expected identifier/name of helper function",
));
}
} else {
errors.push(syn::Error::new(
meta.span(),
"expected name of helper function",
));
}
} else {
errors.push(syn::Error::new(
attribute_arg.span(),
"expected name of helper function",
));
}
}
if errors.len() > 0 {
Err(errors)
} else {
Ok(declared_helper_functions)
}
}
pub fn get_function_info(input: TokenStream) -> Result<FunctionInfo, Vec<Error>> {
let maybe_ast = syn::parse::<ItemFn>(input);
let mut errors = vec![];
if let Ok(ast) = maybe_ast {
if ast.sig.abi.is_some() {
errors.push(syn::Error::new(
ast.sig.span(),
"ABI function cannot be tagged with `#[gpu_use]`",
));
return Err(errors);
}
if ast.sig.asyncness.is_some() {
errors.push(syn::Error::new(
ast.sig.span(),
"async function cannot be tagged with `#[gpu_use]`",
));
return Err(errors);
}
Ok(FunctionInfo {
name: ast.sig.ident,
has_return: if let ReturnType::Default = ast.sig.output {
false
} else {
true
},
})
} else {
Err(vec![Error::new(
Span::call_site().unwrap().into(),
"only functions that are items can be tagged with `#[gpu_use]`",
)])
}
}