Engine

Struct Engine 

Source
pub struct Engine {
    pub stack: Vec<Bucket>,
    pub variables: HashMap<String, Bucket>,
    pub undo_history: VecDeque<Vec<Bucket>>,
    pub undo_variable_history: VecDeque<HashMap<String, Bucket>>,
    pub undo_state_pointer: u8,
    pub previous_answer: Bucket,
}
Expand description

The core evaluation engine responsible for processing Reverse Polish Notation (RPN) operations.

The Engine maintains a stack, variable storage, and undo history to facilitate command execution and state management.

Fields§

§stack: Vec<Bucket>

The stack of bucket items

§variables: HashMap<String, Bucket>

Hashmap of set variables

§undo_history: VecDeque<Vec<Bucket>>

History vecdeque for undo support

§undo_variable_history: VecDeque<HashMap<String, Bucket>>

Variables vecdeque for undo support

§undo_state_pointer: u8

Offset pointer to the current index of the undo history. Index will be calculated by history.len() - pointer - 1

§previous_answer: Bucket

Previous answer

Implementations§

Source§

impl Engine

Source

pub fn new() -> Engine

Initializes an empty stack, variable storage, and undo history, with the previous answer set to zero.

Source

pub fn add_item_to_stack( &mut self, item: Bucket, ) -> Result<EngineSignal, String>

Adds an item to the stack, resolving variables and constants if necessary.

§Arguments
  • item - A Bucket containing the value to be added to the stack.
§Behavior
  • If item is "@", it is replaced with the value of self.previous_answer.
  • If item is a variable (its string representation starts with $), it is resolved using self.variables.
    • If the variable is undefined, an error is returned.
  • If item is a recognized constant, it is converted accordingly.
  • If item is a numeric string, it is parsed into a Float bucket.
  • Otherwise, item is stored as a String bucket.
§Returns
  • Ok(EngineSignal::StackUpdated) if the item is successfully added to the stack.
  • Err(String) if an undefined variable is referenced.
§Errors

Returns an error if the function encounters a reference to an undefined variable.

§Side Effects
  • Modifies self.stack by pushing the resolved Bucket.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.variables.insert("x".to_string(), Bucket::from(42.0));
assert!(engine.add_item_to_stack(Bucket::from("$x")).is_ok()); // Pushes 42.0 to the stack.
assert!(engine.add_item_to_stack(Bucket::from("$y")).is_err()); // Error: Undefined variable.
Source

pub fn get_operands_as_f(&mut self, number: i32) -> Result<Vec<f64>, String>

Retrieves a specified number of operands from the stack as f64 values.

§Arguments
  • number - The number of operands to retrieve from the stack.
§Behavior
  • Ensures that the stack contains at least number elements.
  • Checks that all requested operands are valid types (BucketTypes::Float or BucketTypes::Constant).
  • Extracts the operands from the stack, converting them to f64.
  • Returns the operands in the correct order.
§Returns
  • Ok(Vec<f64>) containing the extracted operands.
  • Err(String) if:
§Errors

Returns an error if:

  • The stack has fewer items than number.
  • An operand is of an incompatible type.
  • Parsing an operand as f64 fails.
§Side Effects
  • Modifies self.stack by removing the retrieved operands.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(3.5));
engine.stack.push(Bucket::from(2.0));

let result = engine.get_operands_as_f(2);
assert_eq!(result, Ok(vec![3.5, 2.0])); // Successfully retrieved operands.
Source

pub fn get_operands_as_dec( &mut self, number: i32, ) -> Result<Vec<Decimal>, String>

Retrieves a specified number of operands from the stack as Decimal values.

§Arguments
  • number - The number of operands to retrieve from the stack.
§Behavior
  • Ensures that the stack contains at least number elements.
  • Checks that all requested operands are valid types (BucketTypes::Float or BucketTypes::Constant).
  • Converts recognized mathematical constants (π, e, etc.) into their corresponding Decimal values.
  • Parses other valid numeric values into Decimal.
  • Returns the operands in the correct order.
