1 /**
2 * Copyright (c) 2021-2025 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 #include "assignmentExpression.h"
17
18 #include "compiler/base/lreference.h"
19 #include "compiler/core/pandagen.h"
20 #include "compiler/core/ETSGen.h"
21 #include "checker/TSchecker.h"
22
23 namespace ark::es2panda::ir {
24
ConvertibleToAssignmentPatternLeft(bool mustBePattern)25 bool AssignmentExpression::ConvertibleToAssignmentPatternLeft(bool mustBePattern)
26 {
27 switch (left_->Type()) {
28 case AstNodeType::ARRAY_EXPRESSION: {
29 return left_->AsArrayExpression()->ConvertibleToArrayPattern();
30 }
31 case AstNodeType::SPREAD_ELEMENT: {
32 return mustBePattern && left_->AsSpreadElement()->ConvertibleToRest(false);
33 }
34 case AstNodeType::OBJECT_EXPRESSION: {
35 return left_->AsObjectExpression()->ConvertibleToObjectPattern();
36 }
37 case AstNodeType::ASSIGNMENT_EXPRESSION: {
38 return left_->AsAssignmentExpression()->ConvertibleToAssignmentPattern(mustBePattern);
39 }
40 case AstNodeType::META_PROPERTY_EXPRESSION:
41 case AstNodeType::CHAIN_EXPRESSION: {
42 return false;
43 }
44 default: {
45 return true;
46 }
47 }
48 }
49
ConvertibleToAssignmentPatternRight()50 bool AssignmentExpression::ConvertibleToAssignmentPatternRight()
51 {
52 switch (right_->Type()) {
53 case AstNodeType::ARRAY_EXPRESSION: {
54 return right_->AsArrayExpression()->ConvertibleToArrayPattern();
55 }
56 case AstNodeType::CHAIN_EXPRESSION:
57 case AstNodeType::SPREAD_ELEMENT: {
58 return false;
59 }
60 case AstNodeType::OBJECT_EXPRESSION: {
61 return right_->AsObjectExpression()->ConvertibleToObjectPattern();
62 }
63 case AstNodeType::ASSIGNMENT_EXPRESSION: {
64 return right_->AsAssignmentExpression()->ConvertibleToAssignmentPattern(false);
65 }
66 default: {
67 return true;
68 }
69 }
70 }
71
ConvertibleToAssignmentPattern(bool mustBePattern)72 bool AssignmentExpression::ConvertibleToAssignmentPattern(bool mustBePattern)
73 {
74 bool convResult = ConvertibleToAssignmentPatternLeft(mustBePattern);
75 if (mustBePattern) {
76 SetType(AstNodeType::ASSIGNMENT_PATTERN);
77 }
78
79 if (!right_->IsAssignmentExpression()) {
80 return convResult;
81 }
82 return ConvertibleToAssignmentPatternRight();
83 }
84
TransformChildren(const NodeTransformer & cb,std::string_view transformationName)85 void AssignmentExpression::TransformChildren(const NodeTransformer &cb, std::string_view transformationName)
86 {
87 if (auto *transformedNode = cb(left_); left_ != transformedNode) {
88 left_->SetTransformedNode(transformationName, transformedNode);
89 left_ = transformedNode->AsExpression();
90 }
91
92 if (auto *transformedNode = cb(right_); right_ != transformedNode) {
93 right_->SetTransformedNode(transformationName, transformedNode);
94 right_ = transformedNode->AsExpression();
95 }
96 }
97
Iterate(const NodeTraverser & cb) const98 void AssignmentExpression::Iterate(const NodeTraverser &cb) const
99 {
100 cb(left_);
101 cb(right_);
102 }
103
Dump(ir::AstDumper * dumper) const104 void AssignmentExpression::Dump(ir::AstDumper *dumper) const
105 {
106 if (type_ == AstNodeType::ASSIGNMENT_EXPRESSION) {
107 dumper->Add({{"type", "AssignmentExpression"}, {"operator", operator_}, {"left", left_}, {"right", right_}});
108 } else {
109 dumper->Add({{"type", "AssignmentPattern"}, {"left", left_}, {"right", right_}});
110 }
111 }
112
Dump(ir::SrcDumper * dumper) const113 void AssignmentExpression::Dump(ir::SrcDumper *dumper) const
114 {
115 ES2PANDA_ASSERT(left_);
116 left_->Dump(dumper);
117 dumper->Add(" ");
118 dumper->Add(TokenToString(operator_));
119 dumper->Add(" ");
120 ES2PANDA_ASSERT(right_);
121 right_->Dump(dumper);
122 }
123
Compile(compiler::PandaGen * pg) const124 void AssignmentExpression::Compile(compiler::PandaGen *pg) const
125 {
126 pg->GetAstCompiler()->Compile(this);
127 }
128
Compile(compiler::ETSGen * etsg) const129 void AssignmentExpression::Compile(compiler::ETSGen *etsg) const
130 {
131 etsg->GetAstCompiler()->Compile(this);
132 }
133
CompilePattern(compiler::PandaGen * pg) const134 void AssignmentExpression::CompilePattern(compiler::PandaGen *pg) const
135 {
136 compiler::RegScope rs(pg);
137 auto lref = compiler::JSLReference::Create(pg, left_, false);
138 right_->Compile(pg);
139 lref.SetValue();
140 }
141
Check(checker::TSChecker * checker)142 checker::Type *AssignmentExpression::Check(checker::TSChecker *checker)
143 {
144 return checker->GetAnalyzer()->Check(this);
145 }
146
Check(checker::ETSChecker * checker)147 checker::VerifiedType AssignmentExpression::Check([[maybe_unused]] checker::ETSChecker *checker)
148 {
149 return {this, checker->GetAnalyzer()->Check(this)};
150 }
151
AssignmentExpression(Tag const tag,AssignmentExpression const & other,Expression * const left,Expression * const right)152 AssignmentExpression::AssignmentExpression([[maybe_unused]] Tag const tag, AssignmentExpression const &other,
153 Expression *const left, Expression *const right)
154 : AssignmentExpression(other)
155 {
156 left_ = left;
157 if (left_ != nullptr) {
158 left_->SetParent(this);
159 }
160
161 right_ = right;
162 if (right_ != nullptr) {
163 right_->SetParent(this);
164 }
165 }
166
Clone(ArenaAllocator * const allocator,AstNode * const parent)167 AssignmentExpression *AssignmentExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent)
168 {
169 auto *const left = left_ != nullptr ? left_->Clone(allocator, nullptr)->AsExpression() : nullptr;
170 auto *const right = right_ != nullptr ? right_->Clone(allocator, nullptr)->AsExpression() : nullptr;
171 auto *const clone = allocator->New<AssignmentExpression>(Tag {}, *this, left, right);
172 ES2PANDA_ASSERT(clone);
173
174 if (parent != nullptr) {
175 clone->SetParent(parent);
176 }
177
178 clone->SetRange(Range());
179 return clone;
180 }
181 } // namespace ark::es2panda::ir
182