expr-lang 2.1.0

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::{ContextProvider, Environment, Value};
use log::trace;
use pest::iterators::Pair;

#[derive(Debug, Clone)]
pub enum UnaryOperator {
    Not,
    Positive,
    Negative,
}

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

impl Environment<'_> {
    pub fn eval_unary_operator(
        &self,
        ctx: &dyn ContextProvider,
        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::Integer(n) => Value::Integer(n),
                Value::Float(f) => Value::Float(f),
                _ => bail!("Invalid operand for operator +"),
            },
            UnaryOperator::Negative => match node {
                Value::Integer(n) => Value::Integer(n.wrapping_neg()),
                Value::Float(f) => Value::Float(-f),
                _ => bail!("Invalid operand for operator -"),
            },
        };

        Ok(result)
    }
}