§Returns
  • Ok(Vec<Decimal>) containing the extracted operands.
  • Err(String) if:
§Errors

Returns an error if:

  • The stack has fewer items than number.
  • An operand is of an incompatible type.
  • Parsing an operand as Decimal fails.
§Side Effects
  • Modifies self.stack by removing the retrieved operands.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(3.1415926535));
engine.stack.push(Bucket::from(2.0));

let result = engine.get_operands_as_dec(2);
assert!(result.is_ok()); // Successfully retrieved operands as Decimals.
Source

pub fn get_operands_as_string( &mut self, number: i32, ) -> Result<Vec<String>, String>

Retrieves a specified number of operands from the stack as String values.

§Arguments
  • number - The number of operands to retrieve from the stack.
§Behavior
  • Ensures that the stack contains at least number elements.
  • Converts each operand to a String.
  • Maintains the correct order of retrieved operands.
§Returns
  • Ok(Vec<String>) containing the extracted operands as strings.
  • Err(String) if there are not enough items on the stack.
§Errors

Returns an error if the stack has fewer items than number.

§Side Effects
  • Modifies self.stack by removing the retrieved operands.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from("hello"));
engine.stack.push(Bucket::from("world"));

let result = engine.get_operands_as_string(2);
assert_eq!(result.unwrap(), vec!["hello", "world"]);
Source

pub fn get_operands_raw(&mut self, number: i32) -> Result<Vec<Bucket>, String>

Retrieves a specified number of operands from the stack as raw Bucket values.

§Arguments
  • number - The number of operands to retrieve from the stack.
§Behavior
  • Ensures that the stack contains at least number elements.
  • Extracts the top number elements from the stack without modifying their types.
  • Maintains the original order of retrieved operands.
§Returns
  • Ok(Vec<Bucket>) containing the extracted operands in their raw form.
  • Err(String) if there are not enough items on the stack.
§Errors

Returns an error if the stack has fewer items than number.

§Side Effects
  • Modifies self.stack by removing the retrieved operands.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(3.14));
engine.stack.push(Bucket::from("test"));

let result = engine.get_operands_raw(2);
assert!(result.is_ok());
assert_eq!(result.unwrap(), vec![Bucket::from(3.14), Bucket::from("test")]);
Source

pub fn update_previous_answer(&mut self) -> Result<EngineSignal, String>

Updates the previous_answer variable to the last item on the stack.

§Behavior
  • If the stack is not empty, the last item is cloned and stored as previous_answer.
  • If the stack is empty, returns an error.
§Algebraic Mode Consideration
  • If you’re application has an algebraic mode, this function must be called after a full algebraic expression has been executed. This ensures that previous_answer is updated at the end of the statement, rather than in the middle of execution.
§Returns
  • Ok(EngineSignal::NOP) if previous_answer is successfully updated.
  • Err(String) if the stack is empty.
§Errors

Returns an error if the stack is empty, as there is no value to store as previous_answer.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(42));

assert!(engine.update_previous_answer().is_ok());
assert_eq!(engine.previous_answer, Bucket::from(42));
Source

pub fn add(&mut self) -> Result<EngineSignal, String>

Performs addition on the top two operands of the stack.

§Behavior
  • Retrieves the top two values from the stack as Decimal numbers.
  • Computes the sum of these values.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack contains fewer than two operands.
  • The operands are of an invalid type that cannot be converted to Decimal.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5));
engine.stack.push(Bucket::from(10));

assert!(engine.add().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(15));
Source

pub fn subtract(&mut self) -> Result<EngineSignal, String>

Performs subtraction on the top two operands of the stack.

§Behavior
  • Retrieves the top two values from the stack as Decimal numbers.
  • Computes the difference of these values.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack contains fewer than two operands.
  • The operands are of an invalid type that cannot be converted to Decimal.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5));
engine.stack.push(Bucket::from(10));

