ralix 0.2.0

A simple, type-safe, tree walking interpreter
use std::collections::HashMap;

use crate::{
    Addr, EvalResult, Evaluator, Expression, HashKey, HashPair, RuntimeError, Value,
    try_eval_result,
};

impl Evaluator<'_> {
    pub fn evaluate_index_expression(
        &mut self,
        left: Expression,
        index: Expression,
    ) -> EvalResult<Value> {
        let left_obj = try_eval_result!(self.evaluate_expression(left));
        let index_obj = try_eval_result!(self.evaluate_expression(index));

        match (left_obj, index_obj) {
            (Value::Array(arr), Value::Int(index)) => {
                self.evaluate_array_index_expression(arr, index)
            }
            (Value::HashMap(hash_map), index) => {
                self.evaluate_hashmap_index_expression(hash_map, index)
            }
            (o1, o2) => EvalResult::Err(RuntimeError::UnsupportedIndexOperation(
                o1.r#type(self.ctx.heap),
                o2.r#type(self.ctx.heap),
            )),
        }
    }

    fn evaluate_array_index_expression(&mut self, arr: Vec<Addr>, index: i64) -> EvalResult<Value> {
        let Some(addr) = arr.get(index as usize) else {
            return Value::NULL.into();
        };

        self.ctx.heap.read(addr).cloned().into()
    }

    fn evaluate_hashmap_index_expression(
        &mut self,
        hash_map: HashMap<HashKey, HashPair>,
        index: Value,
    ) -> EvalResult<Value> {
        let hash_key = index.hash_key().unwrap();

        let Some((_, value_addr)) = hash_map.get(&hash_key) else {
            return Value::NULL.into();
        };

        self.ctx.heap.read(value_addr).cloned().into()
    }
}