1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef ES2PANDA_IR_EXPRESSION_ASSIGNMENT_EXPRESSION_H
17#define ES2PANDA_IR_EXPRESSION_ASSIGNMENT_EXPRESSION_H
18
19#include "ir/expression.h"
20#include "lexer/token/tokenType.h"
21namespace ark::es2panda::checker {
22class ETSAnalyzer;
23}  // namespace ark::es2panda::checker
24namespace ark::es2panda::ir {
25class AssignmentExpression : public Expression {
26private:
27    struct Tag {};
28
29public:
30    AssignmentExpression() = delete;
31    ~AssignmentExpression() override = default;
32
33    NO_COPY_OPERATOR(AssignmentExpression);
34    NO_MOVE_SEMANTIC(AssignmentExpression);
35
36    explicit AssignmentExpression(Expression *const left, Expression *const right,
37                                  lexer::TokenType const assignmentOperator)
38        : AssignmentExpression(AstNodeType::ASSIGNMENT_EXPRESSION, left, right, assignmentOperator)
39    {
40    }
41
42    explicit AssignmentExpression(AstNodeType const type, Expression *const left, Expression *const right,
43                                  lexer::TokenType const assignmentOperator)
44        : Expression(type), left_(left), right_(right), operator_(assignmentOperator)
45    {
46    }
47
48    explicit AssignmentExpression(Tag tag, AssignmentExpression const &other, Expression *left, Expression *right);
49
50    // NOTE (vivienvoros): these friend relationships can be removed once there are getters for private fields
51    friend class checker::ETSAnalyzer;
52
53    [[nodiscard]] const Expression *Left() const noexcept
54    {
55        return left_;
56    }
57
58    [[nodiscard]] Expression *Left() noexcept
59    {
60        return left_;
61    }
62
63    [[nodiscard]] Expression *Right() noexcept
64    {
65        return right_;
66    }
67
68    [[nodiscard]] const Expression *Right() const noexcept
69    {
70        return right_;
71    }
72
73    void SetRight(Expression *const expr) noexcept
74    {
75        right_ = expr;
76
77        if (right_ != nullptr) {
78            right_->SetParent(this);
79        }
80    }
81
82    [[nodiscard]] const Expression *Result() const noexcept
83    {
84        return result_;
85    }
86
87    [[nodiscard]] Expression *Result() noexcept
88    {
89        return result_;
90    }
91
92    [[nodiscard]] lexer::TokenType OperatorType() const noexcept
93    {
94        return operator_;
95    }
96
97    lexer::TokenType SetOperatorType(lexer::TokenType tokenType) noexcept
98    {
99        return operator_ = tokenType;
100    }
101
102    void SetResult(Expression *expr) noexcept
103    {
104        left_ = expr;
105        SetStart(left_->Start());
106    }
107
108    [[nodiscard]] bool IsLogicalExtended() const noexcept
109    {
110        return operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND ||
111               operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_OR;
112    }
113
114    [[nodiscard]] varbinder::Variable *Target() noexcept
115    {
116        return target_;
117    }
118
119    [[nodiscard]] varbinder::Variable *Target() const noexcept
120    {
121        return target_;
122    }
123
124    void SetIgnoreConstAssign()
125    {
126        ignoreConstAssign_ = true;
127    }
128
129    [[nodiscard]] bool IsIgnoreConstAssign() const
130    {
131        return ignoreConstAssign_;
132    }
133
134    [[nodiscard]] AssignmentExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override;
135
136    [[nodiscard]] bool ConvertibleToAssignmentPatternLeft(bool mustBePattern);
137    [[nodiscard]] bool ConvertibleToAssignmentPatternRight();
138    [[nodiscard]] bool ConvertibleToAssignmentPattern(bool mustBePattern = true);
139
140    void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override;
141    void Iterate(const NodeTraverser &cb) const override;
142    void Dump(ir::AstDumper *dumper) const override;
143    void Dump(ir::SrcDumper *dumper) const override;
144    void Compile(compiler::PandaGen *pg) const override;
145    void Compile(compiler::ETSGen *etsg) const override;
146    void CompilePattern(compiler::PandaGen *pg) const;
147    checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override;
148    checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) override;
149
150    void Accept(ASTVisitorT *v) override
151    {
152        v->Accept(this);
153    }
154
155protected:
156    AssignmentExpression(AssignmentExpression const &other) : Expression(static_cast<Expression const &>(other))
157    {
158        operator_ = other.operator_;
159        target_ = other.target_;
160        operationType_ = other.operationType_;
161    }
162
163private:
164    Expression *left_ = nullptr;
165    Expression *right_ = nullptr;
166    Expression *result_ = nullptr;
167    lexer::TokenType operator_;
168    varbinder::Variable *target_ {};
169    checker::Type *operationType_ {};
170    bool ignoreConstAssign_ = false;
171};
172}  // namespace ark::es2panda::ir
173
174#endif
175