//! F2 — Memory monomers: MC_16–MC_23
//!
//! Safe stack and array operations. All bounds are checked.

/// MC_16 — LOAD: Load element from a slice at index.
///
/// Returns `None` if index is out of bounds — never panics.
///
/// ```
/// use brik64_core::mc::load;
/// let v = vec![10i64, 20, 30];
/// assert_eq!(load(&v, 1), Some(20));
/// assert_eq!(load(&v, 99), None);
/// ```
pub fn load(mem: &[i64], index: usize) -> Option<i64> {
    mem.get(index).copied()
}

/// MC_17 — STORE: Store value in a Vec at index.
///
/// Returns `false` if index is out of bounds — never panics.
///
/// ```
/// use brik64_core::mc::store;
/// let mut v = vec![0i64; 3];
/// assert!(store(&mut v, 1, 42));
/// assert_eq!(v[1], 42);
/// assert!(!store(&mut v, 99, 0));
/// ```
pub fn store(mem: &mut Vec<i64>, index: usize, value: i64) -> bool {
    if index < mem.len() {
        mem[index] = value;
        true
    } else {
        false
    }
}

/// MC_18 — PUSH: Push value onto a Vec (stack).
pub fn push(stack: &mut Vec<i64>, value: i64) {
    stack.push(value);
}

/// MC_19 — POP: Pop value from a Vec (stack). Returns `None` if empty.
pub fn pop(stack: &mut Vec<i64>) -> Option<i64> {
    stack.pop()
}

/// MC_20 — PEEK: Peek at top of stack without removing. Returns `None` if empty.
pub fn peek(stack: &[i64]) -> Option<i64> {
    stack.last().copied()
}

/// MC_21 — ALLOC: Allocate a Vec of `n` zeros, capped at 65536 elements.
///
/// ```
/// use brik64_core::mc::alloc;
/// let v = alloc(4);
/// assert_eq!(v.len(), 4);
/// assert_eq!(alloc(0), vec![]);
/// ```
pub fn alloc(n: usize) -> Vec<i64> {
    vec![0i64; n.min(65536)]
}

/// MC_22 — FREE: Clear a Vec (drop all elements).
pub fn free(mem: &mut Vec<i64>) {
    mem.clear();
}

/// MC_23 — LEN_MEM: Length of a slice.
pub fn len_mem(mem: &[i64]) -> usize {
    mem.len()
}
