use alloc::{sync::Arc, vec::Vec};
use vm_core::mast::{ExternalNode, MastForest, MastNodeId};
pub use vm_core::utils::*;
use super::Felt;
use crate::{ErrorContext, ExecutionError, Host};
pub(crate) fn get_trace_len(trace: &[Vec<Felt>]) -> usize {
trace[0].len()
}
#[inline(always)]
pub(crate) fn split_element(value: Felt) -> (Felt, Felt) {
let value = value.as_int();
let lo = (value as u32) as u64;
let hi = value >> 32;
(Felt::new(hi), Felt::new(lo))
}
pub(crate) fn split_element_u32_into_u16(value: Felt) -> (Felt, Felt) {
let (hi, lo) = split_u32_into_u16(value.as_int());
(Felt::new(hi as u64), Felt::new(lo as u64))
}
pub(crate) fn split_u32_into_u16(value: u64) -> (u16, u16) {
const U32MAX: u64 = u32::MAX as u64;
debug_assert!(value <= U32MAX, "not a 32-bit value");
let lo = value as u16;
let hi = (value >> 16) as u16;
(hi, lo)
}
pub(crate) fn resolve_external_node(
external_node: &ExternalNode,
host: &mut impl Host,
) -> Result<(MastNodeId, Arc<MastForest>), ExecutionError> {
let node_digest = external_node.digest();
let mast_forest =
host.get_mast_forest(&node_digest)
.ok_or(ExecutionError::no_mast_forest_with_procedure(
node_digest,
&ErrorContext::default(),
))?;
let root_id = mast_forest.find_procedure_root(node_digest).ok_or(
ExecutionError::malfored_mast_forest_in_host(node_digest, &ErrorContext::default()),
)?;
if mast_forest[root_id].is_external() {
return Err(ExecutionError::CircularExternalNode(node_digest));
}
Ok((root_id, mast_forest))
}