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