various progress around the block
This commit is contained in:
parent
93a4749425
commit
5fe9ca40c6
150
src/instructions/logical.rs
Normal file
150
src/instructions/logical.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
//! # Logical Instructions
|
||||||
|
//!
|
||||||
|
//! This file holds instructions for the boolean stack.
|
||||||
|
|
||||||
|
use super::utils::{LogicalTrait, NumericTrait};
|
||||||
|
use crate::push::state::PushState;
|
||||||
|
|
||||||
|
/// 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 _to_int<T>(vals: Vec<T>) -> Option<T>
|
||||||
|
// where
|
||||||
|
// T: Copy + NumericTrait,
|
||||||
|
// {
|
||||||
|
// Some(T::from_bool(vals))
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::push::state::EMPTY_STATE;
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
}
|
||||||
|
}
|
@ -45,30 +45,6 @@ pub mod macros {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod logical;
|
||||||
pub mod numeric;
|
pub mod numeric;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
// /// A macro that makes a push instruction given: the name of the stack to use,
|
|
||||||
// /// an internal function to call, and the type of a function.
|
|
||||||
// #[macro_export]
|
|
||||||
// macro_rules! make_instruction {
|
|
||||||
// ($stack_name:ident, $fn_name:ident, $fn_type:ty) => {
|
|
||||||
// paste::item! {
|
|
||||||
// fn [< $stack_name $fn_name >] (state: &mut PushState, num_inputs: usize) {
|
|
||||||
// if state.$stack_name.len() < num_inputs {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// let mut inputs: Vec<$fn_type> = Vec::with_capacity(num_inputs);
|
|
||||||
// for n in 0..num_inputs {
|
|
||||||
// inputs.push(state.$stack_name[n]);
|
|
||||||
// }
|
|
||||||
// if let Some(result) = $fn_name(inputs) {
|
|
||||||
// for _ in 0..num_inputs {
|
|
||||||
// state.$stack_name.pop();
|
|
||||||
// }
|
|
||||||
// state.$stack_name.push(result);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
@ -11,7 +11,7 @@ use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
|
|||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::ops::{Add, Div, Mul, Sub};
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
use super::utils::InstructionTrait;
|
use super::utils::NumericTrait;
|
||||||
|
|
||||||
/// Adds two addable values together.
|
/// Adds two addable values together.
|
||||||
fn _add<T>(vals: Vec<T>) -> Option<T>
|
fn _add<T>(vals: Vec<T>) -> Option<T>
|
||||||
@ -46,7 +46,7 @@ make_instruction!(float, float, _mult, Decimal, 2);
|
|||||||
/// Divides two values from each other.
|
/// Divides two values from each other.
|
||||||
fn _div<T>(vals: Vec<T>) -> Option<T>
|
fn _div<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Div<Output = T> + Copy + InstructionTrait,
|
T: Div<Output = T> + Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[1].checked_div(vals[0])
|
vals[1].checked_div(vals[0])
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ make_instruction!(float, float, _div, Decimal, 2);
|
|||||||
/// Takes the remainder of two values
|
/// Takes the remainder of two values
|
||||||
fn _rem<T>(vals: Vec<T>) -> Option<T>
|
fn _rem<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Div<Output = T> + Copy + InstructionTrait,
|
T: Div<Output = T> + Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[1].checked_mod(vals[0])
|
vals[1].checked_mod(vals[0])
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ make_instruction!(float, float, _min, Decimal, 2);
|
|||||||
/// Increments a single value by 1
|
/// Increments a single value by 1
|
||||||
fn _inc<T>(vals: Vec<T>) -> Option<T>
|
fn _inc<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: InstructionTrait + Copy,
|
T: NumericTrait + Copy,
|
||||||
{
|
{
|
||||||
Some(vals[0].increment())
|
Some(vals[0].increment())
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ make_instruction!(float, float, _inc, Decimal, 1);
|
|||||||
/// Decrements a single value by 1
|
/// Decrements a single value by 1
|
||||||
fn _dec<T>(vals: Vec<T>) -> Option<T>
|
fn _dec<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: InstructionTrait + Copy,
|
T: NumericTrait + Copy,
|
||||||
{
|
{
|
||||||
Some(vals[0].decrement())
|
Some(vals[0].decrement())
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ make_instruction!(float, boolean, _gte, Decimal, 2);
|
|||||||
/// Runs sin on a single item.
|
/// Runs sin on a single item.
|
||||||
fn _sin<T>(vals: Vec<T>) -> Option<T>
|
fn _sin<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_sin()
|
vals[0].safe_sin()
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ make_instruction!(float, float, _sin, Decimal, 1);
|
|||||||
/// Runs arcsin on a single item.
|
/// Runs arcsin on a single item.
|
||||||
fn _arcsin<T>(vals: Vec<T>) -> Option<T>
|
fn _arcsin<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_sin()?.inverse()
|
vals[0].safe_sin()?.inverse()
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ make_instruction!(float, float, _arcsin, Decimal, 1);
|
|||||||
/// Runs cos on a single item.
|
/// Runs cos on a single item.
|
||||||
fn _cos<T>(vals: Vec<T>) -> Option<T>
|
fn _cos<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_cos()
|
vals[0].safe_cos()
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ make_instruction!(float, float, _cos, Decimal, 1);
|
|||||||
/// Runs arcsin on a single item.
|
/// Runs arcsin on a single item.
|
||||||
fn _arccos<T>(vals: Vec<T>) -> Option<T>
|
fn _arccos<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_cos()?.inverse()
|
vals[0].safe_cos()?.inverse()
|
||||||
}
|
}
|
||||||
@ -186,7 +186,7 @@ make_instruction!(float, float, _arccos, Decimal, 1);
|
|||||||
/// Runs tan on a single item.
|
/// Runs tan on a single item.
|
||||||
fn _tan<T>(vals: Vec<T>) -> Option<T>
|
fn _tan<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_tan()
|
vals[0].safe_tan()
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ make_instruction!(float, float, _tan, Decimal, 1);
|
|||||||
/// Runs arctan on a single item.
|
/// Runs arctan on a single item.
|
||||||
fn _arctan<T>(vals: Vec<T>) -> Option<T>
|
fn _arctan<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_tan()?.inverse()
|
vals[0].safe_tan()?.inverse()
|
||||||
}
|
}
|
||||||
@ -216,21 +216,21 @@ fn _to_float(vals: Vec<i128>) -> Option<Decimal> {
|
|||||||
make_instruction!(int, float, _to_float, i128, 1);
|
make_instruction!(int, float, _to_float, i128, 1);
|
||||||
|
|
||||||
/// Converts a single number to a bool.
|
/// Converts a single number to a bool.
|
||||||
fn _to_bool<T>(vals: Vec<T>) -> Option<bool>
|
fn _from_bool<T>(vals: Vec<bool>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].to_bool())
|
Some(T::from_bool(vals[0]))
|
||||||
}
|
}
|
||||||
make_instruction!(int, boolean, _to_bool, i128, 1);
|
make_instruction!(int, boolean, _from_bool, bool, 1);
|
||||||
make_instruction!(float, boolean, _to_bool, Decimal, 1);
|
make_instruction!(float, boolean, _from_bool, bool, 1);
|
||||||
|
|
||||||
/// Takes the log base 10 of a single Decimal. Acts as a
|
/// Takes the log base 10 of a single Decimal. Acts as a
|
||||||
/// NoOp if the value is 0. If the value is negative, takes
|
/// NoOp if the value is 0. If the value is negative, takes
|
||||||
/// the absolute value of the number.
|
/// the absolute value of the number.
|
||||||
fn _log<T>(vals: Vec<T>) -> Option<T>
|
fn _log<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].absolute().safe_log10()
|
vals[0].absolute().safe_log10()
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ make_instruction!(float, float, _log, Decimal, 1);
|
|||||||
/// Takes the exp of a single value. Ints get truncated.
|
/// Takes the exp of a single value. Ints get truncated.
|
||||||
fn _exp<T>(vals: Vec<T>) -> Option<T>
|
fn _exp<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_exp()
|
vals[0].safe_exp()
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ make_instruction!(float, float, _exp, Decimal, 1);
|
|||||||
/// Takes the square root of the absolute value of a single value.
|
/// Takes the square root of the absolute value of a single value.
|
||||||
fn _sqrt<T>(vals: Vec<T>) -> Option<T>
|
fn _sqrt<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].safe_sqrt()
|
vals[0].safe_sqrt()
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ make_instruction!(float, float, _sqrt, Decimal, 1);
|
|||||||
/// does nothing (returns None). Truncates an int to 0.
|
/// does nothing (returns None). Truncates an int to 0.
|
||||||
fn _inv<T>(vals: Vec<T>) -> Option<T>
|
fn _inv<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
vals[0].inverse()
|
vals[0].inverse()
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ make_instruction!(float, float, _inv, Decimal, 1);
|
|||||||
/// Takes the absolute value of the top number
|
/// Takes the absolute value of the top number
|
||||||
fn _abs<T>(vals: Vec<T>) -> Option<T>
|
fn _abs<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].absolute())
|
Some(vals[0].absolute())
|
||||||
}
|
}
|
||||||
@ -281,7 +281,7 @@ make_instruction!(float, float, _abs, Decimal, 1);
|
|||||||
/// Reverses the sign of the top number
|
/// Reverses the sign of the top number
|
||||||
fn _sign_reverse<T>(vals: Vec<T>) -> Option<T>
|
fn _sign_reverse<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].sign_reverse())
|
Some(vals[0].sign_reverse())
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ make_instruction!(float, float, _sign_reverse, Decimal, 1);
|
|||||||
/// Squares the top number
|
/// Squares the top number
|
||||||
fn _square<T>(vals: Vec<T>) -> Option<T>
|
fn _square<T>(vals: Vec<T>) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Copy + InstructionTrait,
|
T: Copy + NumericTrait,
|
||||||
{
|
{
|
||||||
Some(vals[0].square())
|
Some(vals[0].square())
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use std::ops::Div;
|
|||||||
///
|
///
|
||||||
/// Trig functions named safe rather than checked to not overlap
|
/// Trig functions named safe rather than checked to not overlap
|
||||||
/// with Decimal library's checked function names.
|
/// with Decimal library's checked function names.
|
||||||
pub trait InstructionTrait: Sized + Div<Output = Self> {
|
pub trait NumericTrait: Sized + Div<Output = Self> {
|
||||||
fn checked_div(self, v: Self) -> Option<Self>;
|
fn checked_div(self, v: Self) -> Option<Self>;
|
||||||
fn checked_mod(self, v: Self) -> Option<Self>;
|
fn checked_mod(self, v: Self) -> Option<Self>;
|
||||||
fn increment(self) -> Self;
|
fn increment(self) -> Self;
|
||||||
@ -24,9 +24,10 @@ pub trait InstructionTrait: Sized + Div<Output = Self> {
|
|||||||
fn to_bool(self) -> bool;
|
fn to_bool(self) -> bool;
|
||||||
fn sign_reverse(self) -> Self;
|
fn sign_reverse(self) -> Self;
|
||||||
fn square(self) -> Self;
|
fn square(self) -> Self;
|
||||||
|
fn from_bool(v: bool) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionTrait for Decimal {
|
impl NumericTrait for Decimal {
|
||||||
fn checked_div(self, v: Self) -> Option<Self> {
|
fn checked_div(self, v: Self) -> Option<Self> {
|
||||||
if v == dec!(0.0) { None } else { Some(self / v) }
|
if v == dec!(0.0) { None } else { Some(self / v) }
|
||||||
}
|
}
|
||||||
@ -72,9 +73,12 @@ impl InstructionTrait for Decimal {
|
|||||||
fn square(self) -> Self {
|
fn square(self) -> Self {
|
||||||
self * self
|
self * self
|
||||||
}
|
}
|
||||||
|
fn from_bool(v: bool) -> Self {
|
||||||
|
if v { dec!(1.0) } else { dec!(0.0) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionTrait for i128 {
|
impl NumericTrait for i128 {
|
||||||
fn checked_div(self, v: Self) -> Option<Self> {
|
fn checked_div(self, v: Self) -> Option<Self> {
|
||||||
if v == 0 { None } else { Some(self / v) }
|
if v == 0 { None } else { Some(self / v) }
|
||||||
}
|
}
|
||||||
@ -125,4 +129,32 @@ impl InstructionTrait for i128 {
|
|||||||
fn square(self) -> Self {
|
fn square(self) -> Self {
|
||||||
self * self
|
self * self
|
||||||
}
|
}
|
||||||
|
fn from_bool(v: bool) -> Self {
|
||||||
|
if v { 1 } else { 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use instructions::utils::InstructionTrait;
|
use instructions::utils::NumericTrait;
|
||||||
use rust_decimal::MathematicalOps;
|
use rust_decimal::MathematicalOps;
|
||||||
use rust_decimal::prelude::*;
|
use rust_decimal::prelude::*;
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use crate::push::state::*;
|
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) {
|
pub fn gene_to_stack(state: &mut PushState, gene: Gene) {
|
||||||
match gene {
|
match gene {
|
||||||
Gene::GeneInt(x) => state.int.push(x),
|
Gene::GeneInt(x) => state.int.push(x),
|
||||||
@ -23,15 +26,22 @@ pub fn gene_to_stack(state: &mut PushState, gene: Gene) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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) {
|
pub fn interpret_program(state: &mut PushState, step_limit: usize, max_stack_size: isize) {
|
||||||
let mut steps: usize = 0;
|
let mut steps: usize = 0;
|
||||||
while state.exec.len() > 0 && steps < step_limit {
|
while state.exec.len() > 0 && steps < step_limit {
|
||||||
if let Some(val) = state.exec.pop() {}
|
if let Some(gene) = state.exec.pop() {
|
||||||
|
gene_to_stack(state, gene);
|
||||||
|
steps += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::instructions::numeric::int_add;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use rust_decimal::dec;
|
use rust_decimal::dec;
|
||||||
|
|
||||||
@ -52,6 +62,89 @@ mod tests {
|
|||||||
assert_eq!(vec![true], test_state.boolean);
|
assert_eq!(vec![true], test_state.boolean);
|
||||||
test_state.boolean.clear();
|
test_state.boolean.clear();
|
||||||
|
|
||||||
// Need to finish these tests later.
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,12 @@ pub struct PushState {
|
|||||||
pub float: Vec<Decimal>,
|
pub float: Vec<Decimal>,
|
||||||
pub string: Vec<Vec<u8>>,
|
pub string: Vec<Vec<u8>>,
|
||||||
pub boolean: Vec<bool>,
|
pub boolean: Vec<bool>,
|
||||||
pub char: Vec<u8>,
|
pub char: Vec<char>,
|
||||||
pub vector_int: Vec<Vec<i128>>,
|
pub vector_int: Vec<Vec<i128>>,
|
||||||
pub vector_float: Vec<Vec<Decimal>>,
|
pub vector_float: Vec<Vec<Decimal>>,
|
||||||
pub vector_string: Vec<Vec<Vec<u8>>>,
|
pub vector_string: Vec<Vec<Vec<u8>>>,
|
||||||
pub vector_boolean: Vec<Vec<bool>>,
|
pub vector_boolean: Vec<Vec<bool>>,
|
||||||
pub vector_char: Vec<Vec<u8>>,
|
pub vector_char: Vec<Vec<char>>,
|
||||||
pub exec: Vec<Gene>,
|
pub exec: Vec<Gene>,
|
||||||
pub code: Vec<Gene>,
|
pub code: Vec<Gene>,
|
||||||
}
|
}
|
||||||
@ -41,12 +41,12 @@ pub enum Gene {
|
|||||||
GeneFloat(Decimal),
|
GeneFloat(Decimal),
|
||||||
GeneBoolean(bool),
|
GeneBoolean(bool),
|
||||||
GeneString(Vec<u8>),
|
GeneString(Vec<u8>),
|
||||||
GeneChar(u8),
|
GeneChar(char),
|
||||||
GeneVectorInt(Vec<i128>),
|
GeneVectorInt(Vec<i128>),
|
||||||
GeneVectorFloat(Vec<Decimal>),
|
GeneVectorFloat(Vec<Decimal>),
|
||||||
GeneVectorBoolean(Vec<bool>),
|
GeneVectorBoolean(Vec<bool>),
|
||||||
GeneVectorString(Vec<Vec<u8>>),
|
GeneVectorString(Vec<Vec<u8>>),
|
||||||
GeneVectorChar(Vec<u8>),
|
GeneVectorChar(Vec<char>),
|
||||||
StateFunc(fn(&mut PushState)),
|
StateFunc(fn(&mut PushState)),
|
||||||
Close,
|
Close,
|
||||||
Open(u8),
|
Open(u8),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user