Skip to main content

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/// A storage access expression of the form `storage[::<namespace_name>]*<.field_name>*`.
367/// E.g.:
368/// - `storage.field`
369/// - `storage::ns1.field`
370/// - `storage::ns1::ns2.field.subfield`
371#[derive(Debug, Clone)]
372pub struct StorageAccessExpression {
373    /// The list of namespace names in the storage access expression, if any.
374    /// E.g.: for `storage::ns1::ns2.field.subfield`, this would be `["ns1", "ns2"]`.
375    pub namespace_names: Vec<Ident>,
376    /// The list of field names in the storage access expression.
377    /// There must be at least one field name.
378    /// E.g.: for `storage::ns1::ns2.field.subfield`, this would be `["field", "subfield"]`.
379    pub field_names: Vec<Ident>,
380    pub storage_keyword_span: Span,
381}
382
383impl EqWithEngines for StorageAccessExpression {}
384impl PartialEqWithEngines for StorageAccessExpression {
385    fn eq(&self, other: &Self, _ctx: &PartialEqWithEnginesContext) -> bool {
386        self.field_names.eq(&other.field_names)
387            && self.storage_keyword_span.eq(&other.storage_keyword_span)
388    }
389}
390
391#[derive(Debug, Clone)]
392pub struct IntrinsicFunctionExpression {
393    pub name: Ident,
394    pub kind_binding: TypeBinding<Intrinsic>,
395    pub arguments: Vec<Expression>,
396}
397
398impl EqWithEngines for IntrinsicFunctionExpression {}
399impl PartialEqWithEngines for IntrinsicFunctionExpression {
400    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
401        self.name.eq(&other.name)
402            && self.kind_binding.eq(&other.kind_binding, ctx)
403            && self.arguments.eq(&other.arguments, ctx)
404    }
405}
406
407#[derive(Debug, Clone)]
408pub struct WhileLoopExpression {
409    pub condition: Box<Expression>,
410    pub body: CodeBlock,
411    pub is_desugared_for_loop: bool,
412}
413
414impl EqWithEngines for WhileLoopExpression {}
415impl PartialEqWithEngines for WhileLoopExpression {
416    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
417        self.condition.eq(&other.condition, ctx) && self.body.eq(&other.body, ctx)
418    }
419}
420
421#[derive(Debug, Clone)]
422pub struct ForLoopExpression {
423    pub desugared: Box<Expression>,
424}
425
426impl EqWithEngines for ForLoopExpression {}
427impl PartialEqWithEngines for ForLoopExpression {
428    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
429        self.desugared.eq(&other.desugared, ctx)
430    }
431}
432
433#[derive(Debug, Clone)]
434pub struct ReassignmentExpression {
435    pub lhs: ReassignmentTarget,
436    pub rhs: Box<Expression>,
437}
438
439impl EqWithEngines for ReassignmentExpression {}
440impl PartialEqWithEngines for ReassignmentExpression {
441    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
442        self.lhs.eq(&other.lhs, ctx) && self.rhs.eq(&other.rhs, ctx)
443    }
444}
445
446#[derive(Debug, Clone)]
447pub enum ExpressionKind {
448    /// A malformed expression.
449    ///
450    /// Used for parser recovery when we cannot form a more specific node.
451    /// The list of `Span`s are for consumption by the LSP and are,
452    /// when joined, the same as that stored in `expr.span`.
453    Error(Box<[Span]>, ErrorEmitted),
454    Literal(Literal),
455    /// An ambiguous path where we don't know until type checking whether this
456    /// is a free function call, an enum variant or a UFCS (Rust term) style associated function call.
457    AmbiguousPathExpression(Box<AmbiguousPathExpression>),
458    FunctionApplication(Box<FunctionApplicationExpression>),
459    LazyOperator(LazyOperatorExpression),
460    /// And ambiguous single ident which could either be a variable or an enum variant
461    AmbiguousVariableExpression(Ident),
462    Variable(Ident),
463    Tuple(Vec<Expression>),
464    TupleIndex(TupleIndexExpression),
465    Array(ArrayExpression),
466    Struct(Box<StructExpression>),
467    CodeBlock(CodeBlock),
468    If(IfExpression),
469    Match(MatchExpression),
470    // separated into other struct for parsing reasons
471    Asm(Box<AsmExpression>),
472    MethodApplication(Box<MethodApplicationExpression>),
473    /// A _subfield expression_ is anything of the form:
474    /// ```ignore
475    /// <ident>.<ident>
476    /// ```
477    ///
478    Subfield(SubfieldExpression),
479    /// A _delineated path_ is anything of the form:
480    /// ```ignore
481    /// <ident>::<ident>
482    /// ```
483    /// Where there are `n >= 2` idents.
484    /// These could be either enum variant constructions, or they could be
485    /// references to some sort of module in the module tree.
486    /// For example, a reference to a module:
487    /// ```ignore
488    /// std::ops::add
489    /// ```
490    ///
491    /// And, an enum declaration:
492    /// ```ignore
493    /// enum MyEnum {
494    ///   Variant1,
495    ///   Variant2
496    /// }
497    ///
498    /// MyEnum::Variant1
499    /// ```
500    DelineatedPath(Box<DelineatedPathExpression>),
501    /// A cast of a hash to an ABI for calling a contract.
502    AbiCast(Box<AbiCastExpression>),
503    ArrayIndex(ArrayIndexExpression),
504    StorageAccess(StorageAccessExpression),
505    IntrinsicFunction(IntrinsicFunctionExpression),
506    /// A control flow element which loops continually until some boolean expression evaluates as
507    /// `false`.
508    WhileLoop(WhileLoopExpression),
509    /// A control flow element which loops between values of an iterator.
510    ForLoop(ForLoopExpression),
511    Break,
512    Continue,
513    Reassignment(ReassignmentExpression),
514    /// An implicit return expression is different from a [Expression::Return] because
515    /// it is not a control flow item. Therefore it is a different variant.
516    ///
517    /// An implicit return expression is an [Expression] at the end of a code block which has no
518    /// semicolon, denoting that it is the [Expression] to be returned from that block.
519    ImplicitReturn(Box<Expression>),
520    Return(Box<Expression>),
521    Panic(Box<Expression>),
522    Ref(RefExpression),
523    Deref(Box<Expression>),
524}
525
526impl EqWithEngines for Expression {}
527impl PartialEqWithEngines for Expression {
528    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
529        self.kind.eq(&other.kind, ctx)
530    }
531}
532
533impl EqWithEngines for ExpressionKind {}
534impl PartialEqWithEngines for ExpressionKind {
535    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
536        match (self, other) {
537            (ExpressionKind::Error(l_span, _), ExpressionKind::Error(r_span, _)) => {
538                l_span == r_span
539            }
540            (ExpressionKind::Literal(l_literal), ExpressionKind::Literal(r_literal)) => {
541                l_literal == r_literal
542            }
543            (
544                ExpressionKind::AmbiguousPathExpression(lhs),
545                ExpressionKind::AmbiguousPathExpression(rhs),
546            ) => lhs.eq(rhs, ctx),
547            (
548                ExpressionKind::FunctionApplication(lhs),
549                ExpressionKind::FunctionApplication(rhs),
550            ) => lhs.eq(rhs, ctx),
551            (ExpressionKind::LazyOperator(lhs), ExpressionKind::LazyOperator(rhs)) => {
552                lhs.eq(rhs, ctx)
553            }
554            (
555                ExpressionKind::AmbiguousVariableExpression(lhs),
556                ExpressionKind::AmbiguousVariableExpression(rhs),
557            ) => lhs == rhs,
558            (ExpressionKind::Variable(lhs), ExpressionKind::Variable(rhs)) => lhs == rhs,
559            (ExpressionKind::Tuple(lhs), ExpressionKind::Tuple(rhs)) => lhs.eq(rhs, ctx),
560            (ExpressionKind::TupleIndex(lhs), ExpressionKind::TupleIndex(rhs)) => lhs.eq(rhs, ctx),
561            (ExpressionKind::Array(lhs), ExpressionKind::Array(rhs)) => lhs.eq(rhs, ctx),
562            (ExpressionKind::Struct(lhs), ExpressionKind::Struct(rhs)) => lhs.eq(rhs, ctx),
563            (ExpressionKind::CodeBlock(lhs), ExpressionKind::CodeBlock(rhs)) => lhs.eq(rhs, ctx),
564            (ExpressionKind::If(lhs), ExpressionKind::If(rhs)) => lhs.eq(rhs, ctx),
565            (ExpressionKind::Match(lhs), ExpressionKind::Match(rhs)) => lhs.eq(rhs, ctx),
566            (ExpressionKind::Asm(lhs), ExpressionKind::Asm(rhs)) => lhs.eq(rhs, ctx),
567            (ExpressionKind::MethodApplication(lhs), ExpressionKind::MethodApplication(rhs)) => {
568                lhs.eq(rhs, ctx)
569            }
570            (ExpressionKind::Subfield(lhs), ExpressionKind::Subfield(rhs)) => lhs.eq(rhs, ctx),
571            (ExpressionKind::DelineatedPath(lhs), ExpressionKind::DelineatedPath(rhs)) => {
572                lhs.eq(rhs, ctx)
573            }
574            (ExpressionKind::AbiCast(lhs), ExpressionKind::AbiCast(rhs)) => lhs.eq(rhs, ctx),
575            (ExpressionKind::ArrayIndex(lhs), ExpressionKind::ArrayIndex(rhs)) => lhs.eq(rhs, ctx),
576            (ExpressionKind::StorageAccess(lhs), ExpressionKind::StorageAccess(rhs)) => {
577                lhs.eq(rhs, ctx)
578            }
579            (ExpressionKind::IntrinsicFunction(lhs), ExpressionKind::IntrinsicFunction(rhs)) => {
580                lhs.eq(rhs, ctx)
581            }
582            (ExpressionKind::WhileLoop(lhs), ExpressionKind::WhileLoop(rhs)) => lhs.eq(rhs, ctx),
583            (ExpressionKind::ForLoop(lhs), ExpressionKind::ForLoop(rhs)) => lhs.eq(rhs, ctx),
584            (ExpressionKind::Break, ExpressionKind::Break) => true,
585            (ExpressionKind::Continue, ExpressionKind::Continue) => true,
586            (ExpressionKind::Reassignment(lhs), ExpressionKind::Reassignment(rhs)) => {
587                lhs.eq(rhs, ctx)
588            }
589            (ExpressionKind::ImplicitReturn(lhs), ExpressionKind::ImplicitReturn(rhs)) => {
590                lhs.eq(rhs, ctx)
591            }
592            (ExpressionKind::Return(lhs), ExpressionKind::Return(rhs)) => lhs.eq(rhs, ctx),
593            (ExpressionKind::Panic(lhs), ExpressionKind::Panic(rhs)) => lhs.eq(rhs, ctx),
594            (ExpressionKind::Ref(lhs), ExpressionKind::Ref(rhs)) => lhs.eq(rhs, ctx),
595            (ExpressionKind::Deref(lhs), ExpressionKind::Deref(rhs)) => lhs.eq(rhs, ctx),
596            _ => false,
597        }
598    }
599}
600
601#[derive(Debug, Clone)]
602pub struct RefExpression {
603    /// True if the reference is a reference to a mutable `value`.
604    pub to_mutable_value: bool,
605    pub value: Box<Expression>,
606}
607
608impl EqWithEngines for RefExpression {}
609impl PartialEqWithEngines for RefExpression {
610    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
611        self.to_mutable_value.eq(&other.to_mutable_value) && self.value.eq(&other.value, ctx)
612    }
613}
614
615#[derive(Debug, Clone)]
616pub enum ReassignmentTarget {
617    /// An [Expression] representing a single variable or a path
618    /// to a part of an aggregate.
619    /// E.g.:
620    ///  - `my_variable`
621    ///  - `array[0].field.x.1`
622    ElementAccess(Box<Expression>),
623    /// An dereferencing [Expression] representing dereferencing
624    /// of an arbitrary reference expression.
625    /// E.g.:
626    ///  - *my_ref
627    ///  - **if x > 0 { &mut &mut a } else { &mut &mut b }
628    Deref(Box<Expression>),
629}
630
631impl EqWithEngines for ReassignmentTarget {}
632impl PartialEqWithEngines for ReassignmentTarget {
633    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
634        match (self, other) {
635            (ReassignmentTarget::ElementAccess(lhs), ReassignmentTarget::ElementAccess(rhs)) => {
636                lhs.eq(rhs, ctx)
637            }
638            (ReassignmentTarget::Deref(lhs), ReassignmentTarget::Deref(rhs)) => lhs.eq(rhs, ctx),
639            _ => false,
640        }
641    }
642}
643
644#[derive(Debug, Clone)]
645pub struct StructExpressionField {
646    pub name: Ident,
647    pub value: Expression,
648}
649
650impl EqWithEngines for StructExpressionField {}
651impl PartialEqWithEngines for StructExpressionField {
652    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
653        self.name == other.name && self.value.eq(&other.value, ctx)
654    }
655}
656
657impl Spanned for Expression {
658    fn span(&self) -> Span {
659        self.span.clone()
660    }
661}
662
663#[derive(Debug)]
664pub(crate) struct Op {
665    pub span: Span,
666    pub op_variant: OpVariant,
667}
668
669impl Op {
670    pub fn to_method_name(&self) -> Ident {
671        Ident::new_with_override(self.op_variant.method_name().to_string(), self.span.clone())
672    }
673}
674
675#[derive(Debug)]
676pub enum OpVariant {
677    Add,
678    Subtract,
679    Divide,
680    Multiply,
681    Modulo,
682    Or,
683    And,
684    Equals,
685    NotEquals,
686    Xor,
687    BinaryOr,
688    BinaryAnd,
689    GreaterThan,
690    LessThan,
691    GreaterThanOrEqualTo,
692    LessThanOrEqualTo,
693}
694
695impl OpVariant {
696    /// For all the operators except [OpVariant::Or] and [OpVariant::And],
697    /// returns the name of the method that can be found on the corresponding
698    /// operator trait. E.g., for `+` that will be the method `add` defined in
699    /// `std::ops::Add::add`.
700    ///
701    /// [OpVariant::Or] and [OpVariant::And] are lazy and must be handled
702    /// internally by the compiler.
703    fn method_name(&self) -> &'static str {
704        use OpVariant::*;
705        match self {
706            Add => "add",
707            Subtract => "subtract",
708            Divide => "divide",
709            Multiply => "multiply",
710            Modulo => "modulo",
711            Or => "$or$",
712            And => "$and$",
713            Equals => "eq",
714            NotEquals => "neq",
715            Xor => "xor",
716            BinaryOr => "binary_or",
717            BinaryAnd => "binary_and",
718            GreaterThan => "gt",
719            LessThan => "lt",
720            LessThanOrEqualTo => "le",
721            GreaterThanOrEqualTo => "ge",
722        }
723    }
724}