state-macro 0.1.1

Syntax sugar for stateful functions
Documentation
use state_macro::{stateful, with_state};
use std::cell::RefCell;
use std::rc::Rc;

// State: a stack machine with a vector of i32 values
type StackState = Rc<RefCell<Vec<i32>>>;

// Create a new empty stack
fn new_stack() -> StackState {
    Rc::new(RefCell::new(Vec::new()))
}

// Operations for the stack machine

// Push a value onto the stack
fn push(state: &StackState, value: i32) {
    state.borrow_mut().push(value);
}

// Pop a value from the stack (returns 0 if stack is empty)
fn pop(state: &StackState) -> i32 {
    state.borrow_mut().pop().unwrap_or(0)
}

// Get the stack length
fn get_len(state: &StackState) -> usize {
    state.borrow().len()
}

// You can also define "stateful" functions using the 'stateful' macro
// Add the top two elements on the stack and push the result
#[stateful(&StackState)]
fn add() {
    if ::get_len() >= 2 {
        let (a, b) = (::pop(), ::pop());
        ::push(a + b);
    }
}

// Example using the with_state! macro
fn stack_sum_with_state(state: &StackState, values: &[i32]) -> i32 {
    // Using the with_state! macro to simplify the code
    with_state! { state;
        // Push all values onto the stack
        for value in values {
            ::push(*value);
        }

        // Reducing loop: while we have at least 2 values, add them
        while ::get_len() >= 2 {
            ::add();
        }

        // Pop and return the result
        ::pop()
    }
}

// Example using the stateful attribute macro
#[stateful(&StackState)]
fn stack_sum_stateful(values: &[i32]) -> i32 {
    // Push all values onto the stack
    for value in values {
        ::push(*value);
    }

    // Reducing loop: while we have at least 2 values, add them
    while ::get_len() >= 2 {
        ::add();
    }

    // Pop and return the result
    ::pop()
}

fn main() {
    let values = [1, 2, 3, 4, 5]; // Sum should be 15

    // Example 1: Using with_state! macro
    let stack1 = new_stack();
    let result1 = stack_sum_with_state(&stack1, &values);
    println!("Result using with_state! macro: {}", result1);

    // Example 2: Using #[stateful] attribute
    let stack2 = new_stack();
    let result2 = stack_sum_stateful(&stack2, &values);
    println!("Result using #[stateful] attribute: {}", result2);
    assert_eq!(result2, 15);

    // Additional example: detailed explanation of how the stack works
    let stack3 = new_stack();

    println!("\nDetailed stack operations demonstration:");
    push(&stack3, 10);
    println!("Pushed 10, stack: {:?}", stack3.borrow());

    push(&stack3, 20);
    println!("Pushed 20, stack: {:?}", stack3.borrow());

    add(&stack3);
    println!("Added top two elements, stack: {:?}", stack3.borrow());

    let result = pop(&stack3);
    println!("Popped result: {}, stack: {:?}", result, stack3.borrow());
}