atlas_vm 0.5.2

The Atlas77 Virtual Machine
Documentation
use crate::errors::RuntimeError;
use crate::memory::object_map::ObjectKind;
use crate::memory::vm_data::VMData;
use crate::runtime::vm_state::VMState;
use crate::CallBack;

pub const STRING_FUNCTIONS: [(&str, CallBack); 5] = [
    ("str_len", str_len),
    ("trim", trim),
    ("to_upper", to_upper),
    ("to_lower", to_lower),
    ("split", split),
];

pub fn str_len(state: VMState) -> Result<VMData, RuntimeError> {
    let string_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
    let raw_string = state.object_map.get(string_ptr)?;
    let string = raw_string.string();
    Ok(VMData::new_i64(string.len() as i64))
}

pub fn trim(state: VMState) -> Result<VMData, RuntimeError> {
    let string_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
    let string = state.object_map.get(string_ptr)?.string().clone();

    let trimmed = string.trim();

    let obj_idx = state.object_map.put(ObjectKind::String(trimmed.to_string()));
    match obj_idx {
        Ok(index) => Ok(VMData::new_string(index)),
        Err(_) => Err(RuntimeError::OutOfMemory),
    }
}

pub fn to_upper(state: VMState) -> Result<VMData, RuntimeError> {
    let string_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
    let raw_string = state.object_map.get(string_ptr)?;
    let string = raw_string.string();

    let upper = string.to_uppercase();

    let obj_idx = state.object_map.put(ObjectKind::String(upper));
    match obj_idx {
        Ok(index) => Ok(VMData::new_string(index)),
        Err(_) => Err(RuntimeError::OutOfMemory),
    }
}

pub fn to_lower(state: VMState) -> Result<VMData, RuntimeError> {
    let string_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
    let raw_string = state.object_map.get(string_ptr)?;
    let string = raw_string.string();

    let lower = string.to_lowercase();

    let obj_idx = state.object_map.put(ObjectKind::String(lower));
    match obj_idx {
        Ok(index) => Ok(VMData::new_string(index)),
        Err(_) => Err(RuntimeError::OutOfMemory),
    }
}

pub fn split(state: VMState) -> Result<VMData, RuntimeError> {
    let delimiter_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();
    let string_ptr = state.stack.pop_with_rc(state.object_map)?.as_object();

    let delimiter = &state.object_map.get(delimiter_ptr)?.string().clone();
    let raw_string = state.object_map.get(string_ptr)?;
    let string = raw_string.string();

    let split_strings: Vec<String> = string.split(delimiter).map(|s| s.to_string()).collect();
    let list: Vec<VMData> = split_strings
        .into_iter()
        .map(|s| {
            let obj_idx = match state.object_map.put(ObjectKind::String(s)) {
                Ok(index) => index,
                Err(_) => panic!("Out of memory"),
            };
            VMData::new_string(obj_idx)
        })
        .collect();

    let list_idx = state.object_map.put(ObjectKind::List(list));
    match list_idx {
        Ok(index) => Ok(VMData::new_list(index)),
        Err(_) => Err(RuntimeError::OutOfMemory),
    }
}