From 88bc6d16602c163d122685997dc269d5d97a93a2 Mon Sep 17 00:00:00 2001 From: mat Date: Fri, 27 May 2022 19:34:09 -0500 Subject: [PATCH] Start making block macro --- Cargo.lock | 40 ++++-- azalea-block/Cargo.toml | 5 +- azalea-block/block-macros/Cargo.toml | 14 ++ azalea-block/block-macros/src/lib.rs | 157 ++++++++++++++++++++++ azalea-block/src/blocks.rs | 188 ++++++++++++++++----------- azalea-block/src/lib.rs | 2 - azalea-block/src/properties.rs | 20 --- 7 files changed, 310 insertions(+), 116 deletions(-) create mode 100644 azalea-block/block-macros/Cargo.toml create mode 100644 azalea-block/block-macros/src/lib.rs delete mode 100644 azalea-block/src/properties.rs diff --git a/Cargo.lock b/Cargo.lock index 87a6a3aa..09523320 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -81,6 +81,9 @@ dependencies = [ [[package]] name = "azalea-block" version = "0.1.0" +dependencies = [ + "block-macros", +] [[package]] name = "azalea-brigadier" @@ -200,6 +203,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bot" version = "0.1.0" @@ -971,11 +983,11 @@ checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -986,9 +998,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ "proc-macro2", ] @@ -1244,13 +1256,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.92" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1407,6 +1419,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + [[package]] name = "unicode-normalization" version = "0.1.19" @@ -1428,12 +1446,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "url" version = "2.2.2" diff --git a/azalea-block/Cargo.toml b/azalea-block/Cargo.toml index ea43e8ae..edeba385 100644 --- a/azalea-block/Cargo.toml +++ b/azalea-block/Cargo.toml @@ -1,8 +1,11 @@ [package] +edition = "2021" name = "azalea-block" version = "0.1.0" -edition = "2021" + +[lib] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +block-macros = {path = "./block-macros"} diff --git a/azalea-block/block-macros/Cargo.toml b/azalea-block/block-macros/Cargo.toml new file mode 100644 index 00000000..03b19e1d --- /dev/null +++ b/azalea-block/block-macros/Cargo.toml @@ -0,0 +1,14 @@ +[package] +edition = "2021" +name = "block-macros" +version = "0.1.0" + +[lib] +proc-macro = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +proc-macro2 = "1.0.39" +quote = "1.0.18" +syn = "1.0.95" diff --git a/azalea-block/block-macros/src/lib.rs b/azalea-block/block-macros/src/lib.rs new file mode 100644 index 00000000..20ec5f3e --- /dev/null +++ b/azalea-block/block-macros/src/lib.rs @@ -0,0 +1,157 @@ +use proc_macro::TokenStream; +use quote::{quote, ToTokens}; +use std::fmt::Debug; +use syn::{ + self, braced, + parse::{Parse, ParseStream, Result}, + parse_macro_input, + punctuated::Punctuated, + Data, DeriveInput, Expr, FieldsNamed, Ident, LitInt, Token, +}; + +struct PropertyDefinition { + name: Ident, + variants: Punctuated, +} +struct PropertyDefinitions { + properties: Vec, +} + +struct BlockDefinition { + name: Ident, + behavior: Expr, + properties: Punctuated, +} +struct BlockDefinitions { + blocks: Vec, +} +struct MakeBlockStates { + property_definitions: PropertyDefinitions, + block_definitions: BlockDefinitions, +} + +impl Parse for PropertyDefinition { + fn parse(input: ParseStream) -> Result { + // Face { + // Floor, + // Wall, + // Ceiling + // }; + let name = input.parse()?; + let variants = input.parse_terminated(Ident::parse)?; + input.parse::()?; + Ok(PropertyDefinition { name, variants }) + } +} + +impl Parse for PropertyDefinitions { + fn parse(input: ParseStream) -> Result { + let mut property_definitions = Vec::new(); + while !input.is_empty() { + property_definitions.push(input.parse()?); + } + + Ok(PropertyDefinitions { + properties: property_definitions, + }) + } +} + +impl Parse for BlockDefinition { + fn parse(input: ParseStream) -> Result { + // acacia_button => BlockBehavior { has_collision: false }, { + // Face, + // Facing, + // Powered + // }; + let name = input.parse()?; + input.parse::]>()?; + let behavior = input.parse()?; + input.parse::()?; + let content; + braced!(content in input); + let properties = content.parse_terminated(Ident::parse)?; + input.parse::()?; + Ok(BlockDefinition { + name, + behavior, + properties, + }) + } +} + +impl Parse for BlockDefinitions { + fn parse(input: ParseStream) -> Result { + let mut blocks = Vec::new(); + while !input.is_empty() { + blocks.push(input.parse()?); + } + + Ok(BlockDefinitions { blocks }) + } +} + +impl Parse for MakeBlockStates { + fn parse(input: ParseStream) -> Result { + // PROPERTIES => { ... } BLOCKS => { ... } + let properties_ident = input.parse::()?; + assert_eq!(properties_ident.to_string(), "PROPERTIES"); + input.parse::]>()?; + let content; + braced!(content in input); + let properties = content.parse()?; + + let blocks_ident = input.parse::()?; + assert_eq!(blocks_ident.to_string(), "BLOCKS"); + input.parse::]>()?; + let content; + braced!(content in input); + let blocks = content.parse()?; + + Ok(MakeBlockStates { + property_definitions: properties, + block_definitions: blocks, + }) + } +} + +#[proc_macro] +pub fn make_block_states(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as MakeBlockStates); + + let mut property_enums = quote! {}; + + for property in &input.property_definitions.properties { + let mut property_enum_variants = quote! {}; + + for variant in &property.variants { + property_enum_variants.extend(quote! { + #variant, + }); + } + + let property_name = property.name; + + property_enums.extend(quote! { + #[derive(Debug, Clone, Copy)] + pub enum #property_name { + #property_enum_variants + } + }); + } + + // let mut block_state_enum_variants = quote! {}; + + // for block in &input.block_definitions.blocks { + // let block_state_enum_variant = quote! { + // #block.name(#block.behavior, #block.properties) + // }; + // block_state_enum_variants.extend(block_state_enum_variant); + // } + + quote! { + #property_enums + // #block_state_enum_variants + } + .into() +} diff --git a/azalea-block/src/blocks.rs b/azalea-block/src/blocks.rs index f6f33a89..6bc82a20 100644 --- a/azalea-block/src/blocks.rs +++ b/azalea-block/src/blocks.rs @@ -1,88 +1,118 @@ use crate::{behavior::BlockBehavior, properties}; -// make_block_states! { -// acacia_button => BlockBehavior { has_collision: false }, { -// Face, -// Facing, -// Powered -// }; -// acacia_door => BlockBehavior { has_collision: true }, { -// Facing, -// Half, -// Hinge, -// Open, -// Powered -// }; +make_block_states! { + PROPERTIES => { + Face { + Floor, + Wall, + Ceiling + }; + } + BLOCKS => { + acacia_button => BlockBehavior { has_collision: false }, { + Face, + Facing, + Powered + }; + acacia_door => BlockBehavior { has_collision: true }, { + Facing, + Half, + Hinge, + Open, + Powered + }; + } +} + +// #[derive(Debug, Clone, Copy)] +// pub enum Face { +// Floor, +// Wall, +// Ceiling, // } -// the underscore makes it more readable, so i think it's fine to allow it -#[allow(non_camel_case_types)] -pub enum BlockState { - AcaciaButton_FloorNorthTrue, - AcaciaButton_WallNorthTrue, - AcaciaButton_CeilingNorthTrue, -} +// #[derive(Debug, Clone, Copy)] +// pub enum Facing { +// North, +// South, +// West, +// East, +// } -pub trait Block { - fn behavior(&self) -> BlockBehavior; -} +// #[derive(Debug, Clone, Copy)] +// pub enum Powered { +// True, +// False, +// } -#[derive(Debug)] -pub struct AcaciaButtonBlock { - pub face: properties::Face, - pub facing: properties::Facing, - pub powered: properties::Powered, -} +// // the underscore makes it more readable, so i think it's fine to allow it +// #[allow(non_camel_case_types)] +// pub enum BlockState { +// AcaciaButton_FloorNorthTrue, +// AcaciaButton_WallNorthTrue, +// AcaciaButton_CeilingNorthTrue, +// } -impl Block for AcaciaButtonBlock { - fn behavior(&self) -> BlockBehavior { - BlockBehavior { - has_collision: false, - } - } -} +// pub trait Block { +// fn behavior(&self) -> BlockBehavior; +// } -pub struct AcaciaDoorBlock { - pub facing: properties::Facing, - // pub half: properties::Half, - // pub hinge: properties::Hinge, - // pub open: properties::Open, - pub powered: properties::Powered, -} +// #[derive(Debug)] +// pub struct AcaciaButtonBlock { +// pub face: properties::Face, +// pub facing: properties::Facing, +// pub powered: properties::Powered, +// } -impl From for &dyn Block { - fn from(b: BlockState) -> Self { - match b { - BlockState::AcaciaButton_FloorNorthTrue => &AcaciaButtonBlock { - face: properties::Face::Floor, - facing: properties::Facing::North, - powered: properties::Powered::True, - }, - // BlockState::AcaciaButton_WallNorthTrue => todo!(), - // BlockState::AcaciaButton_CeilingNorthTrue => todo!(), - _ => todo!(), - } - } -} -impl From for BlockState { - fn from(b: AcaciaButtonBlock) -> Self { - match b { - AcaciaButtonBlock { - face: properties::Face::Floor, - facing: properties::Facing::North, - powered: properties::Powered::True, - } => BlockState::AcaciaButton_FloorNorthTrue, - // AcaciaButtonBlock { - // face: properties::Face::Wall, - // facing: properties::Facing::North, - // powered: properties::Powered::True, - // } => todo!(), - // AcaciaButtonBlock { - // face: properties::Face::Ceiling, - // facing: properties::Facing::North, - // powered: properties::Powered::True, - // } => todo!(), - _ => todo!(), - } - } -} +// impl Block for AcaciaButtonBlock { +// fn behavior(&self) -> BlockBehavior { +// BlockBehavior { +// has_collision: false, +// } +// } +// } + +// pub struct AcaciaDoorBlock { +// pub facing: properties::Facing, +// // pub half: properties::Half, +// // pub hinge: properties::Hinge, +// // pub open: properties::Open, +// pub powered: properties::Powered, +// } + +// impl From for &dyn Block { +// fn from(b: BlockState) -> Self { +// match b { +// BlockState::AcaciaButton_FloorNorthTrue => &AcaciaButtonBlock { +// face: properties::Face::Floor, +// facing: properties::Facing::North, +// powered: properties::Powered::True, +// }, +// // BlockState::AcaciaButton_WallNorthTrue => todo!(), +// // BlockState::AcaciaButton_CeilingNorthTrue => todo!(), +// _ => todo!(), +// } +// } +// } +// impl From for BlockState { +// fn from(b: AcaciaButtonBlock) -> Self { +// match b { +// AcaciaButtonBlock { +// face: properties::Face::Floor, +// facing: properties::Facing::North, +// powered: properties::Powered::True, +// } => BlockState::AcaciaButton_FloorNorthTrue, +// // AcaciaButtonBlock { +// // face: properties::Face::Wall, +// // facing: properties::Facing::North, +// // powered: properties::Powered::True, +// // } => todo!(), +// // AcaciaButtonBlock { +// // face: properties::Face::Ceiling, +// // facing: properties::Facing::North, +// // powered: properties::Powered::True, +// // } => todo!(), +// _ => todo!(), +// } +// } +// } diff --git a/azalea-block/src/lib.rs b/azalea-block/src/lib.rs index db94d081..30f2aadc 100644 --- a/azalea-block/src/lib.rs +++ b/azalea-block/src/lib.rs @@ -1,5 +1,3 @@ pub mod behavior; pub mod blocks; pub mod properties; - -use std::fmt::Debug; diff --git a/azalea-block/src/properties.rs b/azalea-block/src/properties.rs deleted file mode 100644 index ac81fcb3..00000000 --- a/azalea-block/src/properties.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[derive(Debug, Clone, Copy)] -pub enum Face { - Floor, - Wall, - Ceiling, -} - -#[derive(Debug, Clone, Copy)] -pub enum Facing { - North, - South, - West, - East, -} - -#[derive(Debug, Clone, Copy)] -pub enum Powered { - True, - False, -}