run instruction works, time to refactor rush now
This commit is contained in:
parent
cb2e61e8d3
commit
6744896494
@ -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]
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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};
|
@ -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();
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
use rush_macro::run_extractidents;
|
||||
|
||||
#[test]
|
||||
fn extractidents_test() {
|
||||
assert!(true);
|
||||
|
||||
// I'm not sure how to test this tbh.
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);*/
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user