expr/ast/
unary_operator.rs1use crate::ast::node::Node;
2use crate::Rule;
3use crate::Value::Bool;
4use crate::{bail, Result};
5use crate::{ContextProvider, Environment, Value};
6use log::trace;
7use pest::iterators::Pair;
8
9#[derive(Debug, Clone)]
10pub enum UnaryOperator {
11 Not,
12 Positive,
13 Negative,
14}
15
16impl From<Pair<'_, Rule>> for UnaryOperator {
17 fn from(pair: Pair<Rule>) -> Self {
18 trace!("[unary_operator] {pair:?}");
19 match pair.as_str() {
20 "not" | "!" => UnaryOperator::Not,
21 "+" => UnaryOperator::Positive,
22 "-" => UnaryOperator::Negative,
23 op => unreachable!("Invalid operator {op}"),
24 }
25 }
26}
27
28impl Environment<'_> {
29 pub fn eval_unary_operator(
30 &self,
31 ctx: &dyn ContextProvider,
32 operator: &UnaryOperator,
33 node: &Node,
34 ) -> Result<Value> {
35 let node = self.eval_expr(ctx, node)?;
36 let result = match operator {
37 UnaryOperator::Not => match node {
38 Bool(b) => Bool(!b),
39 _ => bail!("Invalid operand for operator !"),
40 },
41 UnaryOperator::Positive => match node {
42 Value::Integer(n) => Value::Integer(n),
43 Value::Float(f) => Value::Float(f),
44 _ => bail!("Invalid operand for operator +"),
45 },
46 UnaryOperator::Negative => match node {
47 Value::Integer(n) => Value::Integer(n.wrapping_neg()),
48 Value::Float(f) => Value::Float(-f),
49 _ => bail!("Invalid operand for operator -"),
50 },
51 };
52
53 Ok(result)
54 }
55}