From 52412638b357203f467670e82c5291691e28c0ec Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 09:57:55 +0800 Subject: [PATCH 01/12] Add boilerplate for new cgp-field crates --- Cargo.lock | 31 +++++++++++++++++++++------ Cargo.toml | 6 ++++++ crates/cgp-component-macro/Cargo.toml | 7 +----- crates/cgp-field-macro-lib/Cargo.toml | 23 ++++++++++++++++++++ crates/cgp-field-macro-lib/src/lib.rs | 1 + crates/cgp-field-macro/Cargo.toml | 23 ++++++++++++++++++++ crates/cgp-field-macro/src/lib.rs | 1 + crates/cgp-field/Cargo.toml | 18 ++++++++++++++++ crates/cgp-field/src/lib.rs | 1 + 9 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 crates/cgp-field-macro-lib/Cargo.toml create mode 100644 crates/cgp-field-macro-lib/src/lib.rs create mode 100644 crates/cgp-field-macro/Cargo.toml create mode 100644 crates/cgp-field-macro/src/lib.rs create mode 100644 crates/cgp-field/Cargo.toml create mode 100644 crates/cgp-field/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index edb8e8e..52a89a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,11 +31,7 @@ name = "cgp-component-macro" version = "0.1.0" dependencies = [ "cgp-component-macro-lib", - "itertools", - "prettyplease", "proc-macro2", - "quote", - "syn", ] [[package]] @@ -83,6 +79,29 @@ dependencies = [ "cgp-core", ] +[[package]] +name = "cgp-field" +version = "0.1.0" + +[[package]] +name = "cgp-field-macro" +version = "0.1.0" +dependencies = [ + "cgp-field-macro-lib", + "proc-macro2", +] + +[[package]] +name = "cgp-field-macro-lib" +version = "0.1.0" +dependencies = [ + "itertools", + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "cgp-inner" version = "0.1.0" @@ -109,9 +128,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "eyre" diff --git a/Cargo.toml b/Cargo.toml index 7800333..ec19578 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,9 @@ members = [ "crates/cgp-component", "crates/cgp-component-macro", "crates/cgp-component-macro-lib", + "crates/cgp-field", + "crates/cgp-field-macro", + "crates/cgp-field-macro-lib", "crates/cgp-error", "crates/cgp-error-eyre", "crates/cgp-error-std", @@ -32,6 +35,9 @@ cgp-sync = { path = "./crates/cgp-sync" } cgp-component = { path = "./crates/cgp-component" } cgp-component-macro = { path = "./crates/cgp-component-macro" } cgp-component-macro-lib = { path = "./crates/cgp-component-macro-lib" } +cgp-field = { path = "./crates/cgp-field" } +cgp-field-macro = { path = "./crates/cgp-field-macro" } +cgp-field-macro-lib = { path = "./crates/cgp-field-macro-lib" } cgp-error = { path = "./crates/cgp-error" } cgp-run = { path = "./crates/cgp-run" } cgp-inner = { path = "./crates/cgp-inner" } diff --git a/crates/cgp-component-macro/Cargo.toml b/crates/cgp-component-macro/Cargo.toml index f366d15..05694ab 100644 --- a/crates/cgp-component-macro/Cargo.toml +++ b/crates/cgp-component-macro/Cargo.toml @@ -20,9 +20,4 @@ proc-macro = true [dependencies] cgp-component-macro-lib = { version = "0.1.0" } - -syn = { version = "2.0.37", features = [ "full" ] } -quote = "1.0.33" -proc-macro2 = "1.0.67" -itertools = "0.11.0" -prettyplease = "0.2.20" +proc-macro2 = "1.0.67" \ No newline at end of file diff --git a/crates/cgp-field-macro-lib/Cargo.toml b/crates/cgp-field-macro-lib/Cargo.toml new file mode 100644 index 0000000..e0fc317 --- /dev/null +++ b/crates/cgp-field-macro-lib/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "cgp-field-macro-lib" +version = "0.1.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +readme = "README.md" +keywords = ["context-generic programming"] +description = """ + Context-generic programming core macros +""" + +[package.metadata.docs.rs] +all-features = true + +[dependencies] +syn = { version = "2.0.37", features = [ "full" ] } +quote = "1.0.33" +proc-macro2 = "1.0.67" +itertools = "0.11.0" +prettyplease = "0.2.20" diff --git a/crates/cgp-field-macro-lib/src/lib.rs b/crates/cgp-field-macro-lib/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/lib.rs @@ -0,0 +1 @@ + diff --git a/crates/cgp-field-macro/Cargo.toml b/crates/cgp-field-macro/Cargo.toml new file mode 100644 index 0000000..100b0c8 --- /dev/null +++ b/crates/cgp-field-macro/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "cgp-field-macro" +version = "0.1.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +readme = "README.md" +keywords = ["context-generic programming"] +description = """ + Context-generic programming core macros +""" + +[package.metadata.docs.rs] +all-features = true + +[lib] +proc-macro = true + +[dependencies] +cgp-field-macro-lib = { version = "0.1.0" } +proc-macro2 = "1.0.67" \ No newline at end of file diff --git a/crates/cgp-field-macro/src/lib.rs b/crates/cgp-field-macro/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/cgp-field-macro/src/lib.rs @@ -0,0 +1 @@ + diff --git a/crates/cgp-field/Cargo.toml b/crates/cgp-field/Cargo.toml new file mode 100644 index 0000000..6343f6d --- /dev/null +++ b/crates/cgp-field/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "cgp-field" +version = "0.1.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +readme = "README.md" +keywords = ["context-generic programming"] +description = """ + Context-generic programming core traits +""" + +[package.metadata.docs.rs] +all-features = true + +[dependencies] diff --git a/crates/cgp-field/src/lib.rs b/crates/cgp-field/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/cgp-field/src/lib.rs @@ -0,0 +1 @@ + From 25e199d3b2615e753e9987f148f9d53234b5ff1b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:02:05 +0800 Subject: [PATCH 02/12] Add HasField trait --- crates/cgp-field/src/lib.rs | 3 +++ crates/cgp-field/src/traits.rs | 7 +++++++ crates/cgp-field/src/types.rs | 1 + 3 files changed, 11 insertions(+) create mode 100644 crates/cgp-field/src/traits.rs create mode 100644 crates/cgp-field/src/types.rs diff --git a/crates/cgp-field/src/lib.rs b/crates/cgp-field/src/lib.rs index 8b13789..e3274e2 100644 --- a/crates/cgp-field/src/lib.rs +++ b/crates/cgp-field/src/lib.rs @@ -1 +1,4 @@ +#![no_std] +pub mod traits; +pub mod types; diff --git a/crates/cgp-field/src/traits.rs b/crates/cgp-field/src/traits.rs new file mode 100644 index 0000000..cd343db --- /dev/null +++ b/crates/cgp-field/src/traits.rs @@ -0,0 +1,7 @@ +use core::marker::PhantomData; + +pub trait HasField { + type Field; + + fn field(key: PhantomData) -> Self::Field; +} diff --git a/crates/cgp-field/src/types.rs b/crates/cgp-field/src/types.rs new file mode 100644 index 0000000..ad63b5c --- /dev/null +++ b/crates/cgp-field/src/types.rs @@ -0,0 +1 @@ +pub struct Char; From 7fc36cd763a43143d7b7b31ad9ec3658b81b70e5 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:13:23 +0800 Subject: [PATCH 03/12] Add symbol! macro --- crates/cgp-field-macro-lib/src/field.rs | 1 + crates/cgp-field-macro-lib/src/lib.rs | 3 ++- crates/cgp-field-macro-lib/src/symbol.rs | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 crates/cgp-field-macro-lib/src/field.rs create mode 100644 crates/cgp-field-macro-lib/src/symbol.rs diff --git a/crates/cgp-field-macro-lib/src/field.rs b/crates/cgp-field-macro-lib/src/field.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/field.rs @@ -0,0 +1 @@ + diff --git a/crates/cgp-field-macro-lib/src/lib.rs b/crates/cgp-field-macro-lib/src/lib.rs index 8b13789..5c0c7b0 100644 --- a/crates/cgp-field-macro-lib/src/lib.rs +++ b/crates/cgp-field-macro-lib/src/lib.rs @@ -1 +1,2 @@ - +pub mod field; +pub mod symbol; diff --git a/crates/cgp-field-macro-lib/src/symbol.rs b/crates/cgp-field-macro-lib/src/symbol.rs new file mode 100644 index 0000000..37fbb21 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/symbol.rs @@ -0,0 +1,23 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::punctuated::Punctuated; +use syn::token::Comma; +use syn::{parse_quote, LitStr, Type}; + +pub fn symbol_from_string(value: &str) -> Type { + let char_types = >::from_iter( + value + .chars() + .map(|c: char| -> Type { parse_quote!( Char< #c > ) }), + ); + + parse_quote!( ( #char_types ) ) +} + +pub fn make_symbol(input: TokenStream) -> TokenStream { + let literal: LitStr = syn::parse2(input).unwrap(); + + let symbol = symbol_from_string(&literal.value()); + + symbol.to_token_stream() +} From 7aa4917999dd536c866d363a07f7008c152f8799 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:29:46 +0800 Subject: [PATCH 04/12] Implement derive_fields macro --- crates/cgp-field-macro-lib/src/field.rs | 44 +++++++++++++++++++++++++ crates/cgp-field/src/traits.rs | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/cgp-field-macro-lib/src/field.rs b/crates/cgp-field-macro-lib/src/field.rs index 8b13789..aea1ff9 100644 --- a/crates/cgp-field-macro-lib/src/field.rs +++ b/crates/cgp-field-macro-lib/src/field.rs @@ -1 +1,45 @@ +use syn::{parse_quote, Fields, ItemImpl, ItemStruct}; +use crate::symbol::symbol_from_string; + +pub fn derive_fields(item_struct: &ItemStruct) -> Vec { + let struct_ident = &item_struct.ident; + + let (impl_generics, ty_generics, where_clause) = item_struct.generics.split_for_impl(); + + let mut item_impls = Vec::new(); + + match &item_struct.fields { + Fields::Named(fields) => { + for field in fields.named.iter() { + let field_ident = field.ident.as_ref().unwrap(); + + let field_symbol = symbol_from_string(&field_ident.to_string()); + + let field_type = &field.ty; + + let item_impl: ItemImpl = parse_quote! { + impl #impl_generics HasField< #field_symbol > + for #struct_ident #ty_generics + #where_clause + { + type Field = #field_type; + + fn get_field( + &self, + key: ::core::marker::PhantomData< #field_symbol >, + ) -> &Self::Field + { + &self. #field_ident + } + } + }; + + item_impls.push(item_impl); + } + } + _ => {} + } + + item_impls +} diff --git a/crates/cgp-field/src/traits.rs b/crates/cgp-field/src/traits.rs index cd343db..e668a09 100644 --- a/crates/cgp-field/src/traits.rs +++ b/crates/cgp-field/src/traits.rs @@ -3,5 +3,5 @@ use core::marker::PhantomData; pub trait HasField { type Field; - fn field(key: PhantomData) -> Self::Field; + fn get_field(&self, key: PhantomData) -> &Self::Field; } From f16a1873c2e9bd50b2d777ceafbc2bcac5d1e00b Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:45:24 +0800 Subject: [PATCH 05/12] Add test for symbol --- crates/cgp-field-macro-lib/src/field.rs | 18 ++++++++++- crates/cgp-field-macro-lib/src/lib.rs | 3 ++ .../src/tests/helper/equal.rs | 7 +++++ .../src/tests/helper/format.rs | 7 +++++ .../src/tests/helper/mod.rs | 2 ++ crates/cgp-field-macro-lib/src/tests/mod.rs | 2 ++ .../cgp-field-macro-lib/src/tests/symbol.rs | 31 +++++++++++++++++++ 7 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 crates/cgp-field-macro-lib/src/tests/helper/equal.rs create mode 100644 crates/cgp-field-macro-lib/src/tests/helper/format.rs create mode 100644 crates/cgp-field-macro-lib/src/tests/helper/mod.rs create mode 100644 crates/cgp-field-macro-lib/src/tests/mod.rs create mode 100644 crates/cgp-field-macro-lib/src/tests/symbol.rs diff --git a/crates/cgp-field-macro-lib/src/field.rs b/crates/cgp-field-macro-lib/src/field.rs index aea1ff9..43f82c1 100644 --- a/crates/cgp-field-macro-lib/src/field.rs +++ b/crates/cgp-field-macro-lib/src/field.rs @@ -1,8 +1,10 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; use syn::{parse_quote, Fields, ItemImpl, ItemStruct}; use crate::symbol::symbol_from_string; -pub fn derive_fields(item_struct: &ItemStruct) -> Vec { +pub fn derive_has_field_impls(item_struct: &ItemStruct) -> Vec { let struct_ident = &item_struct.ident; let (impl_generics, ty_generics, where_clause) = item_struct.generics.split_for_impl(); @@ -43,3 +45,17 @@ pub fn derive_fields(item_struct: &ItemStruct) -> Vec { item_impls } + +pub fn derive_fields(input: TokenStream) -> TokenStream { + let item_struct: ItemStruct = syn::parse2(input).unwrap(); + + let item_impls = derive_has_field_impls(&item_struct); + + let mut output = item_struct.to_token_stream(); + + for item_impl in item_impls { + output.extend(item_impl.to_token_stream()); + } + + output +} diff --git a/crates/cgp-field-macro-lib/src/lib.rs b/crates/cgp-field-macro-lib/src/lib.rs index 5c0c7b0..a9555cf 100644 --- a/crates/cgp-field-macro-lib/src/lib.rs +++ b/crates/cgp-field-macro-lib/src/lib.rs @@ -1,2 +1,5 @@ pub mod field; pub mod symbol; + +#[cfg(test)] +mod tests; diff --git a/crates/cgp-field-macro-lib/src/tests/helper/equal.rs b/crates/cgp-field-macro-lib/src/tests/helper/equal.rs new file mode 100644 index 0000000..0e54436 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/tests/helper/equal.rs @@ -0,0 +1,7 @@ +use proc_macro2::TokenStream; + +use crate::tests::helper::format::format_token_stream; + +pub fn equal_token_stream(left: &TokenStream, right: &TokenStream) -> bool { + format_token_stream(left) == format_token_stream(right) +} diff --git a/crates/cgp-field-macro-lib/src/tests/helper/format.rs b/crates/cgp-field-macro-lib/src/tests/helper/format.rs new file mode 100644 index 0000000..2c96595 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/tests/helper/format.rs @@ -0,0 +1,7 @@ +use prettyplease::unparse; +use proc_macro2::TokenStream; +use syn::parse_file; + +pub fn format_token_stream(stream: &TokenStream) -> String { + unparse(&parse_file(&stream.to_string()).unwrap()) +} diff --git a/crates/cgp-field-macro-lib/src/tests/helper/mod.rs b/crates/cgp-field-macro-lib/src/tests/helper/mod.rs new file mode 100644 index 0000000..e54acd6 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/tests/helper/mod.rs @@ -0,0 +1,2 @@ +pub mod equal; +pub mod format; diff --git a/crates/cgp-field-macro-lib/src/tests/mod.rs b/crates/cgp-field-macro-lib/src/tests/mod.rs new file mode 100644 index 0000000..fa720cc --- /dev/null +++ b/crates/cgp-field-macro-lib/src/tests/mod.rs @@ -0,0 +1,2 @@ +pub mod helper; +pub mod symbol; diff --git a/crates/cgp-field-macro-lib/src/tests/symbol.rs b/crates/cgp-field-macro-lib/src/tests/symbol.rs new file mode 100644 index 0000000..4198073 --- /dev/null +++ b/crates/cgp-field-macro-lib/src/tests/symbol.rs @@ -0,0 +1,31 @@ +use quote::quote; + +use crate::symbol::make_symbol; +use crate::tests::helper::equal::equal_token_stream; + +#[test] +fn test_symbol_macro() { + let symbol = make_symbol(quote!("hello_world")); + + let derived = quote! { + type Symbol = #symbol; + }; + + let expected = quote! { + type Symbol = ( + Char<'h'>, + Char<'e'>, + Char<'l'>, + Char<'l'>, + Char<'o'>, + Char<'_'>, + Char<'w'>, + Char<'o'>, + Char<'r'>, + Char<'l'>, + Char<'d'>, + ); + }; + + assert!(equal_token_stream(&derived, &expected)); +} From b39d0d1ac301c08c9fc338fdb9f50c0e7deb43dc Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:52:55 +0800 Subject: [PATCH 06/12] Test derive HasField --- crates/cgp-field-macro-lib/src/tests/field.rs | 101 ++++++++++++++++++ crates/cgp-field-macro-lib/src/tests/mod.rs | 1 + 2 files changed, 102 insertions(+) create mode 100644 crates/cgp-field-macro-lib/src/tests/field.rs diff --git a/crates/cgp-field-macro-lib/src/tests/field.rs b/crates/cgp-field-macro-lib/src/tests/field.rs new file mode 100644 index 0000000..f1495df --- /dev/null +++ b/crates/cgp-field-macro-lib/src/tests/field.rs @@ -0,0 +1,101 @@ +use quote::quote; + +use crate::field::derive_fields; +use crate::tests::helper::equal::equal_token_stream; +use crate::tests::helper::format::format_token_stream; + +#[test] +fn test_basic_derive_fields() { + let derived = derive_fields(quote! { + pub struct Foo { + pub bar: Bar, + pub baz: Baz, + } + }); + + let expected = quote! { + pub struct Foo { + pub bar: Bar, + pub baz: Baz, + } + + impl HasField<(Char<'b'>, Char<'a'>, Char<'r'>)> for Foo { + type Field = Bar; + + fn get_field( + &self, + key: ::core::marker::PhantomData<(Char<'b'>, Char<'a'>, Char<'r'>)>, + ) -> &Self::Field { + &self.bar + } + } + + impl HasField<(Char<'b'>, Char<'a'>, Char<'z'>)> for Foo { + type Field = Baz; + + fn get_field( + &self, + key: ::core::marker::PhantomData<(Char<'b'>, Char<'a'>, Char<'z'>)>, + ) -> &Self::Field { + &self.baz + } + } + }; + + let expected = quote! { + pub struct Foo + where + FooParamA: Eq, + { + pub bar: Bar, + pub baz: Baz, + } + + impl HasField<(Char<'b'>, Char<'a'>, Char<'r'>)> + for Foo + where + FooParamA: Eq, + { + type Field = Bar; + + fn get_field( + &self, + key: ::core::marker::PhantomData<(Char<'b'>, Char<'a'>, Char<'r'>)>, + ) -> &Self::Field { + &self.bar + } + } + + impl HasField<(Char<'b'>, Char<'a'>, Char<'z'>)> + for Foo + where + FooParamA: Eq, + { + type Field = Baz; + + fn get_field( + &self, + key: ::core::marker::PhantomData<(Char<'b'>, Char<'a'>, Char<'z'>)>, + ) -> &Self::Field { + &self.baz + } + } + }; + + assert!(equal_token_stream(&derived, &expected)); +} + +#[test] +fn test_generic_derive_fields() { + let derived = derive_fields(quote! { + pub struct Foo + where + FooParamA: Eq, + { + pub bar: Bar, + pub baz: Baz, + } + }); + + println!("derived:\n{}", format_token_stream(&derived)); +} diff --git a/crates/cgp-field-macro-lib/src/tests/mod.rs b/crates/cgp-field-macro-lib/src/tests/mod.rs index fa720cc..e7c3ff4 100644 --- a/crates/cgp-field-macro-lib/src/tests/mod.rs +++ b/crates/cgp-field-macro-lib/src/tests/mod.rs @@ -1,2 +1,3 @@ +pub mod field; pub mod helper; pub mod symbol; From d0056fdf297a18002c3d822459fb0e01cf56d8d7 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:57:43 +0800 Subject: [PATCH 07/12] Re-export cgp-field in cgp-core --- Cargo.lock | 4 +++ crates/cgp-core/Cargo.toml | 1 + crates/cgp-core/src/lib.rs | 5 ++- crates/cgp-core/src/prelude.rs | 1 + crates/cgp-field-macro-lib/src/lib.rs | 3 ++ crates/cgp-field-macro-lib/src/tests/field.rs | 31 +++++++++---------- crates/cgp-field-macro/src/lib.rs | 12 +++++++ crates/cgp-field/Cargo.toml | 1 + crates/cgp-field/src/lib.rs | 5 +++ 9 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52a89a1..5273a13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,6 +52,7 @@ dependencies = [ "cgp-async", "cgp-component", "cgp-error", + "cgp-field", "cgp-inner", "cgp-run", ] @@ -82,6 +83,9 @@ dependencies = [ [[package]] name = "cgp-field" version = "0.1.0" +dependencies = [ + "cgp-field-macro", +] [[package]] name = "cgp-field-macro" diff --git a/crates/cgp-core/Cargo.toml b/crates/cgp-core/Cargo.toml index 3ff9bce..7c36c52 100644 --- a/crates/cgp-core/Cargo.toml +++ b/crates/cgp-core/Cargo.toml @@ -19,5 +19,6 @@ all-features = true cgp-async = { version = "0.1.0" } cgp-component = { version = "0.1.0" } cgp-error = { version = "0.1.0" } +cgp-field = { version = "0.1.0" } cgp-run = { version = "0.1.0" } cgp-inner = { version = "0.1.0" } \ No newline at end of file diff --git a/crates/cgp-core/src/lib.rs b/crates/cgp-core/src/lib.rs index ff1478c..cd4fa23 100644 --- a/crates/cgp-core/src/lib.rs +++ b/crates/cgp-core/src/lib.rs @@ -3,4 +3,7 @@ pub mod prelude; pub use cgp_async::{async_trait, Async}; -pub use {cgp_component as component, cgp_error as error, cgp_inner as inner, cgp_run as run}; +pub use { + cgp_component as component, cgp_error as error, cgp_field as field, cgp_inner as inner, + cgp_run as run, +}; diff --git a/crates/cgp-core/src/prelude.rs b/crates/cgp-core/src/prelude.rs index a7b3620..30d4120 100644 --- a/crates/cgp-core/src/prelude.rs +++ b/crates/cgp-core/src/prelude.rs @@ -3,3 +3,4 @@ pub use cgp_component::{ define_components, delegate_components, derive_component, DelegateComponent, HasComponents, }; pub use cgp_error::{CanRaiseError, HasErrorType}; +pub use cgp_field::{derive_fields, symbol, Char, HasField}; diff --git a/crates/cgp-field-macro-lib/src/lib.rs b/crates/cgp-field-macro-lib/src/lib.rs index a9555cf..1439e39 100644 --- a/crates/cgp-field-macro-lib/src/lib.rs +++ b/crates/cgp-field-macro-lib/src/lib.rs @@ -3,3 +3,6 @@ pub mod symbol; #[cfg(test)] mod tests; + +pub use field::derive_fields; +pub use symbol::make_symbol; diff --git a/crates/cgp-field-macro-lib/src/tests/field.rs b/crates/cgp-field-macro-lib/src/tests/field.rs index f1495df..fe380eb 100644 --- a/crates/cgp-field-macro-lib/src/tests/field.rs +++ b/crates/cgp-field-macro-lib/src/tests/field.rs @@ -2,7 +2,6 @@ use quote::quote; use crate::field::derive_fields; use crate::tests::helper::equal::equal_token_stream; -use crate::tests::helper::format::format_token_stream; #[test] fn test_basic_derive_fields() { @@ -42,6 +41,21 @@ fn test_basic_derive_fields() { } }; + assert!(equal_token_stream(&derived, &expected)); +} + +#[test] +fn test_generic_derive_fields() { + let derived = derive_fields(quote! { + pub struct Foo + where + FooParamA: Eq, + { + pub bar: Bar, + pub baz: Baz, + } + }); + let expected = quote! { pub struct Foo where @@ -84,18 +98,3 @@ fn test_basic_derive_fields() { assert!(equal_token_stream(&derived, &expected)); } - -#[test] -fn test_generic_derive_fields() { - let derived = derive_fields(quote! { - pub struct Foo - where - FooParamA: Eq, - { - pub bar: Bar, - pub baz: Baz, - } - }); - - println!("derived:\n{}", format_token_stream(&derived)); -} diff --git a/crates/cgp-field-macro/src/lib.rs b/crates/cgp-field-macro/src/lib.rs index 8b13789..c1c9a28 100644 --- a/crates/cgp-field-macro/src/lib.rs +++ b/crates/cgp-field-macro/src/lib.rs @@ -1 +1,13 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn derive_fields(_attr: TokenStream, item: TokenStream) -> TokenStream { + cgp_field_macro_lib::derive_fields(item.into()).into() +} + +#[proc_macro] +pub fn symbol(body: TokenStream) -> TokenStream { + cgp_field_macro_lib::make_symbol(body.into()).into() +} diff --git a/crates/cgp-field/Cargo.toml b/crates/cgp-field/Cargo.toml index 6343f6d..ff88a44 100644 --- a/crates/cgp-field/Cargo.toml +++ b/crates/cgp-field/Cargo.toml @@ -16,3 +16,4 @@ description = """ all-features = true [dependencies] +cgp-field-macro = { version = "0.1.0" } diff --git a/crates/cgp-field/src/lib.rs b/crates/cgp-field/src/lib.rs index e3274e2..630f412 100644 --- a/crates/cgp-field/src/lib.rs +++ b/crates/cgp-field/src/lib.rs @@ -2,3 +2,8 @@ pub mod traits; pub mod types; + +pub use cgp_field_macro::derive_fields; +pub use cgp_field_macro::symbol; +pub use traits::HasField; +pub use types::Char; From d7e74ee8e2c129aaa5780fcb75ffeb619682d980 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 10:58:20 +0800 Subject: [PATCH 08/12] Reformat imports --- crates/cgp-field/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/cgp-field/src/lib.rs b/crates/cgp-field/src/lib.rs index 630f412..0e18298 100644 --- a/crates/cgp-field/src/lib.rs +++ b/crates/cgp-field/src/lib.rs @@ -3,7 +3,6 @@ pub mod traits; pub mod types; -pub use cgp_field_macro::derive_fields; -pub use cgp_field_macro::symbol; +pub use cgp_field_macro::{derive_fields, symbol}; pub use traits::HasField; pub use types::Char; From 4557329dfd74085e8702a248b66f7ec2edef0ec2 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 11:10:48 +0800 Subject: [PATCH 09/12] Make derive_field a derive macro --- crates/cgp-core/src/prelude.rs | 2 +- crates/cgp-field-macro-lib/src/field.rs | 2 +- crates/cgp-field-macro/src/lib.rs | 4 ++-- crates/cgp-field/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/cgp-core/src/prelude.rs b/crates/cgp-core/src/prelude.rs index 30d4120..f08cbd6 100644 --- a/crates/cgp-core/src/prelude.rs +++ b/crates/cgp-core/src/prelude.rs @@ -3,4 +3,4 @@ pub use cgp_component::{ define_components, delegate_components, derive_component, DelegateComponent, HasComponents, }; pub use cgp_error::{CanRaiseError, HasErrorType}; -pub use cgp_field::{derive_fields, symbol, Char, HasField}; +pub use cgp_field::{symbol, Char, HasField}; diff --git a/crates/cgp-field-macro-lib/src/field.rs b/crates/cgp-field-macro-lib/src/field.rs index 43f82c1..bb9b3e0 100644 --- a/crates/cgp-field-macro-lib/src/field.rs +++ b/crates/cgp-field-macro-lib/src/field.rs @@ -51,7 +51,7 @@ pub fn derive_fields(input: TokenStream) -> TokenStream { let item_impls = derive_has_field_impls(&item_struct); - let mut output = item_struct.to_token_stream(); + let mut output = TokenStream::new(); for item_impl in item_impls { output.extend(item_impl.to_token_stream()); diff --git a/crates/cgp-field-macro/src/lib.rs b/crates/cgp-field-macro/src/lib.rs index c1c9a28..d8446c4 100644 --- a/crates/cgp-field-macro/src/lib.rs +++ b/crates/cgp-field-macro/src/lib.rs @@ -2,8 +2,8 @@ extern crate proc_macro; use proc_macro::TokenStream; -#[proc_macro_attribute] -pub fn derive_fields(_attr: TokenStream, item: TokenStream) -> TokenStream { +#[proc_macro_derive(HasField)] +pub fn derive_fields(item: TokenStream) -> TokenStream { cgp_field_macro_lib::derive_fields(item.into()).into() } diff --git a/crates/cgp-field/src/lib.rs b/crates/cgp-field/src/lib.rs index 0e18298..4b9f3d0 100644 --- a/crates/cgp-field/src/lib.rs +++ b/crates/cgp-field/src/lib.rs @@ -3,6 +3,6 @@ pub mod traits; pub mod types; -pub use cgp_field_macro::{derive_fields, symbol}; +pub use cgp_field_macro::{symbol, HasField}; pub use traits::HasField; pub use types::Char; From 76e82a12adaadae8bd42a2a12218345bcc70d48f Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 11:20:57 +0800 Subject: [PATCH 10/12] Auto derive HasField for contexts that implement Deref --- crates/cgp-field/src/traits.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/cgp-field/src/traits.rs b/crates/cgp-field/src/traits.rs index e668a09..29b5bae 100644 --- a/crates/cgp-field/src/traits.rs +++ b/crates/cgp-field/src/traits.rs @@ -1,7 +1,20 @@ use core::marker::PhantomData; +use core::ops::Deref; pub trait HasField { type Field; fn get_field(&self, key: PhantomData) -> &Self::Field; } + +impl HasField for Context +where + Context: Deref, + Target: HasField + 'static, +{ + type Field = Field; + + fn get_field(&self, key: PhantomData) -> &Self::Field { + self.deref().get_field(key) + } +} From b13e1522085e3a352b4a57e68dd009b1f2ec6a1e Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 12:15:01 +0800 Subject: [PATCH 11/12] Fix clippy --- crates/cgp-field-macro-lib/src/field.rs | 43 ++++++++++++------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/crates/cgp-field-macro-lib/src/field.rs b/crates/cgp-field-macro-lib/src/field.rs index bb9b3e0..eac91b2 100644 --- a/crates/cgp-field-macro-lib/src/field.rs +++ b/crates/cgp-field-macro-lib/src/field.rs @@ -11,36 +11,33 @@ pub fn derive_has_field_impls(item_struct: &ItemStruct) -> Vec { let mut item_impls = Vec::new(); - match &item_struct.fields { - Fields::Named(fields) => { - for field in fields.named.iter() { - let field_ident = field.ident.as_ref().unwrap(); + if let Fields::Named(fields) = &item_struct.fields { + for field in fields.named.iter() { + let field_ident = field.ident.as_ref().unwrap(); - let field_symbol = symbol_from_string(&field_ident.to_string()); + let field_symbol = symbol_from_string(&field_ident.to_string()); - let field_type = &field.ty; + let field_type = &field.ty; - let item_impl: ItemImpl = parse_quote! { - impl #impl_generics HasField< #field_symbol > - for #struct_ident #ty_generics - #where_clause + let item_impl: ItemImpl = parse_quote! { + impl #impl_generics HasField< #field_symbol > + for #struct_ident #ty_generics + #where_clause + { + type Field = #field_type; + + fn get_field( + &self, + key: ::core::marker::PhantomData< #field_symbol >, + ) -> &Self::Field { - type Field = #field_type; - - fn get_field( - &self, - key: ::core::marker::PhantomData< #field_symbol >, - ) -> &Self::Field - { - &self. #field_ident - } + &self. #field_ident } - }; + } + }; - item_impls.push(item_impl); - } + item_impls.push(item_impl); } - _ => {} } item_impls From e82031502b0b5a3c3885403c334f7495bdd9cae5 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 4 Jul 2024 12:49:14 +0800 Subject: [PATCH 12/12] Fix test --- crates/cgp-field-macro-lib/src/tests/field.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/crates/cgp-field-macro-lib/src/tests/field.rs b/crates/cgp-field-macro-lib/src/tests/field.rs index fe380eb..72ad46c 100644 --- a/crates/cgp-field-macro-lib/src/tests/field.rs +++ b/crates/cgp-field-macro-lib/src/tests/field.rs @@ -13,11 +13,6 @@ fn test_basic_derive_fields() { }); let expected = quote! { - pub struct Foo { - pub bar: Bar, - pub baz: Baz, - } - impl HasField<(Char<'b'>, Char<'a'>, Char<'r'>)> for Foo { type Field = Bar; @@ -57,14 +52,6 @@ fn test_generic_derive_fields() { }); let expected = quote! { - pub struct Foo - where - FooParamA: Eq, - { - pub bar: Bar, - pub baz: Baz, - } - impl HasField<(Char<'b'>, Char<'a'>, Char<'r'>)> for Foo where