use crate::runtime::bytecode::OpCode;
use crate::runtime::RuntimeErrorType::{
CompilerError, InputOutputError, SchemaError, StackError, ValueTypeError,
};
use std::error::Error;
use std::fmt;
use std::fmt::Display;
pub mod bytecode;
pub mod compiled_script;
pub mod disassembler;
pub mod sink;
pub mod vm;
#[derive(Debug)]
pub enum RuntimeErrorType {
ValueTypeError(RuntimeState),
StackError(RuntimeState),
CompilerError(RuntimeState),
InputOutputError,
SchemaError,
OtherError,
}
impl Display for RuntimeErrorType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ValueTypeError(rt_state) => {
write!(f, "Value type error: {}", rt_state)?;
}
StackError(rt_state) => {
write!(f, "Stack error: {}", rt_state)?;
}
CompilerError(rt_state) => {
write!(f, "Compiler error: {}", rt_state)?;
}
InputOutputError => {
write!(f, "I/O error",)?;
}
SchemaError => {
write!(f, "Schema error",)?;
}
RuntimeErrorType::OtherError => {
write!(f, "Other")?;
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct RuntimeState {
ip: usize,
op_code: OpCode,
}
impl Display for RuntimeState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "IP: {}, OpCode: {}", self.ip, self.op_code)?;
Ok(())
}
}
#[derive(Debug)]
pub struct RuntimeError {
pub message: String,
pub error_type: RuntimeErrorType,
}
impl RuntimeError {
pub fn new_value_error(message: String, ip: usize, op_code: OpCode) -> Self {
RuntimeError {
message,
error_type: ValueTypeError(RuntimeState { ip, op_code }),
}
}
pub fn new_stack_error(message: String, ip: usize, op_code: OpCode) -> Self {
RuntimeError {
message,
error_type: StackError(RuntimeState { ip, op_code }),
}
}
pub fn new_compiler_error(message: String, ip: usize, op_code: OpCode) -> Self {
RuntimeError {
message,
error_type: CompilerError(RuntimeState { ip, op_code }),
}
}
pub fn new_io_error(message: String) -> Self {
RuntimeError {
message,
error_type: InputOutputError,
}
}
pub fn new_schema_error(message: String) -> Self {
RuntimeError {
message,
error_type: SchemaError,
}
}
}
impl Display for RuntimeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Runtime error: {} ({})", self.message, self.error_type,)?;
Ok(())
}
}
impl From<std::io::Error> for RuntimeError {
fn from(value: std::io::Error) -> Self {
RuntimeError::new_io_error(value.to_string())
}
}
impl Error for RuntimeError {}