use grift_parser::{ArenaIndex, ArenaError, ParseError};
pub const MAX_STACK_DEPTH: usize = 64;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum ErrorKind {
OutOfMemory = 0,
UnboundVariable = 1,
NotAFunction = 2,
WrongArgCount = 3,
TypeError = 4,
DivisionByZero = 5,
Parse = 6,
UserError = 7,
StackOverflow = 8,
NotAPair = 9,
Generic = 10,
SyntaxError = 11,
}
impl ErrorKind {
pub const fn as_str(&self) -> &'static str {
match self {
ErrorKind::OutOfMemory => "out of memory",
ErrorKind::UnboundVariable => "unbound variable",
ErrorKind::NotAFunction => "not a function",
ErrorKind::WrongArgCount => "wrong number of arguments",
ErrorKind::TypeError => "type error",
ErrorKind::DivisionByZero => "division by zero",
ErrorKind::Parse => "parse error",
ErrorKind::UserError => "error",
ErrorKind::StackOverflow => "stack overflow",
ErrorKind::NotAPair => "not a pair",
ErrorKind::Generic => "error",
ErrorKind::SyntaxError => "syntax error",
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct StackFrame {
pub expr: ArenaIndex,
pub func: ArenaIndex,
}
impl Default for StackFrame {
fn default() -> Self {
StackFrame {
expr: ArenaIndex::NIL,
func: ArenaIndex::NIL,
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ArgCountInfo {
pub expected: u16,
pub got: u16,
}
impl ArgCountInfo {
pub const fn new(expected: usize, got: usize) -> Self {
ArgCountInfo {
expected: expected as u16,
got: got as u16,
}
}
}
#[derive(Debug)]
pub struct EvalError {
pub kind: ErrorKind,
pub expr: ArenaIndex,
pub message: &'static str,
pub expected: Option<&'static str>,
pub got: Option<&'static str>,
pub arg_info: Option<ArgCountInfo>,
pub parse_error: Option<ParseError>,
}
impl EvalError {
pub const fn new(kind: ErrorKind) -> Self {
EvalError {
kind,
expr: ArenaIndex::NIL,
message: "",
expected: None,
got: None,
arg_info: None,
parse_error: None,
}
}
pub const fn with_expr(mut self, expr: ArenaIndex) -> Self {
self.expr = expr;
self
}
pub const fn with_message(mut self, msg: &'static str) -> Self {
self.message = msg;
self
}
pub const fn with_types(mut self, expected: &'static str, got: &'static str) -> Self {
self.expected = Some(expected);
self.got = Some(got);
self
}
pub const fn with_args(mut self, expected: usize, got: usize) -> Self {
self.arg_info = Some(ArgCountInfo::new(expected, got));
self
}
pub fn from_parse_error(e: ParseError, expr: ArenaIndex) -> Self {
let mut err = EvalError::new(ErrorKind::Parse);
err.parse_error = Some(e);
err.expr = expr;
err
}
}
impl From<ArenaError> for EvalError {
fn from(e: ArenaError) -> Self {
match e {
ArenaError::OutOfMemory => EvalError::new(ErrorKind::OutOfMemory),
_ => EvalError::new(ErrorKind::Generic),
}
}
}
impl From<ParseError> for EvalError {
fn from(e: ParseError) -> Self {
let mut err = EvalError::new(ErrorKind::Parse);
err.parse_error = Some(e);
err
}
}
pub type EvalResult = Result<ArenaIndex, EvalError>;