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    Panic(Box<Expression>),
512    Ref(RefExpression),
513    Deref(Box<Expression>),
514}
515
516impl EqWithEngines for Expression {}
517impl PartialEqWithEngines for Expression {
518    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
519        self.kind.eq(&other.kind, ctx)
520    }
521}
522
523impl EqWithEngines for ExpressionKind {}
524impl PartialEqWithEngines for ExpressionKind {
525    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
526        match (self, other) {
527            (ExpressionKind::Error(l_span, _), ExpressionKind::Error(r_span, _)) => {
528                l_span == r_span
529            }
530            (ExpressionKind::Literal(l_literal), ExpressionKind::Literal(r_literal)) => {
531                l_literal == r_literal
532            }
533            (
534                ExpressionKind::AmbiguousPathExpression(lhs),
535                ExpressionKind::AmbiguousPathExpression(rhs),
536            ) => lhs.eq(rhs, ctx),
537            (
538                ExpressionKind::FunctionApplication(lhs),
539                ExpressionKind::FunctionApplication(rhs),
540            ) => lhs.eq(rhs, ctx),
541            (ExpressionKind::LazyOperator(lhs), ExpressionKind::LazyOperator(rhs)) => {
542                lhs.eq(rhs, ctx)
543            }
544            (
545                ExpressionKind::AmbiguousVariableExpression(lhs),
546                ExpressionKind::AmbiguousVariableExpression(rhs),
547            ) => lhs == rhs,
548            (ExpressionKind::Variable(lhs), ExpressionKind::Variable(rhs)) => lhs == rhs,
549            (ExpressionKind::Tuple(lhs), ExpressionKind::Tuple(rhs)) => lhs.eq(rhs, ctx),
550            (ExpressionKind::TupleIndex(lhs), ExpressionKind::TupleIndex(rhs)) => lhs.eq(rhs, ctx),
551            (ExpressionKind::Array(lhs), ExpressionKind::Array(rhs)) => lhs.eq(rhs, ctx),
552            (ExpressionKind::Struct(lhs), ExpressionKind::Struct(rhs)) => lhs.eq(rhs, ctx),
553            (ExpressionKind::CodeBlock(lhs), ExpressionKind::CodeBlock(rhs)) => lhs.eq(rhs, ctx),
554            (ExpressionKind::If(lhs), ExpressionKind::If(rhs)) => lhs.eq(rhs, ctx),
555            (ExpressionKind::Match(lhs), ExpressionKind::Match(rhs)) => lhs.eq(rhs, ctx),
556            (ExpressionKind::Asm(lhs), ExpressionKind::Asm(rhs)) => lhs.eq(rhs, ctx),
557            (ExpressionKind::MethodApplication(lhs), ExpressionKind::MethodApplication(rhs)) => {
558                lhs.eq(rhs, ctx)
559            }
560            (ExpressionKind::Subfield(lhs), ExpressionKind::Subfield(rhs)) => lhs.eq(rhs, ctx),
561            (ExpressionKind::DelineatedPath(lhs), ExpressionKind::DelineatedPath(rhs)) => {
562                lhs.eq(rhs, ctx)
563            }
564            (ExpressionKind::AbiCast(lhs), ExpressionKind::AbiCast(rhs)) => lhs.eq(rhs, ctx),
565            (ExpressionKind::ArrayIndex(lhs), ExpressionKind::ArrayIndex(rhs)) => lhs.eq(rhs, ctx),
566            (ExpressionKind::StorageAccess(lhs), ExpressionKind::StorageAccess(rhs)) => {
567                lhs.eq(rhs, ctx)
568            }
569            (ExpressionKind::IntrinsicFunction(lhs), ExpressionKind::IntrinsicFunction(rhs)) => {
570                lhs.eq(rhs, ctx)
571            }
572            (ExpressionKind::WhileLoop(lhs), ExpressionKind::WhileLoop(rhs)) => lhs.eq(rhs, ctx),
573            (ExpressionKind::ForLoop(lhs), ExpressionKind::ForLoop(rhs)) => lhs.eq(rhs, ctx),
574            (ExpressionKind::Break, ExpressionKind::Break) => true,
575            (ExpressionKind::Continue, ExpressionKind::Continue) => true,
576            (ExpressionKind::Reassignment(lhs), ExpressionKind::Reassignment(rhs)) => {
577                lhs.eq(rhs, ctx)
578            }
579            (ExpressionKind::ImplicitReturn(lhs), ExpressionKind::ImplicitReturn(rhs)) => {
580                lhs.eq(rhs, ctx)
581            }
582            (ExpressionKind::Return(lhs), ExpressionKind::Return(rhs)) => lhs.eq(rhs, ctx),
583            (ExpressionKind::Panic(lhs), ExpressionKind::Panic(rhs)) => lhs.eq(rhs, ctx),
584            (ExpressionKind::Ref(lhs), ExpressionKind::Ref(rhs)) => lhs.eq(rhs, ctx),
585            (ExpressionKind::Deref(lhs), ExpressionKind::Deref(rhs)) => lhs.eq(rhs, ctx),
586            _ => false,
587        }
588    }
589}
590
591#[derive(Debug, Clone)]
592pub struct RefExpression {
593    /// True if the reference is a reference to a mutable `value`.
594    pub to_mutable_value: bool,
595    pub value: Box<Expression>,
596}
597
598impl EqWithEngines for RefExpression {}
599impl PartialEqWithEngines for RefExpression {
600    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
601        self.to_mutable_value.eq(&other.to_mutable_value) && self.value.eq(&other.value, ctx)
602    }
603}
604
605#[derive(Debug, Clone)]
606pub enum ReassignmentTarget {
607    /// An [Expression] representing a single variable or a path
608    /// to a part of an aggregate.
609    /// E.g.:
610    ///  - `my_variable`
611    ///  - `array[0].field.x.1`
612    ElementAccess(Box<Expression>),
613    /// An dereferencing [Expression] representing dereferencing
614    /// of an arbitrary reference expression.
615    /// E.g.:
616    ///  - *my_ref
617    ///  - **if x > 0 { &mut &mut a } else { &mut &mut b }
618    Deref(Box<Expression>),
619}
620
621impl EqWithEngines for ReassignmentTarget {}
622impl PartialEqWithEngines for ReassignmentTarget {
623    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
624        match (self, other) {
625            (ReassignmentTarget::ElementAccess(lhs), ReassignmentTarget::ElementAccess(rhs)) => {
626                lhs.eq(rhs, ctx)
627            }
628            (ReassignmentTarget::Deref(lhs), ReassignmentTarget::Deref(rhs)) => lhs.eq(rhs, ctx),
629            _ => false,
630        }
631    }
632}
633
634#[derive(Debug, Clone)]
635pub struct StructExpressionField {
636    pub name: Ident,
637    pub value: Expression,
638}
639
640impl EqWithEngines for StructExpressionField {}
641impl PartialEqWithEngines for StructExpressionField {
642    fn eq(&self, other: &Self, ctx: &PartialEqWithEnginesContext) -> bool {
643        self.name == other.name && self.value.eq(&other.value, ctx)
644    }
645}
646
647impl Spanned for Expression {
648    fn span(&self) -> Span {
649        self.span.clone()
650    }
651}
652
653#[derive(Debug)]
654pub(crate) struct Op {
655    pub span: Span,
656    pub op_variant: OpVariant,
657}
658
659impl Op {
660    pub fn to_method_name(&self) -> Ident {
661        Ident::new_with_override(self.op_variant.method_name().to_string(), self.span.clone())
662    }
663}
664
665#[derive(Debug)]
666pub enum OpVariant {
667    Add,
668    Subtract,
669    Divide,
670    Multiply,
671    Modulo,
672    Or,
673    And,
674    Equals,
675    NotEquals,
676    Xor,
677    BinaryOr,
678    BinaryAnd,
679    GreaterThan,
680    LessThan,
681    GreaterThanOrEqualTo,
682    LessThanOrEqualTo,
683}
684
685impl OpVariant {
686    /// For all the operators except [OpVariant::Or] and [OpVariant::And],
687    /// returns the name of the method that can be found on the corresponding
688    /// operator trait. E.g., for `+` that will be the method `add` defined in
689    /// `std::ops::Add::add`.
690    ///
691    /// [OpVariant::Or] and [OpVariant::And] are lazy and must be handled
692    /// internally by the compiler.
693    fn method_name(&self) -> &'static str {
694        use OpVariant::*;
695        match self {
696            Add => "add",
697            Subtract => "subtract",
698            Divide => "divide",
699            Multiply => "multiply",
700            Modulo => "modulo",
701            Or => "$or$",
702            And => "$and$",
703            Equals => "eq",
704            NotEquals => "neq",
705            Xor => "xor",
706            BinaryOr => "binary_or",
707            BinaryAnd => "binary_and",
708            GreaterThan => "gt",
709            LessThan => "lt",
710            LessThanOrEqualTo => "le",
711            GreaterThanOrEqualTo => "ge",
712        }
713    }
714}