1use crate::{Identifier, IntegerType, Intrinsic, Location, Node, NodeBuilder, NodeID, Path, Type};
18use leo_span::{Span, Symbol};
19
20use serde::{Deserialize, Serialize};
21use std::fmt;
22
23mod array_access;
24pub use array_access::*;
25
26mod async_;
27pub use async_::*;
28
29mod array;
30pub use array::*;
31
32mod binary;
33pub use binary::*;
34
35mod call;
36pub use call::*;
37
38mod cast;
39pub use cast::*;
40
41mod composite_init;
42pub use composite_init::*;
43
44mod err;
45pub use err::*;
46
47mod member_access;
48pub use member_access::*;
49
50mod intrinsic;
51pub use intrinsic::*;
52
53mod repeat;
54pub use repeat::*;
55
56mod ternary;
57pub use ternary::*;
58
59mod tuple;
60pub use tuple::*;
61
62mod tuple_access;
63pub use tuple_access::*;
64
65mod unary;
66pub use unary::*;
67
68mod unit;
69pub use unit::*;
70
71mod literal;
72pub use literal::*;
73
74#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
76pub enum Expression {
77 ArrayAccess(Box<ArrayAccess>),
79 Async(AsyncExpression),
81 Array(ArrayExpression),
83 Binary(Box<BinaryExpression>),
85 Intrinsic(Box<IntrinsicExpression>),
87 Call(Box<CallExpression>),
89 Cast(Box<CastExpression>),
91 Composite(CompositeExpression),
95 Err(ErrExpression),
96 Path(Path),
98 Literal(Literal),
100 MemberAccess(Box<MemberAccess>),
102 Repeat(Box<RepeatExpression>),
104 Ternary(Box<TernaryExpression>),
106 Tuple(TupleExpression),
108 TupleAccess(Box<TupleAccess>),
110 Unary(Box<UnaryExpression>),
112 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 Async(n) => n.span(),
129 Binary(n) => n.span(),
130 Call(n) => n.span(),
131 Cast(n) => n.span(),
132 Composite(n) => n.span(),
133 Err(n) => n.span(),
134 Intrinsic(n) => n.span(),
135 Path(n) => n.span(),
136 Literal(n) => n.span(),
137 MemberAccess(n) => n.span(),
138 Repeat(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 Async(n) => n.set_span(span),
153 Binary(n) => n.set_span(span),
154 Call(n) => n.set_span(span),
155 Cast(n) => n.set_span(span),
156 Composite(n) => n.set_span(span),
157 Err(n) => n.set_span(span),
158 Intrinsic(n) => n.set_span(span),
159 Path(n) => n.set_span(span),
160 Literal(n) => n.set_span(span),
161 MemberAccess(n) => n.set_span(span),
162 Repeat(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 Async(n) => n.id(),
177 Binary(n) => n.id(),
178 Call(n) => n.id(),
179 Cast(n) => n.id(),
180 Composite(n) => n.id(),
181 Path(n) => n.id(),
182 Literal(n) => n.id(),
183 MemberAccess(n) => n.id(),
184 Repeat(n) => n.id(),
185 Err(n) => n.id(),
186 Intrinsic(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 Async(n) => n.set_id(id),
201 Binary(n) => n.set_id(id),
202 Call(n) => n.set_id(id),
203 Cast(n) => n.set_id(id),
204 Composite(n) => n.set_id(id),
205 Path(n) => n.set_id(id),
206 Literal(n) => n.set_id(id),
207 MemberAccess(n) => n.set_id(id),
208 Repeat(n) => n.set_id(id),
209 Err(n) => n.set_id(id),
210 Intrinsic(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 Async(n) => n.fmt(f),
227 Binary(n) => n.fmt(f),
228 Call(n) => n.fmt(f),
229 Cast(n) => n.fmt(f),
230 Composite(n) => n.fmt(f),
231 Err(n) => n.fmt(f),
232 Intrinsic(n) => n.fmt(f),
233 Path(n) => n.fmt(f),
234 Literal(n) => n.fmt(f),
235 MemberAccess(n) => n.fmt(f),
236 Repeat(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(_) => 0,
260 Array(_) | ArrayAccess(_) | Async(_) | Call(_) | Composite(_) | Err(_) | Intrinsic(_) | Path(_)
261 | Literal(_) | MemberAccess(_) | Repeat(_) | Tuple(_) | TupleAccess(_) | Unary(_) | Unit(_) => 20,
262 }
263 }
264
265 pub(crate) fn associativity(&self) -> Associativity {
266 if let Expression::Binary(bin) = self { bin.associativity() } else { Associativity::None }
267 }
268
269 pub fn as_u32(&self) -> Option<u32> {
272 if let Expression::Literal(literal) = &self {
273 if let LiteralVariant::Integer(int_type, s, ..) = &literal.variant {
274 use crate::IntegerType::*;
275 let s = s.replace("_", "");
276
277 return match int_type {
278 U8 => u8::from_str_by_radix(&s).map(|v| v as u32).ok(),
279 U16 => u16::from_str_by_radix(&s).map(|v| v as u32).ok(),
280 U32 => u32::from_str_by_radix(&s).ok(),
281 U64 => u64::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
282 U128 => u128::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
283 I8 => i8::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
284 I16 => i16::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
285 I32 => i32::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
286 I64 => i64::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
287 I128 => i128::from_str_by_radix(&s).ok().and_then(|v| u32::try_from(v).ok()),
288 };
289 } else if let LiteralVariant::Unsuffixed(s) = &literal.variant {
290 let s = s.replace("_", "");
292 return u32::from_str_by_radix(&s).ok();
293 }
294 }
295 None
296 }
297
298 pub fn is_none_expr(&self) -> bool {
299 matches!(self, Expression::Literal(Literal { variant: LiteralVariant::None, .. }))
300 }
301
302 pub fn is_pure(&self, get_type: &impl Fn(NodeID) -> Type) -> bool {
304 match self {
305 Expression::Intrinsic(intr) => {
307 if let Some(intrinsic) = Intrinsic::from_symbol(intr.name, &intr.type_parameters) {
308 intrinsic.is_pure()
309 } else {
310 false
311 }
312 }
313
314 Expression::Call(..) | Expression::Err(..) | Expression::Async(..) | Expression::Cast(..) => false,
317
318 Expression::Binary(expr) => {
319 use BinaryOperation::*;
320 match expr.op {
321 Div | Mod | Rem | Shl | Shr => false,
323 Add | Mul | Pow => !matches!(get_type(expr.id()), Type::Integer(..)),
325 _ => expr.left.is_pure(get_type) && expr.right.is_pure(get_type),
326 }
327 }
328 Expression::Unary(expr) => {
329 use UnaryOperation::*;
330 match expr.op {
331 Abs | Inverse | SquareRoot => false,
333 Negate => !matches!(get_type(expr.id()), Type::Integer(..)),
335 _ => expr.receiver.is_pure(get_type),
336 }
337 }
338
339 Expression::Literal(..) | Expression::Path(..) | Expression::Unit(..) => true,
341
342 Expression::ArrayAccess(expr) => expr.array.is_pure(get_type) && expr.index.is_pure(get_type),
344 Expression::MemberAccess(expr) => expr.inner.is_pure(get_type),
345 Expression::Repeat(expr) => expr.expr.is_pure(get_type) && expr.count.is_pure(get_type),
346 Expression::TupleAccess(expr) => expr.tuple.is_pure(get_type),
347 Expression::Array(expr) => expr.elements.iter().all(|e| e.is_pure(get_type)),
348 Expression::Composite(expr) => {
349 expr.const_arguments.iter().all(|e| e.is_pure(get_type))
350 && expr.members.iter().all(|init| init.expression.as_ref().is_none_or(|e| e.is_pure(get_type)))
351 }
352 Expression::Ternary(expr) => {
353 expr.condition.is_pure(get_type) && expr.if_true.is_pure(get_type) && expr.if_false.is_pure(get_type)
354 }
355 Expression::Tuple(expr) => expr.elements.iter().all(|e| e.is_pure(get_type)),
356 }
357 }
358
359 #[allow(clippy::type_complexity)]
376 pub fn zero(
377 ty: &Type,
378 span: Span,
379 node_builder: &NodeBuilder,
380 composite_lookup: &dyn Fn(&Location) -> Vec<(Symbol, Type)>,
381 ) -> Option<Self> {
382 let id = node_builder.next_id();
383
384 match ty {
385 Type::Integer(IntegerType::I8) => Some(Literal::integer(IntegerType::I8, "0".to_string(), span, id).into()),
387 Type::Integer(IntegerType::I16) => {
388 Some(Literal::integer(IntegerType::I16, "0".to_string(), span, id).into())
389 }
390 Type::Integer(IntegerType::I32) => {
391 Some(Literal::integer(IntegerType::I32, "0".to_string(), span, id).into())
392 }
393 Type::Integer(IntegerType::I64) => {
394 Some(Literal::integer(IntegerType::I64, "0".to_string(), span, id).into())
395 }
396 Type::Integer(IntegerType::I128) => {
397 Some(Literal::integer(IntegerType::I128, "0".to_string(), span, id).into())
398 }
399 Type::Integer(IntegerType::U8) => Some(Literal::integer(IntegerType::U8, "0".to_string(), span, id).into()),
400 Type::Integer(IntegerType::U16) => {
401 Some(Literal::integer(IntegerType::U16, "0".to_string(), span, id).into())
402 }
403 Type::Integer(IntegerType::U32) => {
404 Some(Literal::integer(IntegerType::U32, "0".to_string(), span, id).into())
405 }
406 Type::Integer(IntegerType::U64) => {
407 Some(Literal::integer(IntegerType::U64, "0".to_string(), span, id).into())
408 }
409 Type::Integer(IntegerType::U128) => {
410 Some(Literal::integer(IntegerType::U128, "0".to_string(), span, id).into())
411 }
412
413 Type::Boolean => Some(Literal::boolean(false, span, id).into()),
415
416 Type::Address => Some(
420 Literal::address(
421 "aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc".to_string(),
422 span,
423 id,
424 )
425 .into(),
426 ),
427
428 Type::Field => Some(Literal::field("0".to_string(), span, id).into()),
430 Type::Group => Some(Literal::group("0".to_string(), span, id).into()),
431 Type::Scalar => Some(Literal::scalar("0".to_string(), span, id).into()),
432
433 Type::Signature => Some(
437 Literal::signature(
438 "sign195m229jvzr0wmnshj6f8gwplhkrkhjumgjmad553r997u7pjfgpfz4j2w0c9lp53mcqqdsmut2g3a2zuvgst85w38hv273mwjec3sqjsv9w6uglcy58gjh7x3l55z68zsf24kx7a73ctp8x8klhuw7l2p4s3aq8um5jp304js7qcnwdqj56q5r5088tyvxsgektun0rnmvtsuxpe6sj".to_string(),
439 span,
440 id,
441 )
442 .into(),
443 ),
444
445 Type::Composite(composite_type) => {
447 let path = &composite_type.path;
448 let members = composite_lookup(path.expect_global_location());
449
450 let composite_members = members
451 .into_iter()
452 .map(|(symbol, member_type)| {
453 let member_id = node_builder.next_id();
454 let zero_expr = Self::zero(&member_type, span, node_builder, composite_lookup)?;
455
456 Some(CompositeFieldInitializer {
457 span,
458 id: member_id,
459 identifier: Identifier::new(symbol, node_builder.next_id()),
460 expression: Some(zero_expr),
461 })
462 })
463 .collect::<Option<Vec<_>>>()?;
464
465 Some(Expression::Composite(CompositeExpression {
466 span,
467 id,
468 path: path.clone(),
469 const_arguments: composite_type.const_arguments.clone(),
470 members: composite_members,
471 }))
472 }
473
474 Type::Array(array_type) => {
476 let element_ty = &array_type.element_type;
477
478 let element_expr = Self::zero(element_ty, span, node_builder, composite_lookup)?;
479
480 Some(Expression::Repeat(
481 RepeatExpression { span, id, expr: element_expr, count: *array_type.length.clone() }.into(),
482 ))
483 }
484
485 _ => None,
487 }
488 }
489}