status update
This commit is contained in:
parent
41e2d94e1c
commit
cb2e61e8d3
@ -1,22 +1,34 @@
|
||||
use crate::utils::extractstate::Extract;
|
||||
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_extract(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
pub fn run_canextract(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]
|
||||
|
85
rush_macro/src/utils/canextractstate.rs
Normal file
85
rush_macro/src/utils/canextractstate.rs
Normal file
@ -0,0 +1,85 @@
|
||||
// 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};
|
||||
|
||||
pub struct Extract {
|
||||
state: State,
|
||||
stacks: Vec<Stack>,
|
||||
}
|
||||
|
||||
impl Parse for Extract {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
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 inner_state = &self.state.0;
|
||||
let stacks = &self.stacks;
|
||||
|
||||
let mut counts = Vec::new();
|
||||
for stack in stacks {
|
||||
match counts.iter_mut().find(|(x, _)| x == stack) {
|
||||
Some((_, count)) => *count += 1,
|
||||
None => counts.push((stack, 1usize)),
|
||||
}
|
||||
}
|
||||
|
||||
let conditions = counts.iter().map(|(stack, count)| {
|
||||
let inner_stack = &stack.0;
|
||||
quote! { #inner_state.#inner_stack.len() >= #count }
|
||||
});
|
||||
|
||||
tokens.extend(quote! {
|
||||
true #(&& (#conditions))*
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct State(syn::Ident);
|
||||
|
||||
impl Parse for State {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
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<Self> {
|
||||
_ = input.parse::<syn::Token![,]>();
|
||||
syn::Ident::parse(input).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Stack {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
self.0.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Stack> for &Stack {
|
||||
fn eq(&self, other: &Stack) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
65
rush_macro/src/utils/extractidents.rs
Normal file
65
rush_macro/src/utils/extractidents.rs
Normal file
@ -0,0 +1,65 @@
|
||||
//! 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,83 +1,8 @@
|
||||
// Extract: State (`,` Stack `:` Amount)*
|
||||
//
|
||||
// State: identifier
|
||||
//
|
||||
// Stack: identifier
|
||||
//
|
||||
// Amount: expression
|
||||
// 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};
|
||||
|
||||
pub struct Extract {
|
||||
state: State,
|
||||
stacks: Vec<Stack>,
|
||||
}
|
||||
|
||||
impl Parse for Extract {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
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 inner_state = &self.state.0;
|
||||
let stacks = &self.stacks;
|
||||
|
||||
let mut counts = Vec::new();
|
||||
for stack in stacks {
|
||||
match counts.iter_mut().find(|(x, _)| x == stack) {
|
||||
Some((_, count)) => *count += 1,
|
||||
None => counts.push((stack, 1)),
|
||||
}
|
||||
}
|
||||
|
||||
for (stack, count) in counts {
|
||||
let inner_stack = &stack.0;
|
||||
tokens.extend(quote! {
|
||||
#inner_state.#inner_stack < #count
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct State(syn::Ident);
|
||||
|
||||
impl Parse for State {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
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<Self> {
|
||||
_ = input.parse::<syn::Token![,]>();
|
||||
syn::Ident::parse(input).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Stack {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream2) {
|
||||
self.0.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Stack> for &Stack {
|
||||
fn eq(&self, other: &Stack) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
|
||||
pub mod extractstate;
|
||||
pub mod canextractstate;
|
||||
pub mod extractidents;
|
||||
mod extractstate;
|
||||
pub mod varfunc;
|
||||
|
||||
fn parse_zero_or_more<T: Parse>(input: ParseStream) -> Vec<T> {
|
||||
|
8
rush_macro/tests/extractidents_test.rs
Normal file
8
rush_macro/tests/extractidents_test.rs
Normal file
@ -0,0 +1,8 @@
|
||||
use rush_macro::run_extractidents;
|
||||
|
||||
#[test]
|
||||
fn extractidents_test() {
|
||||
assert!(true);
|
||||
|
||||
// I'm not sure how to test this tbh.
|
||||
}
|
@ -4,6 +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};
|
||||
|
||||
#[macro_use]
|
||||
pub mod macros {
|
||||
@ -309,7 +310,9 @@ pub mod macros {
|
||||
($prefix:ident, $func:ident, $($stacks:ident), *) => {
|
||||
paste::item! {
|
||||
pub fn [< $prefix $func >] (state: &mut PushState) {
|
||||
run_func!($func, extract_state_vals!(state, $($stacks), *))
|
||||
if run_canextract!(state, run_extractidents!($($stacks), *)) {
|
||||
$func extract_state_vals!(state, $($stacks), *)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -325,16 +328,6 @@ pub mod macros {
|
||||
($state.$stack.pop().unwrap(), $(extract_state_vals!($state, $rest)), *)
|
||||
};
|
||||
}
|
||||
|
||||
/// Runs a given function passed in the first argument with all the sequential arguments
|
||||
/// in order.
|
||||
macro_rules! run_func_old {
|
||||
() => {};
|
||||
($func:ident, $($args:expr), *) => {
|
||||
$func($($args), *)
|
||||
};
|
||||
($($args:expr), *) => { $args, run_func!(*) };
|
||||
}
|
||||
}
|
||||
|
||||
pub mod code;
|
||||
@ -787,20 +780,6 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::push::state::EMPTY_STATE;
|
||||
|
||||
#[test]
|
||||
fn run_func_test() {
|
||||
pub fn uadd(x: usize, y: usize, z: usize) -> usize {
|
||||
x + y + z
|
||||
}
|
||||
|
||||
pub fn make_instruction_expr_test() -> usize {
|
||||
run_func_old!(uadd, 1, 2, 3)
|
||||
}
|
||||
|
||||
let res = make_instruction_expr_test();
|
||||
assert_eq!(res, 6);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_state_vals_test() {
|
||||
let mut test_state = EMPTY_STATE;
|
||||
@ -821,6 +800,6 @@ 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);
|
||||
let test_instr = make_instruction_new!(int, _test_func, int, int);
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
|
||||
pub mod instructions;
|
||||
pub mod push;
|
||||
|
@ -21,4 +21,10 @@ fn main() {
|
||||
code_instructions();
|
||||
let mut empty_state = EMPTY_STATE;
|
||||
interpret_program(&mut empty_state, 1000, 1000);
|
||||
|
||||
let mut counts: Vec<(&str, usize)> = vec![];
|
||||
counts.push(("int", 2));
|
||||
counts.push(("float", 1));
|
||||
|
||||
// counts.iter().map()
|
||||
}
|
||||
|
15
tests/extractstate_test.rs
Normal file
15
tests/extractstate_test.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use rush::push::state::EMPTY_STATE;
|
||||
use rush_macro::run_canextract;
|
||||
|
||||
#[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);
|
||||
|
||||
test_state.int = vec![1, 2];
|
||||
let res = run_canextract!(test_state, int, int);
|
||||
assert_eq!(true, res);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user