typed-eval 0.1.0

A type-safe expression evaluation engine.
Documentation
use crate::{BinOp, TypeInfo, UnOp};
use chumsky::error::{Rich, RichReason};
use thiserror::Error;

#[derive(Debug, PartialEq, Error)]
pub enum Error {
    #[error("Invalid float literal: {0}")]
    InvalidLiteral(String),

    #[error("Wrong number of arguments: expected {expected}, got {got}")]
    ArgCountMismatch { expected: usize, got: usize },

    #[error("Cannot cast from type `{from}` to `{to}`")]
    CantCast { from: TypeInfo, to: TypeInfo },

    #[error("Cannot cast expressions of type `{0}` and `{1}` to same type")]
    CantCastSameType(TypeInfo, TypeInfo),

    #[error("No unary operator {op:?} for type `{ty}`")]
    UnknownUnaryOp { op: UnOp, ty: TypeInfo },

    #[error("No binary operator {op:?} for type `{ty}`")]
    UnknownBinaryOp { op: BinOp, ty: TypeInfo },

    #[error("Field `{field}` not found for type `{ty}`")]
    FieldNotFound { ty: TypeInfo, field: String },

    #[error("Method `{method}` not found for type `{ty}`")]
    MethodNotFound { ty: TypeInfo, method: String },

    #[error("Unsupported function call")]
    UnsupportedFunctionCall,

    #[error("Cast from `{from}` to `{to}` already registered")]
    DuplicateCast { from: TypeInfo, to: TypeInfo },

    #[error("Unary operation {op:?} on type `{ty}` already registered")]
    DuplicateUnOp { op: UnOp, ty: TypeInfo },

    #[error("Binary operation {op:?} on type `{ty}` already registered")]
    DuplicateBinOp { op: BinOp, ty: TypeInfo },

    #[error("Field access `{field}` on type `{ty}` already registered")]
    DuplicateField { ty: TypeInfo, field: &'static str },

    #[error("Method `{method}` on type `{ty}` already registered")]
    DuplicateMethod { ty: TypeInfo, method: &'static str },

    #[error("Parse error: expected: {expected:?}, found {found:?}")]
    ParseError {
        expected: Vec<String>,
        found: String,
    },

    #[error("Parse error: {message}")]
    CustomParseError { message: String },

    #[error("Unknown error")]
    UnknownError,

    #[error(
        "Internal compiler error: Wrong number of arguments, expected {expected}, got {got}"
    )]
    InternalArgCountMismatch { expected: usize, got: usize },

    #[error(
        "Internal compiler error: DynFn downcast failed, expected {expected_arg}->{expected_ret}, got {got_arg}->{got_ret}"
    )]
    InternalDynFnDowncastError {
        expected_arg: TypeInfo,
        expected_ret: TypeInfo,
        got_arg: TypeInfo,
        got_ret: TypeInfo,
    },
}

impl<'a> From<Rich<'a, char>> for Error {
    fn from(value: Rich<'a, char>) -> Self {
        match value.into_reason() {
            RichReason::Custom(message) => Error::CustomParseError { message },
            RichReason::ExpectedFound { expected, found } => {
                Error::ParseError {
                    expected: expected
                        .into_iter()
                        .map(|c| c.to_string())
                        .collect::<Vec<_>>(),
                    found: found
                        .map(|c| c.to_string())
                        .unwrap_or_else(|| "End of input".to_string()),
                }
            }
        }
    }
}