assert!(engine.subtract().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(-5));
Source

pub fn multiply(&mut self) -> Result<EngineSignal, String>

Performs multiplication on the top two operands of the stack.

§Behavior
  • Retrieves the top two values from the stack as Decimal numbers.
  • Computes the product of these values.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack contains fewer than two operands.
  • The operands are of an invalid type that cannot be converted to Decimal.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5));
engine.stack.push(Bucket::from(10));

assert!(engine.multiply().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(50));
Source

pub fn divide(&mut self) -> Result<EngineSignal, String>

Performs division on the top two operands of the stack.

§Behavior
  • Retrieves the top two values from the stack as Decimal numbers.
  • Computes the quotient of these values.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack contains fewer than two operands.
  • The operands are of an invalid type that cannot be converted to Decimal.
  • The denominator is zero
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(10));
engine.stack.push(Bucket::from(5));

assert!(engine.divide().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(2));
Source

pub fn power(&mut self) -> Result<EngineSignal, String>

Performs exponentiation on the top two operands of the stack.

§Behavior
  • Retrieves the top two values from the stack as Decimal numbers.
  • Treats the item on the top-1 of the stack as the base and the item on the top of the stack as the exponent.
  • If the exponent is an integer, uses checked_powd from rust_decimal.
  • If the exponent is a decimal, converts both values to f64 and uses powf.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack contains fewer than two operands.
  • Either operand is of an invalid type that cannot be converted to Decimal.
  • Converting a value to f64 fails.
  • Overflow occurs during exponentiation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(2));
engine.stack.push(Bucket::from(3));

assert!(engine.power().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(8));  // 2^3 = 8
Source

pub fn sqrt(&mut self) -> Result<EngineSignal, String>

Calculates the square root of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack as a Decimal number.
  • Computes the square root of this value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack is empty
  • The operand is of an invalid type that cannot be converted to Decimal.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(16));

assert!(engine.sqrt().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(4));
Source

pub fn modulo(&mut self) -> Result<EngineSignal, String>

Performs modulo on the top two operands of the stack.

§Behavior
  • Retrieves the top two values from the stack as Decimal numbers.
  • Computes the euclidean modulo of these values.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated to indicate a successful operation.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if there are not enough operands on the stack or if the operands are invalid.
§Errors

This function will return an error if:

  • The stack contains fewer than two operands.
  • The operands are of an invalid type that cannot be converted to Decimal.
  • The denominator is zero
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(11));
engine.stack.push(Bucket::from(2));

assert!(engine.modulo().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1));
Source

pub fn sin(&mut self) -> Result<EngineSignal, String>

Computes the sine of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the sine of the value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand does not support the sin operation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(0.0));

assert!(engine.sin().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(0.0)); // sin(0) = 0
Source

pub fn cos(&mut self) -> Result<EngineSignal, String>

Computes the cosine of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the cosine of the value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand does not support the cos operation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(0.0));

assert!(engine.cos().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1.0)); // cos(0) = 1
Source

pub fn tan(&mut self) -> Result<EngineSignal, String>

Computes the tangent of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the tangent of the value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand does not support the tan operation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(0.0));

assert!(engine.tan().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(0.0)); // tan(0) = 0
Source

pub fn sec(&mut self) -> Result<EngineSignal, String>

Computes the secant of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the secant of the value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand does not support the sec operation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(0.0));

assert!(engine.sec().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1.0)); // sec(0) = 1
Source

pub fn csc(&mut self) -> Result<EngineSignal, String>

Computes the cosecant of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the cosecant of the value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand does not support the csc operation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(0.0));

assert!(engine.csc().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::new_undefined()); // csc(0) = undefined
Source

pub fn cot(&mut self) -> Result<EngineSignal, String>

Computes the cotangent of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the cotangent of the value.
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand does not support the cot operation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(0.0));

assert!(engine.csc().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::new_undefined()); // cot(0) = undefined
Source

