Compare commits

...

8 Commits

11 changed files with 262 additions and 660 deletions

View File

@ -1,19 +1,47 @@
use crate::utils::varfunc::VarFunc; use crate::utils::instruction::Extract;
use quote::quote; use quote::quote;
use syn::parse_macro_input; use syn::parse_macro_input;
mod utils; mod utils;
/// This macro kinda goes super crazy mode
/// Here's how to use the macro:
///
/// `run_instruction!(function_name, output_stack, push state, any amount of
/// comma separated stacks by name ; (the semicolon instructs use whether the instruction
/// has multiple outputs. If ; passed, assumes multiple, without assumes just one output))`
///
/// An instruction for int add would be:
/// `run_instruction!(_add, int, state, int, int)`
/// assuming the _add function takes two integers and returns a single value (Hint: It does).
///
/// Important notice: the order in which the last amount
/// of stacks are passed in matters. The first `int` identifier will tell
/// the macro to pop the top int first, the second `int` will pop the next int
/// and so on. This even works with multiple different types of stacks.
///
/// Another important notice: This macro generates boundary checking as well.
/// If there are not enough items in the stack to run the function, it
/// will not be called.
///
/// A function with multiple outputs, for example this one:
/// ```
/// fn aux_iadd(x: i128, y: i128) -> Option<Vec<i128>> {
/// Some(vec![x + y, x - y])
/// }
///
/// run_instruction!(aux_iadd, int, state, int, int;);
/// ```
/// would have the ; placed at the end of the instruction. Check rush's `tests/instruction_test.rs`
/// file for an example using this code.
#[proc_macro] #[proc_macro]
pub fn run_func(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 VarFunc); let f = parse_macro_input!(input as Extract);
quote! { #f }.into() quote! { #f }.into()
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
#[test] #[test]
fn it_works() { fn it_works() {
assert!(true); assert!(true);

View File

@ -1,68 +0,0 @@
// 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<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 state = &self.state;
let stacks = &self.stacks;
}
}
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
}
}

View File

