1 /*
2 * Copyright (c) 2021-2022 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 "lreference.h"
17
18 #include <compiler/base/destructuring.h>
19 #include <compiler/core/pandagen.h>
20 #include <ir/base/classDefinition.h>
21 #include <ir/base/spreadElement.h>
22 #include <ir/expressions/assignmentExpression.h>
23 #include <ir/expressions/identifier.h>
24 #include <ir/expressions/memberExpression.h>
25 #include <ir/statements/variableDeclaration.h>
26 #include <ir/statements/variableDeclarator.h>
27 #include <ir/ts/tsAsExpression.h>
28 #include <ir/ts/tsSatisfiesExpression.h>
29 #include <ir/ts/tsTypeAssertion.h>
30 #include <ir/ts/tsNonNullExpression.h>
31
32 namespace panda::es2panda::compiler {
33
34 // LReference
35
LReference(const ir::AstNode * node,PandaGen * pg,bool isDeclaration,ReferenceKind refKind,binder::ScopeFindResult res)36 LReference::LReference(const ir::AstNode *node, PandaGen *pg, bool isDeclaration, ReferenceKind refKind,
37 binder::ScopeFindResult res)
38 : node_(node), pg_(pg), refKind_(refKind), res_(res), isDeclaration_(isDeclaration)
39 {
40 if (refKind == ReferenceKind::MEMBER) {
41 obj_ = pg_->AllocReg();
42
43 node_->AsMemberExpression()->CompileObject(pg_, obj_);
44 if (!node_->AsMemberExpression()->AccessPrivateProperty()) {
45 prop_ = node->AsMemberExpression()->CompileKey(pg_);
46 }
47 }
48 }
49
GetValue()50 void LReference::GetValue()
51 {
52 switch (refKind_) {
53 case ReferenceKind::VAR_OR_GLOBAL: {
54 pg_->LoadVar(node_->AsIdentifier(), res_);
55 break;
56 }
57 case ReferenceKind::MEMBER: {
58 if (node_->AsMemberExpression()->AccessPrivateProperty()) {
59 auto name = node_->AsMemberExpression()->Property()->AsPrivateIdentifier()->Name();
60 auto result = pg_->Scope()->FindPrivateName(name);
61 if (!result.result.isMethod) {
62 pg_->LoadAccumulator(node_, obj_);
63 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.slot);
64 break;
65 }
66
67 if (result.result.isStatic) {
68 pg_->LoadLexicalVar(node_, result.lexLevel, result.result.validateMethodSlot);
69 pg_->Equal(node_, obj_);
70 pg_->ThrowTypeErrorIfFalse(node_, "Object does not have private property");
71 } else {
72 pg_->LoadAccumulator(node_, obj_);
73 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.validateMethodSlot);
74 }
75 if (result.result.isSetter) {
76 pg_->ThrowTypeError(node_, "Property is not defined with Getter");
77 }
78 if (result.result.isGetter) {
79 pg_->LoadAccumulator(node_, obj_);
80 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.slot);
81 break;
82 }
83 pg_->LoadLexicalVar(node_, result.lexLevel, result.result.slot);
84 } else {
85 pg_->LoadObjProperty(node_, obj_, prop_);
86 }
87 break;
88 }
89 default: {
90 UNREACHABLE();
91 }
92 }
93 }
94
SetValue()95 void LReference::SetValue()
96 {
97 switch (refKind_) {
98 case ReferenceKind::VAR_OR_GLOBAL: {
99 pg_->StoreVar(node_, res_, isDeclaration_);
100 break;
101 }
102 case ReferenceKind::MEMBER: {
103 if (node_->AsMemberExpression()->Object()->IsSuperExpression()) {
104 pg_->StoreSuperProperty(node_, obj_, prop_);
105 } else if (node_->AsMemberExpression()->AccessPrivateProperty()) {
106 compiler::RegScope rs(pg_);
107 VReg valueReg = pg_->AllocReg();
108
109 auto name = node_->AsMemberExpression()->Property()->AsPrivateIdentifier()->Name();
110 auto result = pg_->Scope()->FindPrivateName(name, true);
111 if (!result.result.isMethod) {
112 pg_->StorePrivateProperty(node_, result.lexLevel, result.result.slot, obj_);
113 break;
114 }
115 if (!result.result.isSetter) {
116 pg_->ThrowTypeError(node_, "Method is not writable");
117 }
118 // store value
119 pg_->StoreAccumulator(node_, valueReg);
120
121 if (result.result.isStatic) {
122 pg_->LoadLexicalVar(node_, result.lexLevel, result.result.validateMethodSlot);
123 pg_->Equal(node_, obj_);
124 pg_->ThrowTypeErrorIfFalse(node_, "Object does not have private property");
125 } else {
126 pg_->LoadAccumulator(node_, obj_);
127 pg_->LoadPrivateProperty(node_, result.lexLevel, result.result.validateMethodSlot);
128 }
129 pg_->LoadAccumulator(node_, valueReg);
130 pg_->StorePrivateProperty(node_, result.lexLevel, result.result.slot, obj_);
131 } else {
132 pg_->StoreObjProperty(node_, obj_, prop_);
133 }
134
135 break;
136 }
137 case ReferenceKind::DESTRUCTURING: {
138 Destructuring::Compile(pg_, node_->AsExpression());
139 break;
140 }
141 default: {
142 UNREACHABLE();
143 }
144 }
145 }
146
Kind() const147 ReferenceKind LReference::Kind() const
148 {
149 return refKind_;
150 }
151
Variable() const152 binder::Variable *LReference::Variable() const
153 {
154 return res_.variable;
155 }
156
CreateLRef(PandaGen * pg,const ir::AstNode * node,bool isDeclaration)157 LReference LReference::CreateLRef(PandaGen *pg, const ir::AstNode *node, bool isDeclaration)
158 {
159 switch (node->Type()) {
160 case ir::AstNodeType::IDENTIFIER: {
161 const util::StringView &name = node->AsIdentifier()->Name();
162 binder::ScopeFindResult res = pg->Scope()->Find(name);
163
164 return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res};
165 }
166 case ir::AstNodeType::MEMBER_EXPRESSION: {
167 return {node, pg, false, ReferenceKind::MEMBER, {}};
168 }
169 case ir::AstNodeType::VARIABLE_DECLARATION: {
170 ASSERT(node->AsVariableDeclaration()->Declarators().size() == 1);
171 return LReference::CreateLRef(pg, node->AsVariableDeclaration()->Declarators()[0]->Id(), true);
172 }
173 case ir::AstNodeType::VARIABLE_DECLARATOR: {
174 return LReference::CreateLRef(pg, node->AsVariableDeclarator()->Id(), true);
175 }
176 case ir::AstNodeType::ARRAY_PATTERN:
177 case ir::AstNodeType::OBJECT_PATTERN:
178 case ir::AstNodeType::ARRAY_EXPRESSION:
179 case ir::AstNodeType::OBJECT_EXPRESSION: {
180 return {node, pg, isDeclaration, ReferenceKind::DESTRUCTURING, {}};
181 }
182 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
183 return LReference::CreateLRef(pg, node->AsAssignmentPattern()->Left(), true);
184 }
185 case ir::AstNodeType::REST_ELEMENT: {
186 return LReference::CreateLRef(pg, node->AsRestElement()->Argument(), isDeclaration);
187 }
188 case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: {
189 // export default [anonymous class decl]
190 util::StringView name = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
191 binder::ScopeFindResult res = pg->Scope()->Find(name);
192
193 return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res};
194 }
195 case ir::AstNodeType::TS_AS_EXPRESSION: {
196 return LReference::CreateLRef(pg, node->AsTSAsExpression()->Expr(), isDeclaration);
197 }
198 case ir::AstNodeType::TS_SATISFIES_EXPRESSION: {
199 return LReference::CreateLRef(pg, node->AsTSSatisfiesExpression()->Expr(), isDeclaration);
200 }
201 case ir::AstNodeType::TS_TYPE_ASSERTION: {
202 return LReference::CreateLRef(pg, node->AsTSTypeAssertion()->GetExpression(), isDeclaration);
203 }
204 case ir::AstNodeType::TS_NON_NULL_EXPRESSION: {
205 return LReference::CreateLRef(pg, node->AsTSNonNullExpression()->Expr(), isDeclaration);
206 }
207 default: {
208 UNREACHABLE();
209 }
210 }
211 }
212
213 } // namespace panda::es2panda::compiler
214