cairo-vm 2.0.1

Blazing fast Cairo interpreter
Documentation
use core::fmt::{Debug, Formatter};

use crate::Felt252;
use num_traits::ToPrimitive;

use crate::hint_processor::builtin_hint_processor::dict_manager::Dictionary;
use crate::hint_processor::builtin_hint_processor::hint_utils::{
    get_integer_from_var_name, get_ptr_from_var_name,
};
use crate::serde::deserialize_program::ApTracking;
use crate::stdlib::collections::HashMap;

use crate::types::exec_scope::ExecutionScopes;
use crate::types::relocatable::MaybeRelocatable;
use crate::vm::errors::hint_errors::HintError;
use crate::{
    hint_processor::hint_processor_definition::HintReference, vm::vm_core::VirtualMachine,
};

pub fn print_felt(
    vm: &VirtualMachine,
    ids_data: &HashMap<String, HintReference>,
    ap_tracking: &ApTracking,
) -> Result<(), HintError> {
    let val = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?;
    println!("{val}");
    Ok(())
}

fn print_name(
    vm: &VirtualMachine,
    ids_data: &HashMap<String, HintReference>,
    ap_tracking: &ApTracking,
) -> Result<(), HintError> {
    let name = get_integer_from_var_name("name", vm, ids_data, ap_tracking)?;
    let name = String::from_utf8(name.as_ref().to_bigint().to_signed_bytes_be())
        .map_err(|err| HintError::CustomHint(err.to_string().into_boxed_str()))?;
    println!("{name}");
    Ok(())
}

pub fn print_array(
    vm: &VirtualMachine,
    ids_data: &HashMap<String, HintReference>,
    ap_tracking: &ApTracking,
) -> Result<(), HintError> {
    print_name(vm, ids_data, ap_tracking)?;

    let mut acc = Vec::new();
    let arr = get_ptr_from_var_name("arr", vm, ids_data, ap_tracking)?;
    let arr_len = get_integer_from_var_name("arr_len", vm, ids_data, ap_tracking)?;
    let arr_len = arr_len.to_usize().ok_or_else(|| {
        HintError::CustomHint(String::from("arr_len must be a positive integer").into_boxed_str())
    })?;
    for i in 0..arr_len {
        let val = vm.get_integer((arr + i)?)?;
        acc.push(val);
    }
    println!("{:?}", acc);
    Ok(())
}

enum DictValue {
    Int(Felt252),
    Relocatable(Vec<Felt252>),
}

impl Debug for DictValue {
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::Int(int) => write!(f, "{:?}", int),
            Self::Relocatable(relocatable) => write!(f, "{:?}", relocatable),
        }
    }
}

pub fn print_dict(
    vm: &VirtualMachine,
    exec_scopes: &ExecutionScopes,
    ids_data: &HashMap<String, HintReference>,
    ap_tracking: &ApTracking,
) -> Result<(), HintError> {
    print_name(vm, ids_data, ap_tracking)?;

    let dict_ptr = get_ptr_from_var_name("dict_ptr", vm, ids_data, ap_tracking)?;
    let pointer_size = get_integer_from_var_name("pointer_size", vm, ids_data, ap_tracking)?;
    let pointer_size = pointer_size.to_usize().ok_or_else(|| {
        HintError::CustomHint(
            String::from("pointer_size must be a positive integer").into_boxed_str(),
        )
    })?;

    let dict_manager = exec_scopes.get_dict_manager()?;
    let dict_manager = dict_manager.borrow();
    let tracker = dict_manager.get_tracker(dict_ptr)?;

    let map = match &tracker.data {
        Dictionary::SimpleDictionary(dict) => dict,
        Dictionary::DefaultDictionary { dict, .. } => dict,
    };

    let mut acc = HashMap::new();
    for (k, v) in map.iter() {
        let key = k.get_int_ref().ok_or_else(|| {
            HintError::CustomHint(String::from("Expected felt key for dict").into_boxed_str())
        })?;
        match v {
            MaybeRelocatable::Int(value) => {
                acc.insert(key, DictValue::Int(*value));
            }
            MaybeRelocatable::RelocatableValue(val) => {
                let mut structure = Vec::new();
                for i in 0..pointer_size {
                    let val = *vm.get_integer((*val + i)?)?.as_ref();
                    structure.push(val);
                }
                acc.insert(key, DictValue::Relocatable(structure));
            }
        }
    }

    println!("{:?}", acc);
    Ok(())
}