@ -0,0 +1,146 @@
//! This Stack that isn't repeated is the desired output stack.
//! Extract: Function, Stack, State, (`,` Stack)* ;?
//!
//! Function: identifier
//!
//! State: identifier
//!
//! Stack: identifier
//!
//! Aux: 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};
/// Checks if there is a semicolon at the end
fn parse_aux<T: Parse>(input: ParseStream) -> bool {
if let Ok(_) = input.parse::<syn::Token![;]>() {
return true;
}
false
}
pub struct Extract {
func: Function,
out_stack: Stack,
state: State,
stacks: Vec<Stack>,
aux: bool,
}
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);
let aux = parse_aux::<syn::Token![,]>(input);
Ok(Extract {
func,
out_stack,
state,
stacks,
aux,
})
}
}
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;
let aux = &self.aux;
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 }
});
let values = stacks.iter().map(|stack| {
let inner_stack = &&stack.0;
quote! { #inner_state.#inner_stack.pop().unwrap() }
});
let aux_run = match aux {
true => quote! {
if let Some(result) = #inner_func(#(#values),*) {
#inner_state.#inner_out_stack.extend(result.iter());
}
},
false => quote! {
if let Some(result) = #inner_func(#(#values),*) {
#inner_state.#inner_out_stack.push(result);
}
},
};
tokens.extend(quote! {
if true #(&& (#conditions))* {
#aux_run
}
});
}
}
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)
}
}
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
}
}
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,7 +1,6 @@
use syn::parse::{Parse, ParseStream}; use syn::parse::{Parse, ParseStream};
pub mod extractstate; pub mod instruction;
pub mod varfunc;
fn parse_zero_or_more<T: Parse>(input: ParseStream) -> Vec<T> { fn parse_zero_or_more<T: Parse>(input: ParseStream) -> Vec<T> {
let mut result = Vec::new(); 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,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,6 +4,7 @@ use crate::instructions::logical::*;
use crate::instructions::numeric::*; use crate::instructions::numeric::*;
use crate::instructions::vector::*; use crate::instructions::vector::*;
use crate::push::state::PushState; use crate::push::state::PushState;
use rush_macro::run_instruction;
#[macro_use] #[macro_use]
pub mod macros { pub mod macros {
@ -306,34 +307,25 @@ pub mod macros {
/// Runs a function and ensures needed variables are extracted from a state without error /// Runs a function and ensures needed variables are extracted from a state without error
macro_rules! make_instruction_new { macro_rules! make_instruction_new {
($prefix:ident, $func:ident, $($stacks:ident), *) => { ($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
paste::item! { paste::item! {
pub fn [< $prefix $func >] (state: &mut PushState) { pub fn [< $prefix $func >] (state: &mut PushState) {
run_func!($func, extract_state_vals!(state, $($stacks), *)) rush_macro::run_instruction!($func, $out_stack, state, $($stacks), *);
} }
} }
}; };
} }
/// Extracts values from passed state based on an amount of stacks passed. /// Runs a function and ensures needed variables are extracted from a state without error while
macro_rules! extract_state_vals { /// returning multiple variables from the function
($state:ident) => {}; macro_rules! make_instruction_new_aux {
($state:ident, $stack:ident) => { ($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
$state.$stack.pop().unwrap() paste::item! {
pub fn [< $prefix $func >] (state: &mut PushState) {
rush_macro::run_instruction!($func, $out_stack, state, $($stacks), *, ;);
}
}
}; };
($state:ident, $stack:ident, $($rest:ident), *) => {
($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!(*) };
} }
} }
@ -344,483 +336,31 @@ pub mod numeric;
pub mod utils; pub mod utils;
pub mod vector; pub mod vector;
// unsure how to procedurally read a file and put all functions
// into a vector. Probably need to use procedural macros, but I'm not there yet.
pub fn int_instructions() -> Vec<fn(&mut PushState)> {
vec![
// numeric.rs
int_add,
int_sub,
int_mult,
int_div,
int_rem,
int_max,
int_min,
int_inc,
int_dec,
int_lt,
int_gt,
int_lte,
int_gte,
int_sin,
int_arcsin,
int_cos,
int_arccos,
int_tan,
int_arctan,
int_from_float,
int_from_boolean,
int_log,
int_exp,
int_sqrt,
int_inv,
int_abs,
int_sign_reverse,
int_square,
// common.rs
int_pop,
]
}
pub fn float_instructions() -> Vec<fn(&mut PushState)> {
vec![
// numeric
float_add,
float_sub,
float_mult,
float_div,
float_rem,
float_max,
float_min,
float_inc,
float_dec,
float_lt,
float_gt,
float_lte,
float_gte,
float_sin,
float_arcsin,
float_cos,
float_arccos,
float_tan,
float_arctan,
float_from_int,
float_from_boolean,
float_log,
float_exp,
float_sqrt,
float_inv,
float_abs,
float_sign_reverse,
float_square,
// common.rs
float_pop,
]
}
pub fn string_instructions() -> Vec<fn(&mut PushState)> {
vec![
// numeric.rs
string_concat,
string_conj,
string_conj_end,
string_take_n,
string_take_last_n,
string_sub,
string_first,
string_from_first_prim,
string_from_prim,
string_last,
string_from_last_prim,
string_nth,
string_from_nth_prim,
string_rest,
string_but_last,
string_drop,
string_drop_last,
string_length,
string_reverse,
string_push_all,
string_make_empty,
string_is_empty,
string_contains,
string_contains_vector_non_contiguous,
string_contains_vector_contiguous,
string_index_of,
string_index_of_vector,
string_occurrences_of,
string_occurrences_of_vector,
string_parse_to_prim,
string_set_nth,
string_split_on,
string_replace,
string_remove,
string_insert,
string_insert_vector,
// common.rs
string_pop,
]
}
pub fn boolean_instructions() -> Vec<fn(&mut PushState)> {
vec![
// logical.rs
boolean_and,
boolean_or,
boolean_not,
boolean_xor,
boolean_invert_first_then_and,
boolean_invert_second_then_and,
boolean_from_int,
boolean_from_float,
// common.rs
boolean_pop,
]
}
pub fn char_instructions() -> Vec<fn(&mut PushState)> {
vec![
// common.rs
char_pop,
]
}
pub fn vector_int_instructions() -> Vec<fn(&mut PushState)> {
vec![
// vector.rs
vector_int_concat,
vector_int_conj,
vector_int_conj_end,
vector_int_take_n,
vector_int_take_last_n,
vector_int_sub,
vector_int_first,
vector_int_from_first_prim,
vector_int_from_prim,
vector_int_last,
vector_int_from_last_prim,
vector_int_nth,
vector_int_from_nth_prim,
vector_int_rest,
vector_int_but_last,
vector_int_drop,
vector_int_drop_last,
vector_int_length,
vector_int_reverse,
vector_int_push_all,
vector_int_make_empty,
vector_int_is_empty,
vector_int_contains,
vector_int_contains_vector_non_contiguous,
vector_int_contains_vector_contiguous,
vector_int_index_of,
vector_int_index_of_vector,
vector_int_occurrences_of,
vector_int_occurrences_of_vector,
vector_int_parse_to_prim,
vector_int_set_nth,
vector_int_split_on,
vector_int_replace,
vector_int_remove,
vector_int_iterate,
vector_int_sort,
vector_int_sort_reverse,
vector_int_insert,
vector_int_insert_vector,
vector_int_mean,
vector_int_maximum,
vector_int_minimum,
vector_int_sum,
vector_int_mode,
vector_int_two_norm,
vector_int_cumulative_sum,
// common.rs
vector_int_pop,
]
}
pub fn vector_float_instructions() -> Vec<fn(&mut PushState)> {
vec![
// vector.rs
vector_float_concat,
vector_float_conj,
vector_float_conj_end,
vector_float_take_n,
vector_float_take_last_n,
vector_float_sub,
vector_float_first,
vector_float_from_first_prim,
vector_float_from_prim,
vector_float_last,
vector_float_from_last_prim,
vector_float_nth,
vector_float_from_nth_prim,
vector_float_rest,
vector_float_but_last,
vector_float_drop,
vector_float_drop_last,
vector_float_length,
vector_float_reverse,
vector_float_push_all,
vector_float_make_empty,
vector_float_is_empty,
vector_float_contains,
vector_float_contains_vector_non_contiguous,
vector_float_contains_vector_contiguous,
vector_float_index_of,
vector_float_index_of_vector,
vector_float_occurrences_of,
vector_float_occurrences_of_vector,
vector_float_parse_to_prim,
vector_float_set_nth,
vector_float_split_on,
vector_float_replace,
vector_float_remove,
vector_float_iterate,
vector_float_sort,
vector_float_sort_reverse,
vector_float_insert,
vector_float_insert_vector,
vector_float_mean,
vector_float_maximum,
vector_float_minimum,
vector_float_sum,
vector_float_mode,
vector_float_two_norm,
vector_float_cumulative_sum,
// common.rs
vector_float_pop,
]
}
pub fn vector_string_instructions() -> Vec<fn(&mut PushState)> {
vec![
// vector.rs
vector_string_concat,
vector_string_conj,
vector_string_conj_end,
vector_string_take_n,
vector_string_take_last_n,
vector_string_sub,
vector_string_first,
vector_string_from_first_prim,
vector_string_from_prim,
vector_string_last,
vector_string_from_last_prim,
vector_string_nth,
vector_string_from_nth_prim,
vector_string_rest,
vector_string_but_last,
vector_string_drop,
vector_string_drop_last,
vector_string_length,
vector_string_reverse,
vector_string_make_empty,
vector_string_is_empty,
vector_string_contains,
vector_string_contains_vector_non_contiguous,
vector_string_contains_vector_contiguous,
vector_string_index_of,
vector_string_index_of_vector,
vector_string_occurrences_of,
vector_string_occurrences_of_vector,
vector_string_parse_to_prim,
vector_string_set_nth,
vector_string_split_on,
vector_string_replace,
vector_string_remove,
vector_string_insert,
vector_string_insert_vector,
// common.rs
vector_string_pop,
]
}
pub fn vector_boolean_instructions() -> Vec<fn(&mut PushState)> {
vec![
// vector.rs
vector_boolean_concat,
vector_boolean_conj,
vector_boolean_conj_end,
vector_boolean_take_n,
vector_boolean_take_last_n,
vector_boolean_sub,
vector_boolean_first,
vector_boolean_from_first_prim,
vector_boolean_from_prim,
vector_boolean_last,
vector_boolean_from_last_prim,
vector_boolean_nth,
vector_boolean_from_nth_prim,
vector_boolean_rest,
vector_boolean_but_last,
vector_boolean_drop,
vector_boolean_drop_last,
vector_boolean_length,
vector_boolean_reverse,
vector_boolean_push_all,
vector_boolean_make_empty,
vector_boolean_is_empty,
vector_boolean_contains,
vector_boolean_contains_vector_non_contiguous,
vector_boolean_contains_vector_contiguous,
vector_boolean_index_of,
vector_boolean_index_of_vector,
vector_boolean_occurrences_of,
vector_boolean_occurrences_of_vector,
vector_boolean_parse_to_prim,
vector_boolean_set_nth,
vector_boolean_split_on,
vector_boolean_replace,
vector_boolean_remove,
vector_boolean_iterate,
vector_boolean_insert,
vector_boolean_insert_vector,
// common.rs
vector_boolean_pop,
]
}
pub fn vector_char_instructions() -> Vec<fn(&mut PushState)> {
vec![
// vector.rs
vector_char_concat,
vector_char_conj,
vector_char_conj_end,
vector_char_take_n,
vector_char_take_last_n,
vector_char_sub,
vector_char_first,
vector_char_from_first_prim,
vector_char_from_prim,
vector_char_last,
vector_char_from_last_prim,
vector_char_nth,
vector_char_from_nth_prim,
vector_char_rest,
vector_char_but_last,
vector_char_drop,
vector_char_drop_last,
vector_char_length,
vector_char_reverse,
vector_char_push_all,
vector_char_make_empty,
vector_char_is_empty,
vector_char_contains,
vector_char_contains_vector_non_contiguous,
vector_char_contains_vector_contiguous,
vector_char_index_of,
vector_char_index_of_vector,
vector_char_occurrences_of,
vector_char_occurrences_of_vector,
vector_char_parse_to_prim,
vector_char_set_nth,
vector_char_split_on,
vector_char_replace,
vector_char_remove,
vector_char_iterate,
vector_char_insert,
vector_char_insert_vector,
// common.rs
vector_char_pop,
]
}
pub fn exec_instructions() -> Vec<fn(&mut PushState)> {
vec![
// code.rs
exec_do_range,
exec_do_count,
exec_do_times,
exec_while,
exec_do_while,
exec_if,
exec_when,
exec_make_empty_block,
exec_is_empty_block,
exec_size,
// common.rs
exec_noop,
exec_noop_block,
exec_pop,
]
}
pub fn code_instructions() -> Vec<fn(&mut PushState)> {
vec![
// code.rs
code_is_block,
code_is_singular,
code_length,
code_first,
code_last,
code_rest,
code_but_last,
code_wrap_block,
code_combine,
code_do_then_pop,
code_do_range,
code_do_count,
code_do_times,
code_map,
code_if,
code_when,
code_member,
code_nth,
code_make_empty_block,
code_is_empty_block,
code_size,
code_extract,
code_insert,
code_insert,
code_first_position,
code_reverse,
// common.rs
code_noop,
code_noop_block,
code_pop,
code_from_int,
code_from_float,
code_from_string,
code_from_boolean,
code_from_char,
code_from_vector_int,
code_from_vector_float,
code_from_vector_string,
code_from_vector_boolean,
code_from_vector_char,
code_from_exec,
]
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::push::state::EMPTY_STATE; 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;
test_state.int = vec![0, 1];
test_state.boolean = vec![true];
let res = extract_state_vals!(test_state, int, int, boolean);
assert_eq!((1, 0, true), res);
}
#[test] #[test]
fn make_instruction_new_test() { fn make_instruction_new_test() {
fn _test_func(x: i128, y: i128) -> i128 { fn _test_func(x: i128, y: i128) -> Option<i128> {
x + y Some(x + y)
}
fn _aux_test_func(x: i128, y: i128) -> Option<Vec<i128>> {
Some(vec![x + y, x - y])
} }
let mut test_state = EMPTY_STATE; let mut test_state = EMPTY_STATE;
test_state.int = vec![0, 1]; test_state.int = vec![1, 2];
//let test_instr = make_instruction_new!(int, _test_func, int, int); make_instruction_new!(_test_func, int, int, int, int);
int_test_func(&mut test_state);
assert_eq!(vec![3], test_state.int);
test_state.int = vec![1, 2];
make_instruction_new_aux!(_aux_test_func, int, int, int, int);
int_aux_test_func(&mut test_state);
assert_eq!(vec![3, 1], test_state.int);
} }
} }

View File

@ -12,17 +12,15 @@ use std::ops::{Add, Div, Mul, Sub};
use super::utils::{CastingTrait, NumericTrait}; use super::utils::{CastingTrait, NumericTrait};
/// Adds two addable values together. /// Adds two values together.
fn _add<T>(vals: Vec<T>) -> Option<T> fn _add<T>(a: T, b: T) -> Option<T>
where where
T: Add<Output = T> + Copy, T: Add<Output = T> + Copy,
{ {
Some(vals[1] + vals[0]) Some(b + a)
} }
make_instruction!(int, int, _add, i128, 2);
make_instruction!(float, float, _add, Decimal, 2);
/// Subtracts two subtractable values from each other. /// Subtracts two values from each other.
fn _sub<T>(vals: Vec<T>) -> Option<T> fn _sub<T>(vals: Vec<T>) -> Option<T>
where where
T: Sub<Output = T> + Copy, T: Sub<Output = T> + Copy,
@ -32,7 +30,7 @@ where
make_instruction!(int, int, _sub, i128, 2); make_instruction!(int, int, _sub, i128, 2);
make_instruction!(float, float, _sub, Decimal, 2); make_instruction!(float, float, _sub, Decimal, 2);
/// Multiplies two multipliable values together. /// Multiplies two values with each other.
fn _mult<T>(vals: Vec<T>) -> Option<T> fn _mult<T>(vals: Vec<T>) -> Option<T>
where where
T: Mul<Output = T> + Copy, T: Mul<Output = T> + Copy,
@ -303,6 +301,17 @@ where
make_instruction!(int, int, _square, i128, 1); make_instruction!(int, int, _square, i128, 1);
make_instruction!(float, float, _square, Decimal, 1); make_instruction!(float, float, _square, Decimal, 1);
macro_rules! make_instructions {
($stack:ident) => {
paste::item! {
make_instruction_new!(_add, $stack, $stack, $stack, $stack);
}
};
}
make_instructions!(int);
make_instructions!(float);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -312,11 +321,8 @@ mod tests {
/// Tests the _add function. /// Tests the _add function.
#[test] #[test]
fn add_test() { fn add_test() {
let vals: Vec<i64> = vec![1, 2]; assert_eq!(Some(3), _add(1, 2));
assert_eq!(Some(3), _add(vals)); assert_eq!(Some(dec!(3.3)), _add(dec!(1.1), dec!(2.2)));
let vals: Vec<Decimal> = vec![dec!(1.1), dec!(2.2)];
assert_eq!(Some(dec!(3.3)), _add(vals));
} }
/// Tests the _sub function. /// Tests the _sub function.

View File

@ -1 +1,2 @@
pub mod instructions;
pub mod push;

View File

@ -7,18 +7,12 @@ mod push;
fn main() { fn main() {
// These need to stay so linter doesn't go crazy. // These need to stay so linter doesn't go crazy.
int_instructions();
float_instructions();
string_instructions();
boolean_instructions();
char_instructions();
vector_int_instructions();
vector_float_instructions();
vector_string_instructions();
vector_boolean_instructions();
vector_char_instructions();
exec_instructions();
code_instructions();
let mut empty_state = EMPTY_STATE; let mut empty_state = EMPTY_STATE;
interpret_program(&mut empty_state, 1000, 1000); 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()
} }

29
tests/instruction_test.rs Normal file
View File

@ -0,0 +1,29 @@
use rush::push::state::EMPTY_STATE;
use rush_macro::run_instruction;
fn iadd(x: i128, y: i128) -> Option<i128> {
Some(x + y)
}
fn aux_iadd(x: i128, y: i128) -> Option<Vec<i128>> {
Some(vec![x + y, x - y])
}
#[test]
fn run_extract_test() {
let mut test_state = EMPTY_STATE;
test_state.int = vec![1, 2];
run_instruction!(iadd, int, test_state, int, int);
assert_eq!(vec![3], test_state.int);
test_state.int = vec![1];
run_instruction!(iadd, int, test_state, int, int);
assert_eq!(vec![1], test_state.int);
// If you're coming from the run_instruction docs, this is
// the one.
test_state.int = vec![1, 2];
run_instruction!(aux_iadd, int, test_state, int, int;);
assert_eq!(vec![3, 1], test_state.int);
}