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