leo_ast/expressions/
mod.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 crate::{Identifier, Node, NodeID};
18use leo_span::Span;
19
20use serde::{Deserialize, Serialize};
21use std::fmt;
22
23mod array_access;
24pub use array_access::*;
25
26mod associated_constant;
27pub use associated_constant::*;
28
29mod associated_function;
30pub use associated_function::*;
31
32mod array;
33pub use array::*;
34
35mod binary;
36pub use binary::*;
37
38mod call;
39pub use call::*;
40
41mod cast;
42pub use cast::*;
43
44mod err;
45pub use err::*;
46
47mod member_access;
48pub use member_access::*;
49
50mod struct_init;
51pub use struct_init::*;
52
53mod ternary;
54pub use ternary::*;
55
56mod tuple;
57pub use tuple::*;
58
59mod tuple_access;
60pub use tuple_access::*;
61
62mod unary;
63pub use unary::*;
64
65mod unit;
66pub use unit::*;
67
68mod literal;
69pub use literal::*;
70
71pub mod locator;
72pub use locator::*;
73
74/// Expression that evaluates to a value.
75#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
76pub enum Expression {
77    /// An array access, e.g. `arr[i]`.
78    ArrayAccess(Box<ArrayAccess>),
79    /// An associated constant; e.g., `group::GEN`.
80    AssociatedConstant(AssociatedConstantExpression),
81    /// An associated function; e.g., `BHP256::hash_to_field`.
82    AssociatedFunction(AssociatedFunctionExpression),
83    /// An array expression, e.g., `[true, false, true, false]`.
84    Array(ArrayExpression),
85    /// A binary expression, e.g., `42 + 24`.
86    Binary(Box<BinaryExpression>),
87    /// A call expression, e.g., `my_fun(args)`.
88    Call(Box<CallExpression>),
89    /// A cast expression, e.g., `42u32 as u8`.
90    Cast(Box<CastExpression>),
91    /// An expression of type "error".
92    /// Will result in a compile error eventually.
93    Err(ErrExpression),
94    /// An identifier.
95    Identifier(Identifier),
96    /// A literal expression.
97    Literal(Literal),
98    /// A locator expression, e.g., `hello.aleo/foo`.
99    Locator(LocatorExpression),
100    /// An access of a struct member, e.g. `struc.member`.
101    MemberAccess(Box<MemberAccess>),
102    /// An expression constructing a struct like `Foo { bar: 42, baz }`.
103    Struct(StructExpression),
104    /// A ternary conditional expression `cond ? if_expr : else_expr`.
105    Ternary(Box<TernaryExpression>),
106    /// A tuple expression e.g., `(foo, 42, true)`.
107    Tuple(TupleExpression),
108    /// A tuple access expression e.g., `foo.2`.
109    TupleAccess(Box<TupleAccess>),
110    /// An unary expression.
111    Unary(Box<UnaryExpression>),
112    /// A unit expression e.g. `()`
113    Unit(UnitExpression),
114}
115
116impl Default for Expression {
117    fn default() -> Self {
118        Expression::Err(Default::default())
119    }
120}
121
122impl Node for Expression {
123    fn span(&self) -> Span {
124        use Expression::*;
125        match self {
126            ArrayAccess(n) => n.span(),
127            Array(n) => n.span(),
128            AssociatedConstant(n) => n.span(),
129            AssociatedFunction(n) => n.span(),
130            Binary(n) => n.span(),
131            Call(n) => n.span(),
132            Cast(n) => n.span(),
133            Err(n) => n.span(),
134            Identifier(n) => n.span(),
135            Literal(n) => n.span(),
136            Locator(n) => n.span(),
137            MemberAccess(n) => n.span(),
138            Struct(n) => n.span(),
139            Ternary(n) => n.span(),
140            Tuple(n) => n.span(),
141            TupleAccess(n) => n.span(),
142            Unary(n) => n.span(),
143            Unit(n) => n.span(),
144        }
145    }
146
147    fn set_span(&mut self, span: Span) {
148        use Expression::*;
149        match self {
150            ArrayAccess(n) => n.set_span(span),
151            Array(n) => n.set_span(span),
152            AssociatedConstant(n) => n.set_span(span),
153            AssociatedFunction(n) => n.set_span(span),
154            Binary(n) => n.set_span(span),
155            Call(n) => n.set_span(span),
156            Cast(n) => n.set_span(span),
157            Err(n) => n.set_span(span),
158            Identifier(n) => n.set_span(span),
159            Literal(n) => n.set_span(span),
160            Locator(n) => n.set_span(span),
161            MemberAccess(n) => n.set_span(span),
162            Struct(n) => n.set_span(span),
163            Ternary(n) => n.set_span(span),
164            Tuple(n) => n.set_span(span),
165            TupleAccess(n) => n.set_span(span),
166            Unary(n) => n.set_span(span),
167            Unit(n) => n.set_span(span),
168        }
169    }
170
171    fn id(&self) -> NodeID {
172        use Expression::*;
173        match self {
174            Array(n) => n.id(),
175            ArrayAccess(n) => n.id(),
176            AssociatedConstant(n) => n.id(),
177            AssociatedFunction(n) => n.id(),
178            Binary(n) => n.id(),
179            Call(n) => n.id(),
180            Cast(n) => n.id(),
181            Identifier(n) => n.id(),
182            Literal(n) => n.id(),
183            Locator(n) => n.id(),
184            MemberAccess(n) => n.id(),
185            Err(n) => n.id(),
186            Struct(n) => n.id(),
187            Ternary(n) => n.id(),
188            Tuple(n) => n.id(),
189            TupleAccess(n) => n.id(),
190            Unary(n) => n.id(),
191            Unit(n) => n.id(),
192        }
193    }
194
195    fn set_id(&mut self, id: NodeID) {
196        use Expression::*;
197        match self {
198            Array(n) => n.set_id(id),
199            ArrayAccess(n) => n.set_id(id),
200            AssociatedConstant(n) => n.set_id(id),
201            AssociatedFunction(n) => n.set_id(id),
202            Binary(n) => n.set_id(id),
203            Call(n) => n.set_id(id),
204            Cast(n) => n.set_id(id),
205            Identifier(n) => n.set_id(id),
206            Literal(n) => n.set_id(id),
207            Locator(n) => n.set_id(id),
208            MemberAccess(n) => n.set_id(id),
209            Err(n) => n.set_id(id),
210            Struct(n) => n.set_id(id),
211            Ternary(n) => n.set_id(id),
212            Tuple(n) => n.set_id(id),
213            TupleAccess(n) => n.set_id(id),
214            Unary(n) => n.set_id(id),
215            Unit(n) => n.set_id(id),
216        }
217    }
218}
219
220impl fmt::Display for Expression {
221    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
222        use Expression::*;
223        match &self {
224            Array(n) => n.fmt(f),
225            ArrayAccess(n) => n.fmt(f),
226            AssociatedConstant(n) => n.fmt(f),
227            AssociatedFunction(n) => n.fmt(f),
228            Binary(n) => n.fmt(f),
229            Call(n) => n.fmt(f),
230            Cast(n) => n.fmt(f),
231            Err(n) => n.fmt(f),
232            Identifier(n) => n.fmt(f),
233            Literal(n) => n.fmt(f),
234            Locator(n) => n.fmt(f),
235            MemberAccess(n) => n.fmt(f),
236            Struct(n) => n.fmt(f),
237            Ternary(n) => n.fmt(f),
238            Tuple(n) => n.fmt(f),
239            TupleAccess(n) => n.fmt(f),
240            Unary(n) => n.fmt(f),
241            Unit(n) => n.fmt(f),
242        }
243    }
244}
245
246#[derive(Clone, Copy, Eq, PartialEq)]
247pub(crate) enum Associativity {
248    Left,
249    Right,
250    None,
251}
252
253impl Expression {
254    pub(crate) fn precedence(&self) -> u32 {
255        use Expression::*;
256        match self {
257            Binary(e) => e.precedence(),
258            Cast(_) => 12,
259            Ternary(_) => 14,
260            Array(_)
261            | ArrayAccess(_)
262            | AssociatedConstant(_)
263            | AssociatedFunction(_)
264            | Call(_)
265            | Err(_)
266            | Identifier(_)
267            | Literal(_)
268            | Locator(_)
269            | MemberAccess(_)
270            | Struct(_)
271            | Tuple(_)
272            | TupleAccess(_)
273            | Unary(_)
274            | Unit(_) => 20,
275        }
276    }
277
278    pub(crate) fn associativity(&self) -> Associativity {
279        if let Expression::Binary(bin) = self { bin.associativity() } else { Associativity::None }
280    }
281}