#![allow(unsafe_code)]
use super::value::Value;
#[derive(Debug)]
#[allow(dead_code)]
pub struct CallFrame {
pub(crate) closure: Value,
pub(crate) ip: *const u8,
pub(crate) base: usize,
pub(crate) locals: usize,
}
unsafe impl Send for CallFrame {}
#[derive(Debug)]
pub enum InterpreterResult {
Continue,
Jump(usize),
Return(Value),
Error(InterpreterError),
}
#[derive(Debug, Clone)]
pub enum InterpreterError {
TypeError(String),
RuntimeError(String),
StackOverflow,
StackUnderflow,
InvalidInstruction,
DivisionByZero,
IndexOutOfBounds,
Break(Option<String>, Value),
Continue(Option<String>),
Return(Value),
Throw(Value),
AssertionFailed(String),
RecursionLimitExceeded(usize, usize),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_interpreter_error_type_error() {
let err = InterpreterError::TypeError("expected i64".to_string());
match err {
InterpreterError::TypeError(msg) => assert_eq!(msg, "expected i64"),
_ => panic!("Expected TypeError"),
}
}
#[test]
fn test_interpreter_error_runtime_error() {
let err = InterpreterError::RuntimeError("undefined variable".to_string());
match err {
InterpreterError::RuntimeError(msg) => assert_eq!(msg, "undefined variable"),
_ => panic!("Expected RuntimeError"),
}
}
#[test]
fn test_interpreter_error_stack_overflow() {
let err = InterpreterError::StackOverflow;
assert!(matches!(err, InterpreterError::StackOverflow));
}
#[test]
fn test_interpreter_error_stack_underflow() {
let err = InterpreterError::StackUnderflow;
assert!(matches!(err, InterpreterError::StackUnderflow));
}
#[test]
fn test_interpreter_error_division_by_zero() {
let err = InterpreterError::DivisionByZero;
assert!(matches!(err, InterpreterError::DivisionByZero));
}
#[test]
fn test_interpreter_error_index_out_of_bounds() {
let err = InterpreterError::IndexOutOfBounds;
assert!(matches!(err, InterpreterError::IndexOutOfBounds));
}
#[test]
fn test_interpreter_error_break() {
let err = InterpreterError::Break(Some("outer".to_string()), Value::Integer(42));
match err {
InterpreterError::Break(Some(label), Value::Integer(val)) => {
assert_eq!(label, "outer");
assert_eq!(val, 42);
}
_ => panic!("Expected Break"),
}
}
#[test]
fn test_interpreter_error_continue() {
let err = InterpreterError::Continue(None);
assert!(matches!(err, InterpreterError::Continue(None)));
}
#[test]
fn test_interpreter_error_return() {
let err = InterpreterError::Return(Value::Bool(true));
match err {
InterpreterError::Return(Value::Bool(b)) => assert!(b),
_ => panic!("Expected Return"),
}
}
#[test]
fn test_interpreter_error_throw() {
let err = InterpreterError::Throw(Value::from_string("error message".to_string()));
assert!(matches!(err, InterpreterError::Throw(_)));
}
#[test]
fn test_interpreter_error_assertion_failed() {
let err = InterpreterError::AssertionFailed("expected true".to_string());
match err {
InterpreterError::AssertionFailed(msg) => assert_eq!(msg, "expected true"),
_ => panic!("Expected AssertionFailed"),
}
}
#[test]
fn test_interpreter_error_recursion_limit() {
let err = InterpreterError::RecursionLimitExceeded(101, 100);
match err {
InterpreterError::RecursionLimitExceeded(current, max) => {
assert_eq!(current, 101);
assert_eq!(max, 100);
}
_ => panic!("Expected RecursionLimitExceeded"),
}
}
#[test]
fn test_interpreter_error_clone() {
let err = InterpreterError::TypeError("test".to_string());
let cloned = err.clone();
assert!(matches!(cloned, InterpreterError::TypeError(_)));
}
#[test]
fn test_interpreter_result_continue() {
let result = InterpreterResult::Continue;
assert!(matches!(result, InterpreterResult::Continue));
}
#[test]
fn test_interpreter_result_jump() {
let result = InterpreterResult::Jump(42);
match result {
InterpreterResult::Jump(addr) => assert_eq!(addr, 42),
_ => panic!("Expected Jump"),
}
}
#[test]
fn test_interpreter_result_return() {
let result = InterpreterResult::Return(Value::Integer(100));
match result {
InterpreterResult::Return(Value::Integer(val)) => assert_eq!(val, 100),
_ => panic!("Expected Return"),
}
}
#[test]
fn test_interpreter_result_error() {
let result = InterpreterResult::Error(InterpreterError::DivisionByZero);
assert!(matches!(
result,
InterpreterResult::Error(InterpreterError::DivisionByZero)
));
}
#[test]
fn test_call_frame_creation() {
let frame = CallFrame {
closure: Value::Nil,
ip: std::ptr::null(),
base: 0,
locals: 5,
};
assert_eq!(frame.base, 0);
assert_eq!(frame.locals, 5);
}
#[test]
fn test_call_frame_is_send() {
fn assert_send<T: Send>() {}
assert_send::<CallFrame>();
}
}