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