leo_ast/expressions/
unary.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use super::*;
18use leo_span::{Symbol, sym};
19
20/// A unary operator for a unary expression.
21#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub enum UnaryOperation {
23    /// Absolute value checking for overflow, i.e. `.abs()`.
24    Abs,
25    /// Absolute value wrapping around at the boundary of the type, i.e. `.abs_wrapped()`.
26    AbsWrapped,
27    /// Double operation, i.e. `.double()`.
28    Double,
29    /// Multiplicative inverse, i.e. `.inv()`.
30    Inverse,
31    /// Negate operation, i.e. `.neg()`.
32    Negate,
33    /// Bitwise NOT, i.e. `!`, `.not()`.
34    Not,
35    /// Square operation, i.e. `.square()`.
36    Square,
37    /// Square root operation, i.e. `.sqrt()`.
38    SquareRoot,
39    /// Converts a group element to its x-coordinate, i.e. `.to_x_coordinate()`.
40    ToXCoordinate,
41    /// Converts a group element to its y-coordinate, i.e. `.to_y_coordinate()`.
42    ToYCoordinate,
43}
44
45impl UnaryOperation {
46    /// Returns a `UnaryOperation` from the given `Symbol`.
47    pub fn from_symbol(symbol: Symbol) -> Option<Self> {
48        Some(match symbol {
49            sym::abs => Self::Abs,
50            sym::abs_wrapped => Self::AbsWrapped,
51            sym::double => Self::Double,
52            sym::inv => Self::Inverse,
53            sym::neg => Self::Negate,
54            sym::not => Self::Not,
55            sym::square => Self::Square,
56            sym::square_root => Self::SquareRoot,
57            sym::to_x_coordinate => Self::ToXCoordinate,
58            sym::to_y_coordinate => Self::ToYCoordinate,
59            _ => return None,
60        })
61    }
62
63    /// Represents the operator as a string.
64    fn as_str(self) -> &'static str {
65        match self {
66            Self::Abs => "abs",
67            Self::AbsWrapped => "abs_wrapped",
68            Self::Double => "double",
69            Self::Inverse => "inv",
70            Self::Negate => "neg",
71            Self::Not => "not",
72            Self::Square => "square",
73            Self::SquareRoot => "square_root",
74            Self::ToXCoordinate => "to_x_coordinate",
75            Self::ToYCoordinate => "to_y_coordinate",
76        }
77    }
78}
79
80impl fmt::Display for UnaryOperation {
81    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82        write!(f, "{}", self.as_str())
83    }
84}
85
86/// An unary expression applying an operator to an inner expression.
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
88pub struct UnaryExpression {
89    /// The inner expression `op` is applied to.
90    pub receiver: Expression,
91    /// The unary operator to apply to `inner`.
92    pub op: UnaryOperation,
93    /// The span covering `op inner`.
94    pub span: Span,
95    /// The ID of the node.
96    pub id: NodeID,
97}
98
99impl fmt::Display for UnaryExpression {
100    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101        if self.receiver.precedence() < 20 {
102            write!(f, "({})", self.receiver)?;
103        } else {
104            write!(f, "{}", self.receiver)?;
105        }
106        write!(f, ".{}()", self.op)
107    }
108}
109
110impl From<UnaryExpression> for Expression {
111    fn from(value: UnaryExpression) -> Self {
112        Expression::Unary(Box::new(value))
113    }
114}
115
116crate::simple_node_impl!(UnaryExpression);