expr-lang 1.1.1

Implementation of expr language in Rust
Documentation
use crate::ast::node::Node;
use crate::Rule;
use crate::Value::Bool;
use crate::{bail, Result};
use crate::{Context, Environment, Value};
use log::trace;
use pest::iterators::Pair;
use std::str::FromStr;

#[derive(Debug, Clone, strum::EnumString)]
pub enum UnaryOperator {
    #[strum(serialize = "!")]
    Not,
    #[strum(serialize = "+")]
    Positive,
    #[strum(serialize = "-")]
    Negative,
}

impl From<Pair<'_, Rule>> for UnaryOperator {
    fn from(pair: Pair<Rule>) -> Self {
        trace!("[unary_operator] {pair:?}");
        match pair.as_str() {
            "not" => UnaryOperator::Not,
            op => UnaryOperator::from_str(op)
                .unwrap_or_else(|_| unreachable!("Invalid operator {op}")),
        }
    }
}

impl Environment<'_> {
    pub fn eval_unary_operator(
        &self,
        ctx: &Context,
        operator: UnaryOperator,
        node: Node,
    ) -> Result<Value> {
        let node = self.eval_expr(ctx, node)?;
        let result = match operator {
            UnaryOperator::Not => match node {
                Bool(b) => Bool(!b),
                _ => bail!("Invalid operand for operator !"),
            },
            UnaryOperator::Positive => match node {
                Value::Number(n) => Value::Number(n),
                Value::Float(f) => Value::Float(f),
                _ => bail!("Invalid operand for operator +"),
            },
            UnaryOperator::Negative => match node {
                Value::Number(n) => Value::Number(-n),
                Value::Float(f) => Value::Float(-f),
                _ => bail!("Invalid operand for operator -"),
            },
        };

        Ok(result)
    }
}