diff --git a/src/instructions/code.rs b/src/instructions/code.rs deleted file mode 100644 index 2462ca9..0000000 --- a/src/instructions/code.rs +++ /dev/null @@ -1,353 +0,0 @@ -use std::ops::Not; - -use crate::push::state::{Gene, PushState}; - -/// Checks to see if a single gene is a block. -fn _is_block(vals: Vec) -> Option { - Some(match vals[0] { - Gene::Block(_) => true, - _ => false, - }) -} -make_instruction_clone!(code, boolean, _is_block, Gene, 1); - -/// Checks to see if a single gene is not a block. -fn _is_singular(vals: Vec) -> Option { - Some(_is_block(vals)?.not()) -} -make_instruction_clone!(code, boolean, _is_singular, Gene, 1); - -/// Returns the length of a block, else 1 if not a block -fn _length(vals: Vec) -> Option { - Some(match &vals[0] { - Gene::Block(x) => x.len() as i128, - _ => 1, - }) -} -make_instruction_clone!(code, int, _length, Gene, 1); - -/// Returns the first item in a block if doable, else None -fn _first(vals: Vec) -> Option { - match &vals[0] { - Gene::Block(x) => { - if x.len() > 1 { - Some(x[0].clone()) - } else { - None - } - } - _ => None, - } -} -make_instruction_clone!(code, code, _first, Gene, 1); - -/// Returns the first item in a block if applicable, else None -fn _last(vals: Vec) -> Option { - match &vals[0] { - Gene::Block(x) => { - if x.len() > 1 { - Some(x.last()?.clone()) - } else { - None - } - } - _ => None, - } -} -make_instruction_clone!(code, code, _last, Gene, 1); - -/// Returns all but the first code item in a block if applicable, else None -fn _rest(vals: Vec) -> Option { - match &vals[0] { - Gene::Block(x) => { - if x.len() > 1 { - Some(Gene::Block(Box::new(x[1..].to_vec()))) - } else { - None - } - } - _ => None, - } -} -make_instruction_clone!(code, code, _rest, Gene, 1); - -/// Returns all but the first code item in a block if applicable, else None -fn _but_last(vals: Vec) -> Option { - match &vals[0] { - Gene::Block(x) => { - let x_len = x.len(); - if x_len > 1 { - Some(Gene::Block(Box::new(x[..x_len - 1].to_vec()))) - } else { - None - } - } - _ => None, - } -} -make_instruction_clone!(code, code, _but_last, Gene, 1); - -/// Returns all of the vals wrapped in a code block -fn _wrap_block(vals: Vec) -> Option { - Some(Gene::Block(Box::new(vals))) -} -make_instruction_clone!(code, code, _wrap_block, Gene, 1); - -/// Combines two genes into one. Accounts for blocks. -/// If the second gene is a block and the first one isn't, -/// appends the first gene to the second gene. -fn _combine(vals: Vec) -> Option { - match (&vals[0], &vals[1]) { - (Gene::Block(x), Gene::Block(y)) => { - let x_clone = x.clone(); - let mut y_clone = y.clone(); - y_clone.extend(x_clone.into_iter()); - Some(Gene::Block(y_clone)) - } - (Gene::Block(x), y) => { - let mut x_clone = x.clone(); - x_clone.push(y.clone()); - Some(Gene::Block(x_clone)) - } - (x, Gene::Block(y)) => { - let mut y_clone = y.clone(); - y_clone.push(x.clone()); - Some(Gene::Block(y_clone)) - } - (x, y) => Some(Gene::Block(Box::new(vec![x.clone(), y.clone()]))), - } -} -make_instruction_clone!(code, code, _combine, Gene, 2); - -#[cfg(test)] -mod tests { - use super::*; - use crate::push::state::EMPTY_STATE; - use rust_decimal::dec; - - #[test] - fn is_block_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![]))]; - code_is_block(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - test_state.boolean.clear(); - - test_state.code = vec![(Gene::GeneInt(1))]; - code_is_block(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - } - - #[test] - fn is_singular_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![]))]; - code_is_singular(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - test_state.boolean.clear(); - - test_state.code = vec![(Gene::GeneInt(1))]; - code_is_singular(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - } - - #[test] - fn length_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - ]))]; - code_length(&mut test_state); - assert_eq!(vec![2], test_state.int); - test_state.int.clear(); - - test_state.code = vec![Gene::Block(Box::new(vec![]))]; - code_length(&mut test_state); - assert_eq!(vec![0], test_state.int); - test_state.int.clear(); - - test_state.code = vec![Gene::GeneInt(3)]; - code_length(&mut test_state); - assert_eq!(vec![1], test_state.int); - } - - #[test] - fn first_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - ]))]; - code_first(&mut test_state); - assert_eq!(vec![Gene::GeneInt(1)], test_state.code); - - test_state.code = vec![]; - code_first(&mut test_state); - let empty_vec: Vec = vec![]; - assert_eq!(empty_vec, test_state.code); - drop(empty_vec); - - test_state.code = vec![Gene::GeneInt(1)]; - code_first(&mut test_state); - assert_eq!(vec![Gene::GeneInt(1)], test_state.code); - } - - #[test] - fn last_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - ]))]; - code_last(&mut test_state); - assert_eq!(vec![Gene::GeneFloat(dec!(3.8))], test_state.code); - - test_state.code = vec![]; - code_last(&mut test_state); - let empty_vec: Vec = vec![]; - assert_eq!(empty_vec, test_state.code); - drop(empty_vec); - - test_state.code = vec![Gene::GeneInt(1)]; - code_last(&mut test_state); - assert_eq!(vec![Gene::GeneInt(1)], test_state.code); - } - - #[test] - fn rest_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - Gene::GeneBoolean(true), - ]))]; - code_rest(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![ - Gene::GeneFloat(dec!(3.8)), - Gene::GeneBoolean(true) - ]))], - test_state.code - ); - - test_state.code = vec![]; - code_rest(&mut test_state); - let empty_vec: Vec = vec![]; - assert_eq!(empty_vec, test_state.code); - drop(empty_vec); - - test_state.code = vec![Gene::GeneInt(1)]; - code_rest(&mut test_state); - assert_eq!(vec![Gene::GeneInt(1)], test_state.code); - } - - #[test] - fn but_last_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - Gene::GeneBoolean(true), - ]))]; - code_but_last(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - ]))], - test_state.code - ); - - test_state.code = vec![]; - code_but_last(&mut test_state); - let empty_vec: Vec = vec![]; - assert_eq!(empty_vec, test_state.code); - drop(empty_vec); - - test_state.code = vec![Gene::GeneInt(1)]; - code_but_last(&mut test_state); - assert_eq!(vec![Gene::GeneInt(1)], test_state.code); - } - - #[test] - fn wrap_block_test() { - let mut test_state = EMPTY_STATE; - - test_state.code = vec![Gene::GeneInt(1)]; - code_wrap_block(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![Gene::GeneInt(1)]))], - test_state.code - ); - } - - #[test] - fn combine_test() { - let mut test_state = EMPTY_STATE; - - test_state - .code - .push(Gene::Block(Box::new(vec![Gene::GeneInt(1)]))); - test_state.code.push(Gene::Block(Box::new(vec![ - Gene::GeneFloat(dec!(3.8)), - Gene::GeneBoolean(true), - ]))); - code_combine(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(3.8)), - Gene::GeneBoolean(true), - ]))], - test_state.code - ); - test_state.code.clear(); - - test_state - .code - .push(Gene::Block(Box::new(vec![Gene::GeneInt(1)]))); - test_state.code.push(Gene::GeneFloat(dec!(4.0))); - code_combine(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(4.0)), - ]))], - test_state.code - ); - test_state.code.clear(); - - test_state.code.push(Gene::GeneFloat(dec!(4.0))); - test_state - .code - .push(Gene::Block(Box::new(vec![Gene::GeneInt(1)]))); - code_combine(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(4.0)), - ]))], - test_state.code - ); - test_state.code.clear(); - - test_state.code.push(Gene::GeneFloat(dec!(4.0))); - test_state.code.push(Gene::GeneChar('z')); - code_combine(&mut test_state); - assert_eq!( - vec![Gene::Block(Box::new(vec![ - Gene::GeneChar('z'), - Gene::GeneFloat(dec!(4.0)), - ]))], - test_state.code - ); - } -} diff --git a/src/instructions/common.rs b/src/instructions/common.rs deleted file mode 100644 index 8e04a3b..0000000 --- a/src/instructions/common.rs +++ /dev/null @@ -1,29 +0,0 @@ -use crate::push::state::{Gene, PushState}; - -/// Acts as a NoOp, does nothing with the vals list. -fn _noop(_: Vec) -> Option { - None -} -make_instruction_clone!(code, code, _noop, Gene, 0); -make_instruction_clone!(exec, exec, _noop, Gene, 0); - -#[cfg(test)] -mod tests { - use super::*; - use crate::push::state::EMPTY_STATE; - - #[test] - fn noop_test() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![1, 2]; - let test_state_copy = test_state.clone(); - code_noop(&mut test_state); - assert_eq!(test_state, test_state_copy); - - test_state.int = vec![1, 2]; - let test_state_copy = test_state.clone(); - exec_noop(&mut test_state); - assert_eq!(test_state, test_state_copy); - } -} diff --git a/src/instructions/logical.rs b/src/instructions/logical.rs deleted file mode 100644 index 62f291f..0000000 --- a/src/instructions/logical.rs +++ /dev/null @@ -1,198 +0,0 @@ -//! # Logical Instructions -//! -//! This file holds instructions for the boolean stack. - -use super::utils::{CastingTrait, LogicalTrait}; -use crate::push::state::PushState; -use rust_decimal::Decimal; - -/// Runs logical and on two values -fn _and(vals: Vec) -> Option -where - T: Copy + LogicalTrait, -{ - Some(vals[0].logical_and(vals[1])) -} -make_instruction!(boolean, boolean, _and, bool, 2); - -/// Runs logical or on two values -fn _or(vals: Vec) -> Option -where - T: Copy + LogicalTrait, -{ - Some(vals[0].logical_or(vals[1])) -} -make_instruction!(boolean, boolean, _or, bool, 2); - -/// Runs logical not on two values -fn _not(vals: Vec) -> Option -where - T: Copy + LogicalTrait, -{ - Some(vals[0].logical_not()) -} -make_instruction!(boolean, boolean, _not, bool, 1); - -/// Runs logical xor on two values -fn _xor(vals: Vec) -> Option -where - T: Copy + LogicalTrait, -{ - Some(vals[0].logical_xor(vals[1])) -} -make_instruction!(boolean, boolean, _xor, bool, 2); - -/// Inverts the first value and runs logical and on two values -fn _invert_first_then_and(vals: Vec) -> Option -where - T: Copy + LogicalTrait, -{ - Some(vals[0].logical_not().logical_and(vals[1])) -} -make_instruction!(boolean, boolean, _invert_first_then_and, bool, 2); - -/// Inverts the second value and runs logical and on two values -fn _invert_second_then_and(vals: Vec) -> Option -where - T: Copy + LogicalTrait, -{ - Some(vals[0].logical_and(vals[1].logical_not())) -} -make_instruction!(boolean, boolean, _invert_second_then_and, bool, 2); - -fn _from_int(vals: Vec) -> Option -where - T: Copy + CastingTrait, -{ - T::from_int(vals[0]) -} -make_instruction_out!(int, boolean, _from_int, i128, 1); - -fn _from_float(vals: Vec) -> Option -where - T: Copy + CastingTrait, -{ - T::from_float(vals[0]) -} -make_instruction_out!(float, boolean, _from_float, Decimal, 1); - -pub fn boolean_instructions() -> Vec { - vec![ - boolean_and, - boolean_or, - boolean_not, - boolean_xor, - boolean_invert_first_then_and, - boolean_invert_second_then_and, - boolean_from_int, - boolean_from_float, - ] -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::push::state::EMPTY_STATE; - use rust_decimal::dec; - - #[test] - fn and_test() { - let mut test_state = EMPTY_STATE; - - test_state.boolean = vec![true, false, true]; - boolean_and(&mut test_state); - assert_eq!(vec![true, false], test_state.boolean); - - test_state.boolean = vec![true, true]; - boolean_and(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - } - - #[test] - fn or_test() { - let mut test_state = EMPTY_STATE; - - test_state.boolean = vec![true, false, true]; - boolean_or(&mut test_state); - assert_eq!(vec![true, true], test_state.boolean); - - test_state.boolean = vec![false, false]; - boolean_or(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - } - - #[test] - fn not_test() { - let mut test_state = EMPTY_STATE; - - test_state.boolean = vec![true, false, true]; - boolean_not(&mut test_state); - assert_eq!(vec![true, false, false], test_state.boolean); - - test_state.boolean = vec![false, false]; - boolean_not(&mut test_state); - assert_eq!(vec![false, true], test_state.boolean); - } - - #[test] - fn xor_test() { - let mut test_state = EMPTY_STATE; - - test_state.boolean = vec![true, false, true]; - boolean_xor(&mut test_state); - assert_eq!(vec![true, true], test_state.boolean); - - test_state.boolean = vec![false, false]; - boolean_xor(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.boolean = vec![true, true]; - boolean_xor(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - } - - #[test] - fn invert_test() { - let mut test_state = EMPTY_STATE; - - test_state.boolean = vec![true, false]; - boolean_invert_first_then_and(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - - test_state.boolean = vec![false, false]; - boolean_invert_first_then_and(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.boolean = vec![true, false]; - boolean_invert_second_then_and(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.boolean = vec![false, true]; - boolean_invert_second_then_and(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - } - - #[test] - fn cast_test() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![1]; - boolean_from_int(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - test_state.boolean.clear(); - - test_state.int = vec![0]; - boolean_from_int(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - test_state.boolean.clear(); - - test_state.float = vec![dec!(2.0)]; - boolean_from_float(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - test_state.boolean.clear(); - - test_state.float = vec![dec!(0.0)]; - boolean_from_float(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - } -} diff --git a/src/instructions/mod.rs b/src/instructions/mod.rs deleted file mode 100644 index 3405beb..0000000 --- a/src/instructions/mod.rs +++ /dev/null @@ -1,135 +0,0 @@ -#[macro_use] -pub mod macros { - /// A macro that makes a push instruction given: the name of the input stack to use, - /// the name of the output stack, an internal function to call, the type of a function, - /// and the arity of the internal function call. - /// - /// The `in_stack` argument refers to which push stack should this operate on. - /// The `out_stack` argument refers to which push stack should the result be pushed to. - /// The `fn_name` argement refers to the name of the function that is to operate - /// on the values popped from `in_stack`. - /// The `fn_type` argument refers to the type of `in_stack`. For example, the - /// int stack is type: *Vec*. `fn_type` is *i128* in this case. - /// The `fn_arity` argument refers to how many popped stack items are needed to - /// execute the instruction. If the amount of items in the stack is less than - /// this value, the instruction does nothing. - /// - /// What causes an instruction to NoOp: - /// 1) There aren't enough values on a stack to execute an instruction. - /// 2) The internal operation the instruction executes is unable to be ran without - /// erroring such as division by 0. - #[macro_export] - macro_rules! make_instruction { - ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => { - paste::item! { - /// Runs the $fn_name function on the top $fn_arity items from - /// the $in_stack and places the calculated value on the $out_stack. - pub fn [< $in_stack $fn_name >] (state: &mut PushState) { - let in_stack_len = state.$in_stack.len(); - if in_stack_len < $fn_arity { - return; - } - let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); - for n in 1..=$fn_arity { - inputs.push(state.$in_stack[in_stack_len - n]); - } - if let Some(result) = $fn_name(inputs) { - for _ in 0..$fn_arity { - state.$in_stack.pop(); - } - state.$out_stack.push(result); - } - } - } - }; - } - - /// The same as make_instruction above but prepends the output - /// stack to the function name rather than the input stack. - #[macro_export] - macro_rules! make_instruction_out { - ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => { - paste::item! { - /// Runs the $fn_name function on the top $fn_arity items from - /// the $in_stack and places the calculated value on the $out_stack. - pub fn [< $out_stack $fn_name >] (state: &mut PushState) { - let in_stack_len = state.$in_stack.len(); - if in_stack_len < $fn_arity { - return; - } - let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); - for n in 1..=$fn_arity { - inputs.push(state.$in_stack[in_stack_len - n]); - } - if let Some(result) = $fn_name(inputs) { - for _ in 0..$fn_arity { - state.$in_stack.pop(); - } - state.$out_stack.push(result); - } - } - } - }; - } - - /// The same as make_instruction but uses clone() to fill the arguments - /// to each function rather than a reference. Is slower, but will be okay - /// for the time being. - #[macro_export] - macro_rules! make_instruction_clone { - ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => { - paste::item! { - /// Runs the $fn_name function on the top $fn_arity items from - /// the $in_stack and places the calculated value on the $out_stack. - pub fn [< $in_stack $fn_name >] (state: &mut PushState) { - let in_stack_len = state.$in_stack.len(); - if in_stack_len < $fn_arity { - return; - } - let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); - for n in 1..=$fn_arity { - inputs.push(state.$in_stack[in_stack_len - n].clone()); - } - if let Some(result) = $fn_name(inputs) { - for _ in 0..$fn_arity { - state.$in_stack.pop(); - } - state.$out_stack.push(result); - } - } - } - }; - } - - #[macro_export] - macro_rules! make_instruction_mult { - ($in_stack:ident, $out_stack:ident, $fn_name:ident, $fn_type:ty, $fn_arity:stmt) => { - paste::item! { - /// Runs the $fn_name function on the top $fn_arity items from - /// the $in_stack and places the calculated value on the $out_stack. - pub fn [< $in_stack $fn_name >] (state: &mut PushState) { - let in_stack_len = state.$in_stack.len(); - if in_stack_len < $fn_arity { - return; - } - let mut inputs: Vec<$fn_type> = Vec::with_capacity($fn_arity); - for n in 1..=$fn_arity { - inputs.push(state.$in_stack[in_stack_len - n]); - } - if let Some(result) = $fn_name(inputs) { - for _ in 0..$fn_arity { - state.$in_stack.pop(); - } - state.$out_stack.extend(result.iter()); - } - } - } - }; - } -} - -pub mod code; -pub mod common; -pub mod logical; -pub mod numeric; -pub mod utils; diff --git a/src/instructions/numeric.rs b/src/instructions/numeric.rs deleted file mode 100644 index d5a1273..0000000 --- a/src/instructions/numeric.rs +++ /dev/null @@ -1,936 +0,0 @@ -//! # Numeric Instructions -//! -//! This file contains numeric instructions for int and float. - -// There has to be a better way to declare these functions. -// Just don't know enough Rust yet ig. - -use crate::push::state::PushState; -use rust_decimal::Decimal; -use rust_decimal::prelude::{FromPrimitive, ToPrimitive}; -use std::cmp::{max, min}; -use std::ops::{Add, Div, Mul, Sub}; - -use super::utils::{CastingTrait, NumericTrait}; - -/// Adds two addable values together. -fn _add(vals: Vec) -> Option -where - T: Add + Copy, -{ - Some(vals[1] + vals[0]) -} -make_instruction!(int, int, _add, i128, 2); -make_instruction!(float, float, _add, Decimal, 2); - -/// Subtracts two subtractable values from each other. -fn _sub(vals: Vec) -> Option -where - T: Sub + Copy, -{ - Some(vals[1] - vals[0]) -} -make_instruction!(int, int, _sub, i128, 2); -make_instruction!(float, float, _sub, Decimal, 2); - -/// Multiplies two multipliable values together. -fn _mult(vals: Vec) -> Option -where - T: Mul + Copy, -{ - Some(vals[1] * vals[0]) -} -make_instruction!(int, int, _mult, i128, 2); -make_instruction!(float, float, _mult, Decimal, 2); - -/// Divides two values from each other. -fn _div(vals: Vec) -> Option -where - T: Div + Copy + NumericTrait, -{ - vals[1].checked_div(vals[0]) -} -make_instruction!(int, int, _div, i128, 2); -make_instruction!(float, float, _div, Decimal, 2); - -/// Takes the remainder of two values -fn _rem(vals: Vec) -> Option -where - T: Div + Copy + NumericTrait, -{ - vals[1].checked_mod(vals[0]) -} -make_instruction!(int, int, _rem, i128, 2); -make_instruction!(float, float, _rem, Decimal, 2); - -/// Takes the max of two values -fn _max(vals: Vec) -> Option -where - T: Ord + Copy, -{ - Some(max(vals[1], vals[0])) -} -make_instruction!(int, int, _max, i128, 2); -make_instruction!(float, float, _max, Decimal, 2); - -/// Takes the min of two values -fn _min(vals: Vec) -> Option -where - T: Ord + Copy, -{ - Some(min(vals[1], vals[0])) -} -make_instruction!(int, int, _min, i128, 2); -make_instruction!(float, float, _min, Decimal, 2); - -/// Increments a single value by 1 -fn _inc(vals: Vec) -> Option -where - T: NumericTrait + Copy, -{ - Some(vals[0].increment()) -} -make_instruction!(int, int, _inc, i128, 1); -make_instruction!(float, float, _inc, Decimal, 1); - -/// Decrements a single value by 1 -fn _dec(vals: Vec) -> Option -where - T: NumericTrait + Copy, -{ - Some(vals[0].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 -fn _lt(vals: Vec) -> Option -where - T: Ord + Copy, -{ - Some(vals[1] < vals[0]) -} -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 -fn _gt(vals: Vec) -> Option -where - T: Ord + Copy, -{ - Some(vals[1] > vals[0]) -} -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 -fn _lte(vals: Vec) -> Option -where - T: Ord + Copy, -{ - Some(vals[1] <= vals[0]) -} -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 -fn _gte(vals: Vec) -> Option -where - T: Ord + Copy, -{ - Some(vals[1] >= vals[0]) -} -make_instruction!(int, boolean, _gte, i128, 2); -make_instruction!(float, boolean, _gte, Decimal, 2); - -/// Runs sin on a single item. -fn _sin(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].safe_sin() -} -make_instruction!(int, int, _sin, i128, 1); -make_instruction!(float, float, _sin, Decimal, 1); - -/// Runs arcsin on a single item. -fn _arcsin(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].safe_sin()?.inverse() -} -make_instruction!(int, int, _arcsin, i128, 1); -make_instruction!(float, float, _arcsin, Decimal, 1); - -/// Runs cos on a single item. -fn _cos(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].safe_cos() -} -make_instruction!(int, int, _cos, i128, 1); -make_instruction!(float, float, _cos, Decimal, 1); - -/// Runs arcsin on a single item. -fn _arccos(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].safe_cos()?.inverse() -} -make_instruction!(int, int, _arccos, i128, 1); -make_instruction!(float, float, _arccos, Decimal, 1); - -/// Runs tan on a single item. -fn _tan(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].safe_tan() -} -make_instruction!(int, int, _tan, i128, 1); -make_instruction!(float, float, _tan, Decimal, 1); - -/// Runs arctan on a single item. -fn _arctan(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].safe_tan()?.inverse() -} -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. -fn _from_int(vals: Vec) -> Option -where - T: Copy + CastingTrait, -{ - T::from_int(vals[0]) -} -make_instruction_out!(int, float, _from_int, i128, 1); - -/// Converts a single value from a float to an arbitrary type. -fn _from_float(vals: Vec) -> Option -where - T: Copy + CastingTrait, -{ - T::from_float(vals[0]) -} -make_instruction_out!(float, int, _from_float, Decimal, 1); - -/// Converts a bool to a to a new type. -fn _from_boolean(vals: Vec) -> Option -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 -/// the absolute value of the number. -fn _log(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].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. -fn _exp(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].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. -fn _sqrt(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].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, -/// does nothing (returns None). Truncates an int to 0. -fn _inv(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - vals[0].inverse() -} -make_instruction!(int, int, _inv, i128, 1); -make_instruction!(float, float, _inv, Decimal, 1); - -/// Takes the absolute value of the top number -fn _abs(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - Some(vals[0].absolute()) -} -make_instruction!(int, int, _abs, i128, 1); -make_instruction!(float, float, _abs, Decimal, 1); - -/// Reverses the sign of the top number -fn _sign_reverse(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - Some(vals[0].sign_reverse()) -} -make_instruction!(int, int, _sign_reverse, i128, 1); -make_instruction!(float, float, _sign_reverse, Decimal, 1); - -/// Squares the top number -fn _square(vals: Vec) -> Option -where - T: Copy + NumericTrait, -{ - Some(vals[0].square()) -} -make_instruction!(int, int, _square, i128, 1); -make_instruction!(float, float, _square, Decimal, 1); - -/// A list of all of the defined int functions in this file. -/// Must manually register functions in this list if added. -pub fn int_instructions() -> Vec { - vec![ - 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, - ] -} - -/// All of the float instructions declared in this file. -pub fn float_instructions() -> Vec { - vec![ - 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, - ] -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::push::state::EMPTY_STATE; - use rust_decimal::dec; - - /// Tests the _add function. - #[test] - fn add_test() { - let vals: Vec = vec![1, 2]; - assert_eq!(Some(3), _add(vals)); - - let vals: Vec = vec![dec!(1.1), dec!(2.2)]; - assert_eq!(Some(dec!(3.3)), _add(vals)); - } - - /// Tests the _sub function. - #[test] - fn sub_test() { - let vals: Vec = vec![1, 2]; - assert_eq!(Some(1), _sub(vals)); - - let vals: Vec = vec![dec!(1.1), dec!(2.2)]; - assert_eq!(Some(dec!(1.1)), _sub(vals)); - } - - /// Tests the _mult function. - #[test] - fn mult_test() { - let vals: Vec = vec![4, 5]; - assert_eq!(Some(20), _mult(vals)); - - let vals: Vec = vec![dec!(1.1), dec!(2.2)]; - assert_eq!(Some(dec!(2.42)), _mult(vals)); - } - - /// Tests the _div function - #[test] - fn div_test() { - let vals: Vec = vec![4, 20]; - assert_eq!(Some(5), _div(vals)); - - let vals: Vec = vec![3, 20]; - assert_eq!(Some(6), _div(vals)); - - let vals: Vec = vec![dec!(1.6), dec!(2.2)]; - assert_eq!(Some(dec!(1.375)), _div(vals)); - - let vals: Vec = vec![0, 1]; - assert_eq!(None, _div(vals)); - } - - /// Tests the _rem function - #[test] - fn rem_test() { - let vals: Vec = vec![3, 20]; - assert_eq!(Some(2), _rem(vals)); - - let vals: Vec = vec![20, 20]; - assert_eq!(Some(0), _rem(vals)); - - let vals: Vec = vec![0, 9]; - assert_eq!(None, _rem(vals)); - } - - /// Tests the _max function - #[test] - fn max_test() { - let vals: Vec = vec![1, 2]; - assert_eq!(Some(2), _max(vals)); - - let vals: Vec = vec![3, 0]; - assert_eq!(Some(3), _max(vals)); - - let vals: Vec = vec![dec!(2.2), dec!(1.1)]; - assert_eq!(Some(dec!(2.2)), _max(vals)); - - let vals: Vec = vec![dec!(3.3), dec!(-1.1)]; - assert_eq!(Some(dec!(3.3)), _max(vals)); - } - - /// Tests the _min function - #[test] - fn min_test() { - let vals: Vec = vec![1, 2]; - assert_eq!(Some(1), _min(vals)); - - let vals: Vec = vec![3, 0]; - assert_eq!(Some(0), _min(vals)); - - let vals: Vec = vec![dec!(2.2), dec!(1.1)]; - assert_eq!(Some(dec!(1.1)), _min(vals)); - - let vals: Vec = vec![dec!(3.3), dec!(-1.1)]; - assert_eq!(Some(dec!(-1.1)), _min(vals)); - } - - /// Tests the _inc and _dec functions - #[test] - fn inc_dec_test() { - let vals: Vec = vec![2]; - assert_eq!(Some(3), _inc(vals)); - - let vals: Vec = vec![10]; - assert_eq!(Some(9), _dec(vals)); - - let vals: Vec = vec![dec!(2.2)]; - assert_eq!(Some(dec!(3.2)), _inc(vals)); - - let vals: Vec = vec![dec!(5.6)]; - assert_eq!(Some(dec!(4.6)), _dec(vals)); - } - - /// Tests the _lt, _gt, _lte, and _gte functions - #[test] - fn lt_gt_lte_gte_test() { - let vals: Vec = vec![3, 2]; - assert_eq!(Some(true), _lt(vals)); - - let vals: Vec = vec![1, 4]; - assert_eq!(Some(false), _lt(vals)); - - let vals: Vec = vec![3, 3]; - assert_eq!(Some(false), _lt(vals)); - - let vals: Vec = vec![2, 3]; - assert_eq!(Some(true), _gt(vals)); - - let vals: Vec = vec![4, 1]; - assert_eq!(Some(false), _gt(vals)); - - let vals: Vec = vec![3, 3]; - assert_eq!(Some(false), _gt(vals)); - - let vals: Vec = vec![3, 2]; - assert_eq!(Some(true), _lte(vals)); - - let vals: Vec = vec![1, 4]; - assert_eq!(Some(false), _lte(vals)); - - let vals: Vec = vec![3, 3]; - assert_eq!(Some(true), _lte(vals)); - - let vals: Vec = vec![2, 3]; - assert_eq!(Some(true), _gte(vals)); - - let vals: Vec = vec![4, 1]; - assert_eq!(Some(false), _gte(vals)); - - let vals: Vec = vec![3, 3]; - assert_eq!(Some(true), _gte(vals)); - } - - /// Tests the various trig functions. - #[test] - fn trig_tests() { - let vals = vec![Decimal::PI]; - assert_eq!(Some(dec!(0.0)), _sin(vals)); - - let vals = vec![Decimal::QUARTER_PI]; - assert_eq!(Some(dec!(1.4142135623869512272301701717)), _arcsin(vals)); - - let vals = vec![Decimal::PI]; - assert_eq!(Some(dec!(-1.0)), _cos(vals)); - - let vals = vec![Decimal::QUARTER_PI]; - assert_eq!(Some(dec!(1.4142135626023406165042434783)), _arccos(vals)); - - 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. - #[test] - fn state_add() { - let mut test_state = EMPTY_STATE; - test_state.int = vec![1, 2]; - test_state.float = vec![dec!(1.1), dec!(2.2)]; - - int_add(&mut test_state); - assert_eq!(vec![3], test_state.int); - - float_add(&mut test_state); - assert_eq!(vec![dec!(3.3)], test_state.float); - } - - /// Tests the various subtraction functions. - #[test] - fn state_sub() { - let mut test_state = EMPTY_STATE; - test_state.int = vec![1, 2]; - test_state.float = vec![dec!(1.1), dec!(2.2)]; - - int_sub(&mut test_state); - assert_eq!(vec![-1], test_state.int); - - float_sub(&mut test_state); - assert_eq!(vec![dec!(-1.1)], test_state.float); - } - - /// Tests the various multiplication functions. - #[test] - fn state_mult() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![0]; - int_mult(&mut test_state); - assert_eq!(vec![0], test_state.int); - - test_state.int = vec![10, 3, 2]; - test_state.float = vec![dec!(1.1), dec!(2.2)]; - - int_mult(&mut test_state); - assert_eq!(vec![10, 6], test_state.int); - - float_mult(&mut test_state); - assert_eq!(vec![dec!(2.42)], test_state.float); - } - - /// Tests the division functions in the state - #[test] - fn state_div() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![0]; - int_div(&mut test_state); - assert_eq!(vec![0], test_state.int); - - test_state.int = vec![2, 0]; - int_div(&mut test_state); - assert_eq!(vec![2, 0], test_state.int); - - test_state.int = vec![6, 3]; - - int_div(&mut test_state); - assert_eq!(vec![2], test_state.int); - - test_state.float = vec![dec!(2.2), dec!(1.6)]; - float_div(&mut test_state); - assert_eq!(vec![dec!(1.375)], test_state.float); - } - - /// Tests the remainder functions in the state. - #[test] - fn state_rem() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![0]; - int_rem(&mut test_state); - assert_eq!(vec![0], test_state.int); - - test_state.int = vec![2, 0]; - int_rem(&mut test_state); - assert_eq!(vec![2, 0], test_state.int); - - test_state.int = vec![60, 80, 20, 3]; - int_rem(&mut test_state); - assert_eq!(vec![60, 80, 2], test_state.int); - - test_state.float = vec![dec!(2.7), dec!(1.2)]; - float_rem(&mut test_state); - assert_eq!(vec![dec!(0.3)], test_state.float); - } - - /// Tests the min and max functions in the state - #[test] - fn state_min_max() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![0]; - int_max(&mut test_state); - assert_eq!(vec![0], test_state.int); - - test_state.int = vec![0]; - int_min(&mut test_state); - assert_eq!(vec![0], test_state.int); - - test_state.int = vec![1, 2, 3]; - int_max(&mut test_state); - assert_eq!(vec![1, 3], test_state.int); - - test_state.int = vec![1, 2, 3]; - int_min(&mut test_state); - assert_eq!(vec![1, 2], test_state.int); - - test_state.float = vec![dec!(1.2), dec!(4.6)]; - float_max(&mut test_state); - assert_eq!(vec![dec!(4.6)], test_state.float); - - test_state.float = vec![dec!(0.0), dec!(1.2), dec!(4.6)]; - float_min(&mut test_state); - assert_eq!(vec![dec!(0.0), dec!(1.2)], test_state.float); - } - - /// Tests the inc and dec functions in the state - #[test] - fn state_inc_dec() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![]; - int_inc(&mut test_state); - let empty_vec: Vec = vec![]; - assert_eq!(empty_vec, test_state.int); - - drop(empty_vec); - - test_state.int = vec![-2, 1]; - int_inc(&mut test_state); - assert_eq!(vec![-2, 2], test_state.int); - - test_state.int = vec![-2, 1]; - int_dec(&mut test_state); - assert_eq!(vec![-2, 0], test_state.int); - - test_state.float = vec![dec!(1.1)]; - float_inc(&mut test_state); - assert_eq!(vec![dec!(2.1)], test_state.float); - - test_state.float = vec![dec!(1.1)]; - float_dec(&mut test_state); - assert_eq!(vec![dec!(0.1)], test_state.float); - } - - /// Tests the lt, gt, lte, gte functions in the state - #[test] - fn state_lt_gt_lte_gte() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![2, 3]; - int_lt(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - - test_state.int = vec![4, 1]; - test_state.boolean = vec![]; - int_lt(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.int = vec![3, 3]; - test_state.boolean = vec![]; - int_lt(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.int = vec![3, 2]; - test_state.boolean = vec![]; - int_gt(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - - test_state.int = vec![1, 4]; - test_state.boolean = vec![]; - int_gt(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.int = vec![3, 3]; - test_state.boolean = vec![]; - int_gt(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.int = vec![2, 3]; - test_state.boolean = vec![]; - int_lte(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - - test_state.int = vec![4, 1]; - test_state.boolean = vec![]; - int_lte(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.int = vec![3, 3]; - test_state.boolean = vec![]; - int_lte(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - - test_state.int = vec![3, 2]; - test_state.boolean = vec![]; - int_gte(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - - test_state.int = vec![1, 4]; - test_state.boolean = vec![]; - int_gte(&mut test_state); - assert_eq!(vec![false], test_state.boolean); - - test_state.int = vec![3, 3]; - test_state.boolean = vec![]; - int_gte(&mut test_state); - assert_eq!(vec![true], test_state.boolean); - } - - /// Tests the various trig functions when they should revert. - #[test] - fn state_trig() { - let mut test_state = EMPTY_STATE; - - test_state.float = vec![Decimal::HALF_PI]; - float_tan(&mut test_state); - assert_eq!(vec![Decimal::HALF_PI], test_state.float); - - test_state.float = vec![Decimal::HALF_PI]; - float_arccos(&mut test_state); - assert_eq!(vec![Decimal::HALF_PI], test_state.float); - - test_state.float = vec![dec!(3.4), Decimal::PI]; - float_arcsin(&mut test_state); - assert_eq!(vec![dec!(3.4), Decimal::PI], test_state.float); - } - - /// Tests the int and float casting functions - #[test] - fn state_cast() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![0, 1]; - float_from_int(&mut test_state); - assert_eq!(vec![dec!(1.0)], test_state.float); - test_state.int.clear(); - - test_state.float = vec![dec!(2.1)]; - int_from_float(&mut test_state); - assert_eq!(vec![2], test_state.int); - } - - /// Tests the log function - #[test] - fn state_log() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![1]; - int_log(&mut test_state); - assert_eq!(vec![0], test_state.int); - test_state.int.clear(); - - test_state.float = vec![dec!(2)]; - float_log(&mut test_state); - assert_eq!(vec![dec!(0.3010299956639811952137388949)], test_state.float); - test_state.float.clear(); - - test_state.int = vec![6, 7, 0]; - int_log(&mut test_state); - assert_eq!(vec![6, 7, 0], test_state.int); - - test_state.float = vec![dec!(-4.5)]; - float_log(&mut test_state); - assert_eq!(vec![dec!(0.6532125137753436793763169119)], test_state.float); - } - - /// Tests the exp function - #[test] - fn state_exp() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![0]; - int_exp(&mut test_state); - assert_eq!(vec![1], test_state.int); - - test_state.int = vec![0, 2]; - int_exp(&mut test_state); - assert_eq!(vec![0, 7], test_state.int); - - test_state.int.clear(); - test_state.float = vec![dec!(1.2)]; - float_exp(&mut test_state); - assert_eq!(vec![dec!(3.3201169022444051948051948052)], test_state.float); - } - - /// Tests the sqrt function - #[test] - fn state_sqrt() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![4]; - int_sqrt(&mut test_state); - assert_eq!(vec![2], test_state.int); - - test_state.int = vec![5]; - int_sqrt(&mut test_state); - assert_eq!(vec![2], test_state.int); - - test_state.float = vec![dec!(4.84)]; - float_sqrt(&mut test_state); - assert_eq!(vec![dec!(2.2)], test_state.float); - - test_state.int = vec![-1]; - int_sqrt(&mut test_state); - assert_eq!(vec![1], test_state.int); - - test_state.float = vec![dec!(-1.0)]; - float_sqrt(&mut test_state); - assert_eq!(vec![dec!(1.0)], test_state.float); - } - - /// Tests the inv function - #[test] - fn state_inv() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![-1, 10]; - int_inv(&mut test_state); - assert_eq!(vec![-1, 0], test_state.int); - - test_state.float = vec![dec!(-10)]; - float_inv(&mut test_state); - assert_eq!(vec![dec!(-0.1)], test_state.float); - - test_state.int = vec![0]; - int_inv(&mut test_state); - assert_eq!(vec![0], test_state.int); - } - - /// Tests the abs function - #[test] - fn state_abs() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![-1]; - int_abs(&mut test_state); - assert_eq!(vec![1], test_state.int); - - test_state.float = vec![dec!(-2.7)]; - float_abs(&mut test_state); - assert_eq!(vec![dec!(2.7)], test_state.float); - } - - /// Tests the sign reverse function - #[test] - fn state_sign_reverse() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![-2]; - int_sign_reverse(&mut test_state); - assert_eq!(vec![2], test_state.int); - - test_state.int = vec![3]; - int_sign_reverse(&mut test_state); - assert_eq!(vec![-3], test_state.int); - - test_state.float = vec![dec!(3.0), dec!(-2.0)]; - float_sign_reverse(&mut test_state); - assert_eq!(vec![dec!(3.0), dec!(2.0)], test_state.float); - - test_state.float = vec![dec!(3.0)]; - float_sign_reverse(&mut test_state); - assert_eq!(vec![dec!(-3.0)], test_state.float); - } - - /// Tests the square function - #[test] - fn state_square() { - let mut test_state = EMPTY_STATE; - - test_state.int = vec![2, 3]; - int_square(&mut test_state); - assert_eq!(vec![2, 9], test_state.int); - - test_state.float = vec![dec!(-4.0)]; - float_square(&mut test_state); - assert_eq!(vec![dec!(16.0)], test_state.float); - } -} diff --git a/src/instructions/utils.rs b/src/instructions/utils.rs deleted file mode 100644 index 2ed90e5..0000000 --- a/src/instructions/utils.rs +++ /dev/null @@ -1,191 +0,0 @@ -use rust_decimal::Decimal; -use rust_decimal::prelude::*; -use std::ops::Div; - -/// This trait houses various methods for making instructions -/// more generic instead of declaring a separate function for each -/// stack. In a way I'm doing that here, but in a more Rusty way. -/// -/// Trig functions named safe rather than checked to not overlap -/// with Decimal library's checked function names. -pub trait NumericTrait: Sized + Div { - fn checked_div(self, v: Self) -> Option; - fn checked_mod(self, v: Self) -> Option; - fn increment(self) -> Self; - fn decrement(self) -> Self; - fn safe_sin(self) -> Option; - fn safe_cos(self) -> Option; - fn safe_tan(self) -> Option; - fn inverse(self) -> Option; - fn safe_exp(self) -> Option; - fn absolute(self) -> Self; - fn safe_log10(self) -> Option; - fn safe_sqrt(self) -> Option; - fn sign_reverse(self) -> Self; - fn square(self) -> Self; -} - -impl NumericTrait for Decimal { - fn checked_div(self, v: Self) -> Option { - if v == dec!(0.0) { None } else { Some(self / v) } - } - fn checked_mod(self, v: Self) -> Option { - if v == dec!(0.0) { None } else { Some(self % v) } - } - fn increment(self) -> Self { - self + dec!(1.0) - } - fn decrement(self) -> Self { - self - dec!(1.0) - } - fn safe_sin(self) -> Option { - self.checked_sin() - } - fn safe_cos(self) -> Option { - self.checked_cos() - } - fn safe_tan(self) -> Option { - self.checked_tan() - } - fn inverse(self) -> Option { - dec!(1.0).checked_div(self) - } - fn safe_exp(self) -> Option { - self.checked_exp() - } - fn absolute(self) -> Self { - self.abs() - } - fn safe_log10(self) -> Option { - self.absolute().checked_log10() - } - fn safe_sqrt(self) -> Option { - self.absolute().sqrt() - } - fn sign_reverse(self) -> Self { - self * dec!(-1) - } - fn square(self) -> Self { - self * self - } -} - -impl NumericTrait for i128 { - fn checked_div(self, v: Self) -> Option { - if v == 0 { None } else { Some(self / v) } - } - fn checked_mod(self, v: Self) -> Option { - if v == 0 { None } else { Some(self % v) } - } - fn increment(self) -> Self { - self + 1 - } - fn decrement(self) -> Self { - self - 1 - } - /// Casts the i128 to a Decimal and takes the checked_sin - /// of the value. Casts the calculated value back to an i128. - fn safe_sin(self) -> Option { - Decimal::from_i128(self)?.checked_sin()?.to_i128() - } - fn safe_cos(self) -> Option { - Decimal::from_i128(self)?.checked_cos()?.to_i128() - } - fn safe_tan(self) -> Option { - Decimal::from_i128(self)?.checked_tan()?.to_i128() - } - fn inverse(self) -> Option { - if self == 0 { None } else { Some(1 / self) } - } - fn safe_exp(self) -> Option { - Decimal::from_i128(self)?.checked_exp()?.to_i128() - } - fn absolute(self) -> Self { - self.abs() - } - fn safe_log10(self) -> Option { - Decimal::from_i128(self)? - .absolute() - .checked_log10()? - .to_i128() - } - fn safe_sqrt(self) -> Option { - Decimal::from_i128(self)?.absolute().sqrt()?.to_i128() - } - fn sign_reverse(self) -> Self { - -1 * self - } - fn square(self) -> Self { - self * self - } -} - -/// A trait for types to implement logical functions that work -/// for push types. -pub trait LogicalTrait { - fn logical_and(self, v: Self) -> Self; - fn logical_or(self, v: Self) -> Self; - fn logical_not(self) -> Self; - fn logical_xor(self, v: Self) -> Self; -} - -impl LogicalTrait for bool { - fn logical_and(self, v: Self) -> Self { - self && v - } - fn logical_or(self, v: Self) -> Self { - self || v - } - fn logical_not(self) -> Self { - !self - } - fn logical_xor(self, v: Self) -> Self { - match (self, v) { - (true, true) | (false, false) => false, - _ => true, - } - } -} - -/// A trait for uniform conversions between types. -pub trait CastingTrait: Sized { - fn from_bool(v: bool) -> Option; - fn from_int(v: i128) -> Option; - fn from_float(v: Decimal) -> Option; -} - -impl CastingTrait for i128 { - fn from_bool(v: bool) -> Option { - Some(if v { 1 } else { 0 }) - } - fn from_int(v: i128) -> Option { - Some(v) - } - fn from_float(v: Decimal) -> Option { - v.to_i128() - } -} - -impl CastingTrait for Decimal { - fn from_bool(v: bool) -> Option { - Some(if v { dec!(1.0) } else { dec!(0.0) }) - } - fn from_int(v: i128) -> Option { - Decimal::from_i128(v) - } - fn from_float(v: Decimal) -> Option { - Some(v) - } -} - -impl CastingTrait for bool { - fn from_bool(v: bool) -> Option { - Some(v) - } - fn from_int(v: i128) -> Option { - Some(if v != 0 { true } else { false }) - } - fn from_float(v: Decimal) -> Option { - Some(if v != dec!(0.0) { true } else { false }) - } -} diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 53994f4..0000000 --- a/src/main.rs +++ /dev/null @@ -1,36 +0,0 @@ -use instructions::utils::NumericTrait; -use rust_decimal::MathematicalOps; -use rust_decimal::prelude::*; - -mod instructions; -mod push; - -fn test_func() {} -fn another_test_func() {} - -fn main() { - // let sixth_pi = Decimal::PI / dec!(6.0); - // let result = dec!(1).sin(); - // let result = Decimal::PI.sin().checked_div(Decimal::PI.cos()); - // let result = dec!(1.0) / Decimal::HALF_PI.sin(); - // let result = sixth_pi.sin(); - // let result = Decimal::HALF_PI.cos(); - // let result = Decimal::PI.sin(); - // let result = Decimal::PI.tan(); - // let result = dec!(1.0) / Decimal::QUARTER_PI.tan(); - // let result = dec!(1.0) / Decimal::QUARTER_PI.cos(); - // let result = dec!(1.2).checked_exp(); - // let result = dec!(2).log10(); - let result = vec![0, 1, 2]; - let r_len = result.len(); - let fin_result = &result[..r_len - 1]; - println!("{fin_result:?}"); - - // println!("{result:?}"); - // println!("{sixth_pi}"); - - // casting a function call to a usize is a way to - // test for function equality. - // let test_func_result = test_func as usize == test_func as usize; - // println!("{test_func_result}"); -} diff --git a/src/push/interpreter.rs b/src/push/interpreter.rs deleted file mode 100644 index 43d4058..0000000 --- a/src/push/interpreter.rs +++ /dev/null @@ -1,150 +0,0 @@ -use crate::push::state::*; - -/// The main function that disperses the exec stack Genes into -/// the respective stacks. Also is where the individual instructions -/// (such as int_add) is ran. -pub fn gene_to_stack(state: &mut PushState, gene: Gene) { - match gene { - Gene::GeneInt(x) => state.int.push(x), - Gene::GeneFloat(x) => state.float.push(x), - Gene::GeneBoolean(x) => state.boolean.push(x), - Gene::GeneString(x) => state.string.push(x), - Gene::GeneChar(x) => state.char.push(x), - Gene::GeneVectorInt(x) => state.vector_int.push(x), - Gene::GeneVectorFloat(x) => state.vector_float.push(x), - Gene::GeneVectorBoolean(x) => state.vector_boolean.push(x), - Gene::GeneVectorString(x) => state.vector_string.push(x), - Gene::GeneVectorChar(x) => state.vector_char.push(x), - Gene::StateFunc(func) => func(state), - Gene::Block(x) => state.exec.extend(x.into_iter()), - Gene::Close => panic!("Close found in the exec stack, this should not happen!"), - Gene::Open(_) => panic!("Open found in the exec stack, this should not happen!"), - Gene::Skip => panic!("Skip found in the exec stack, this should not happen!"), - Gene::CrossoverPadding => { - panic!("CrossoverPadding found in the exec stack, this should not happen!") - } - } -} - -/// Where a push program's exec stack is interpreted to completion. -/// TODO: Decide where to place loading in a push program. -pub fn interpret_program(state: &mut PushState, step_limit: usize, max_stack_size: isize) { - let mut steps: usize = 0; - while state.exec.len() > 0 && steps < step_limit { - if let Some(gene) = state.exec.pop() { - gene_to_stack(state, gene); - steps += 1; - } - } -} - -#[cfg(test)] -mod tests { - use crate::instructions::numeric::int_add; - - use super::*; - use rust_decimal::dec; - - #[test] - fn gene_to_stack_test() { - let mut test_state = EMPTY_STATE; - - gene_to_stack(&mut test_state, Gene::GeneInt(1)); - assert_eq!(vec![1], test_state.int); - test_state.int.clear(); - - gene_to_stack(&mut test_state, Gene::GeneFloat(dec!(1.2))); - gene_to_stack(&mut test_state, Gene::GeneFloat(dec!(2.4))); - assert_eq!(vec![dec!(1.2), dec!(2.4)], test_state.float); - test_state.float.clear(); - - gene_to_stack(&mut test_state, Gene::GeneBoolean(true)); - assert_eq!(vec![true], test_state.boolean); - test_state.boolean.clear(); - - gene_to_stack( - &mut test_state, - Gene::GeneString("test".as_bytes().to_vec()), - ); - assert_eq!(vec!["test".as_bytes().to_vec()], test_state.string); - test_state.string.clear(); - - gene_to_stack(&mut test_state, Gene::GeneChar('a')); - gene_to_stack(&mut test_state, Gene::GeneChar('b')); - gene_to_stack(&mut test_state, Gene::GeneChar('c')); - assert_eq!(vec!['a', 'b', 'c'], test_state.char); - test_state.char.clear(); - - gene_to_stack(&mut test_state, Gene::GeneVectorInt(vec![1, 2, 3])); - gene_to_stack(&mut test_state, Gene::GeneVectorInt(vec![4, 5, 6])); - assert_eq!(vec![vec![1, 2, 3], vec![4, 5, 6]], test_state.vector_int); - test_state.vector_int.clear(); - - gene_to_stack( - &mut test_state, - Gene::GeneVectorFloat(vec![dec!(1.7), dec!(2.4), dec!(3.9)]), - ); - gene_to_stack( - &mut test_state, - Gene::GeneVectorFloat(vec![dec!(4.7), dec!(5.4), dec!(6.9)]), - ); - assert_eq!( - vec![ - vec![dec!(1.7), dec!(2.4), dec!(3.9)], - vec![dec!(4.7), dec!(5.4), dec!(6.9)] - ], - test_state.vector_float - ); - test_state.vector_float.clear(); - - gene_to_stack(&mut test_state, Gene::GeneVectorBoolean(vec![true, false])); - assert_eq!(vec![vec![true, false]], test_state.vector_boolean); - test_state.vector_boolean.clear(); - - gene_to_stack( - &mut test_state, - Gene::GeneVectorString(vec!["test0".as_bytes().to_vec()]), - ); - gene_to_stack( - &mut test_state, - Gene::GeneVectorString(vec![ - "test1".as_bytes().to_vec(), - "test2".as_bytes().to_vec(), - ]), - ); - assert_eq!( - vec![ - vec!["test0".as_bytes().to_vec()], - vec!["test1".as_bytes().to_vec(), "test2".as_bytes().to_vec()] - ], - test_state.vector_string - ); - test_state.vector_string.clear(); - - gene_to_stack(&mut test_state, Gene::GeneVectorChar(vec!['a', 'b'])); - gene_to_stack(&mut test_state, Gene::GeneVectorChar(vec!['b', 'c', 'd'])); - assert_eq!( - vec![vec!['a', 'b'], vec!['b', 'c', 'd']], - test_state.vector_char - ); - test_state.vector_char.clear(); - - let test_block: Gene = Gene::Block(Box::new(vec![ - Gene::GeneInt(1), - Gene::GeneFloat(dec!(2.3)), - Gene::StateFunc(int_add), - ])); - test_state.exec.push(Gene::GeneInt(2)); - gene_to_stack(&mut test_state, test_block); - assert_eq!( - vec![ - Gene::GeneInt(2), - Gene::GeneInt(1), - Gene::GeneFloat(dec!(2.3)), - Gene::StateFunc(int_add) - ], - test_state.exec - ); - // println!("{:?}", test_state.exec); - } -} diff --git a/src/push/mod.rs b/src/push/mod.rs deleted file mode 100644 index 7181eca..0000000 --- a/src/push/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod interpreter; -pub mod state; diff --git a/src/push/state.rs b/src/push/state.rs deleted file mode 100644 index 78b0596..0000000 --- a/src/push/state.rs +++ /dev/null @@ -1,56 +0,0 @@ -use rust_decimal::prelude::*; - -/// The declaration of the state that push operates on. -/// -/// I chose to use `rust_decimal` crate here because -/// there are round off errors with the build in `f64`. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct PushState { - pub int: Vec, - pub float: Vec, - pub string: Vec>, - pub boolean: Vec, - pub char: Vec, - pub vector_int: Vec>, - pub vector_float: Vec>, - pub vector_string: Vec>>, - pub vector_boolean: Vec>, - pub vector_char: Vec>, - pub exec: Vec, - pub code: Vec, -} - -pub const EMPTY_STATE: PushState = PushState { - int: vec![], - float: vec![], - string: vec![], - boolean: vec![], - char: vec![], - vector_int: vec![], - vector_float: vec![], - vector_string: vec![], - vector_boolean: vec![], - vector_char: vec![], - exec: vec![], - code: vec![], -}; - -#[derive(PartialEq, Eq, Debug, Clone)] -pub enum Gene { - GeneInt(i128), - GeneFloat(Decimal), - GeneBoolean(bool), - GeneString(Vec), - GeneChar(char), - GeneVectorInt(Vec), - GeneVectorFloat(Vec), - GeneVectorBoolean(Vec), - GeneVectorString(Vec>), - GeneVectorChar(Vec), - StateFunc(fn(&mut PushState)), - Close, - Open(u8), - Skip, - Block(Box>), - CrossoverPadding, -}