From d07c538779b6d330edd8a68efe9a817202ef5a6f Mon Sep 17 00:00:00 2001 From: Martin Larralde Date: Mon, 14 May 2018 00:49:15 +0200 Subject: [PATCH] Port `pyo3cls` to latest `syn` --- pyo3-derive-backend/src/module.rs | 2 +- pyo3cls/src/lib.rs | 125 +++++++++++++----------------- 2 files changed, 55 insertions(+), 72 deletions(-) diff --git a/pyo3-derive-backend/src/module.rs b/pyo3-derive-backend/src/module.rs index ec1bf4ba..f5c8f22e 100644 --- a/pyo3-derive-backend/src/module.rs +++ b/pyo3-derive-backend/src/module.rs @@ -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; // We can't convert &'static str to *const c_char within a static initializer, // 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")] pyo3::ffi::PyEval_InitThreads(); diff --git a/pyo3cls/src/lib.rs b/pyo3cls/src/lib.rs index b3023dee..ba8516dd 100644 --- a/pyo3cls/src/lib.rs +++ b/pyo3cls/src/lib.rs @@ -6,136 +6,119 @@ extern crate proc_macro; extern crate pyo3_derive_backend; extern crate quote; +#[macro_use] extern crate syn; +use std::str::FromStr; + use proc_macro::TokenStream; use pyo3_derive_backend::*; use quote::{ToTokens, Tokens}; -use std::str::FromStr; +use syn::buffer::TokenBuffer; +use syn::punctuated::Punctuated; + #[proc_macro_attribute] pub fn mod2init(attr: TokenStream, input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let source = input.to_string(); + // Parse the token stream into a syntax tree + let mut ast: syn::ItemFn = syn::parse(input).unwrap(); - // Parse the string representation into a syntax tree - let mut ast = syn::parse_item(&source).unwrap(); + // Extract the mod name + let modname: syn::Ident = syn::parse(attr).unwrap(); - // Build the output + // Process the functions within the module module::process_functions_in_module(&mut ast); - let attr = utils::attr_with_parentheses(attr); - - let modname = &attr[1..attr.len() - 1].to_string(); - + // Create the module initialisation function let init = module::py2_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false)); - // Return the generated impl as a TokenStream - let mut tokens = Tokens::new(); - ast.to_tokens(&mut tokens); - let s = String::from(tokens.as_str()) + init.as_str(); - - TokenStream::from_str(s.as_str()).unwrap() + // Return the generated code as a TokenStream + let mut tokens = ast.into_tokens(); + tokens.append_all(init); + tokens.into() } #[proc_macro_attribute] pub fn mod3init(attr: TokenStream, input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let source = input.to_string(); + // Parse the token stream into a syntax tree + let mut ast: syn::ItemFn = syn::parse(input).unwrap(); - // Parse the string representation into a syntax tree - let mut ast = syn::parse_item(&source).unwrap(); + // Extract the mod name + let modname: syn::Ident = syn::parse(attr).unwrap(); - // Build the output + // Process the functions within the module module::process_functions_in_module(&mut ast); - let attr = utils::attr_with_parentheses(attr); - - let modname = &attr[1..attr.len() - 1].to_string(); - + // Create the module initialisation function let init = module::py3_init(&ast.ident, &modname, utils::get_doc(&ast.attrs, false)); - // Return the generated impl as a TokenStream - let mut tokens = Tokens::new(); - ast.to_tokens(&mut tokens); - let s = String::from(tokens.as_str()) + init.as_str(); - - TokenStream::from_str(s.as_str()).unwrap() + // Return the generated code as a TokenStream + let mut tokens = ast.into_tokens(); + tokens.append_all(init); + tokens.into() } #[proc_macro_attribute] pub fn proto(_: TokenStream, input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let source = input.to_string(); - - // Parse the string representation into a syntax tree - let mut ast = syn::parse_item(&source).unwrap(); + // Parse the token stream into a syntax tree + let mut ast: syn::Item = syn::parse(input).unwrap(); // Build the output let expanded = py_proto::build_py_proto(&mut ast); // Return the generated impl as a TokenStream - let mut tokens = Tokens::new(); - ast.to_tokens(&mut tokens); - let s = String::from(tokens.as_str()) + expanded.as_str(); - - TokenStream::from_str(s.as_str()).unwrap() + let mut tokens = ast.into_tokens(); + tokens.append_all(expanded); + tokens.into() } #[proc_macro_attribute] pub fn class(attr: TokenStream, input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let source = input.to_string(); + // Parse the token stream into a syntax tree + let mut ast: syn::DeriveInput = syn::parse(input).unwrap(); - // Parse the string representation into a syntax tree - let mut ast = syn::parse_derive_input(&source).unwrap(); + // Parse the macro arguments into a list of expressions + let mut args: Vec = { + let buffer = TokenBuffer::new(attr); + let punc = Punctuated::::parse_terminated(buffer.begin()); + punc.expect("could not parse arguments").0.into_iter().collect() + }; // 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 - let mut tokens = Tokens::new(); - ast.to_tokens(&mut tokens); - let s = String::from(tokens.as_str()) + expanded.as_str(); - - TokenStream::from_str(s.as_str()).unwrap() + let mut tokens = ast.into_tokens(); + tokens.append_all(expanded); + tokens.into() } #[proc_macro_attribute] pub fn methods(_: TokenStream, input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let source = input.to_string(); - - // Parse the string representation into a syntax tree - let mut ast = syn::parse_item(&source).unwrap(); + // Parse the token stream into a syntax tree + let mut ast: syn::Item = syn::parse(input).unwrap(); // Build the output let expanded = py_impl::build_py_methods(&mut ast); // Return the generated impl as a TokenStream - let mut tokens = Tokens::new(); - ast.to_tokens(&mut tokens); - let s = String::from(tokens.as_str()) + expanded.as_str(); - - TokenStream::from_str(s.as_str()).unwrap() + let mut tokens = ast.into_tokens(); + tokens.append_all(expanded); + tokens.into() } #[proc_macro_attribute] pub fn function(_: TokenStream, input: TokenStream) -> TokenStream { - // Construct a string representation of the type definition - let source = input.to_string(); - - // Parse the string representation into a syntax tree - let mut ast = syn::parse_item(&source).unwrap(); + // Parse the token stream into a syntax tree + let mut ast: syn::ItemFn = syn::parse(input) + .expect("#[function] must be used on function definitions"); // Build the output let python_name = ast.ident.clone(); let expanded = module::add_fn_to_module(&mut ast, &python_name, Vec::new()); // Return the generated impl as a TokenStream - let mut tokens = Tokens::new(); - ast.to_tokens(&mut tokens); - let s = String::from(tokens.as_str()) + expanded.as_str(); - - TokenStream::from_str(s.as_str()).unwrap() + let mut tokens = ast.into_tokens(); + tokens.append_all(expanded); + tokens.into() }