sway_core/language/parsed/expression/
mod.rs

1use crate::{
2    decl_engine::parsed_id::ParsedDeclId,
3    engine_threading::{
4        DebugWithEngines, DisplayWithEngines, EqWithEngines, HashWithEngines, OrdWithEngines,
5        OrdWithEnginesContext, PartialEqWithEngines, PartialEqWithEnginesContext,
6    },
7    language::{parsed::CodeBlock, *},
8    type_system::TypeBinding,
9    Engines, GenericArgument, TypeId,
10};
11use serde::{Deserialize, Serialize};
12use std::{cmp::Ordering, fmt, hash::Hasher};
13use sway_error::handler::ErrorEmitted;
14use sway_types::{ident::Ident, Span, Spanned};
15
16mod asm;
17mod match_branch;
18mod method_name;
19mod scrutinee;
20pub(crate) use asm::*;
21pub(crate) use match_branch::MatchBranch;
22pub use method_name::MethodName;
23pub use scrutinee::*;
24use sway_ast::intrinsics::Intrinsic;
25
26use super::{FunctionDeclaration, StructDeclaration};
27
28/// Represents a parsed, but not yet type checked, [Expression](https://en.wikipedia.org/wiki/Expression_(computer_science)).
29#[derive(Debug, Clone)]
30pub struct Expression {
31    pub kind: ExpressionKind,
32    pub span: Span,
33}
34
35#[derive(Debug, Clone)]
36pub struct FunctionApplicationExpression {
37    pub call_path_binding: TypeBinding<CallPath>,
38    pub resolved_call_path_binding:
39        Option<TypeBinding<ResolvedCallPath<ParsedDeclId<FunctionDeclaration>>>>,
40    pub arguments: Vec<Expression>,
41}
42
43impl EqWithEngines for FunctionApplicationExpression {}
44impl PartialEqWithEngines for FunctionApplicationExpression {
45    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
46        self.call_path_binding.eq(&other.call_path_binding, ctx)
47            && self.arguments.eq(&other.arguments, ctx)
48    }
49}
50
51#[derive(Debug, Clone)]
52pub struct LazyOperatorExpression {
53    pub op: LazyOp,
54    pub lhs: Box<Expression>,
55    pub rhs: Box<Expression>,
56}
57
58impl EqWithEngines for LazyOperatorExpression {}
59impl PartialEqWithEngines for LazyOperatorExpression {
60    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
61        self.op == other.op && self.lhs.eq(&other.lhs, ctx) && self.rhs.eq(&other.rhs, ctx)
62    }
63}
64
65#[derive(Debug, Clone)]
66pub struct TupleIndexExpression {
67    pub prefix: Box<Expression>,
68    pub index: usize,
69    pub index_span: Span,
70}
71
72impl EqWithEngines for TupleIndexExpression {}
73impl PartialEqWithEngines for TupleIndexExpression {
74    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
75        self.prefix.eq(&other.prefix, ctx)
76            && self.index == other.index
77            && self.index_span == other.index_span
78    }
79}
80
81#[derive(Debug, Clone)]
82pub enum ArrayExpression {
83    Explicit {
84        contents: Vec<Expression>,
85        length_span: Option<Span>,
86    },
87    Repeat {
88        value: Box<Expression>,
89        length: Box<Expression>,
90    },
91}
92
93impl EqWithEngines for ArrayExpression {}
94impl PartialEqWithEngines for ArrayExpression {
95    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
96        match (self, other) {
97            (
98                ArrayExpression::Explicit {
99                    contents: self_contents,
100                    length_span: self_length_span,
101                },
102                ArrayExpression::Explicit {
103                    contents: other_contents,
104                    length_span: other_length_span,
105                },
106            ) => self_contents.eq(other_contents, ctx) && self_length_span == other_length_span,
107            (
108                ArrayExpression::Repeat {
109                    value: self_value,
110                    length: self_length,
111                },
112                ArrayExpression::Repeat {
113                    value: other_value,
114                    length: other_length,
115                },
116            ) => self_value.eq(other_value, ctx) && self_length.eq(other_length, ctx),
117            _ => false,
118        }
119    }
120}
121
122#[derive(Debug, Clone)]
123pub struct StructExpression {
124    pub resolved_call_path_binding:
125        Option<TypeBinding<ResolvedCallPath<ParsedDeclId<StructDeclaration>>>>,
126    pub call_path_binding: TypeBinding<CallPath>,
127    pub fields: Vec<StructExpressionField>,
128}
129
130impl EqWithEngines for StructExpression {}
131impl PartialEqWithEngines for StructExpression {
132    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
133        self.call_path_binding.eq(&other.call_path_binding, ctx)
134            && self.fields.eq(&other.fields, ctx)
135    }
136}
137
138#[derive(Debug, Clone)]
139pub struct IfExpression {
140    pub condition: Box<Expression>,
141    pub then: Box<Expression>,
142    pub r#else: Option<Box<Expression>>,
143}
144
145impl EqWithEngines for IfExpression {}
146impl PartialEqWithEngines for IfExpression {
147    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
148        self.condition.eq(&other.condition, ctx)
149            && self.then.eq(&other.then, ctx)
150            && self.r#else.eq(&other.r#else, ctx)
151    }
152}
153
154#[derive(Debug, Clone)]
155pub struct MatchExpression {
156    pub value: Box<Expression>,
157    pub branches: Vec<MatchBranch>,
158}
159
160impl EqWithEngines for MatchExpression {}
161impl PartialEqWithEngines for MatchExpression {
162    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
163        self.value.eq(&other.value, ctx) && self.branches.eq(&other.branches, ctx)
164    }
165}
166
167#[derive(Debug, Clone)]
168pub struct MethodApplicationExpression {
169    pub method_name_binding: TypeBinding<MethodName>,
170    pub contract_call_params: Vec<StructExpressionField>,
171    pub arguments: Vec<Expression>,
172}
173
174impl EqWithEngines for MethodApplicationExpression {}
175impl PartialEqWithEngines for MethodApplicationExpression {
176    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
177        self.method_name_binding.eq(&other.method_name_binding, ctx)
178            && self
179                .contract_call_params
180                .eq(&other.contract_call_params, ctx)
181            && self.arguments.eq(&other.arguments, ctx)
182    }
183}
184
185#[derive(Debug, Clone)]
186pub struct SubfieldExpression {
187    pub prefix: Box<Expression>,
188    pub field_to_access: Ident,
189}
190
191impl EqWithEngines for SubfieldExpression {}
192impl PartialEqWithEngines for SubfieldExpression {
193    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
194        self.prefix.eq(&other.prefix, ctx) && self.field_to_access == other.field_to_access
195    }
196}
197
198#[derive(Debug, Clone)]
199pub struct AmbiguousSuffix {
200    /// If the suffix is a pair, the ambiguous part of the suffix.
201    ///
202    /// For example, if we have `Foo::bar()`,
203    /// we don't know whether `Foo` is a module or a type,
204    /// so `before` would be `Foo` here with any type arguments.
205    pub before: Option<TypeBinding<Ident>>,
206    /// The final suffix, i.e., the function or variant name.
207    ///
208    /// In the example above, this would be `bar`.
209    pub suffix: Ident,
210}
211
212impl EqWithEngines for AmbiguousSuffix {}
213impl PartialEqWithEngines for AmbiguousSuffix {
214    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
215        self.before.eq(&other.before, ctx) && self.suffix == other.suffix
216    }
217}
218
219impl Spanned for AmbiguousSuffix {
220    fn span(&self) -> Span {
221        if let Some(before) = &self.before {
222            Span::join(before.span(), &self.suffix.span())
223        } else {
224            self.suffix.span()
225        }
226    }
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct QualifiedPathType {
231    pub ty: GenericArgument,
232    pub as_trait: TypeId,
233    pub as_trait_span: Span,
234}
235
236impl HashWithEngines for QualifiedPathType {
237    fn hash<H: Hasher>(&self, state: &mut H, engines: &Engines) {
238        let QualifiedPathType {
239            ty,
240            as_trait,
241            // ignored fields
242            as_trait_span: _,
243        } = self;
244        ty.hash(state, engines);
245        engines.te().get(*as_trait).hash(state, engines);
246    }
247}
248
249impl EqWithEngines for QualifiedPathType {}
250impl PartialEqWithEngines for QualifiedPathType {
251    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
252        let QualifiedPathType {
253            ty,
254            as_trait,
255            // ignored fields
256            as_trait_span: _,
257        } = self;
258        ty.eq(&other.ty, ctx)
259            && ctx
260                .engines()
261                .te()
262                .get(*as_trait)
263                .eq(&ctx.engines().te().get(other.as_trait), ctx)
264    }
265}
266
267impl OrdWithEngines for QualifiedPathType {
268    fn cmp(&self, other: &Self, ctx: &OrdWithEnginesContext) -> Ordering {
269        let QualifiedPathType {
270            ty: l_ty,
271            as_trait: l_as_trait,
272            // ignored fields
273            as_trait_span: _,
274        } = self;
275        let QualifiedPathType {
276            ty: r_ty,
277            as_trait: r_as_trait,
278            // ignored fields
279            as_trait_span: _,
280        } = other;
281        l_ty.cmp(r_ty, ctx).then_with(|| {
282            ctx.engines()
283                .te()
284                .get(*l_as_trait)
285                .cmp(&ctx.engines().te().get(*r_as_trait), ctx)
286        })
287    }
288}
289
290impl DisplayWithEngines for QualifiedPathType {
291    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
292        write!(
293            f,
294            "<{} as {}>",
295            engines.help_out(self.ty.clone()),
296            engines.help_out(self.as_trait)
297        )
298    }
299}
300
301impl DebugWithEngines for QualifiedPathType {
302    fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result {
303        write!(f, "{}", engines.help_out(self),)
304    }
305}
306
307#[derive(Debug, Clone)]
308pub struct AmbiguousPathExpression {
309    pub qualified_path_root: Option<QualifiedPathType>,
310    pub call_path_binding: TypeBinding<CallPath<AmbiguousSuffix>>,
311    pub args: Vec<Expression>,
312}
313
314impl EqWithEngines for AmbiguousPathExpression {}
315impl PartialEqWithEngines for AmbiguousPathExpression {
316    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
317        self.qualified_path_root.eq(&other.qualified_path_root, ctx)
318            && PartialEqWithEngines::eq(&self.call_path_binding, &other.call_path_binding, ctx)
319            && self.args.eq(&other.args, ctx)
320    }
321}
322
323#[derive(Debug, Clone)]
324pub struct DelineatedPathExpression {
325    pub call_path_binding: TypeBinding<QualifiedCallPath>,
326    /// When args is equal to Option::None then it means that the
327    /// [DelineatedPathExpression] was initialized from an expression
328    /// that does not end with parenthesis.
329    pub args: Option<Vec<Expression>>,
330}
331
332impl EqWithEngines for DelineatedPathExpression {}
333impl PartialEqWithEngines for DelineatedPathExpression {
334    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
335        self.call_path_binding.eq(&other.call_path_binding, ctx) && self.args.eq(&other.args, ctx)
336    }
337}
338
339#[derive(Debug, Clone)]
340pub struct AbiCastExpression {
341    pub abi_name: CallPath,
342    pub address: Box<Expression>,
343}
344
345impl EqWithEngines for AbiCastExpression {}
346impl PartialEqWithEngines for AbiCastExpression {
347    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
348        PartialEqWithEngines::eq(&self.abi_name, &other.abi_name, ctx)
349            && self.address.eq(&other.address, ctx)
350    }
351}
352
353#[derive(Debug, Clone)]
354pub struct ArrayIndexExpression {
355    pub prefix: Box<Expression>,
356    pub index: Box<Expression>,
357}
358
359impl EqWithEngines for ArrayIndexExpression {}
360impl PartialEqWithEngines for ArrayIndexExpression {
361    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
362        self.prefix.eq(&other.prefix, ctx) && self.index.eq(&other.index, ctx)
363    }
364}
365
366#[derive(Debug, Clone)]
367pub struct StorageAccessExpression {
368    pub namespace_names: Vec<Ident>,
369    pub field_names: Vec<Ident>,
370    pub storage_keyword_span: Span,
371}
372
373impl EqWithEngines for StorageAccessExpression {}
374impl PartialEqWithEngines for StorageAccessExpression {
375    fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool {
376        self.field_names.eq(&other.field_names)
377            && self.storage_keyword_span.eq(&other.storage_keyword_span)
378    }
379}
380
381#[derive(Debug, Clone)]
382pub struct IntrinsicFunctionExpression {
383    pub name: Ident,
384    pub kind_binding: TypeBinding<Intrinsic>,
385    pub arguments: Vec<Expression>,
386}
387
388impl EqWithEngines for IntrinsicFunctionExpression {}
389impl PartialEqWithEngines for IntrinsicFunctionExpression {
390    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
391        self.name.eq(&other.name)
392            && self.kind_binding.eq(&other.kind_binding, ctx)
393            && self.arguments.eq(&other.arguments, ctx)
394    }
395}
396
397#[derive(Debug, Clone)]
398pub struct WhileLoopExpression {
399    pub condition: Box<Expression>,
400    pub body: CodeBlock,
401    pub is_desugared_for_loop: bool,
402}
403
404impl EqWithEngines for WhileLoopExpression {}
405impl PartialEqWithEngines for WhileLoopExpression {
406    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
407        self.condition.eq(&other.condition, ctx) && self.body.eq(&other.body, ctx)
408    }
409}
410
411#[derive(Debug, Clone)]
412pub struct ForLoopExpression {
413    pub desugared: Box<Expression>,
414}
415
416impl EqWithEngines for ForLoopExpression {}
417impl PartialEqWithEngines for ForLoopExpression {
418    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
419        self.desugared.eq(&other.desugared, ctx)
420    }
421}
422
423#[derive(Debug, Clone)]
424pub struct ReassignmentExpression {
425    pub lhs: ReassignmentTarget,
426    pub rhs: Box<Expression>,
427}
428
429impl EqWithEngines for ReassignmentExpression {}
430impl PartialEqWithEngines for ReassignmentExpression {
431    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
432        self.lhs.eq(&other.lhs, ctx) && self.rhs.eq(&other.rhs, ctx)
433    }
434}
435
436#[derive(Debug, Clone)]
437pub enum ExpressionKind {
438    /// A malformed expression.
439    ///
440    /// Used for parser recovery when we cannot form a more specific node.
441    /// The list of `Span`s are for consumption by the LSP and are,
442    /// when joined, the same as that stored in `expr.span`.
443    Error(Box<[Span]>, ErrorEmitted),
444    Literal(Literal),
445    /// An ambiguous path where we don't know until type checking whether this
446    /// is a free function call, an enum variant or a UFCS (Rust term) style associated function call.
447    AmbiguousPathExpression(Box<AmbiguousPathExpression>),
448    FunctionApplication(Box<FunctionApplicationExpression>),
449    LazyOperator(LazyOperatorExpression),
450    /// And ambiguous single ident which could either be a variable or an enum variant
451    AmbiguousVariableExpression(Ident),
452    Variable(Ident),
453    Tuple(Vec<Expression>),
454    TupleIndex(TupleIndexExpression),
455    Array(ArrayExpression),
456    Struct(Box<StructExpression>),
457    CodeBlock(CodeBlock),
458    If(IfExpression),
459    Match(MatchExpression),
460    // separated into other struct for parsing reasons
461    Asm(Box<AsmExpression>),
462    MethodApplication(Box<MethodApplicationExpression>),
463    /// A _subfield expression_ is anything of the form:
464    /// ```ignore
465    /// <ident>.<ident>
466    /// ```
467    ///
468    Subfield(SubfieldExpression),
469    /// A _delineated path_ is anything of the form:
470    /// ```ignore
471    /// <ident>::<ident>
472    /// ```
473    /// Where there are `n >= 2` idents.
474    /// These could be either enum variant constructions, or they could be
475    /// references to some sort of module in the module tree.
476    /// For example, a reference to a module:
477    /// ```ignore
478    /// std::ops::add
479    /// ```
480    ///
481    /// And, an enum declaration:
482    /// ```ignore
483    /// enum MyEnum {
484    ///   Variant1,
485    ///   Variant2
486    /// }
487    ///
488    /// MyEnum::Variant1
489    /// ```
490    DelineatedPath(Box<DelineatedPathExpression>),
491    /// A cast of a hash to an ABI for calling a contract.
492    AbiCast(Box<AbiCastExpression>),
493    ArrayIndex(ArrayIndexExpression),
494    StorageAccess(StorageAccessExpression),
495    IntrinsicFunction(IntrinsicFunctionExpression),
496    /// A control flow element which loops continually until some boolean expression evaluates as
497    /// `false`.
498    WhileLoop(WhileLoopExpression),
499    /// A control flow element which loops between values of an iterator.
500    ForLoop(ForLoopExpression),
501    Break,
502    Continue,
503    Reassignment(ReassignmentExpression),
504    /// An implicit return expression is different from a [Expression::Return] because
505    /// it is not a control flow item. Therefore it is a different variant.
506    ///
507    /// An implicit return expression is an [Expression] at the end of a code block which has no
508    /// semicolon, denoting that it is the [Expression] to be returned from that block.
509    ImplicitReturn(Box<Expression>),
510    Return(Box<Expression>),
511    Ref(RefExpression),
512    Deref(Box<Expression>),
513}
514
515impl EqWithEngines for Expression {}
516impl PartialEqWithEngines for Expression {
517    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
518        self.kind.eq(&other.kind, ctx)
519    }
520}
521
522impl EqWithEngines for ExpressionKind {}
523impl PartialEqWithEngines for ExpressionKind {
524    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
525        match (self, other) {
526            (ExpressionKind::Error(l_span, _), ExpressionKind::Error(r_span, _)) => {
527                l_span == r_span
528            }
529            (ExpressionKind::Literal(l_literal), ExpressionKind::Literal(r_literal)) => {
530                l_literal == r_literal
531            }
532            (
533                ExpressionKind::AmbiguousPathExpression(lhs),
534                ExpressionKind::AmbiguousPathExpression(rhs),
535            ) => lhs.eq(rhs, ctx),
536            (
537                ExpressionKind::FunctionApplication(lhs),
538                ExpressionKind::FunctionApplication(rhs),
539            ) => lhs.eq(rhs, ctx),
540            (ExpressionKind::LazyOperator(lhs), ExpressionKind::LazyOperator(rhs)) => {
541                lhs.eq(rhs, ctx)
542            }
543            (
544                ExpressionKind::AmbiguousVariableExpression(lhs),
545                ExpressionKind::AmbiguousVariableExpression(rhs),
546            ) => lhs == rhs,
547            (ExpressionKind::Variable(lhs), ExpressionKind::Variable(rhs)) => lhs == rhs,
548            (ExpressionKind::Tuple(lhs), ExpressionKind::Tuple(rhs)) => lhs.eq(rhs, ctx),
549            (ExpressionKind::TupleIndex(lhs), ExpressionKind::TupleIndex(rhs)) => lhs.eq(rhs, ctx),
550            (ExpressionKind::Array(lhs), ExpressionKind::Array(rhs)) => lhs.eq(rhs, ctx),
551            (ExpressionKind::Struct(lhs), ExpressionKind::Struct(rhs)) => lhs.eq(rhs, ctx),
552            (ExpressionKind::CodeBlock(lhs), ExpressionKind::CodeBlock(rhs)) => lhs.eq(rhs, ctx),
553            (ExpressionKind::If(lhs), ExpressionKind::If(rhs)) => lhs.eq(rhs, ctx),
554            (ExpressionKind::Match(lhs), ExpressionKind::Match(rhs)) => lhs.eq(rhs, ctx),
555            (ExpressionKind::Asm(lhs), ExpressionKind::Asm(rhs)) => lhs.eq(rhs, ctx),
556            (ExpressionKind::MethodApplication(lhs), ExpressionKind::MethodApplication(rhs)) => {
557                lhs.eq(rhs, ctx)
558            }
559            (ExpressionKind::Subfield(lhs), ExpressionKind::Subfield(rhs)) => lhs.eq(rhs, ctx),
560            (ExpressionKind::DelineatedPath(lhs), ExpressionKind::DelineatedPath(rhs)) => {
561                lhs.eq(rhs, ctx)
562            }
563            (ExpressionKind::AbiCast(lhs), ExpressionKind::AbiCast(rhs)) => lhs.eq(rhs, ctx),
564            (ExpressionKind::ArrayIndex(lhs), ExpressionKind::ArrayIndex(rhs)) => lhs.eq(rhs, ctx),
565            (ExpressionKind::StorageAccess(lhs), ExpressionKind::StorageAccess(rhs)) => {
566                lhs.eq(rhs, ctx)
567            }
568            (ExpressionKind::IntrinsicFunction(lhs), ExpressionKind::IntrinsicFunction(rhs)) => {
569                lhs.eq(rhs, ctx)
570            }
571            (ExpressionKind::WhileLoop(lhs), ExpressionKind::WhileLoop(rhs)) => lhs.eq(rhs, ctx),
572            (ExpressionKind::ForLoop(lhs), ExpressionKind::ForLoop(rhs)) => lhs.eq(rhs, ctx),
573            (ExpressionKind::Break, ExpressionKind::Break) => true,
574            (ExpressionKind::Continue, ExpressionKind::Continue) => true,
575            (ExpressionKind::Reassignment(lhs), ExpressionKind::Reassignment(rhs)) => {
576                lhs.eq(rhs, ctx)
577            }
578            (ExpressionKind::ImplicitReturn(lhs), ExpressionKind::ImplicitReturn(rhs)) => {
579                lhs.eq(rhs, ctx)
580            }
581            (ExpressionKind::Return(lhs), ExpressionKind::Return(rhs)) => lhs.eq(rhs, ctx),
582            (ExpressionKind::Ref(lhs), ExpressionKind::Ref(rhs)) => lhs.eq(rhs, ctx),
583            (ExpressionKind::Deref(lhs), ExpressionKind::Deref(rhs)) => lhs.eq(rhs, ctx),
584            _ => false,
585        }
586    }
587}
588
589#[derive(Debug, Clone)]
590pub struct RefExpression {
591    /// True if the reference is a reference to a mutable `value`.
592    pub to_mutable_value: bool,
593    pub value: Box<Expression>,
594}
595
596impl EqWithEngines for RefExpression {}
597impl PartialEqWithEngines for RefExpression {
598    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
599        self.to_mutable_value.eq(&other.to_mutable_value) && self.value.eq(&other.value, ctx)
600    }
601}
602
603#[derive(Debug, Clone)]
604pub enum ReassignmentTarget {
605    /// An [Expression] representing a single variable or a path
606    /// to a part of an aggregate.
607    /// E.g.:
608    ///  - `my_variable`
609    ///  - `array[0].field.x.1`
610    ElementAccess(Box<Expression>),
611    /// An dereferencing [Expression] representing dereferencing
612    /// of an arbitrary reference expression.
613    /// E.g.:
614    ///  - *my_ref
615    ///  - **if x > 0 { &mut &mut a } else { &mut &mut b }
616    Deref(Box<Expression>),
617}
618
619impl EqWithEngines for ReassignmentTarget {}
620impl PartialEqWithEngines for ReassignmentTarget {
621    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
622        match (self, other) {
623            (ReassignmentTarget::ElementAccess(lhs), ReassignmentTarget::ElementAccess(rhs)) => {
624                lhs.eq(rhs, ctx)
625            }
626            (ReassignmentTarget::Deref(lhs), ReassignmentTarget::Deref(rhs)) => lhs.eq(rhs, ctx),
627            _ => false,
628        }
629    }
630}
631
632#[derive(Debug, Clone)]
633pub struct StructExpressionField {
634    pub name: Ident,
635    pub value: Expression,
636}
637
638impl EqWithEngines for StructExpressionField {}
639impl PartialEqWithEngines for StructExpressionField {
640    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
641        self.name == other.name && self.value.eq(&other.value, ctx)
642    }
643}
644
645impl Spanned for Expression {
646    fn span(&self) -> Span {
647        self.span.clone()
648    }
649}
650
651#[derive(Debug)]
652pub(crate) struct Op {
653    pub span: Span,
654    pub op_variant: OpVariant,
655}
656
657impl Op {
658    pub fn to_method_name(&self) -> Ident {
659        Ident::new_with_override(self.op_variant.method_name().to_string(), self.span.clone())
660    }
661}
662
663#[derive(Debug)]
664pub enum OpVariant {
665    Add,
666    Subtract,
667    Divide,
668    Multiply,
669    Modulo,
670    Or,
671    And,
672    Equals,
673    NotEquals,
674    Xor,
675    BinaryOr,
676    BinaryAnd,
677    GreaterThan,
678    LessThan,
679    GreaterThanOrEqualTo,
680    LessThanOrEqualTo,
681}
682
683impl OpVariant {
684    /// For all the operators except [OpVariant::Or] and [OpVariant::And],
685    /// returns the name of the method that can be found on the corresponding
686    /// operator trait. E.g., for `+` that will be the method `add` defined in
687    /// `std::ops::Add::add`.
688    ///
689    /// [OpVariant::Or] and [OpVariant::And] are lazy and must be handled
690    /// internally by the compiler.
691    fn method_name(&self) -> &'static str {
692        use OpVariant::*;
693        match self {
694            Add => "add",
695            Subtract => "subtract",
696            Divide => "divide",
697            Multiply => "multiply",
698            Modulo => "modulo",
699            Or => "$or$",
700            And => "$and$",
701            Equals => "eq",
702            NotEquals => "neq",
703            Xor => "xor",
704            BinaryOr => "binary_or",
705            BinaryAnd => "binary_and",
706            GreaterThan => "gt",
707            LessThan => "lt",
708            LessThanOrEqualTo => "le",
709            GreaterThanOrEqualTo => "ge",
710        }
711    }
712}