Port `pyo3cls` to latest `syn`

This commit is contained in:
Martin Larralde 2018-05-14 00:49:15 +02:00
parent bf550c3c1f
commit d07c538779
2 changed files with 55 additions and 72 deletions

View File

@ -26,7 +26,7 @@ pub fn py3_init(fnname: &syn::Ident, name: &syn::Ident, doc: syn::Lit) -> Tokens
static mut MODULE_DEF: pyo3::ffi::PyModuleDef = pyo3::ffi::PyModuleDef_INIT; static mut MODULE_DEF: pyo3::ffi::PyModuleDef = pyo3::ffi::PyModuleDef_INIT;
// We can't convert &'static str to *const c_char within a static initializer, // We can't convert &'static str to *const c_char within a static initializer,
// so we'll do it here in the module initialization: // so we'll do it here in the module initialization:
MODULE_DEF.name = concat!(stringify!(#name), "\0").as_ptr() as *const _; MODULE_DEF.m_name = concat!(stringify!(#name), "\0").as_ptr() as *const _;
#[cfg(py_sys_config = "WITH_THREAD")] #[cfg(py_sys_config = "WITH_THREAD")]
pyo3::ffi::PyEval_InitThreads(); pyo3::ffi::PyEval_InitThreads();

View File

@ -6,136 +6,119 @@
extern crate proc_macro; extern crate proc_macro;
extern crate pyo3_derive_backend; extern crate pyo3_derive_backend;
extern crate quote; extern crate quote;
#[macro_use]
extern crate syn; extern crate syn;
use std::str::FromStr;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use pyo3_derive_backend::*; use pyo3_derive_backend::*;
use quote::{ToTokens, Tokens}; use quote::{ToTokens, Tokens};
use std::str::FromStr; use syn::buffer::TokenBuffer;
use syn::punctuated::Punctuated;
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn mod2init(attr: TokenStream, input: TokenStream) -> TokenStream { pub fn mod2init(attr: TokenStream, input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition // Parse the token stream into a syntax tree
let source = input.to_string(); let mut ast: syn::ItemFn = syn::parse(input).unwrap();
// Parse the string representation into a syntax tree // Extract the mod name
let mut ast = syn::parse_item(&source).unwrap(); let modname: syn::Ident = syn::parse(attr).unwrap();
// Build the output // Process the functions within the module
module::process_functions_in_module(&mut ast); module::process_functions_in_module(&mut ast);
let attr = utils::attr_with_parentheses(attr); // Create the module initialisation function
let modname = &attr[1..attr.len() - 1].to_string();
let init = module::py2_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false)); let init = module::py2_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false));
// Return the generated impl as a TokenStream // Return the generated code as a TokenStream
let mut tokens = Tokens::new(); let mut tokens = ast.into_tokens();
ast.to_tokens(&mut tokens); tokens.append_all(init);
let s = String::from(tokens.as_str()) + init.as_str(); tokens.into()
TokenStream::from_str(s.as_str()).unwrap()
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn mod3init(attr: TokenStream, input: TokenStream) -> TokenStream { pub fn mod3init(attr: TokenStream, input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition // Parse the token stream into a syntax tree
let source = input.to_string(); let mut ast: syn::ItemFn = syn::parse(input).unwrap();
// Parse the string representation into a syntax tree // Extract the mod name
let mut ast = syn::parse_item(&source).unwrap(); let modname: syn::Ident = syn::parse(attr).unwrap();
// Build the output // Process the functions within the module
module::process_functions_in_module(&mut ast); module::process_functions_in_module(&mut ast);
let attr = utils::attr_with_parentheses(attr); // Create the module initialisation function
let modname = &attr[1..attr.len() - 1].to_string();
let init = module::py3_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false)); let init = module::py3_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false));
// Return the generated impl as a TokenStream // Return the generated code as a TokenStream
let mut tokens = Tokens::new(); let mut tokens = ast.into_tokens();
ast.to_tokens(&mut tokens); tokens.append_all(init);
let s = String::from(tokens.as_str()) + init.as_str(); tokens.into()
TokenStream::from_str(s.as_str()).unwrap()
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn proto(_: TokenStream, input: TokenStream) -> TokenStream { pub fn proto(_: TokenStream, input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition // Parse the token stream into a syntax tree
let source = input.to_string(); let mut ast: syn::Item = syn::parse(input).unwrap();
// Parse the string representation into a syntax tree
let mut ast = syn::parse_item(&source).unwrap();
// Build the output // Build the output
let expanded = py_proto::build_py_proto(&mut ast); let expanded = py_proto::build_py_proto(&mut ast);
// Return the generated impl as a TokenStream // Return the generated impl as a TokenStream
let mut tokens = Tokens::new(); let mut tokens = ast.into_tokens();
ast.to_tokens(&mut tokens); tokens.append_all(expanded);
let s = String::from(tokens.as_str()) + expanded.as_str(); tokens.into()
TokenStream::from_str(s.as_str()).unwrap()
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn class(attr: TokenStream, input: TokenStream) -> TokenStream { pub fn class(attr: TokenStream, input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition // Parse the token stream into a syntax tree
let source = input.to_string(); let mut ast: syn::DeriveInput = syn::parse(input).unwrap();
// Parse the string representation into a syntax tree // Parse the macro arguments into a list of expressions
let mut ast = syn::parse_derive_input(&source).unwrap(); let mut args: Vec<syn::Expr> = {
let buffer = TokenBuffer::new(attr);
let punc = Punctuated::<syn::Expr, Token![,]>::parse_terminated(buffer.begin());
punc.expect("could not parse arguments").0.into_iter().collect()
};
// Build the output // Build the output
let expanded = py_class::build_py_class(&mut ast, utils::attr_with_parentheses(attr)); let expanded = py_class::build_py_class(&mut ast, &args);
// Return the generated impl as a TokenStream // Return the generated impl as a TokenStream
let mut tokens = Tokens::new(); let mut tokens = ast.into_tokens();
ast.to_tokens(&mut tokens); tokens.append_all(expanded);
let s = String::from(tokens.as_str()) + expanded.as_str(); tokens.into()
TokenStream::from_str(s.as_str()).unwrap()
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn methods(_: TokenStream, input: TokenStream) -> TokenStream { pub fn methods(_: TokenStream, input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition // Parse the token stream into a syntax tree
let source = input.to_string(); let mut ast: syn::Item = syn::parse(input).unwrap();
// Parse the string representation into a syntax tree
let mut ast = syn::parse_item(&source).unwrap();
// Build the output // Build the output
let expanded = py_impl::build_py_methods(&mut ast); let expanded = py_impl::build_py_methods(&mut ast);
// Return the generated impl as a TokenStream // Return the generated impl as a TokenStream
let mut tokens = Tokens::new(); let mut tokens = ast.into_tokens();
ast.to_tokens(&mut tokens); tokens.append_all(expanded);
let s = String::from(tokens.as_str()) + expanded.as_str(); tokens.into()
TokenStream::from_str(s.as_str()).unwrap()
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn function(_: TokenStream, input: TokenStream) -> TokenStream { pub fn function(_: TokenStream, input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition // Parse the token stream into a syntax tree
let source = input.to_string(); let mut ast: syn::ItemFn = syn::parse(input)
.expect("#[function] must be used on function definitions");
// Parse the string representation into a syntax tree
let mut ast = syn::parse_item(&source).unwrap();
// Build the output // Build the output
let python_name = ast.ident.clone(); let python_name = ast.ident.clone();
let expanded = module::add_fn_to_module(&mut ast, &python_name, Vec::new()); let expanded = module::add_fn_to_module(&mut ast, &python_name, Vec::new());
// Return the generated impl as a TokenStream // Return the generated impl as a TokenStream
let mut tokens = Tokens::new(); let mut tokens = ast.into_tokens();
ast.to_tokens(&mut tokens); tokens.append_all(expanded);
let s = String::from(tokens.as_str()) + expanded.as_str(); tokens.into()
TokenStream::from_str(s.as_str()).unwrap()
} }