diff --git a/Cargo.toml b/Cargo.toml index f6daca5..1793912 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2024" rand = "0.9.0" paste = "1.0.15" rust_decimal = { version = "1.37", features = ["macros", "maths"] } +rush_macro = { path = "rush_macro" } \ No newline at end of file diff --git a/rush_macro/Cargo.toml b/rush_macro/Cargo.toml index a3fc13a..e262311 100644 --- a/rush_macro/Cargo.toml +++ b/rush_macro/Cargo.toml @@ -3,7 +3,10 @@ name = "rush_macro" version = "0.1.0" edition = "2024" +[lib] +proc-macro = true + [dependencies] -syn = { version = "2.0.100" } +syn = { version = "2.0.100", features = ["full"] } quote = { version = "1.0.40" } -proc_macro2 = { version = "1.0.95" } +proc-macro2 = { version = "1.0.95" } diff --git a/rush_macro/src/lib.rs b/rush_macro/src/lib.rs index b93cf3f..97d8977 100644 --- a/rush_macro/src/lib.rs +++ b/rush_macro/src/lib.rs @@ -1,5 +1,13 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right +use crate::utils::varfunc::VarFunc; +use quote::quote; +use syn::parse_macro_input; + +mod utils; + +#[proc_macro] +pub fn run_func(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let f = parse_macro_input!(input as VarFunc); + quote! { #f }.into() } #[cfg(test)] @@ -8,7 +16,6 @@ mod tests { #[test] fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); + assert!(true); } } diff --git a/rush_macro/src/utils/extractstate.rs b/rush_macro/src/utils/extractstate.rs new file mode 100644 index 0000000..73f4c20 --- /dev/null +++ b/rush_macro/src/utils/extractstate.rs @@ -0,0 +1,68 @@ +// Extract: State (`,` Stack `:` Amount)* +// +// State: identifier +// +// Stack: identifier +// +// Amount: expression + +use crate::utils::parse_zero_or_more; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ToTokens, quote}; +use std::cmp::PartialEq; +use syn::parse::{Parse, ParseStream}; + +struct Extract { + state: State, + stacks: Vec, +} + +impl Parse for Extract { + fn parse(input: ParseStream) -> syn::Result { + let state = input.parse()?; + let stacks = parse_zero_or_more(input); + Ok(Extract { state, stacks }) + } +} + +impl ToTokens for Extract { + fn to_tokens(&self, tokens: &mut TokenStream2) { + let state = &self.state; + let stacks = &self.stacks; + } +} + +struct State(syn::Ident); + +impl Parse for State { + fn parse(input: ParseStream) -> syn::Result { + syn::Ident::parse(input).map(Self) + } +} + +impl ToTokens for State { + fn to_tokens(&self, tokens: &mut TokenStream2) { + self.0.to_tokens(tokens) + } +} + +struct Stack(syn::Ident); + +impl Parse for Stack { + fn parse(input: ParseStream) -> syn::Result { + _ = input.parse::(); + syn::Ident::parse(input).map(Self) + } +} + +impl ToTokens for Stack { + fn to_tokens(&self, tokens: &mut TokenStream2) { + self.0.to_tokens(tokens) + } +} + +impl PartialEq for &Stack { + fn eq(&self, other: &Stack) -> bool { + self.0 == other.0 + } +} diff --git a/rush_macro/src/utils/mod.rs b/rush_macro/src/utils/mod.rs new file mode 100644 index 0000000..0d38e16 --- /dev/null +++ b/rush_macro/src/utils/mod.rs @@ -0,0 +1,12 @@ +use syn::parse::{Parse, ParseStream}; + +pub mod extractstate; +pub mod varfunc; + +fn parse_zero_or_more(input: ParseStream) -> Vec { + let mut result = Vec::new(); + while let Ok(item) = input.parse() { + result.push(item); + } + result +} diff --git a/rush_macro/src/utils/varfunc.rs b/rush_macro/src/utils/varfunc.rs new file mode 100644 index 0000000..3812b70 --- /dev/null +++ b/rush_macro/src/utils/varfunc.rs @@ -0,0 +1,62 @@ +// Run: Function Argument* +// +// Function: identifier +// +// Argument: (, expression) + +use crate::utils::parse_zero_or_more; +use proc_macro2::TokenStream as TokenStream2; +use quote::{ToTokens, quote}; +use syn::parse::{Parse, ParseStream}; + +pub struct VarFunc { + func: Function, + args: Vec, +} + +impl Parse for VarFunc { + fn parse(input: ParseStream) -> syn::Result { + let func = input.parse()?; + let args = parse_zero_or_more(input); + Ok(Self { func, args }) + } +} + +impl ToTokens for VarFunc { + fn to_tokens(&self, tokens: &mut TokenStream2) { + let function = &self.func; + let args = &self.args; + tokens.extend(quote! { + #function(#(#args),*) + }) + } +} + +struct Function(syn::Ident); + +impl Parse for Function { + fn parse(input: ParseStream) -> syn::Result { + syn::Ident::parse(input).map(Self) + } +} + +impl ToTokens for Function { + fn to_tokens(&self, tokens: &mut TokenStream2) { + self.0.to_tokens(tokens) + } +} + +struct Argument(syn::Expr); + +impl Parse for Argument { + fn parse(input: ParseStream) -> syn::Result { + _ = input.parse::()?; + syn::Expr::parse(input).map(Self) + } +} + +impl ToTokens for Argument { + fn to_tokens(&self, tokens: &mut TokenStream2) { + self.0.to_tokens(tokens) + } +} diff --git a/rush_macro/tests/var_func_test.rs b/rush_macro/tests/var_func_test.rs new file mode 100644 index 0000000..daaf598 --- /dev/null +++ b/rush_macro/tests/var_func_test.rs @@ -0,0 +1,11 @@ +use rush_macro::run_func; + +fn uadd(x: usize, y: usize, z: usize) -> usize { + x + y + z +} + +#[test] +fn run_func_test() { + let res = run_func!(uadd, 1, 4, 2); + assert_eq!(res, 7); +} diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs index 8424843..73fbba2 100644 --- a/src/instructions/mod.rs +++ b/src/instructions/mod.rs @@ -328,7 +328,7 @@ pub mod macros { /// Runs a given function passed in the first argument with all the sequential arguments /// in order. - macro_rules! run_func { + macro_rules! run_func_old { () => {}; ($func:ident, $($args:expr), *) => { $func($($args), *) @@ -794,7 +794,7 @@ mod tests { } pub fn make_instruction_expr_test() -> usize { - run_func!(uadd, 1, 2, 3) + run_func_old!(uadd, 1, 2, 3) } let res = make_instruction_expr_test();