• 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 <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