• 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/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 
28 namespace panda::es2panda::compiler {
29 
30 // LReference
31 
LReference(const ir::AstNode * node,PandaGen * pg,bool isDeclaration,ReferenceKind refKind,binder::ScopeFindResult res)32 LReference::LReference(const ir::AstNode *node, PandaGen *pg, bool isDeclaration, ReferenceKind refKind,
33                        binder::ScopeFindResult res)
34     : node_(node), pg_(pg), refKind_(refKind), res_(res), isDeclaration_(isDeclaration)
35 {
36     if (refKind == ReferenceKind::MEMBER) {
37         obj_ = pg_->AllocReg();
38 
39         node_->AsMemberExpression()->CompileObject(pg_, obj_);
40         prop_ = node->AsMemberExpression()->CompileKey(pg_);
41     }
42 }
43 
GetValue()44 void LReference::GetValue()
45 {
46     switch (refKind_) {
47         case ReferenceKind::VAR_OR_GLOBAL: {
48             pg_->LoadVar(node_->AsIdentifier(), res_);
49             break;
50         }
51         case ReferenceKind::MEMBER: {
52             pg_->LoadObjProperty(node_, obj_, prop_);
53             break;
54         }
55         default: {
56             UNREACHABLE();
57         }
58     }
59 }
60 
SetValue()61 void LReference::SetValue()
62 {
63     switch (refKind_) {
64         case ReferenceKind::VAR_OR_GLOBAL: {
65             pg_->StoreVar(node_, res_, isDeclaration_);
66             break;
67         }
68         case ReferenceKind::MEMBER: {
69             if (node_->AsMemberExpression()->Object()->IsSuperExpression()) {
70                 pg_->StoreSuperProperty(node_, obj_, prop_);
71             } else {
72                 pg_->StoreObjProperty(node_, obj_, prop_);
73             }
74 
75             break;
76         }
77         case ReferenceKind::DESTRUCTURING: {
78             Destructuring::Compile(pg_, node_->AsExpression());
79             break;
80         }
81         default: {
82             UNREACHABLE();
83         }
84     }
85 }
86 
Kind() const87 ReferenceKind LReference::Kind() const
88 {
89     return refKind_;
90 }
91 
Variable() const92 binder::Variable *LReference::Variable() const
93 {
94     return res_.variable;
95 }
96 
CreateLRef(PandaGen * pg,const ir::AstNode * node,bool isDeclaration)97 LReference LReference::CreateLRef(PandaGen *pg, const ir::AstNode *node, bool isDeclaration)
98 {
99     switch (node->Type()) {
100         case ir::AstNodeType::IDENTIFIER: {
101             const util::StringView &name = node->AsIdentifier()->Name();
102             binder::ScopeFindResult res = pg->Scope()->Find(name);
103 
104             return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res};
105         }
106         case ir::AstNodeType::MEMBER_EXPRESSION: {
107             return {node, pg, false, ReferenceKind::MEMBER, {}};
108         }
109         case ir::AstNodeType::VARIABLE_DECLARATION: {
110             ASSERT(node->AsVariableDeclaration()->Declarators().size() == 1);
111             return LReference::CreateLRef(pg, node->AsVariableDeclaration()->Declarators()[0]->Id(), true);
112         }
113         case ir::AstNodeType::VARIABLE_DECLARATOR: {
114             return LReference::CreateLRef(pg, node->AsVariableDeclarator()->Id(), true);
115         }
116         case ir::AstNodeType::ARRAY_PATTERN:
117         case ir::AstNodeType::OBJECT_PATTERN:
118         case ir::AstNodeType::ARRAY_EXPRESSION:
119         case ir::AstNodeType::OBJECT_EXPRESSION: {
120             return {node, pg, isDeclaration, ReferenceKind::DESTRUCTURING, {}};
121         }
122         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
123             return LReference::CreateLRef(pg, node->AsAssignmentPattern()->Left(), true);
124         }
125         case ir::AstNodeType::REST_ELEMENT: {
126             return LReference::CreateLRef(pg, node->AsRestElement()->Argument(), isDeclaration);
127         }
128         case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: {
129             // export default [anonymous class decl]
130             util::StringView name = parser::SourceTextModuleRecord::DEFAULT_LOCAL_NAME;
131             binder::ScopeFindResult res = pg->Scope()->Find(name);
132 
133             return {node, pg, isDeclaration, ReferenceKind::VAR_OR_GLOBAL, res};
134         }
135         default: {
136             UNREACHABLE();
137         }
138     }
139 }
140 
141 }  // namespace panda::es2panda::compiler
142