glowdust 0.0.1

A DBMS with a data model based on functions and pattern matching
Documentation
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;

// All these are mostly examples, don't feel bound by them at all
#[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 {}