pub fn asin(&mut self) -> Result<EngineSignal, String>

Computes the arcsine (inverse sine) of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the arcsine of the value (in radians).
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand is not a valid input for the arcsine function (e.g., out of the range [-1, 1]).
§Example
use squiid_engine::bucket::{Bucket, ConstantTypes};
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(1.0));

assert!(engine.asin().is_ok());
// asin(1) = HalfPi
assert_eq!(engine.stack.last().unwrap().value, Bucket::from_constant(ConstantTypes::HalfPi).value);
Source

pub fn acos(&mut self) -> Result<EngineSignal, String>

Computes the arccosine (inverse cosine) of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the arccosine of the value (in radians).
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand is not a valid input for the arcsine function (e.g., out of the range [-1, 1]).
§Example
use squiid_engine::bucket::{Bucket, ConstantTypes};
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(-1.0));

assert!(engine.acos().is_ok());
// acos(-1) = Pi
assert_eq!(engine.stack.last().unwrap().value, Bucket::from_constant(ConstantTypes::Pi).value);
Source

pub fn atan(&mut self) -> Result<EngineSignal, String>

Computes the arctangent (inverse tangent) of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the arctangent of the value (in radians).
  • Pushes the result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand is not a valid input for the arcsine function (e.g., out of the range [-sqrt(3), sqrt(3)]).
§Example
use squiid_engine::bucket::{Bucket, ConstantTypes};
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(1.0));

assert!(engine.atan().is_ok());
// atan(1) = pi/4
assert_eq!(engine.stack.last().unwrap().value, Bucket::from_constant(ConstantTypes::QuarterPi).value);
Source

pub fn chs(&mut self) -> Result<EngineSignal, String>

Changes the sign (negates) of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Negates the value (multiplies by -1).
  • Pushes the negated result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand cannot be processed (e.g., invalid type).
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(10.0));

assert!(engine.chs().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(-10.0));
Source

pub fn log(&mut self) -> Result<EngineSignal, String>

Computes the base-10 logarithm of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Computes the base-10 logarithm (log10) of the value.
  • If the value is 0 or negative, it returns an error.
  • Pushes the result of the logarithm back onto the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the operand is less than or equal to 0, or if the stack is empty.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand is less than or equal to zero (logarithm of 0 or negative number is undefined).
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(100.0));

assert!(engine.log().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(2.0)); // log10(100) = 2
Source

pub fn blog(&mut self) -> Result<EngineSignal, String>

Computes the logarithm of a number with a specified base using the change of base formula.

The change of base formula is:

log_b(a) = (log_d(a)) / (log_d(b))

where:

  • a is the number whose logarithm is to be calculated.
  • b is the base of the logarithm.
§Behavior
  • Retrieves two operands from the stack: the number a and the base b.
  • Uses the change of base formula to compute the logarithm of a with base b.
  • If either operand is 0 or negative, or if division by zero occurs, it returns an error.
  • Pushes the result back onto the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if any of the following errors occur:
    • Either operand is 0 or negative.
    • Division by zero occurs.
§Errors

This function will return an error if:

  • Either operand is less than or equal to 0.
  • Division by zero occurs during the calculation.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(100.0));  // 'a' value
engine.stack.push(Bucket::from(10.0));   // 'b' value (base)

assert!(engine.blog().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(2.0)); // log_10(100) = 2
Source

pub fn ln(&mut self) -> Result<EngineSignal, String>

Computes the natural logarithm (ln) of a number.

The natural logarithm is the logarithm to the base of Euler’s number (e). It is defined for positive real numbers.

§Behavior
  • Retrieves one operand from the stack (the number a).
  • Computes the natural logarithm (ln) of the operand.
  • If the operand is 0 or negative, returns an error.
  • Pushes the result back onto the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the operand is 0 or negative.
§Errors

This function will return an error if:

  • The operand is less than or equal to 0, as the natural logarithm is only defined for positive real numbers.
