Compare commits
4 Commits
df4c6cfcfa
...
0a1f0fa601
Author | SHA1 | Date | |
---|---|---|---|
0a1f0fa601 | |||
9abb9d1feb | |||
bcb9d130c7 | |||
cd2071f965 |
@ -34,6 +34,11 @@ mod utils;
|
|||||||
/// ```
|
/// ```
|
||||||
/// would have the ; placed at the end of the instruction. Check rush's `tests/instruction_test.rs`
|
/// would have the ; placed at the end of the instruction. Check rush's `tests/instruction_test.rs`
|
||||||
/// file for an example using this code.
|
/// file for an example using this code.
|
||||||
|
///
|
||||||
|
/// Suggestion: If you need to pull an index from the int stack, make it the first argument
|
||||||
|
/// to your function.
|
||||||
|
///
|
||||||
|
/// If there is an instruction with no stacks as input, must put a comma at the end.
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn run_instruction(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);
|
let f = parse_macro_input!(input as Extract);
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
//! Where the hard work for automatically generating instructions is done.
|
||||||
|
//! Check `run_instruction!` for more details.
|
||||||
|
//!
|
||||||
//! This Stack that isn't repeated is the desired output stack.
|
//! This Stack that isn't repeated is the desired output stack.
|
||||||
//! Extract: Function, Stack, State, (`,` Stack)* ;?
|
//! Extract: Function, Stack, State (`,` Stack)* ;?
|
||||||
//!
|
//!
|
||||||
//! Function: identifier
|
//! Function: identifier
|
||||||
//!
|
//!
|
||||||
@ -56,6 +59,12 @@ impl ToTokens for Extract {
|
|||||||
let stacks = &self.stacks;
|
let stacks = &self.stacks;
|
||||||
let aux = &self.aux;
|
let aux = &self.aux;
|
||||||
|
|
||||||
|
// Gets the counts of each stack passed to the macro held
|
||||||
|
// similarly to a map as: (stack, count).
|
||||||
|
//
|
||||||
|
// Chosen over a HashMap bc these types don't implement Hash
|
||||||
|
// HashMaps are O(nlogn) at worst this is O(n^2). Largest instruction
|
||||||
|
// passes 4 stacks so this shouldn't matter in the long run.
|
||||||
let mut counts = Vec::new();
|
let mut counts = Vec::new();
|
||||||
for stack in stacks {
|
for stack in stacks {
|
||||||
match counts.iter_mut().find(|(x, _)| x == stack) {
|
match counts.iter_mut().find(|(x, _)| x == stack) {
|
||||||
@ -64,31 +73,64 @@ impl ToTokens for Extract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes the piece of the code that ensures the stacks have enough values
|
||||||
|
// to function without error.
|
||||||
let conditions = counts.iter().map(|(stack, count)| {
|
let conditions = counts.iter().map(|(stack, count)| {
|
||||||
let inner_stack = &stack.0;
|
let inner_stack = &stack.0;
|
||||||
quote! { #inner_state.#inner_stack.len() >= #count }
|
quote! { #inner_state.#inner_stack.len() >= #count }
|
||||||
});
|
});
|
||||||
|
|
||||||
let values = stacks.iter().map(|stack| {
|
// In case the instruction returns None (meaning revert the state),
|
||||||
|
// need to store the values to return them
|
||||||
|
let store_values = stacks.iter().enumerate().map(|(i, stack)| {
|
||||||
let inner_stack = &&stack.0;
|
let inner_stack = &&stack.0;
|
||||||
quote! { #inner_state.#inner_stack.pop().unwrap() }
|
let var_name = quote::format_ident!("val_{}", i);
|
||||||
|
quote! { let #var_name = #inner_state.#inner_stack.pop().unwrap(); }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Create the variable names themselves to store the
|
||||||
|
// popped values.
|
||||||
|
let value_vars = (0..stacks.len())
|
||||||
|
.map(|i| quote::format_ident!("val_{}", i))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Create restore code in case None is returned from the function.
|
||||||
|
let restore_values =
|
||||||
|
stacks
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.zip(value_vars.iter().rev())
|
||||||
|
.map(|(stack, var)| {
|
||||||
|
let inner_stack = &&stack.0;
|
||||||
|
quote! { #inner_state.#inner_stack.push(#var.clone()); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// The logic for running the function and returning values
|
||||||
|
// if bad.
|
||||||
let aux_run = match aux {
|
let aux_run = match aux {
|
||||||
true => quote! {
|
true => quote! {
|
||||||
if let Some(result) = #inner_func(#(#values),*) {
|
let result = #inner_func(#(#value_vars.clone()),*);
|
||||||
|
if let Some(result) = result {
|
||||||
#inner_state.#inner_out_stack.extend(result.iter());
|
#inner_state.#inner_out_stack.extend(result.iter());
|
||||||
|
} else {
|
||||||
|
#(#restore_values)*
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false => quote! {
|
false => quote! {
|
||||||
if let Some(result) = #inner_func(#(#values),*) {
|
let result = #inner_func(#(#value_vars.clone()),*);
|
||||||
|
if let Some(result) = result {
|
||||||
#inner_state.#inner_out_stack.push(result);
|
#inner_state.#inner_out_stack.push(result);
|
||||||
|
} else {
|
||||||
|
#(#restore_values)*
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Where the pieces of the puzzle are put together.
|
||||||
|
// tokens then used to create the function.
|
||||||
tokens.extend(quote! {
|
tokens.extend(quote! {
|
||||||
if true #(&& (#conditions))* {
|
if true #(&& (#conditions))* {
|
||||||
|
#(#store_values)*
|
||||||
#aux_run
|
#aux_run
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,32 +5,29 @@ use crate::push::state::{Gene, PushState};
|
|||||||
use super::common::{code_from_exec, code_pop, int_pop};
|
use super::common::{code_from_exec, code_pop, int_pop};
|
||||||
|
|
||||||
/// Checks to see if a single gene is a block.
|
/// Checks to see if a single gene is a block.
|
||||||
fn _is_block(vals: Vec<Gene>) -> Option<bool> {
|
fn _is_block(a: Gene) -> Option<bool> {
|
||||||
Some(match vals[0] {
|
Some(match a {
|
||||||
Gene::Block(_) => true,
|
Gene::Block(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, boolean, _is_block, Gene, 1);
|
|
||||||
|
|
||||||
/// Checks to see if a single gene is not a block.
|
/// Checks to see if a single gene is not a block.
|
||||||
fn _is_singular(vals: Vec<Gene>) -> Option<bool> {
|
fn _is_singular(a: Gene) -> Option<bool> {
|
||||||
Some(_is_block(vals)?.not())
|
Some(_is_block(a)?.not())
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, boolean, _is_singular, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the length of a block, else 1 if not a block
|
/// Returns the length of a block, else 1 if not a block
|
||||||
fn _length(vals: Vec<Gene>) -> Option<i128> {
|
fn _length(a: Gene) -> Option<i128> {
|
||||||
Some(match &vals[0] {
|
Some(match &a {
|
||||||
Gene::Block(x) => x.len() as i128,
|
Gene::Block(x) => x.len() as i128,
|
||||||
_ => 1,
|
_ => 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, int, _length, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the first item in a block if doable, else None
|
/// Returns the first item in a block if doable, else None
|
||||||
fn _first(vals: Vec<Gene>) -> Option<Gene> {
|
fn _first(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
if x.len() > 1 {
|
if x.len() > 1 {
|
||||||
Some(x[0].clone())
|
Some(x[0].clone())
|
||||||
@ -41,11 +38,10 @@ fn _first(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _first, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the first item in a block if applicable, else None
|
/// Returns the first item in a block if applicable, else None
|
||||||
fn _last(vals: Vec<Gene>) -> Option<Gene> {
|
fn _last(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
if x.len() > 1 {
|
if x.len() > 1 {
|
||||||
Some(x.last()?.clone())
|
Some(x.last()?.clone())
|
||||||
@ -56,11 +52,10 @@ fn _last(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _last, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns all but the first code item in a block if applicable, else None
|
/// Returns all but the first code item in a block if applicable, else None
|
||||||
fn _rest(vals: Vec<Gene>) -> Option<Gene> {
|
fn _rest(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
if x.len() > 1 {
|
if x.len() > 1 {
|
||||||
Some(Gene::Block(x[1..].to_vec()))
|
Some(Gene::Block(x[1..].to_vec()))
|
||||||
@ -71,11 +66,10 @@ fn _rest(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _rest, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns all but the first code item in a block if applicable, else None
|
/// Returns all but the first code item in a block if applicable, else None
|
||||||
fn _but_last(vals: Vec<Gene>) -> Option<Gene> {
|
fn _but_last(a: Gene) -> Option<Gene> {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(x) => {
|
Gene::Block(x) => {
|
||||||
let x_len = x.len();
|
let x_len = x.len();
|
||||||
if x_len > 1 {
|
if x_len > 1 {
|
||||||
@ -87,19 +81,17 @@ fn _but_last(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _but_last, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns all the vals wrapped in a code block
|
/// Returns a gene wrapped in a block
|
||||||
fn _wrap_block(vals: Vec<Gene>) -> Option<Gene> {
|
fn _wrap_block(a: Gene) -> Option<Gene> {
|
||||||
Some(Gene::Block(vals))
|
Some(Gene::Block(vec![a]))
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _wrap_block, Gene, 1);
|
|
||||||
|
|
||||||
/// Combines two genes into one. Accounts for blocks.
|
/// Combines two genes into one. Accounts for blocks.
|
||||||
/// If the second gene is a block and the first one isn't,
|
/// If the second gene is a block and the first one isn't,
|
||||||
/// appends the first gene to the second gene.
|
/// appends the first gene to the second gene.
|
||||||
fn _combine(vals: Vec<Gene>) -> Option<Gene> {
|
fn _combine(a: Gene, b: Gene) -> Option<Gene> {
|
||||||
match (&vals[0], &vals[1]) {
|
match (&a, &b) {
|
||||||
(Gene::Block(x), Gene::Block(y)) => {
|
(Gene::Block(x), Gene::Block(y)) => {
|
||||||
let x_clone = x.clone();
|
let x_clone = x.clone();
|
||||||
let mut y_clone = y.clone();
|
let mut y_clone = y.clone();
|
||||||
@ -119,7 +111,6 @@ fn _combine(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
(x, y) => Some(Gene::Block(vec![x.clone(), y.clone()])),
|
(x, y) => Some(Gene::Block(vec![x.clone(), y.clone()])),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _combine, Gene, 2);
|
|
||||||
|
|
||||||
/// Pushes `code_pop` and the top item of the code stack to the exec stack.
|
/// Pushes `code_pop` and the top item of the code stack to the exec stack.
|
||||||
/// Top code item gets executed before being removed from code stack.
|
/// Top code item gets executed before being removed from code stack.
|
||||||
@ -330,15 +321,9 @@ pub fn code_map(state: &mut PushState) {
|
|||||||
|
|
||||||
/// If top bool is true, execute top element of code/exec stack and skip the second.
|
/// If top bool is true, execute top element of code/exec stack and skip the second.
|
||||||
/// If false, execute second element and skip the top.
|
/// If false, execute second element and skip the top.
|
||||||
pub fn _if(vals: Vec<Gene>, auxs: Vec<bool>) -> Option<Gene> {
|
pub fn _if(a: Gene, b: Gene, cond: bool) -> Option<Gene> {
|
||||||
Some(if auxs[0] {
|
Some(if cond { a } else { b })
|
||||||
vals[0].clone()
|
|
||||||
} else {
|
|
||||||
vals[1].clone()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
make_instruction_aux!(code, exec, _if, Gene, 2, boolean, 1, bool);
|
|
||||||
make_instruction_aux!(exec, exec, _if, Gene, 2, boolean, 1, bool);
|
|
||||||
|
|
||||||
/// Evaluates the top code item if the top code is true, else pops it.
|
/// Evaluates the top code item if the top code is true, else pops it.
|
||||||
pub fn code_when(state: &mut PushState) {
|
pub fn code_when(state: &mut PushState) {
|
||||||
@ -364,20 +349,19 @@ pub fn exec_when(state: &mut PushState) {
|
|||||||
|
|
||||||
/// Pushes true if the second code item is found within the first item.
|
/// Pushes true if the second code item is found within the first item.
|
||||||
/// If the first item isn't a block, coerced into one.
|
/// If the first item isn't a block, coerced into one.
|
||||||
pub fn _member(vals: Vec<Gene>) -> Option<bool> {
|
pub fn _member(a: Gene, b: Gene) -> Option<bool> {
|
||||||
let block = match vals[0].clone() {
|
let block = match b {
|
||||||
Gene::Block(val) => val,
|
Gene::Block(val) => val,
|
||||||
val => vec![val],
|
val => vec![val],
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(block.contains(&vals[1]))
|
Some(block.contains(&a))
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, boolean, _member, Gene, 2);
|
|
||||||
|
|
||||||
/// Pushes the nth item of the top element of the code stack.
|
/// Pushes the nth item of the top element of the code stack.
|
||||||
/// If top code item isn't a block, wrap one around it.
|
/// If top code item isn't a block, wrap one around it.
|
||||||
pub fn _nth(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
pub fn _nth(a: Gene, idx: i128) -> Option<Gene> {
|
||||||
let gene_vec = match vals[0].clone() {
|
let gene_vec = match a {
|
||||||
Gene::Block(val) => val,
|
Gene::Block(val) => val,
|
||||||
val => vec![val],
|
val => vec![val],
|
||||||
};
|
};
|
||||||
@ -385,22 +369,19 @@ pub fn _nth(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
|||||||
if gene_vec_len == 0 {
|
if gene_vec_len == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ndx = auxs[0].abs() as usize % gene_vec_len;
|
let ndx = idx.abs() as usize % gene_vec_len;
|
||||||
Some(gene_vec[ndx].clone())
|
Some(gene_vec[ndx].clone())
|
||||||
}
|
}
|
||||||
make_instruction_aux!(code, code, _nth, Gene, 1, int, 1, i128);
|
|
||||||
|
|
||||||
/// Pushes an empty block to the top of a stack.
|
/// Pushes an empty block to the top of a stack.
|
||||||
pub fn _make_empty_block<T>(_: Vec<T>) -> Option<Gene> {
|
pub fn _make_empty_block<T>() -> Option<Gene> {
|
||||||
Some(Gene::Block(vec![]))
|
Some(Gene::Block(vec![]))
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _make_empty_block, Gene, 0);
|
|
||||||
make_instruction_clone!(exec, exec, _make_empty_block, Gene, 0);
|
|
||||||
|
|
||||||
/// Checks to see if the top item on the code/exec stack is an empty block.
|
/// Checks to see if the top item on the code/exec stack is an empty block.
|
||||||
/// True if is, False if not.
|
/// True if is, False if not.
|
||||||
pub fn _is_empty_block(vals: Vec<Gene>) -> Option<bool> {
|
pub fn _is_empty_block(a: Gene) -> Option<bool> {
|
||||||
Some(match vals[0].clone() {
|
Some(match a {
|
||||||
Gene::Block(val) => {
|
Gene::Block(val) => {
|
||||||
if val.is_empty() {
|
if val.is_empty() {
|
||||||
true
|
true
|
||||||
@ -411,70 +392,64 @@ pub fn _is_empty_block(vals: Vec<Gene>) -> Option<bool> {
|
|||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, boolean, _is_empty_block, Gene, 1);
|
|
||||||
make_instruction_clone!(exec, boolean, _is_empty_block, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns the size of the top item on the code/exec stack.
|
/// Returns the size of the top item on the code/exec stack.
|
||||||
pub fn _size(vals: Vec<Gene>) -> Option<i128> {
|
pub fn _size(a: Gene) -> Option<i128> {
|
||||||
Some(match vals[0].clone() {
|
Some(match a.clone() {
|
||||||
Gene::Block(val) => val.len() as i128,
|
Gene::Block(val) => val.len() as i128,
|
||||||
_ => 1,
|
_ => 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, int, _size, Gene, 1);
|
|
||||||
make_instruction_clone!(exec, int, _size, Gene, 1);
|
|
||||||
|
|
||||||
/// Returns a nested element inside a block based on an int.
|
/// Returns a nested element inside a block based on an int.
|
||||||
pub fn _extract(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
pub fn _extract(a: Gene, idx: i128) -> Option<Gene> {
|
||||||
match vals[0].clone() {
|
match &a {
|
||||||
block @ Gene::Block(_) => {
|
block @ Gene::Block(_) => {
|
||||||
let block_len = block.rec_len();
|
let block_len = block.rec_len();
|
||||||
if block_len == 0 {
|
if block_len == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let ndx = (auxs[0] % block_len as i128).abs() as usize;
|
let ndx = (idx % block_len as i128).abs() as usize;
|
||||||
Some(vals[0].clone().code_at_point(ndx)?)
|
Some(a.code_at_point(ndx)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val => Some(val),
|
_ => Some(a),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
make_instruction_aux!(code, code, _extract, Gene, 1, int, 1, i128);
|
|
||||||
|
|
||||||
/// Inserts a gene at a given position in into the top block based off an
|
/// Inserts a gene at a given position in into the top block based off an
|
||||||
/// int from the top of the int stack. The top code item is coerced into a block
|
/// int from the top of the int stack. The top code item is coerced into a block
|
||||||
/// if needed.
|
/// if needed.
|
||||||
pub fn _insert(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
pub fn _insert(a: Gene, b: Gene, idx: i128) -> Option<Gene> {
|
||||||
let mut block = match vals[0].clone() {
|
let mut block = match a.clone() {
|
||||||
iblock @ Gene::Block(_) => iblock,
|
iblock @ Gene::Block(_) => iblock,
|
||||||
val => Gene::Block(vec![val]),
|
val => Gene::Block(vec![val]),
|
||||||
};
|
};
|
||||||
if block.rec_len() == 0 {
|
if block.rec_len() == 0 {
|
||||||
return _combine(vec![block, vals[1].clone()]);
|
return _combine(block, b);
|
||||||
}
|
}
|
||||||
let ndx = auxs[0].abs() as usize % block.rec_len();
|
let ndx = idx.abs() as usize % block.rec_len();
|
||||||
block.with_code_inserted_at_point(vals[1].clone(), ndx);
|
block.with_code_inserted_at_point(b, ndx);
|
||||||
Some(block)
|
Some(block)
|
||||||
}
|
}
|
||||||
make_instruction_aux!(code, code, _insert, Gene, 2, int, 1, i128);
|
|
||||||
|
|
||||||
/// Pushes the first position of the 2nd code item within the top code item.
|
/// Pushes the first position of the 2nd code item within the top code item.
|
||||||
/// If not found, pushes -1. If top code item isn't a block, returns 0 if top
|
/// If not found, pushes -1. If top code item isn't a block, returns 0 if top
|
||||||
/// two code items equal, -1 otherwise.
|
/// two code items equal, -1 otherwise.
|
||||||
pub fn _first_position(vals: Vec<Gene>) -> Option<i128> {
|
pub fn _first_position(a: Gene, b: Gene) -> Option<i128> {
|
||||||
let bad_cond: bool = match &vals[0] {
|
let bad_cond: bool = match &a {
|
||||||
Gene::Block(val) => val.len() == 0,
|
Gene::Block(val) => val.len() == 0,
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
if bad_cond {
|
if bad_cond {
|
||||||
if vals[0] == vals[1] {
|
if a == b {
|
||||||
return Some(0);
|
return Some(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match &vals[0] {
|
match &a {
|
||||||
Gene::Block(val) => {
|
Gene::Block(val) => {
|
||||||
for (idx, el) in val.iter().enumerate() {
|
for (idx, el) in val.iter().enumerate() {
|
||||||
if el == &vals[1] {
|
if el == &b {
|
||||||
return Some(idx as i128);
|
return Some(idx as i128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -484,11 +459,10 @@ pub fn _first_position(vals: Vec<Gene>) -> Option<i128> {
|
|||||||
}
|
}
|
||||||
Some(-1)
|
Some(-1)
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, int, _first_position, Gene, 2);
|
|
||||||
|
|
||||||
/// Reverses the top block. Does nothing if not a block.
|
/// Reverses the top block. Does nothing if not a block.
|
||||||
pub fn _reverse(vals: Vec<Gene>) -> Option<Gene> {
|
pub fn _reverse(a: Gene) -> Option<Gene> {
|
||||||
Some(match vals[0].clone() {
|
Some(match a {
|
||||||
Gene::Block(mut val) => {
|
Gene::Block(mut val) => {
|
||||||
val.reverse();
|
val.reverse();
|
||||||
Gene::Block(val)
|
Gene::Block(val)
|
||||||
@ -496,7 +470,38 @@ pub fn _reverse(vals: Vec<Gene>) -> Option<Gene> {
|
|||||||
val => val,
|
val => val,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _reverse, Gene, 1);
|
|
||||||
|
macro_rules! make_code_instructions {
|
||||||
|
($stack:ident) => {
|
||||||
|
make_instruction_new!(_is_block, $stack, boolean, $stack);
|
||||||
|
make_instruction_new!(_is_singular, $stack, boolean, $stack);
|
||||||
|
make_instruction_new!(_length, $stack, int, $stack);
|
||||||
|
make_instruction_new!(_first, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_last, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_rest, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_but_last, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_wrap_block, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_combine, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_if, $stack, exec, $stack, $stack, boolean);
|
||||||
|
make_instruction_new!(_member, $stack, boolean, $stack, $stack);
|
||||||
|
make_instruction_new!(_nth, $stack, $stack, $stack, int);
|
||||||
|
make_instruction_empty!(_make_empty_block, $stack, $stack, Gene);
|
||||||
|
make_instruction_new!(_is_empty_block, $stack, boolean, $stack);
|
||||||
|
make_instruction_new!(_size, $stack, int, $stack);
|
||||||
|
make_instruction_new!(_extract, $stack, $stack, $stack, int);
|
||||||
|
make_instruction_new!(_insert, $stack, $stack, $stack, $stack, int);
|
||||||
|
make_instruction_new!(_first_position, $stack, int, $stack, $stack);
|
||||||
|
make_instruction_new!(_reverse, $stack, $stack, $stack);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! all_code_instructions {
|
||||||
|
() => {
|
||||||
|
make_code_instructions!(code);
|
||||||
|
make_code_instructions!(exec);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
all_code_instructions!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -950,24 +955,24 @@ mod tests {
|
|||||||
let mut test_state = EMPTY_STATE;
|
let mut test_state = EMPTY_STATE;
|
||||||
|
|
||||||
test_state.code = vec![
|
test_state.code = vec![
|
||||||
Gene::GeneInt(0),
|
|
||||||
Gene::Block(vec![
|
Gene::Block(vec![
|
||||||
Gene::GeneInt(0),
|
Gene::GeneInt(0),
|
||||||
Gene::GeneInt(4),
|
Gene::GeneInt(4),
|
||||||
Gene::StateFunc(exec_do_range),
|
Gene::StateFunc(exec_do_range),
|
||||||
]),
|
]),
|
||||||
|
Gene::GeneInt(0),
|
||||||
];
|
];
|
||||||
code_member(&mut test_state);
|
code_member(&mut test_state);
|
||||||
assert_eq!(vec![true], test_state.boolean);
|
assert_eq!(vec![true], test_state.boolean);
|
||||||
test_state.boolean.clear();
|
test_state.boolean.clear();
|
||||||
|
|
||||||
test_state.code = vec![
|
test_state.code = vec![
|
||||||
Gene::GeneInt(0),
|
|
||||||
Gene::Block(vec![
|
Gene::Block(vec![
|
||||||
Gene::GeneInt(5),
|
Gene::GeneInt(5),
|
||||||
Gene::GeneInt(4),
|
Gene::GeneInt(4),
|
||||||
Gene::StateFunc(exec_do_range),
|
Gene::StateFunc(exec_do_range),
|
||||||
]),
|
]),
|
||||||
|
Gene::GeneInt(0),
|
||||||
];
|
];
|
||||||
code_member(&mut test_state);
|
code_member(&mut test_state);
|
||||||
assert_eq!(vec![false], test_state.boolean);
|
assert_eq!(vec![false], test_state.boolean);
|
||||||
|
@ -7,74 +7,86 @@ use crate::push::state::PushState;
|
|||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
|
|
||||||
/// Runs logical and on two values
|
/// Runs logical and on two values
|
||||||
fn _and<T>(vals: Vec<T>) -> Option<T>
|
fn _and<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + LogicalTrait,
|
T: LogicalTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].logical_and(vals[1]))
|
Some(b.logical_and(a))
|
||||||
}
|
}
|
||||||
make_instruction!(boolean, boolean, _and, bool, 2);
|
|
||||||
|
|
||||||
/// Runs logical or on two values
|
/// Runs logical or on two values
|
||||||
fn _or<T>(vals: Vec<T>) -> Option<T>
|
fn _or<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + LogicalTrait,
|
T: LogicalTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].logical_or(vals[1]))
|
Some(b.logical_or(a))
|
||||||
}
|
}
|
||||||
make_instruction!(boolean, boolean, _or, bool, 2);
|
|
||||||
|
|
||||||
/// Runs logical not on two values
|
/// Runs logical not on two values
|
||||||
fn _not<T>(vals: Vec<T>) -> Option<T>
|
fn _not<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + LogicalTrait,
|
T: LogicalTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].logical_not())
|
Some(a.logical_not())
|
||||||
}
|
}
|
||||||
make_instruction!(boolean, boolean, _not, bool, 1);
|
|
||||||
|
|
||||||
/// Runs logical xor on two values
|
/// Runs logical xor on two values
|
||||||
fn _xor<T>(vals: Vec<T>) -> Option<T>
|
fn _xor<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + LogicalTrait,
|
T: LogicalTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].logical_xor(vals[1]))
|
Some(b.logical_xor(a))
|
||||||
}
|
}
|
||||||
make_instruction!(boolean, boolean, _xor, bool, 2);
|
|
||||||
|
|
||||||
/// Inverts the first value and runs logical and on two values
|
/// Inverts the first value and runs logical and on two values
|
||||||
fn _invert_first_then_and<T>(vals: Vec<T>) -> Option<T>
|
fn _invert_first_then_and<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + LogicalTrait,
|
T: LogicalTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].logical_not().logical_and(vals[1]))
|
Some(a.logical_not().logical_and(b))
|
||||||
}
|
}
|
||||||
make_instruction!(boolean, boolean, _invert_first_then_and, bool, 2);
|
|
||||||
|
|
||||||
/// Inverts the second value and runs logical and on two values
|
/// Inverts the second value and runs logical and on two values
|
||||||
fn _invert_second_then_and<T>(vals: Vec<T>) -> Option<T>
|
fn _invert_second_then_and<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + LogicalTrait,
|
T: LogicalTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].logical_and(vals[1].logical_not()))
|
Some(a.logical_and(b.logical_not()))
|
||||||
}
|
}
|
||||||
make_instruction!(boolean, boolean, _invert_second_then_and, bool, 2);
|
|
||||||
|
|
||||||
fn _from_int<T>(vals: Vec<i128>) -> Option<T>
|
fn _from_int<T>(a: i128) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + CastingTrait,
|
T: CastingTrait,
|
||||||
{
|
{
|
||||||
T::from_int(vals[0])
|
T::from_int(a)
|
||||||
}
|
}
|
||||||
make_instruction_out!(int, boolean, _from_int, i128, 1);
|
|
||||||
|
|
||||||
fn _from_float<T>(vals: Vec<Decimal>) -> Option<T>
|
fn _from_float<T>(a: Decimal) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + CastingTrait,
|
T: CastingTrait,
|
||||||
{
|
{
|
||||||
T::from_float(vals[0])
|
T::from_float(a)
|
||||||
}
|
}
|
||||||
make_instruction_out!(float, boolean, _from_float, Decimal, 1);
|
|
||||||
|
macro_rules! make_logical_instructions {
|
||||||
|
($stack:ident) => {
|
||||||
|
make_instruction_new!(_and, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_or, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_not, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_xor, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_invert_first_then_and, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_invert_second_then_and, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_from_int, $stack, $stack, int);
|
||||||
|
make_instruction_new!(_from_float, $stack, $stack, float);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! all_logical_instructions {
|
||||||
|
() => {
|
||||||
|
make_logical_instructions!(boolean);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
all_logical_instructions!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
use crate::instructions::code::*;
|
|
||||||
use crate::instructions::common::*;
|
|
||||||
use crate::instructions::logical::*;
|
|
||||||
use crate::instructions::numeric::*;
|
|
||||||
use crate::instructions::vector::*;
|
|
||||||
use crate::push::state::PushState;
|
|
||||||
use rush_macro::run_instruction;
|
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros {
|
pub mod macros {
|
||||||
/// A macro that makes a push instruction given: the name of the input stack to use,
|
/// A macro that makes a push instruction given: the name of the input stack to use,
|
||||||
@ -305,7 +297,7 @@ pub mod macros {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a function and ensures needed variables are extracted from a state without error
|
/// Runs a function and ensures the necessary variables are extracted from a state without error
|
||||||
macro_rules! make_instruction_new {
|
macro_rules! make_instruction_new {
|
||||||
($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
|
($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
|
||||||
paste::item! {
|
paste::item! {
|
||||||
@ -316,7 +308,7 @@ pub mod macros {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs a function and ensures needed variables are extracted from a state without error while
|
/// Runs a function and ensures the necessary variables are extracted from a state without error while
|
||||||
/// returning multiple variables from the function
|
/// returning multiple variables from the function
|
||||||
macro_rules! make_instruction_new_aux {
|
macro_rules! make_instruction_new_aux {
|
||||||
($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
|
($func:ident, $prefix:ident, $out_stack:ident, $($stacks:ident), *) => {
|
||||||
@ -327,6 +319,20 @@ pub mod macros {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Makes an instruction that takes no input stacks. Must specify a type for this
|
||||||
|
/// one so because the result needs a type, and the compiler can't infer it here :(
|
||||||
|
macro_rules! make_instruction_empty {
|
||||||
|
($func:ident, $prefix:ident, $out_stack:ident, $out_type:ty) => {
|
||||||
|
paste::item! {
|
||||||
|
pub fn [< $prefix $func >] (state: &mut PushState) {
|
||||||
|
if let Some(result) = $func::<$out_type>() {
|
||||||
|
state.$out_stack.push(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod code;
|
pub mod code;
|
||||||
@ -338,8 +344,8 @@ pub mod vector;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
//use super::*;
|
||||||
use crate::push::state::EMPTY_STATE;
|
use crate::push::state::{EMPTY_STATE, PushState};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn make_instruction_new_test() {
|
fn make_instruction_new_test() {
|
||||||
|
@ -15,302 +15,279 @@ use super::utils::{CastingTrait, NumericTrait};
|
|||||||
/// Adds two values together.
|
/// Adds two values together.
|
||||||
fn _add<T>(a: T, b: T) -> Option<T>
|
fn _add<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Add<Output = T> + Copy,
|
T: Add<Output = T>,
|
||||||
{
|
{
|
||||||
Some(b + a)
|
Some(b + a)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtracts two values from each other.
|
/// Subtracts two values from each other.
|
||||||
fn _sub<T>(vals: Vec<T>) -> Option<T>
|
fn _sub<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Sub<Output = T> + Copy,
|
T: Sub<Output = T>,
|
||||||
{
|
{
|
||||||
Some(vals[1] - vals[0])
|
Some(b - a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _sub, i128, 2);
|
|
||||||
make_instruction!(float, float, _sub, Decimal, 2);
|
|
||||||
|
|
||||||
/// Multiplies two values with each other.
|
/// Multiplies two values with each other.
|
||||||
fn _mult<T>(vals: Vec<T>) -> Option<T>
|
fn _mult<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Mul<Output = T> + Copy,
|
T: Mul<Output = T> + Copy,
|
||||||
{
|
{
|
||||||
Some(vals[1] * vals[0])
|
Some(b * a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _mult, i128, 2);
|
|
||||||
make_instruction!(float, float, _mult, Decimal, 2);
|
|
||||||
|
|
||||||
/// Divides two values from each other.
|
/// Divides two values from each other.
|
||||||
fn _div<T>(vals: Vec<T>) -> Option<T>
|
fn _div<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Div<Output = T> + Copy + NumericTrait,
|
T: Div<Output = T> + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[1].checked_div(vals[0])
|
b.checked_div(a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _div, i128, 2);
|
|
||||||
make_instruction!(float, float, _div, Decimal, 2);
|
|
||||||
|
|
||||||
/// Takes the remainder of two values
|
/// Takes the remainder of two values
|
||||||
fn _rem<T>(vals: Vec<T>) -> Option<T>
|
fn _rem<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Div<Output = T> + Copy + NumericTrait,
|
T: Div<Output = T> + Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[1].checked_mod(vals[0])
|
b.checked_mod(a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _rem, i128, 2);
|
|
||||||
make_instruction!(float, float, _rem, Decimal, 2);
|
|
||||||
|
|
||||||
/// Takes the max of two values
|
/// Takes the max of two values
|
||||||
fn _max<T>(vals: Vec<T>) -> Option<T>
|
fn _max<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Ord + Copy,
|
T: Ord,
|
||||||
{
|
{
|
||||||
Some(max(vals[1], vals[0]))
|
Some(max(a, b))
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _max, i128, 2);
|
|
||||||
make_instruction!(float, float, _max, Decimal, 2);
|
|
||||||
|
|
||||||
/// Takes the min of two values
|
/// Takes the min of two values
|
||||||
fn _min<T>(vals: Vec<T>) -> Option<T>
|
fn _min<T>(a: T, b: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Ord + Copy,
|
T: Ord,
|
||||||
{
|
{
|
||||||
Some(min(vals[1], vals[0]))
|
Some(min(a, b))
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _min, i128, 2);
|
|
||||||
make_instruction!(float, float, _min, Decimal, 2);
|
|
||||||
|
|
||||||
/// Increments a single value by 1
|
/// Increments a single value by 1
|
||||||
fn _inc<T>(vals: Vec<T>) -> Option<T>
|
fn _inc<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: NumericTrait + Copy,
|
T: NumericTrait + Copy,
|
||||||
{
|
{
|
||||||
Some(vals[0].increment())
|
Some(a.increment())
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _inc, i128, 1);
|
|
||||||
make_instruction!(float, float, _inc, Decimal, 1);
|
|
||||||
|
|
||||||
/// Decrements a single value by 1
|
/// Decrements a single value by 1
|
||||||
fn _dec<T>(vals: Vec<T>) -> Option<T>
|
fn _dec<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: NumericTrait + Copy,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].decrement())
|
Some(a.decrement())
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _dec, i128, 1);
|
|
||||||
make_instruction!(float, float, _dec, Decimal, 1);
|
|
||||||
|
|
||||||
/// Checks if the 2nd to top value is less than the top value
|
/// Checks if the 2nd to top value is less than the top value
|
||||||
fn _lt<T>(vals: Vec<T>) -> Option<bool>
|
fn _lt<T>(a: T, b: T) -> Option<bool>
|
||||||
where
|
where
|
||||||
T: Ord + Copy,
|
T: Ord,
|
||||||
{
|
{
|
||||||
Some(vals[1] < vals[0])
|
Some(b < a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, boolean, _lt, i128, 2);
|
|
||||||
make_instruction!(float, boolean, _lt, Decimal, 2);
|
|
||||||
|
|
||||||
/// Checks if the 2nd to top value is greater than the top value
|
/// Checks if the 2nd to top value is greater than the top value
|
||||||
fn _gt<T>(vals: Vec<T>) -> Option<bool>
|
fn _gt<T>(a: T, b: T) -> Option<bool>
|
||||||
where
|
where
|
||||||
T: Ord + Copy,
|
T: Ord,
|
||||||
{
|
{
|
||||||
Some(vals[1] > vals[0])
|
Some(b > a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, boolean, _gt, i128, 2);
|
|
||||||
make_instruction!(float, boolean, _gt, Decimal, 2);
|
|
||||||
|
|
||||||
/// Checks if the 2nd to top value is less than or equal to the top value
|
/// Checks if the 2nd to top value is less than or equal to the top value
|
||||||
fn _lte<T>(vals: Vec<T>) -> Option<bool>
|
fn _lte<T>(a: T, b: T) -> Option<bool>
|
||||||
where
|
where
|
||||||
T: Ord + Copy,
|
T: Ord + Copy,
|
||||||
{
|
{
|
||||||
Some(vals[1] <= vals[0])
|
Some(b <= a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, boolean, _lte, i128, 2);
|
|
||||||
make_instruction!(float, boolean, _lte, Decimal, 2);
|
|
||||||
|
|
||||||
/// Checks if the 2nd to top value is greater than or equal to the top value
|
/// Checks if the 2nd to top value is greater than or equal to the top value
|
||||||
fn _gte<T>(vals: Vec<T>) -> Option<bool>
|
fn _gte<T>(a: T, b: T) -> Option<bool>
|
||||||
where
|
where
|
||||||
T: Ord + Copy,
|
T: Ord,
|
||||||
{
|
{
|
||||||
Some(vals[1] >= vals[0])
|
Some(b >= a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, boolean, _gte, i128, 2);
|
|
||||||
make_instruction!(float, boolean, _gte, Decimal, 2);
|
|
||||||
|
|
||||||
/// Runs sin on a single item.
|
/// Runs sin on a single item.
|
||||||
fn _sin<T>(vals: Vec<T>) -> Option<T>
|
fn _sin<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_sin()
|
a.safe_sin()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _sin, i128, 1);
|
|
||||||
make_instruction!(float, float, _sin, Decimal, 1);
|
|
||||||
|
|
||||||
/// Runs arcsin on a single item.
|
/// Runs arcsin on a single item.
|
||||||
fn _arcsin<T>(vals: Vec<T>) -> Option<T>
|
fn _arcsin<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_sin()?.inverse()
|
a.safe_sin()?.inverse()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _arcsin, i128, 1);
|
|
||||||
make_instruction!(float, float, _arcsin, Decimal, 1);
|
|
||||||
|
|
||||||
/// Runs cos on a single item.
|
/// Runs cos on a single item.
|
||||||
fn _cos<T>(vals: Vec<T>) -> Option<T>
|
fn _cos<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_cos()
|
a.safe_cos()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _cos, i128, 1);
|
|
||||||
make_instruction!(float, float, _cos, Decimal, 1);
|
|
||||||
|
|
||||||
/// Runs arcsin on a single item.
|
/// Runs arcsin on a single item.
|
||||||
fn _arccos<T>(vals: Vec<T>) -> Option<T>
|
fn _arccos<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_cos()?.inverse()
|
a.safe_cos()?.inverse()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _arccos, i128, 1);
|
|
||||||
make_instruction!(float, float, _arccos, Decimal, 1);
|
|
||||||
|
|
||||||
/// Runs tan on a single item.
|
/// Runs tan on a single item.
|
||||||
fn _tan<T>(vals: Vec<T>) -> Option<T>
|
fn _tan<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_tan()
|
a.safe_tan()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _tan, i128, 1);
|
|
||||||
make_instruction!(float, float, _tan, Decimal, 1);
|
|
||||||
|
|
||||||
/// Runs arctan on a single item.
|
/// Runs arctan on a single item.
|
||||||
fn _arctan<T>(vals: Vec<T>) -> Option<T>
|
fn _arctan<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_tan()?.inverse()
|
a.safe_tan()?.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a single value from an int to an arbitrary type.
|
||||||
|
fn _from_int<T>(a: i128) -> Option<T>
|
||||||
|
where
|
||||||
|
T: CastingTrait,
|
||||||
|
{
|
||||||
|
T::from_int(a)
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _arctan, i128, 1);
|
|
||||||
make_instruction!(float, float, _arctan, Decimal, 1);
|
|
||||||
|
|
||||||
/// Converts a single value from a float to an arbitrary type.
|
/// Converts a single value from a float to an arbitrary type.
|
||||||
fn _from_int<T>(vals: Vec<i128>) -> Option<T>
|
fn _from_float<T>(a: Decimal) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + CastingTrait,
|
T: CastingTrait,
|
||||||
{
|
{
|
||||||
T::from_int(vals[0])
|
T::from_float(a)
|
||||||
}
|
}
|
||||||
make_instruction_out!(int, float, _from_int, i128, 1);
|
|
||||||
|
|
||||||
/// Converts a single value from a float to an arbitrary type.
|
/// Converts a bool to a new type.
|
||||||
fn _from_float<T>(vals: Vec<Decimal>) -> Option<T>
|
fn _from_boolean<T>(a: bool) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + CastingTrait,
|
T: CastingTrait,
|
||||||
{
|
{
|
||||||
T::from_float(vals[0])
|
T::from_bool(a)
|
||||||
}
|
}
|
||||||
make_instruction_out!(float, int, _from_float, Decimal, 1);
|
|
||||||
|
|
||||||
/// Converts a bool to a to a new type.
|
/// Takes log base 10 of a single Decimal. Acts as a
|
||||||
fn _from_boolean<T>(vals: Vec<bool>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Copy + CastingTrait,
|
|
||||||
{
|
|
||||||
T::from_bool(vals[0])
|
|
||||||
}
|
|
||||||
make_instruction_out!(boolean, int, _from_boolean, bool, 1);
|
|
||||||
make_instruction_out!(boolean, float, _from_boolean, bool, 1);
|
|
||||||
|
|
||||||
/// Takes the log base 10 of a single Decimal. Acts as a
|
|
||||||
/// NoOp if the value is 0. If the value is negative, takes
|
/// NoOp if the value is 0. If the value is negative, takes
|
||||||
/// the absolute value of the number.
|
/// the absolute value of the number.
|
||||||
fn _log<T>(vals: Vec<T>) -> Option<T>
|
fn _log<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].absolute().safe_log10()
|
a.absolute().safe_log10()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _log, i128, 1);
|
|
||||||
make_instruction!(float, float, _log, Decimal, 1);
|
|
||||||
|
|
||||||
/// Takes the exp of a single value. Ints get truncated.
|
/// Takes the exp of a single value. Ints get truncated.
|
||||||
fn _exp<T>(vals: Vec<T>) -> Option<T>
|
fn _exp<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_exp()
|
a.safe_exp()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _exp, i128, 1);
|
|
||||||
make_instruction!(float, float, _exp, Decimal, 1);
|
|
||||||
|
|
||||||
/// Takes the square root of the absolute value of a single value.
|
/// Takes the square root of the absolute value of a single value.
|
||||||
fn _sqrt<T>(vals: Vec<T>) -> Option<T>
|
fn _sqrt<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_sqrt()
|
a.safe_sqrt()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _sqrt, i128, 1);
|
|
||||||
make_instruction!(float, float, _sqrt, Decimal, 1);
|
|
||||||
|
|
||||||
/// Takes the inverse of a single value. If the number is 0,
|
/// Takes the inverse of a single value. If the number is 0,
|
||||||
/// does nothing (returns None). Truncates an int to 0.
|
/// does nothing (returns None). Truncates an int to 0.
|
||||||
fn _inv<T>(vals: Vec<T>) -> Option<T>
|
fn _inv<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].inverse()
|
a.inverse()
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _inv, i128, 1);
|
|
||||||
make_instruction!(float, float, _inv, Decimal, 1);
|
|
||||||
|
|
||||||
/// Takes the absolute value of the top number
|
/// Takes the absolute value of the top number
|
||||||
fn _abs<T>(vals: Vec<T>) -> Option<T>
|
fn _abs<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].absolute())
|
Some(a.absolute())
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _abs, i128, 1);
|
|
||||||
make_instruction!(float, float, _abs, Decimal, 1);
|
|
||||||
|
|
||||||
/// Reverses the sign of the top number
|
/// Reverses the sign of the top number
|
||||||
fn _sign_reverse<T>(vals: Vec<T>) -> Option<T>
|
fn _sign_reverse<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].sign_reverse())
|
Some(a.sign_reverse())
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _sign_reverse, i128, 1);
|
|
||||||
make_instruction!(float, float, _sign_reverse, Decimal, 1);
|
|
||||||
|
|
||||||
/// Squares the top number
|
/// Squares the top number
|
||||||
fn _square<T>(vals: Vec<T>) -> Option<T>
|
fn _square<T>(a: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + NumericTrait,
|
T: NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].square())
|
Some(a.square())
|
||||||
}
|
}
|
||||||
make_instruction!(int, int, _square, i128, 1);
|
|
||||||
make_instruction!(float, float, _square, Decimal, 1);
|
|
||||||
|
|
||||||
macro_rules! make_instructions {
|
macro_rules! make_numeric_instructions {
|
||||||
($stack:ident) => {
|
($stack:ident) => {
|
||||||
paste::item! {
|
|
||||||
make_instruction_new!(_add, $stack, $stack, $stack, $stack);
|
make_instruction_new!(_add, $stack, $stack, $stack, $stack);
|
||||||
}
|
make_instruction_new!(_sub, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_mult, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_div, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_rem, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_max, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_min, $stack, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_inc, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_dec, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_lt, $stack, boolean, $stack, $stack);
|
||||||
|
make_instruction_new!(_gt, $stack, boolean, $stack, $stack);
|
||||||
|
make_instruction_new!(_lte, $stack, boolean, $stack, $stack);
|
||||||
|
make_instruction_new!(_gte, $stack, boolean, $stack, $stack);
|
||||||
|
make_instruction_new!(_sin, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_arcsin, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_cos, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_arccos, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_tan, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_arctan, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_from_boolean, $stack, $stack, boolean);
|
||||||
|
make_instruction_new!(_log, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_exp, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_sqrt, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_inv, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_abs, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_sign_reverse, $stack, $stack, $stack);
|
||||||
|
make_instruction_new!(_square, $stack, $stack, $stack);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
make_instructions!(int);
|
macro_rules! all_numeric_instructions {
|
||||||
make_instructions!(float);
|
() => {
|
||||||
|
make_numeric_instructions!(int);
|
||||||
|
make_numeric_instructions!(float);
|
||||||
|
make_instruction_new!(_from_int, float, float, int);
|
||||||
|
make_instruction_new!(_from_float, int, int, float);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
all_numeric_instructions!();
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -328,160 +305,93 @@ mod tests {
|
|||||||
/// Tests the _sub function.
|
/// Tests the _sub function.
|
||||||
#[test]
|
#[test]
|
||||||
fn sub_test() {
|
fn sub_test() {
|
||||||
let vals: Vec<i64> = vec![1, 2];
|
assert_eq!(Some(1), _sub(1, 2));
|
||||||
assert_eq!(Some(1), _sub(vals));
|
assert_eq!(Some(dec!(1.1)), _sub(dec!(1.1), dec!(2.2)));
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(1.1), dec!(2.2)];
|
|
||||||
assert_eq!(Some(dec!(1.1)), _sub(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _mult function.
|
/// Tests the _mult function.
|
||||||
#[test]
|
#[test]
|
||||||
fn mult_test() {
|
fn mult_test() {
|
||||||
let vals: Vec<i128> = vec![4, 5];
|
assert_eq!(Some(20), _mult(5, 4));
|
||||||
assert_eq!(Some(20), _mult(vals));
|
assert_eq!(Some(dec!(2.42)), _mult(dec!(2.2), dec!(1.1)));
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(1.1), dec!(2.2)];
|
|
||||||
assert_eq!(Some(dec!(2.42)), _mult(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _div function
|
/// Tests the _div function
|
||||||
#[test]
|
#[test]
|
||||||
fn div_test() {
|
fn div_test() {
|
||||||
let vals: Vec<i128> = vec![4, 20];
|
assert_eq!(Some(5), _div(4, 20));
|
||||||
assert_eq!(Some(5), _div(vals));
|
assert_eq!(Some(6), _div(3, 20));
|
||||||
|
assert_eq!(Some(dec!(1.375)), _div(dec!(1.6), dec!(2.2)));
|
||||||
let vals: Vec<i128> = vec![3, 20];
|
assert_eq!(None, _div(0, 1));
|
||||||
assert_eq!(Some(6), _div(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(1.6), dec!(2.2)];
|
|
||||||
assert_eq!(Some(dec!(1.375)), _div(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![0, 1];
|
|
||||||
assert_eq!(None, _div(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _rem function
|
/// Tests the _rem function
|
||||||
#[test]
|
#[test]
|
||||||
fn rem_test() {
|
fn rem_test() {
|
||||||
let vals: Vec<i128> = vec![3, 20];
|
assert_eq!(Some(2), _rem(3, 20));
|
||||||
assert_eq!(Some(2), _rem(vals));
|
assert_eq!(Some(0), _rem(20, 20));
|
||||||
|
assert_eq!(None, _rem(0, 9));
|
||||||
let vals: Vec<i128> = vec![20, 20];
|
|
||||||
assert_eq!(Some(0), _rem(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![0, 9];
|
|
||||||
assert_eq!(None, _rem(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _max function
|
/// Tests the _max function
|
||||||
#[test]
|
#[test]
|
||||||
fn max_test() {
|
fn max_test() {
|
||||||
let vals: Vec<i128> = vec![1, 2];
|
assert_eq!(Some(2), _max(1, 2));
|
||||||
assert_eq!(Some(2), _max(vals));
|
assert_eq!(Some(3), _max(3, 0));
|
||||||
|
assert_eq!(Some(dec!(2.2)), _max(dec!(2.2), dec!(1.1)));
|
||||||
let vals: Vec<i128> = vec![3, 0];
|
assert_eq!(Some(dec!(3.3)), _max(dec!(3.3), dec!(-1.1)));
|
||||||
assert_eq!(Some(3), _max(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(2.2), dec!(1.1)];
|
|
||||||
assert_eq!(Some(dec!(2.2)), _max(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(3.3), dec!(-1.1)];
|
|
||||||
assert_eq!(Some(dec!(3.3)), _max(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _min function
|
/// Tests the _min function
|
||||||
#[test]
|
#[test]
|
||||||
fn min_test() {
|
fn min_test() {
|
||||||
let vals: Vec<i128> = vec![1, 2];
|
assert_eq!(Some(1), _min(1, 2));
|
||||||
assert_eq!(Some(1), _min(vals));
|
assert_eq!(Some(0), _min(3, 0));
|
||||||
|
assert_eq!(Some(dec!(1.1)), _min(dec!(2.2), dec!(1.1)));
|
||||||
let vals: Vec<i128> = vec![3, 0];
|
assert_eq!(Some(dec!(-1.1)), _min(dec!(3.3), dec!(-1.1)));
|
||||||
assert_eq!(Some(0), _min(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(2.2), dec!(1.1)];
|
|
||||||
assert_eq!(Some(dec!(1.1)), _min(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(3.3), dec!(-1.1)];
|
|
||||||
assert_eq!(Some(dec!(-1.1)), _min(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _inc and _dec functions
|
/// Tests the _inc and _dec functions
|
||||||
#[test]
|
#[test]
|
||||||
fn inc_dec_test() {
|
fn inc_dec_test() {
|
||||||
let vals: Vec<i128> = vec![2];
|
assert_eq!(Some(3), _inc(2));
|
||||||
assert_eq!(Some(3), _inc(vals));
|
assert_eq!(Some(9), _dec(10));
|
||||||
|
assert_eq!(Some(dec!(3.2)), _inc(dec!(2.2)));
|
||||||
let vals: Vec<i128> = vec![10];
|
assert_eq!(Some(dec!(4.6)), _dec(dec!(5.6)));
|
||||||
assert_eq!(Some(9), _dec(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(2.2)];
|
|
||||||
assert_eq!(Some(dec!(3.2)), _inc(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = vec![dec!(5.6)];
|
|
||||||
assert_eq!(Some(dec!(4.6)), _dec(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the _lt, _gt, _lte, and _gte functions
|
/// Tests the _lt, _gt, _lte, and _gte functions
|
||||||
#[test]
|
#[test]
|
||||||
fn lt_gt_lte_gte_test() {
|
fn lt_gt_lte_gte_test() {
|
||||||
let vals: Vec<i128> = vec![3, 2];
|
assert_eq!(Some(true), _lt(3, 2));
|
||||||
assert_eq!(Some(true), _lt(vals));
|
assert_eq!(Some(false), _lt(1, 4));
|
||||||
|
assert_eq!(Some(false), _lt(3, 3));
|
||||||
let vals: Vec<i128> = vec![1, 4];
|
assert_eq!(Some(true), _gt(2, 3));
|
||||||
assert_eq!(Some(false), _lt(vals));
|
assert_eq!(Some(false), _gt(4, 1));
|
||||||
|
assert_eq!(Some(false), _gt(3, 3));
|
||||||
let vals: Vec<i128> = vec![3, 3];
|
assert_eq!(Some(true), _lte(3, 2));
|
||||||
assert_eq!(Some(false), _lt(vals));
|
assert_eq!(Some(false), _lte(1, 4));
|
||||||
|
assert_eq!(Some(true), _lte(3, 3));
|
||||||
let vals: Vec<i128> = vec![2, 3];
|
assert_eq!(Some(true), _gte(2, 3));
|
||||||
assert_eq!(Some(true), _gt(vals));
|
assert_eq!(Some(false), _gte(4, 1));
|
||||||
|
assert_eq!(Some(true), _gte(3, 3));
|
||||||
let vals: Vec<i128> = vec![4, 1];
|
|
||||||
assert_eq!(Some(false), _gt(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 3];
|
|
||||||
assert_eq!(Some(false), _gt(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 2];
|
|
||||||
assert_eq!(Some(true), _lte(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![1, 4];
|
|
||||||
assert_eq!(Some(false), _lte(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 3];
|
|
||||||
assert_eq!(Some(true), _lte(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![2, 3];
|
|
||||||
assert_eq!(Some(true), _gte(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![4, 1];
|
|
||||||
assert_eq!(Some(false), _gte(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 3];
|
|
||||||
assert_eq!(Some(true), _gte(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the various trig functions.
|
/// Tests the various trig functions.
|
||||||
#[test]
|
#[test]
|
||||||
fn trig_tests() {
|
fn trig_tests() {
|
||||||
let vals = vec![Decimal::PI];
|
assert_eq!(Some(dec!(0.0)), _sin(Decimal::PI));
|
||||||
assert_eq!(Some(dec!(0.0)), _sin(vals));
|
assert_eq!(
|
||||||
|
Some(dec!(1.4142135623869512272301701717)),
|
||||||
let vals = vec![Decimal::QUARTER_PI];
|
_arcsin(Decimal::QUARTER_PI)
|
||||||
assert_eq!(Some(dec!(1.4142135623869512272301701717)), _arcsin(vals));
|
);
|
||||||
|
assert_eq!(Some(dec!(-1.0)), _cos(Decimal::PI));
|
||||||
let vals = vec![Decimal::PI];
|
assert_eq!(Some(dec!(-1.0)), _arccos(Decimal::PI));
|
||||||
assert_eq!(Some(dec!(-1.0)), _cos(vals));
|
assert_eq!(Some(dec!(0.0)), _tan(Decimal::PI));
|
||||||
|
assert_eq!(
|
||||||
let vals = vec![Decimal::QUARTER_PI];
|
Some(dec!(1.0000000043184676055890307049)),
|
||||||
assert_eq!(Some(dec!(1.4142135626023406165042434783)), _arccos(vals));
|
_arctan(Decimal::QUARTER_PI)
|
||||||
|
);
|
||||||
let vals = vec![Decimal::PI];
|
|
||||||
assert_eq!(Some(dec!(0.0)), _tan(vals));
|
|
||||||
|
|
||||||
let vals = vec![Decimal::QUARTER_PI];
|
|
||||||
assert_eq!(Some(dec!(1.0000000043184676055890307049)), _arctan(vals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests that the various addition functions.
|
/// Tests that the various addition functions.
|
||||||
@ -545,7 +455,6 @@ mod tests {
|
|||||||
assert_eq!(vec![2, 0], test_state.int);
|
assert_eq!(vec![2, 0], test_state.int);
|
||||||
|
|
||||||
test_state.int = vec![6, 3];
|
test_state.int = vec![6, 3];
|
||||||
|
|
||||||
int_div(&mut test_state);
|
int_div(&mut test_state);
|
||||||
assert_eq!(vec![2], test_state.int);
|
assert_eq!(vec![2], test_state.int);
|
||||||
|
|
||||||
@ -731,6 +640,13 @@ mod tests {
|
|||||||
test_state.float = vec![dec!(2.1)];
|
test_state.float = vec![dec!(2.1)];
|
||||||
int_from_float(&mut test_state);
|
int_from_float(&mut test_state);
|
||||||
assert_eq!(vec![2], test_state.int);
|
assert_eq!(vec![2], test_state.int);
|
||||||
|
test_state.float.clear();
|
||||||
|
test_state.int.clear();
|
||||||
|
|
||||||
|
test_state.boolean = vec![true];
|
||||||
|
int_from_boolean(&mut test_state);
|
||||||
|
assert_eq!(vec![1], test_state.int);
|
||||||
|
test_state.boolean.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests the log function
|
/// Tests the log function
|
||||||
|
@ -9,6 +9,10 @@ fn aux_iadd(x: i128, y: i128) -> Option<Vec<i128>> {
|
|||||||
Some(vec![x + y, x - y])
|
Some(vec![x + y, x - y])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn two_stacks(x: i128, y: i128, cond: bool) -> Option<i128> {
|
||||||
|
if cond { Some(x + y) } else { Some(x - y) }
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn run_extract_test() {
|
fn run_extract_test() {
|
||||||
let mut test_state = EMPTY_STATE;
|
let mut test_state = EMPTY_STATE;
|
||||||
@ -26,4 +30,8 @@ fn run_extract_test() {
|
|||||||
test_state.int = vec![1, 2];
|
test_state.int = vec![1, 2];
|
||||||
run_instruction!(aux_iadd, int, test_state, int, int;);
|
run_instruction!(aux_iadd, int, test_state, int, int;);
|
||||||
assert_eq!(vec![3, 1], test_state.int);
|
assert_eq!(vec![3, 1], test_state.int);
|
||||||
|
|
||||||
|
test_state.int = vec![1, 2];
|
||||||
|
test_state.boolean = vec![true];
|
||||||
|
run_instruction!(two_stacks, int, test_state, int, int, boolean);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user