From 185dd4a795cd8791cd0b2a3a76fdea9e526fddf3 Mon Sep 17 00:00:00 2001 From: Noa Date: Mon, 19 Dec 2022 18:48:07 -0600 Subject: [PATCH] Split derive-impl and derive --- Cargo.lock | 10 +- Cargo.toml | 2 +- compiler/src/lib.rs | 2 +- derive-impl/Cargo.toml | 18 +++ .../src/compile_bytecode.rs | 0 {derive => derive-impl}/src/error.rs | 0 {derive => derive-impl}/src/from_args.rs | 0 derive-impl/src/lib.rs | 79 ++++++++++++ {derive => derive-impl}/src/pyclass.rs | 2 +- {derive => derive-impl}/src/pymodule.rs | 0 {derive => derive-impl}/src/pypayload.rs | 0 {derive => derive-impl}/src/pystructseq.rs | 0 {derive => derive-impl}/src/util.rs | 0 derive/Cargo.toml | 14 +-- derive/src/lib.rs | 118 ++++++------------ 15 files changed, 148 insertions(+), 97 deletions(-) create mode 100644 derive-impl/Cargo.toml rename {derive => derive-impl}/src/compile_bytecode.rs (100%) rename {derive => derive-impl}/src/error.rs (100%) rename {derive => derive-impl}/src/from_args.rs (100%) create mode 100644 derive-impl/src/lib.rs rename {derive => derive-impl}/src/pyclass.rs (99%) rename {derive => derive-impl}/src/pymodule.rs (100%) rename {derive => derive-impl}/src/pypayload.rs (100%) rename {derive => derive-impl}/src/pystructseq.rs (100%) rename {derive => derive-impl}/src/util.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 837590665..fd5f36fe3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1996,6 +1996,15 @@ dependencies = [ [[package]] name = "rustpython-derive" version = "0.1.2" +dependencies = [ + "rustpython-compiler", + "rustpython-derive-impl", + "syn", +] + +[[package]] +name = "rustpython-derive-impl" +version = "0.0.0" dependencies = [ "indexmap", "itertools", @@ -2003,7 +2012,6 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "rustpython-compiler", "rustpython-compiler-core", "rustpython-doc", "syn", diff --git a/Cargo.toml b/Cargo.toml index 75470c52c..69337db4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ include = ["LICENSE", "Cargo.toml", "src/**/*.rs"] resolver = "2" members = [ "compiler", "compiler/ast", "compiler/core", "compiler/codegen", "compiler/parser", - ".", "common", "derive", "jit", "vm", "pylib", "stdlib", "wasm/lib", + ".", "common", "derive", "jit", "vm", "pylib", "stdlib", "wasm/lib", "derive-impl", ] [features] diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index c488a4003..1a8d6f321 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -1,5 +1,4 @@ use rustpython_codegen::{compile, symboltable}; -use rustpython_compiler_core::CodeObject; use rustpython_parser::{ ast::{fold::Fold, ConstantOptimizer}, error::ParseErrorType, @@ -7,6 +6,7 @@ use rustpython_parser::{ }; pub use rustpython_codegen::compile::CompileOpts; +pub use rustpython_compiler_core::CodeObject; pub use rustpython_compiler_core::{BaseError as CompileErrorBody, Mode}; #[derive(Debug, thiserror::Error)] diff --git a/derive-impl/Cargo.toml b/derive-impl/Cargo.toml new file mode 100644 index 000000000..3ecfc54cc --- /dev/null +++ b/derive-impl/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "rustpython-derive-impl" +version = "0.0.0" +edition = "2021" + +[dependencies] +rustpython-compiler-core = { path = "../compiler/core", version = "0.1.1" } +rustpython-doc = { git = "https://github.com/RustPython/__doc__", branch = "main" } + +indexmap = "1.8.1" +itertools = "0.10.3" +maplit = "1.0.2" +once_cell = "1.10.0" +proc-macro2 = "1.0.37" +quote = "1.0.18" +syn = { version = "1.0.91", features = ["full", "extra-traits"] } +syn-ext = { version = "0.4.0", features = ["full"] } +textwrap = { version = "0.15.0", default-features = false } diff --git a/derive/src/compile_bytecode.rs b/derive-impl/src/compile_bytecode.rs similarity index 100% rename from derive/src/compile_bytecode.rs rename to derive-impl/src/compile_bytecode.rs diff --git a/derive/src/error.rs b/derive-impl/src/error.rs similarity index 100% rename from derive/src/error.rs rename to derive-impl/src/error.rs diff --git a/derive/src/from_args.rs b/derive-impl/src/from_args.rs similarity index 100% rename from derive/src/from_args.rs rename to derive-impl/src/from_args.rs diff --git a/derive-impl/src/lib.rs b/derive-impl/src/lib.rs new file mode 100644 index 000000000..ee3b00c61 --- /dev/null +++ b/derive-impl/src/lib.rs @@ -0,0 +1,79 @@ +#![recursion_limit = "128"] +#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")] +#![doc(html_root_url = "https://docs.rs/rustpython-derive/")] + +extern crate proc_macro; + +#[macro_use] +extern crate maplit; + +#[macro_use] +mod error; +#[macro_use] +mod util; + +mod compile_bytecode; +mod from_args; +mod pyclass; +mod pymodule; +mod pypayload; +mod pystructseq; + +use error::{extract_spans, Diagnostic}; +use proc_macro2::TokenStream; +use quote::ToTokens; +use rustpython_doc as doc; +use syn::{AttributeArgs, DeriveInput, Item}; + +pub use compile_bytecode::Compiler; + +fn result_to_tokens(result: Result>) -> TokenStream { + result + .map_err(|e| e.into()) + .unwrap_or_else(ToTokens::into_token_stream) +} + +pub fn derive_from_args(input: DeriveInput) -> TokenStream { + result_to_tokens(from_args::impl_from_args(input)) +} + +pub fn pyclass(attr: AttributeArgs, item: Item) -> TokenStream { + if matches!(item, syn::Item::Impl(_) | syn::Item::Trait(_)) { + result_to_tokens(pyclass::impl_pyimpl(attr, item)) + } else { + result_to_tokens(pyclass::impl_pyclass(attr, item)) + } +} + +pub use pyclass::PyExceptionDef; +pub fn define_exception(exc_def: PyExceptionDef) -> TokenStream { + result_to_tokens(pyclass::impl_define_exception(exc_def)) +} + +pub fn pyexception(attr: AttributeArgs, item: Item) -> TokenStream { + result_to_tokens(pyclass::impl_pyexception(attr, item)) +} + +pub fn pymodule(attr: AttributeArgs, item: Item) -> TokenStream { + result_to_tokens(pymodule::impl_pymodule(attr, item)) +} + +pub fn pystruct_sequence(input: DeriveInput) -> TokenStream { + result_to_tokens(pystructseq::impl_pystruct_sequence(input)) +} + +pub fn pystruct_sequence_try_from_object(input: DeriveInput) -> TokenStream { + result_to_tokens(pystructseq::impl_pystruct_sequence_try_from_object(input)) +} + +pub fn py_compile(input: TokenStream, compiler: &dyn Compiler) -> TokenStream { + result_to_tokens(compile_bytecode::impl_py_compile(input, compiler)) +} + +pub fn py_freeze(input: TokenStream, compiler: &dyn Compiler) -> TokenStream { + result_to_tokens(compile_bytecode::impl_py_freeze(input, compiler)) +} + +pub fn pypayload(input: DeriveInput) -> TokenStream { + result_to_tokens(pypayload::impl_pypayload(input)) +} diff --git a/derive/src/pyclass.rs b/derive-impl/src/pyclass.rs similarity index 99% rename from derive/src/pyclass.rs rename to derive-impl/src/pyclass.rs index 4f88adeaf..47ef69006 100644 --- a/derive/src/pyclass.rs +++ b/derive-impl/src/pyclass.rs @@ -1284,7 +1284,7 @@ where } #[derive(Debug)] -pub(crate) struct PyExceptionDef { +pub struct PyExceptionDef { pub class_name: Ident, pub base_class: Ident, pub ctx_name: Ident, diff --git a/derive/src/pymodule.rs b/derive-impl/src/pymodule.rs similarity index 100% rename from derive/src/pymodule.rs rename to derive-impl/src/pymodule.rs diff --git a/derive/src/pypayload.rs b/derive-impl/src/pypayload.rs similarity index 100% rename from derive/src/pypayload.rs rename to derive-impl/src/pypayload.rs diff --git a/derive/src/pystructseq.rs b/derive-impl/src/pystructseq.rs similarity index 100% rename from derive/src/pystructseq.rs rename to derive-impl/src/pystructseq.rs diff --git a/derive/src/util.rs b/derive-impl/src/util.rs similarity index 100% rename from derive/src/util.rs rename to derive-impl/src/util.rs diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 6b565af75..472e03d68 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -12,15 +12,5 @@ proc-macro = true [dependencies] rustpython-compiler = { path = "../compiler", version = "0.1.1" } -rustpython-compiler-core = { path = "../compiler/core", version = "0.1.1" } -rustpython-doc = { git = "https://github.com/RustPython/__doc__", branch = "main" } - -indexmap = "1.8.1" -itertools = "0.10.3" -maplit = "1.0.2" -once_cell = "1.10.0" -proc-macro2 = "1.0.37" -quote = "1.0.18" -syn = { version = "1.0.91", features = ["full", "extra-traits"] } -syn-ext = { version = "0.4.0", features = ["full"] } -textwrap = { version = "0.15.0", default-features = false } +rustpython-derive-impl = { path = "../derive-impl" } +syn = "1.0.91" diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 563095f87..1839b06e4 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -2,54 +2,21 @@ #![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")] #![doc(html_root_url = "https://docs.rs/rustpython-derive/")] -extern crate proc_macro; - -#[macro_use] -extern crate maplit; - -#[macro_use] -mod error; -#[macro_use] -mod util; - -mod compile_bytecode; -mod from_args; -mod pyclass; -mod pymodule; -mod pypayload; -mod pystructseq; - -use error::{extract_spans, Diagnostic}; -use proc_macro2::TokenStream; -use quote::ToTokens; -use rustpython_doc as doc; -use syn::{parse_macro_input, AttributeArgs, DeriveInput, Item}; - -fn result_to_tokens(result: Result>) -> proc_macro::TokenStream { - result - .map_err(|e| e.into()) - .unwrap_or_else(ToTokens::into_token_stream) - .into() -} +use proc_macro::TokenStream; +use rustpython_derive_impl as derive_impl; +use syn::parse_macro_input; #[proc_macro_derive(FromArgs, attributes(pyarg))] -pub fn derive_from_args(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - result_to_tokens(from_args::impl_from_args(input)) +pub fn derive_from_args(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input); + derive_impl::derive_from_args(input).into() } #[proc_macro_attribute] -pub fn pyclass( - attr: proc_macro::TokenStream, - item: proc_macro::TokenStream, -) -> proc_macro::TokenStream { - let attr = parse_macro_input!(attr as AttributeArgs); - let item = parse_macro_input!(item as Item); - if matches!(item, syn::Item::Impl(_) | syn::Item::Trait(_)) { - result_to_tokens(pyclass::impl_pyimpl(attr, item)) - } else { - result_to_tokens(pyclass::impl_pyclass(attr, item)) - } +pub fn pyclass(attr: TokenStream, item: TokenStream) -> TokenStream { + let attr = parse_macro_input!(attr); + let item = parse_macro_input!(item); + derive_impl::pyclass(attr, item).into() } /// This macro serves a goal of generating multiple @@ -63,75 +30,64 @@ pub fn pyclass( /// So, we use `extend_class!` macro as the second /// step in exception type definition. #[proc_macro] -pub fn define_exception(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let exc_def = parse_macro_input!(input as pyclass::PyExceptionDef); - result_to_tokens(pyclass::impl_define_exception(exc_def)) +pub fn define_exception(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input); + derive_impl::define_exception(input).into() } /// Helper macro to define `Exception` types. /// More-or-less is an alias to `pyclass` macro. #[proc_macro_attribute] -pub fn pyexception( - attr: proc_macro::TokenStream, - item: proc_macro::TokenStream, -) -> proc_macro::TokenStream { - let attr = parse_macro_input!(attr as AttributeArgs); - let item = parse_macro_input!(item as Item); - result_to_tokens(pyclass::impl_pyexception(attr, item)) +pub fn pyexception(attr: TokenStream, item: TokenStream) -> TokenStream { + let attr = parse_macro_input!(attr); + let item = parse_macro_input!(item); + derive_impl::pyexception(attr, item).into() } #[proc_macro_attribute] -pub fn pymodule( - attr: proc_macro::TokenStream, - item: proc_macro::TokenStream, -) -> proc_macro::TokenStream { - let attr = parse_macro_input!(attr as AttributeArgs); - let item = parse_macro_input!(item as Item); - result_to_tokens(pymodule::impl_pymodule(attr, item)) +pub fn pymodule(attr: TokenStream, item: TokenStream) -> TokenStream { + let attr = parse_macro_input!(attr); + let item = parse_macro_input!(item); + derive_impl::pymodule(attr, item).into() } #[proc_macro_derive(PyStructSequence)] -pub fn pystruct_sequence(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - result_to_tokens(pystructseq::impl_pystruct_sequence(input)) +pub fn pystruct_sequence(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input); + derive_impl::pystruct_sequence(input).into() } #[proc_macro_derive(TryIntoPyStructSequence)] -pub fn pystruct_sequence_try_from_object( - input: proc_macro::TokenStream, -) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - result_to_tokens(pystructseq::impl_pystruct_sequence_try_from_object(input)) +pub fn pystruct_sequence_try_from_object(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input); + derive_impl::pystruct_sequence_try_from_object(input).into() } -// would be cool to move all the macro implementation to a separate rustpython-derive-shared -// that just depends on rustpython-compiler-core, and then rustpython-derive would hook -compiler -// up to it; so that (the bulk of) rustpython-derive and rustpython-codegen could build in parallel struct Compiler; -impl compile_bytecode::Compiler for Compiler { +impl derive_impl::Compiler for Compiler { fn compile( &self, source: &str, - mode: rustpython_compiler_core::Mode, + mode: rustpython_compiler::Mode, module_name: String, - ) -> Result> { + ) -> Result> { use rustpython_compiler::{compile, CompileOpts}; Ok(compile(source, mode, module_name, CompileOpts::default())?) } } #[proc_macro] -pub fn py_compile(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - result_to_tokens(compile_bytecode::impl_py_compile(input.into(), &Compiler)) +pub fn py_compile(input: TokenStream) -> TokenStream { + derive_impl::py_compile(input.into(), &Compiler).into() } #[proc_macro] -pub fn py_freeze(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - result_to_tokens(compile_bytecode::impl_py_freeze(input.into(), &Compiler)) +pub fn py_freeze(input: TokenStream) -> TokenStream { + derive_impl::py_freeze(input.into(), &Compiler).into() } #[proc_macro_derive(PyPayload)] -pub fn pypayload(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input = parse_macro_input!(input as DeriveInput); - result_to_tokens(pypayload::impl_pypayload(input)) +pub fn pypayload(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input); + derive_impl::pypayload(input).into() }