§Example
use squiid_engine::bucket::{Bucket, ConstantTypes};
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from_constant(ConstantTypes::E));  // Euler's number

assert!(engine.ln().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1.0)); // ln(e) = 1
Source

pub fn abs(&mut self) -> Result<EngineSignal, String>

Computes the absolute value of the top operand on the stack.

§Behavior
  • Retrieves the top value from the stack.
  • Takes the absolute value
  • Pushes the negated result back onto the stack.
  • Returns EngineSignal::StackUpdated upon success.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • Err(String) if the stack is empty or the operand cannot be processed.
§Errors

This function will return an error if:

  • The stack contains no operands.
  • The operand cannot be processed (e.g., invalid type).
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(-10.0));

assert!(engine.abs().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(10.0));
Source

pub fn equal(&mut self) -> Result<EngineSignal, String>

Compares two operands for equality.

This function compares the top two operands on the stack to check if they are equal.

§Behavior
  • Retrieves two operands from the stack (operands a and b).
  • Compares the operands for equality (a == b).
  • If the operands are equal, pushes 1 (as a u32) onto the stack; otherwise, pushes 0.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • The result is 1 if the operands are equal, otherwise 0.
§Errors

This function does not explicitly handle errors related to operand types. It assumes that the operands are of compatible types (in this case, f64). If incompatible types are used, an error will be returned by the get_operands_as_f function.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));
engine.stack.push(Bucket::from(5.0));

assert!(engine.equal().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1)); // 5.0 == 5.0, so result is 1
Source

pub fn gt(&mut self) -> Result<EngineSignal, String>

Compares two operands to check if the first is greater than the second.

This function compares the top two operands on the stack to check if the first operand is greater than the second operand.

§Behavior
  • Retrieves two operands from the stack (operands a and b).
  • Compares the operands to check if a > b.
  • If the first operand is greater, pushes 1 (as a u32) onto the stack; otherwise, pushes 0.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • The result is 1 if the first operand is greater than the second, otherwise 0.
§Errors

This function does not explicitly handle errors related to operand types. It assumes that the operands are of compatible types (in this case, f64). If incompatible types are used, an error will be returned by the get_operands_as_f function.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(10.0));
engine.stack.push(Bucket::from(5.0));

assert!(engine.gt().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1)); // 10.0 > 5.0, so result is 1
Source

pub fn lt(&mut self) -> Result<EngineSignal, String>

Compares two operands to check if the first is less than the second.

This function compares the top two operands on the stack to check if the first operand is less than the second operand.

§Behavior
  • Retrieves two operands from the stack (operands a and b).
  • Compares the operands to check if a < b.
  • If the first operand is less, pushes 1 (as a u32) onto the stack; otherwise, pushes 0.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • The result is 1 if the first operand is greater than the second, otherwise 0.
§Errors

This function does not explicitly handle errors related to operand types. It assumes that the operands are of compatible types (in this case, f64). If incompatible types are used, an error will be returned by the get_operands_as_f function.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));
engine.stack.push(Bucket::from(10.0));

assert!(engine.lt().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1)); // 5.0 < 10.0, so result is 1
Source

pub fn geq(&mut self) -> Result<EngineSignal, String>

Compares two operands to check if the first is greater than or equal to the second.

This function compares the top two operands on the stack to check if the first operand is greater than or equal to the second operand.

§Behavior
  • Retrieves two operands from the stack (operands a and b).
  • Compares the operands to check if a >= b.
  • If the first operand is greater or equal, pushes 1 (as a u32) onto the stack; otherwise, pushes 0.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • The result is 1 if the first operand is greater than or equal to the second, otherwise 0.
§Errors

This function does not explicitly handle errors related to operand types. It assumes that the operands are of compatible types (in this case, f64). If incompatible types are used, an error will be returned by the get_operands_as_f function.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(10.0));
engine.stack.push(Bucket::from(9.0));

assert!(engine.geq().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1)); // 10.0 >= 9.0, so result is 1
Source

