runmat-vm 0.4.4

RunMat virtual machine and bytecode interpreter
Documentation
use crate::indexing::selectors::index_scalar_from_value;
use crate::interpreter::errors::mex;
use runmat_builtins::{CellArray, Value};
use runmat_runtime::RuntimeError;

pub async fn collect_linear_indices(
    stack: &mut Vec<Value>,
    count: usize,
) -> Result<Vec<f64>, RuntimeError> {
    let mut indices = Vec::with_capacity(count);
    for _ in 0..count {
        let mut index_value = stack
            .pop()
            .ok_or_else(|| mex("StackUnderflow", "stack underflow"))?;
        let original_value = index_value.clone();
        if matches!(index_value, Value::GpuTensor(_)) {
            index_value = runmat_runtime::dispatcher::gather_if_needed_async(&index_value).await?;
        }
        let index_val = match index_scalar_from_value(&index_value).await? {
            Some(val) => val as f64,
            None => {
                return Err(mex(
                    "UnsupportedIndexType",
                    &format!(
                        "Unsupported index type: expected numeric scalar, got {original_value:?}"
                    ),
                ))
            }
        };
        indices.push(index_val);
    }
    indices.reverse();
    Ok(indices)
}

pub fn build_object_subsref_cell(indices: &[f64]) -> Result<Value, RuntimeError> {
    let cell = CellArray::new(
        indices.iter().map(|n| Value::Num(*n)).collect(),
        1,
        indices.len(),
    )
    .map_err(|e| format!("subsref build error: {e}"))?;
    Ok(Value::Cell(cell))
}

pub async fn generic_index(base: &Value, indices: &[f64]) -> Result<Value, RuntimeError> {
    runmat_runtime::perform_indexing(base, indices).await
}