• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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