pub fn leq(&mut self) -> Result<EngineSignal, String>

Compares two operands to check if the first is less than or equal to the second.

This function compares the top two operands on the stack to check if the first operand is less than or equal to the second operand.

§Behavior
  • Retrieves two operands from the stack (operands a and b).
  • Compares the operands to check if a <= b.
  • If the first operand is less or equal, pushes 1 (as a u32) onto the stack; otherwise, pushes 0.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • The result is 1 if the first operand is less than or equal to the second, otherwise 0.
§Errors

This function does not explicitly handle errors related to operand types. It assumes that the operands are of compatible types (in this case, f64). If incompatible types are used, an error will be returned by the get_operands_as_f function.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(9.0));
engine.stack.push(Bucket::from(10.0));

assert!(engine.leq().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(1)); // 9.0 <= 10.0, so result is 1
Source

pub fn round(&mut self) -> Result<EngineSignal, String>

Rounds a number to the nearest integer.

This function takes the top operand from the stack and rounds it to the nearest integer. The result is then pushed back onto the stack.

§Behavior
  • Retrieves one operand from the stack.
  • Rounds the operand to the nearest integer using Rust’s f64::round method.
  • Pushes the rounded result back onto the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful.
  • The result is the rounded value of the operand.
§Errors

This function does not explicitly handle errors related to operand types. It assumes that the operand is of type f64. If the operand is of an incompatible type, an error will be returned by the get_operands_as_f function.

§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(3.7));

assert!(engine.round().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(4.0)); // Rounded from 3.7 to 4.0
Source

pub fn invert(&mut self) -> Result<EngineSignal, String>

Inverts the top operand on the stack.

This function takes the top operand from the stack and computes its multiplicative inverse (1 / operand). If the operand is zero, an error is returned since division by zero is undefined. The result is then pushed back onto the stack.

§Behavior
  • Retrieves one operand from the stack.
  • Checks if the operand is zero. If it is, returns an error (division by zero).
  • Computes the inverse of the operand (1 / operand) if it is non-zero.
  • Pushes the result back onto the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) if the operation is successful and the result is pushed onto the stack.
  • Err(String) if the operand is zero, indicating division by zero.
§Errors
  • Returns an error if the operand is zero, as division by zero is not allowed.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));

assert!(engine.invert().is_ok());
assert_eq!(engine.stack.last().unwrap(), &Bucket::from(0.2)); // Inverted from 5.0 to 0.2

engine.stack.push(Bucket::from(0.0));
assert!(engine.invert().is_err()); // Division by zero error
Source

pub fn drop(&mut self) -> Result<EngineSignal, String>

Removes the top item from the stack.

This function pops the last item from the stack. If the stack is not empty, the item is removed. If the stack is empty, the function does nothing but still returns EngineSignal::StackUpdated.

§Behavior
  • Removes the top item from the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function doesn’t return an error variant, and is only written this way to be compatible with the other engine functions.

§Notes
  • If the stack is empty, the function will simply return without making changes, but still indicate that the stack has been updated.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(10.0));

assert!(engine.drop().is_ok());
assert!(engine.stack.is_empty()); // Stack is empty after dropping the item
Source

pub fn swap(&mut self) -> Result<EngineSignal, String>

Swaps the top two items on the stack.

This function takes the last two values from the stack, removes them, and then places them back in reverse order.

§Behavior
  • Retrieves the top two items from the stack.
  • Swaps their positions on the stack.
§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function doesn’t return an error variant, and is only written this way to be compatible with the other engine functions.

§Notes
  • If the stack has fewer than two items, the function will return an error indicating that not enough operands are present.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));
engine.stack.push(Bucket::from(10.0));

assert!(engine.swap().is_ok());
assert_eq!(engine.stack[0], Bucket::from(10.0)); // Top item after swap
assert_eq!(engine.stack[1], Bucket::from(5.0));  // Second item after swap
Source

