run instruction works, time to refactor rush now

This commit is contained in:
Rowan Torbitzky-Lane 2025-04-18 00:10:17 -05:00
parent cb2e61e8d3
commit 6744896494
10 changed files with 58 additions and 194 deletions

View File

@ -1,34 +1,16 @@
use crate::utils::canextractstate::Extract;
use crate::utils::extractidents::ExtractIdents;
use crate::utils::varfunc::VarFunc;
use quote::quote;
use syn::parse_macro_input;
mod utils;
/// Runs a function passed as the first argument with a variable amount of functions
/// passed to it afterward.
#[proc_macro]
pub fn run_func(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let f = parse_macro_input!(input as VarFunc);
quote! { #f }.into()
}
/// Checks to see if extracting values from a state is possible.
#[proc_macro]
pub fn run_canextract(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
pub fn run_instruction(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let f = parse_macro_input!(input as Extract);
quote! { #f }.into()
}
/// Returns the arguments to this proc macro in a usable way to other
/// functions. Check the utils file for a more in depth explanation.
#[proc_macro]
pub fn run_extractidents(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let f = parse_macro_input!(input as ExtractIdents);
quote! { #f }.into()
}
#[cfg(test)]
mod tests {
#[test]

View File

@ -1,10 +1,11 @@
// Extract: State (`,` Stack `:` Amount)*
// This Stack that isn't repeated is the desired output stack.
// Extract: Function, Stack, State, (`,` Stack)*
//
// Function: identifier
//
// State: identifier
//
// Stack: identifier
//
// Amount: expression
use crate::utils::parse_zero_or_more;
use proc_macro2::TokenStream as TokenStream2;
@ -13,20 +14,31 @@ use std::cmp::PartialEq;
use syn::parse::{Parse, ParseStream};
pub struct Extract {
func: Function,
out_stack: Stack,
state: State,
stacks: Vec<Stack>,
}
impl Parse for Extract {
fn parse(input: ParseStream) -> syn::Result<Self> {
let func = input.parse()?;
let out_stack = input.parse()?;
let state = input.parse()?;
let stacks = parse_zero_or_more(input);
Ok(Extract { state, stacks })
Ok(Extract {
func,
out_stack,
state,
stacks,
})
}
}
impl ToTokens for Extract {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let inner_func = &self.func;
let inner_out_stack = &self.out_stack.0;
let inner_state = &self.state.0;
let stacks = &self.stacks;
@ -43,8 +55,16 @@ impl ToTokens for Extract {
quote! { #inner_state.#inner_stack.len() >= #count }
});
let values = stacks.iter().map(|stack| {
let inner_stack = &&stack.0;
quote! { #inner_state.#inner_stack.pop().unwrap() }
});
tokens.extend(quote! {
true #(&& (#conditions))*
if true #(&& (#conditions))* {
let result = vec![#inner_func(#(#values, )*)];
#inner_state.#inner_out_stack.extend(result.iter());
}
});
}
}
@ -53,6 +73,7 @@ struct State(syn::Ident);
impl Parse for State {
fn parse(input: ParseStream) -> syn::Result<Self> {
_ = input.parse::<syn::Token![,]>();
syn::Ident::parse(input).map(Self)
}
}
@ -83,3 +104,17 @@ impl PartialEq<Stack> for &Stack {
self.0 == other.0
}
}
struct Function(syn::Ident);
impl Parse for Function {
fn parse(input: ParseStream) -> syn::Result<Self> {
syn::Ident::parse(input).map(Self)
}
}
impl ToTokens for Function {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.0.to_tokens(tokens)
}
}

View File

@ -1,65 +0,0 @@
//! Extracts identifiers from a passed list of them.
//!
//! IdentExtract: identifier CommaIdentifier*
//!
//! CommaIdentifier: (, identifier)
//!
//! For Example:
//! run_extract_idents!(int, int, int) would return (literally):
//! `int, int, int` to rust
use crate::utils::parse_zero_or_more;
use proc_macro2::TokenStream as TokenStream2;
use quote::{ToTokens, quote};
use std::io::stdout;
use syn::parse::{Parse, ParseStream};
pub struct ExtractIdents {
ident: syn::Ident,
comma_idents: Vec<CommaIdentifiers>,
}
impl Parse for ExtractIdents {
fn parse(input: ParseStream) -> syn::Result<Self> {
let ident = input.parse()?;
let comma_idents = parse_zero_or_more(input);
Ok(Self {
ident,
comma_idents,
})
}
}
impl ToTokens for ExtractIdents {
fn to_tokens(&self, tokens: &mut TokenStream2) {
let first_ident = &self.ident;
let comma_idents = &self.comma_idents;
/*tokens.extend(quote! { #first_ident });
for id in comma_idents {
let syn_id = &id.0;
tokens.(syn_id);
}*/
let output = quote! {
#first_ident #(, #comma_idents)*
};
tokens.extend(output);
}
}
pub struct CommaIdentifiers(syn::Ident);
impl Parse for CommaIdentifiers {
fn parse(input: ParseStream) -> syn::Result<Self> {
_ = input.parse::<syn::Token![,]>()?;
syn::Ident::parse(input).map(Self)
}
}
impl ToTokens for CommaIdentifiers {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.0.to_tokens(tokens)
}
}

View File

@ -1,8 +0,0 @@
// The parsing will be same for canextractstate.rs but
// instead of chaining trues at the end, will just chain the values.
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};

View File

@ -1,9 +1,6 @@
use syn::parse::{Parse, ParseStream};
pub mod canextractstate;
pub mod extractidents;
mod extractstate;
pub mod varfunc;
fn parse_zero_or_more<T: Parse>(input: ParseStream) -> Vec<T> {
let mut result = Vec::new();

View File

@ -1,62 +0,0 @@
// 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<Argument>,
}
impl Parse for VarFunc {
fn parse(input: ParseStream) -> syn::Result<Self> {
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<Self> {
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<Self> {
_ = input.parse::<syn::Token![,]>()?;
syn::Expr::parse(input).map(Self)
}
}
impl ToTokens for Argument {
fn to_tokens(&self, tokens: &mut TokenStream2) {
self.0.to_tokens(tokens)
}
}

View File

@ -1,8 +0,0 @@
use rush_macro::run_extractidents;
#[test]
fn extractidents_test() {
assert!(true);
// I'm not sure how to test this tbh.
}

View File

@ -1,11 +0,0 @@
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);
}

View File

@ -4,7 +4,7 @@ use crate::instructions::logical::*;
use crate::instructions::numeric::*;
use crate::instructions::vector::*;
use crate::push::state::PushState;
use rush_macro::{run_canextract, run_extractidents, run_func};
use rush_macro::run_instruction;
#[macro_use]
pub mod macros {
@ -307,12 +307,10 @@ pub mod macros {
/// Runs a function and ensures needed variables are extracted from a state without error
macro_rules! make_instruction_new {
($prefix:ident, $func:ident, $($stacks:ident), *) => {
($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
paste::item! {
pub fn [< $prefix $func >] (state: &mut PushState) {
if run_canextract!(state, run_extractidents!($($stacks), *)) {
$func extract_state_vals!(state, $($stacks), *)
}
run_instruction!($func, $out_stack, state, $($stacks), *);
}
}
};
@ -799,7 +797,9 @@ mod tests {
let mut test_state = EMPTY_STATE;
test_state.int = vec![0, 1];
let test_instr = make_instruction_new!(int, _test_func, int, int);
test_state.int = vec![1, 2];
make_instruction_new!(_test_func, int, int, int, int);
int_test_func(&mut test_state);
assert_eq!(vec![3], test_state.int);
}
}

View File

@ -1,15 +1,19 @@
use rush::push::state::EMPTY_STATE;
use rush_macro::run_canextract;
use rush_macro::run_instruction;
fn iadd(x: i128, y: i128) -> i128 {
x + y
}
#[test]
fn run_extract_test() {
let mut test_state = EMPTY_STATE;
test_state.int = vec![1, 2];
let res = run_canextract!(test_state, int, int, float);
assert_eq!(false, res);
run_instruction!(iadd, int, test_state, int, int);
assert_eq!(vec![3], test_state.int);
test_state.int = vec![1, 2];
let res = run_canextract!(test_state, int, int);
assert_eq!(true, res);
/*test_state.int = vec![1];
run_instruction!(iadd, int, test_state, int, int);
assert_eq!(vec![1], test_state.int);*/
}