need to redesign, can't just start programming
This commit is contained in:
parent
e0414009ff
commit
528aeb1c9b
@ -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<Gene>) -> Option<bool> {
|
|
||||||
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<Gene>) -> Option<bool> {
|
|
||||||
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<Gene>) -> Option<i128> {
|
|
||||||
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<Gene>) -> Option<Gene> {
|
|
||||||
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<Gene>) -> Option<Gene> {
|
|
||||||
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<Gene>) -> Option<Gene> {
|
|
||||||
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<Gene>) -> Option<Gene> {
|
|
||||||
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<Gene>) -> Option<Gene> {
|
|
||||||
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<Gene>) -> Option<Gene> {
|
|
||||||
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<Gene> = 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<Gene> = 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<Gene> = 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<Gene> = 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
use crate::push::state::{Gene, PushState};
|
|
||||||
|
|
||||||
/// Acts as a NoOp, does nothing with the vals list.
|
|
||||||
fn _noop<T>(_: Vec<T>) -> Option<T> {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Copy + LogicalTrait,
|
|
||||||
{
|
|
||||||
Some(vals[0].logical_not())
|
|
||||||
}
|
|
||||||
make_instruction!(boolean, boolean, _not, bool, 1);
|
|
||||||
|
|
||||||
/// Runs logical xor on two values
|
|
||||||
fn _xor<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<i128>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Copy + CastingTrait,
|
|
||||||
{
|
|
||||||
T::from_int(vals[0])
|
|
||||||
}
|
|
||||||
make_instruction_out!(int, boolean, _from_int, i128, 1);
|
|
||||||
|
|
||||||
fn _from_float<T>(vals: Vec<Decimal>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Copy + CastingTrait,
|
|
||||||
{
|
|
||||||
T::from_float(vals[0])
|
|
||||||
}
|
|
||||||
make_instruction_out!(float, boolean, _from_float, Decimal, 1);
|
|
||||||
|
|
||||||
pub fn boolean_instructions() -> Vec<fn(&mut PushState)> {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<i128>*. `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;
|
|
@ -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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Add<Output = T> + 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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Sub<Output = T> + 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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Mul<Output = T> + 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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Div<Output = T> + 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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
where
|
|
||||||
T: Div<Output = T> + 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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<bool>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<bool>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<bool>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<bool>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<i128>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<Decimal>) -> Option<T>
|
|
||||||
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<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
|
|
||||||
/// the absolute value of the number.
|
|
||||||
fn _log<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<T>(vals: Vec<T>) -> Option<T>
|
|
||||||
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<fn(&mut PushState)> {
|
|
||||||
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<fn(&mut PushState)> {
|
|
||||||
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<i64> = vec![1, 2];
|
|
||||||
assert_eq!(Some(3), _add(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = 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<i64> = vec![1, 2];
|
|
||||||
assert_eq!(Some(1), _sub(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = 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<i128> = vec![4, 5];
|
|
||||||
assert_eq!(Some(20), _mult(vals));
|
|
||||||
|
|
||||||
let vals: Vec<Decimal> = 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<i128> = vec![4, 20];
|
|
||||||
assert_eq!(Some(5), _div(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 20];
|
|
||||||
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
|
|
||||||
#[test]
|
|
||||||
fn rem_test() {
|
|
||||||
let vals: Vec<i128> = vec![3, 20];
|
|
||||||
assert_eq!(Some(2), _rem(vals));
|
|
||||||
|
|
||||||
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
|
|
||||||
#[test]
|
|
||||||
fn max_test() {
|
|
||||||
let vals: Vec<i128> = vec![1, 2];
|
|
||||||
assert_eq!(Some(2), _max(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 0];
|
|
||||||
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
|
|
||||||
#[test]
|
|
||||||
fn min_test() {
|
|
||||||
let vals: Vec<i128> = vec![1, 2];
|
|
||||||
assert_eq!(Some(1), _min(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 0];
|
|
||||||
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
|
|
||||||
#[test]
|
|
||||||
fn inc_dec_test() {
|
|
||||||
let vals: Vec<i128> = vec![2];
|
|
||||||
assert_eq!(Some(3), _inc(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![10];
|
|
||||||
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
|
|
||||||
#[test]
|
|
||||||
fn lt_gt_lte_gte_test() {
|
|
||||||
let vals: Vec<i128> = vec![3, 2];
|
|
||||||
assert_eq!(Some(true), _lt(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![1, 4];
|
|
||||||
assert_eq!(Some(false), _lt(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![3, 3];
|
|
||||||
assert_eq!(Some(false), _lt(vals));
|
|
||||||
|
|
||||||
let vals: Vec<i128> = vec![2, 3];
|
|
||||||
assert_eq!(Some(true), _gt(vals));
|
|
||||||
|
|
||||||
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.
|
|
||||||
#[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<i128> = 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Output = Self> {
|
|
||||||
fn checked_div(self, v: Self) -> Option<Self>;
|
|
||||||
fn checked_mod(self, v: Self) -> Option<Self>;
|
|
||||||
fn increment(self) -> Self;
|
|
||||||
fn decrement(self) -> Self;
|
|
||||||
fn safe_sin(self) -> Option<Self>;
|
|
||||||
fn safe_cos(self) -> Option<Self>;
|
|
||||||
fn safe_tan(self) -> Option<Self>;
|
|
||||||
fn inverse(self) -> Option<Self>;
|
|
||||||
fn safe_exp(self) -> Option<Self>;
|
|
||||||
fn absolute(self) -> Self;
|
|
||||||
fn safe_log10(self) -> Option<Self>;
|
|
||||||
fn safe_sqrt(self) -> Option<Self>;
|
|
||||||
fn sign_reverse(self) -> Self;
|
|
||||||
fn square(self) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NumericTrait for Decimal {
|
|
||||||
fn checked_div(self, v: Self) -> Option<Self> {
|
|
||||||
if v == dec!(0.0) { None } else { Some(self / v) }
|
|
||||||
}
|
|
||||||
fn checked_mod(self, v: Self) -> Option<Self> {
|
|
||||||
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> {
|
|
||||||
self.checked_sin()
|
|
||||||
}
|
|
||||||
fn safe_cos(self) -> Option<Self> {
|
|
||||||
self.checked_cos()
|
|
||||||
}
|
|
||||||
fn safe_tan(self) -> Option<Self> {
|
|
||||||
self.checked_tan()
|
|
||||||
}
|
|
||||||
fn inverse(self) -> Option<Self> {
|
|
||||||
dec!(1.0).checked_div(self)
|
|
||||||
}
|
|
||||||
fn safe_exp(self) -> Option<Self> {
|
|
||||||
self.checked_exp()
|
|
||||||
}
|
|
||||||
fn absolute(self) -> Self {
|
|
||||||
self.abs()
|
|
||||||
}
|
|
||||||
fn safe_log10(self) -> Option<Self> {
|
|
||||||
self.absolute().checked_log10()
|
|
||||||
}
|
|
||||||
fn safe_sqrt(self) -> Option<Self> {
|
|
||||||
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<Self> {
|
|
||||||
if v == 0 { None } else { Some(self / v) }
|
|
||||||
}
|
|
||||||
fn checked_mod(self, v: Self) -> Option<Self> {
|
|
||||||
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<Self> {
|
|
||||||
Decimal::from_i128(self)?.checked_sin()?.to_i128()
|
|
||||||
}
|
|
||||||
fn safe_cos(self) -> Option<Self> {
|
|
||||||
Decimal::from_i128(self)?.checked_cos()?.to_i128()
|
|
||||||
}
|
|
||||||
fn safe_tan(self) -> Option<Self> {
|
|
||||||
Decimal::from_i128(self)?.checked_tan()?.to_i128()
|
|
||||||
}
|
|
||||||
fn inverse(self) -> Option<Self> {
|
|
||||||
if self == 0 { None } else { Some(1 / self) }
|
|
||||||
}
|
|
||||||
fn safe_exp(self) -> Option<Self> {
|
|
||||||
Decimal::from_i128(self)?.checked_exp()?.to_i128()
|
|
||||||
}
|
|
||||||
fn absolute(self) -> Self {
|
|
||||||
self.abs()
|
|
||||||
}
|
|
||||||
fn safe_log10(self) -> Option<Self> {
|
|
||||||
Decimal::from_i128(self)?
|
|
||||||
.absolute()
|
|
||||||
.checked_log10()?
|
|
||||||
.to_i128()
|
|
||||||
}
|
|
||||||
fn safe_sqrt(self) -> Option<Self> {
|
|
||||||
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<Self>;
|
|
||||||
fn from_int(v: i128) -> Option<Self>;
|
|
||||||
fn from_float(v: Decimal) -> Option<Self>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CastingTrait for i128 {
|
|
||||||
fn from_bool(v: bool) -> Option<Self> {
|
|
||||||
Some(if v { 1 } else { 0 })
|
|
||||||
}
|
|
||||||
fn from_int(v: i128) -> Option<Self> {
|
|
||||||
Some(v)
|
|
||||||
}
|
|
||||||
fn from_float(v: Decimal) -> Option<Self> {
|
|
||||||
v.to_i128()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CastingTrait for Decimal {
|
|
||||||
fn from_bool(v: bool) -> Option<Self> {
|
|
||||||
Some(if v { dec!(1.0) } else { dec!(0.0) })
|
|
||||||
}
|
|
||||||
fn from_int(v: i128) -> Option<Self> {
|
|
||||||
Decimal::from_i128(v)
|
|
||||||
}
|
|
||||||
fn from_float(v: Decimal) -> Option<Self> {
|
|
||||||
Some(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CastingTrait for bool {
|
|
||||||
fn from_bool(v: bool) -> Option<Self> {
|
|
||||||
Some(v)
|
|
||||||
}
|
|
||||||
fn from_int(v: i128) -> Option<Self> {
|
|
||||||
Some(if v != 0 { true } else { false })
|
|
||||||
}
|
|
||||||
fn from_float(v: Decimal) -> Option<Self> {
|
|
||||||
Some(if v != dec!(0.0) { true } else { false })
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
|
|
36
src/main.rs
36
src/main.rs
@ -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}");
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
pub mod interpreter;
|
|
||||||
pub mod state;
|
|
@ -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<i128>,
|
|
||||||
pub float: Vec<Decimal>,
|
|
||||||
pub string: Vec<Vec<u8>>,
|
|
||||||
pub boolean: Vec<bool>,
|
|
||||||
pub char: Vec<char>,
|
|
||||||
pub vector_int: Vec<Vec<i128>>,
|
|
||||||
pub vector_float: Vec<Vec<Decimal>>,
|
|
||||||
pub vector_string: Vec<Vec<Vec<u8>>>,
|
|
||||||
pub vector_boolean: Vec<Vec<bool>>,
|
|
||||||
pub vector_char: Vec<Vec<char>>,
|
|
||||||
pub exec: Vec<Gene>,
|
|
||||||
pub code: Vec<Gene>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<u8>),
|
|
||||||
GeneChar(char),
|
|
||||||
GeneVectorInt(Vec<i128>),
|
|
||||||
GeneVectorFloat(Vec<Decimal>),
|
|
||||||
GeneVectorBoolean(Vec<bool>),
|
|
||||||
GeneVectorString(Vec<Vec<u8>>),
|
|
||||||
GeneVectorChar(Vec<char>),
|
|
||||||
StateFunc(fn(&mut PushState)),
|
|
||||||
Close,
|
|
||||||
Open(u8),
|
|
||||||
Skip,
|
|
||||||
Block(Box<Vec<Gene>>),
|
|
||||||
CrossoverPadding,
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user