pub fn dup(&mut self) -> Result<EngineSignal, String>

Duplicates the last item on the stack.

This function takes the top item from the stack and pushes it onto the stack twice, duplicating the top value.

§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function doesn’t return an error variant, and is only written this way to be compatible with the other engine functions.

§Notes
  • If the stack is empty, the function will return an error indicating that no operand is available for duplication.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));

assert!(engine.dup().is_ok());
assert_eq!(engine.stack[0], Bucket::from(5.0)); // Top item after duplication
assert_eq!(engine.stack[1], Bucket::from(5.0)); // Duplicate item
Source

pub fn roll_down(&mut self) -> Result<EngineSignal, String>

Rolls the stack down, rotating the elements to the right.

This function moves the topmost item to the bottom of the stack by rotating the stack right by one position.

§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function will return an error if:

  • The stack is empty.
§Notes
  • If the stack is empty, the function will return an error indicating that the operation cannot be performed.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(1.0));
engine.stack.push(Bucket::from(2.0));
engine.stack.push(Bucket::from(3.0));

assert!(engine.roll_down().is_ok());
assert_eq!(engine.stack[0], Bucket::from(3.0)); // Top item after roll
assert_eq!(engine.stack[2], Bucket::from(2.0)); // Last item moved to the bottom
Source

pub fn roll_up(&mut self) -> Result<EngineSignal, String>

Rolls the stack up, rotating the elements to the left.

This function moves the bottommost item to the top of the stack by rotating the stack left by one position.

§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function will return an error if:

  • The stack is empty.
§Notes
  • If the stack is empty, the function will return an error indicating that the operation cannot be performed.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(1.0));
engine.stack.push(Bucket::from(2.0));
engine.stack.push(Bucket::from(3.0));

assert!(engine.roll_up().is_ok());
assert_eq!(engine.stack[2], Bucket::from(1.0)); // Bottom item moved to the top
assert_eq!(engine.stack[0], Bucket::from(2.0));
Source

pub fn store(&mut self) -> Result<EngineSignal, String>

Stores a value in a variable.

This function stores the topmost value from the stack into a variable, validating that the variable name follows a valid identifier pattern.

§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function will return an error if:

  • The variable name is not a valid ID
§Notes
  • If the second operand is not a valid variable name, an error is returned.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));
engine.stack.push(Bucket::from("var1"));

assert!(engine.store().is_ok());
// Variable "var1" should now store the value 5.0
assert!(engine.variables.get("var1").is_some());
Source

pub fn purge(&mut self) -> Result<EngineSignal, String>

Deletes a variable from memory.

This function removes a variable from the internal variable store if it exists. It only works if the variable is a valid identifier.

§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function will return an error if:

  • The variable name is not a valid ID
  • The variable is not set
§Notes
  • If the variable does not exist or is not a valid identifier, an error is returned.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));
engine.stack.push(Bucket::from("var1"));
engine.store(); // Store a value in a variable
assert!(engine.variables.get("var1").is_some());

engine.stack.push(Bucket::from("var1"));
assert!(engine.purge().is_ok());
// Variable should now be removed
assert!(engine.variables.get("var1").is_none());
Source

pub fn invstore(&mut self) -> Result<EngineSignal, String>

Stores a value in a variable, with inverted argument order. Useful for how variable assignments are parsed in algebraic mode.

This function swaps the top two values on the stack and then calls the store function to store the value in the variable.

§Returns
  • Ok(EngineSignal::StackUpdated) when the operation is successfully completed and the stack is updated.
§Errors

This function will return an error if:

  • The variable name is not a valid ID
§Notes
  • This function uses swap() and will return an error if swapping fails.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from("var1"));
engine.stack.push(Bucket::from(5.0));

assert!(engine.invstore().is_ok());
// Variable "var1" should now store the value 5.0
assert!(engine.variables.get("var1").is_some());
Source

pub fn clear(&mut self) -> Result<EngineSignal, String>

Clears the entire stack.

