oris 0.2.1

An interpreter for Monkey
Documentation
use crate::{eval::value::Value, parse::ast};

#[derive(Debug)]
pub(crate) enum Error {
    AssertEq {
        pos: usize,
        left: Value,
        right: Value,
    },
    Parse(crate::parse::Error),
    Undefined(ast::Ident),
    Index {
        pos: usize,
        base: Value,
        subscript: Value,
    },
    Unary {
        pos: usize,
        op: ast::UnaryOp,
        operand: Value,
    },
    Binary {
        pos: usize,
        left: Value,
        op: ast::BinaryOp,
        right: Value,
    },
    Call {
        pos: usize,
        target: Value,
        args: Box<[Value]>,
    },
    ArgCount {
        pos: usize,
        supplied: usize,
        expected: usize,
    },
    ArgType {
        pos: usize,
        supplied: Value,
        expected: &'static str,
    },
    ArgValue {
        pos: usize,
        message: &'static str,
    },
}

impl Error {
    pub(crate) fn pos(&self) -> usize {
        match self {
            Self::AssertEq { pos, .. } => *pos,
            Self::Parse(error) => error.pos(),
            Self::Undefined(ident) => ident.pos(),
            Self::Index { pos, .. } => *pos,
            Self::Unary { pos, .. } => *pos,
            Self::Binary { pos, .. } => *pos,
            Self::Call { pos, .. } => *pos,
            Self::ArgCount { pos, .. } => *pos,
            Self::ArgType { pos, .. } => *pos,
            Self::ArgValue { pos, .. } => *pos,
        }
    }
}

impl From<crate::parse::Error> for Error {
    fn from(err: crate::parse::Error) -> Self {
        Self::Parse(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match &self {
            Self::AssertEq {
                pos: _,
                left,
                right,
            } => {
                f.write_str("assert_eq failed\n")?;
                write!(f, " left: {:?}\n", left)?;
                write!(f, "right: {:?}", right)?;
                Ok(())
            }
            Self::Undefined(ident) => {
                write!(f, "undefined identifier: {}", ident)
            }
            Self::Index {
                pos: _,
                base,
                subscript,
            } => {
                write!(f, "index {:?} with {:?}", base, subscript)
            }
            Self::Unary {
                pos: _,
                op,
                operand,
            } => {
                write!(f, "invalid unary operator {} for {:?}", op, operand)
            }
            Self::Binary {
                pos: _,
                left,
                op,
                right,
            } => {
                write!(
                    f,
                    "invalid binary operator {} between {:?} and {:?}",
                    op, left, right
                )
            }
            Self::Call { target, .. } => {
                write!(f, "{:?} is not callable", target)
            }
            Self::ArgCount {
                pos: _,
                supplied,
                expected,
            } => {
                write!(f, "accept arg x {}, but got {}", expected, supplied)
            }
            Self::ArgType {
                pos: _,
                supplied,
                expected,
            } => {
                write!(f, "accept arg of type {}, but got {:?}", expected, supplied)
            }
            Self::ArgValue { pos: _, message } => f.write_str(message),
            Self::Parse(error) => error.fmt(f),
        }
    }
}