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;
// 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();

View File

@ -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<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
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()
}