This function empties the stack, removing all items stored in it.

§Returns
  • Ok(EngineSignal::StackUpdated) when the stack has been successfully cleared.
§Errors

This function doesn’t return an error variant, and is only written this way to be compatible with the other engine functions.

§Notes
  • This function does not return an error; the stack is simply cleared.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();
engine.stack.push(Bucket::from(5.0));
engine.stack.push(Bucket::from(10.0));

assert!(engine.clear().is_ok());
assert!(engine.stack.is_empty()); // Stack is now empty
Source

pub fn undo(&mut self) -> Result<EngineSignal, String>

Undoes the last operation by reverting the stack and variables to their previous state.

This function reverts the stack and variables to the state they were in at the time of the last operation. If no operations have been performed or the undo history has been exhausted, an error is returned.

§Returns
  • Ok(EngineSignal::StackUpdated) when the undo is successfully performed and the stack and variables are updated.
  • Err(String) if there is no operation to undo.
§Errors

This function will return an error if:

  • You try to undo further than the history allows
§Notes
  • The undo history is stored, and each undo operation increments a pointer to track the state.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;
use squiid_engine;

let mut engine = Engine::new();
// after each command, we must push a copy of the stack to the engine history
let _ = squiid_engine::handle_data(&mut engine, "1");
let _ = squiid_engine::handle_data(&mut engine, "2");
let _ = squiid_engine::handle_data(&mut engine, "test");

// test undo of adding something to the stack
let _ = engine.undo();
assert_eq!(engine.stack, vec![Bucket::from(1), Bucket::from(2),]);
Source

pub fn redo(&mut self) -> Result<EngineSignal, String>

Redoes the last undone operation by restoring the stack and variables.

This function restores the stack and variables to the state they were in at the time of the last undone operation. If no operations have been undone or the redo history is exhausted, an error is returned.

§Returns
  • Ok(EngineSignal::StackUpdated) when the redo is successfully performed and the stack and variables are updated.
  • Err(String) if there are no operations to redo.
§Errors

This function will return an error if:

  • You try to redo further than the number of undone operations
§Notes
  • The redo history is tracked using the undo state pointer to determine the next state to restore.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;
use squiid_engine;

let mut engine = Engine::new();
// after each command, we must push a copy of the stack to the engine history
let _ = squiid_engine::handle_data(&mut engine, "1");
let _ = squiid_engine::handle_data(&mut engine, "2");
let _ = squiid_engine::handle_data(&mut engine, "test");

// test undo of adding something to the stack
let _ = engine.undo();
assert_eq!(engine.stack, vec![Bucket::from(1), Bucket::from(2),]);

// test redo
let _ = engine.redo();
assert_eq!(engine.stack, vec![Bucket::from(1), Bucket::from(2), Bucket::from("test")]);
Source

pub fn quit(&mut self) -> Result<EngineSignal, String>

Terminates the engine and signals the system to quit.

This function sends a quit signal to the engine, indicating that it should stop processing and exit.

§Returns
  • Ok(EngineSignal::Quit) when the quit signal is sent.
§Errors

This function doesn’t return an error variant, and is only written this way to be compatible with the other engine functions.

§Notes
  • This function does not affect the state of the stack or variables but instead signals the engine to stop execution.
§Example
use squiid_engine::bucket::Bucket;
use squiid_engine::engine::Engine;

let mut engine = Engine::new();

assert!(engine.quit().is_ok()); // The engine is now quitting

Trait Implementations§

Source§

impl Clone for Engine

Source§

fn clone(&self) -> Engine

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Engine

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Engine

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for Engine

Source§

fn eq(&self, other: &Engine) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for Engine

Source§

impl StructuralPartialEq for Engine

Auto Trait Implementations§

§

impl Freeze for Engine

§

impl RefUnwindSafe for Engine

§

impl Send for Engine

§

impl Sync for Engine

§

impl Unpin for Engine

§

impl UnwindSafe for Engine

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.